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(HAVE_LONG_LONG)
2357 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2358 # define SLAP_LONG long long
2360 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2361 # define SLAP_LONG long
2362 #endif /* HAVE_STRTOLL ... */
2370 struct berval *value,
2371 void *assertedValue )
2373 SLAP_LONG lValue, lAssertedValue;
2376 /* safe to assume integers are NUL terminated? */
2377 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2378 if( errno == ERANGE )
2380 return LDAP_CONSTRAINT_VIOLATION;
2383 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2385 if( errno == ERANGE )
2387 return LDAP_CONSTRAINT_VIOLATION;
2390 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2391 return LDAP_SUCCESS;
2400 struct berval *value,
2401 void *assertedValue )
2403 SLAP_LONG lValue, lAssertedValue;
2406 /* safe to assume integers are NUL terminated? */
2407 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2408 if( errno == ERANGE )
2410 return LDAP_CONSTRAINT_VIOLATION;
2413 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2415 if( errno == ERANGE )
2417 return LDAP_CONSTRAINT_VIOLATION;
2420 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2421 return LDAP_SUCCESS;
2425 serialNumberAndIssuerValidate(
2431 struct berval sn, i;
2433 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2436 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2438 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2439 /* Parse old format */
2440 i.bv_val = ber_bvchr( in, '$' );
2441 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2443 sn.bv_val = in->bv_val;
2444 sn.bv_len = i.bv_val - in->bv_val;
2447 i.bv_len = in->bv_len - (sn.bv_len + 1);
2449 /* eat leading zeros */
2450 for( n=0; n < (sn.bv_len-1); n++ ) {
2451 if( sn.bv_val[n] != '0' ) break;
2456 for( n=0; n < sn.bv_len; n++ ) {
2457 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2461 /* Parse GSER format */
2462 int havesn=0,haveissuer=0;
2463 struct berval x = *in;
2467 /* eat leading spaces */
2468 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2472 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2473 return LDAP_INVALID_SYNTAX;
2476 /* should be at issuer or serialNumber NamedValue */
2477 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2479 x.bv_val += STRLENOF("issuer");
2480 x.bv_len -= STRLENOF("issuer");
2482 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2483 x.bv_val++; x.bv_len--;
2485 /* eat leading spaces */
2486 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2490 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2491 x.bv_val++; x.bv_len--;
2493 i.bv_val = x.bv_val;
2496 for( ; i.bv_len < x.bv_len; ) {
2497 if ( i.bv_val[i.bv_len] != '"' ) {
2501 if ( i.bv_val[i.bv_len+1] == '"' ) {
2508 x.bv_val += i.bv_len+1;
2509 x.bv_len -= i.bv_len+1;
2511 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2512 return LDAP_INVALID_SYNTAX;
2517 } else if( strncasecmp( x.bv_val, "serialNumber",
2518 STRLENOF("serialNumber")) == 0 )
2520 /* parse serialNumber */
2522 x.bv_val += STRLENOF("serialNumber");
2523 x.bv_len -= STRLENOF("serialNumber");
2525 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2526 x.bv_val++; x.bv_len--;
2528 /* eat leading spaces */
2529 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2533 sn.bv_val = x.bv_val;
2536 if( sn.bv_val[0] == '-' ) {
2541 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2542 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2545 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2546 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2547 return LDAP_INVALID_SYNTAX;
2550 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2552 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2553 return LDAP_INVALID_SYNTAX;
2558 } else return LDAP_INVALID_SYNTAX;
2560 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2561 x.bv_val++; x.bv_len--;
2564 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2568 /* should be at remaining NamedValue */
2569 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2570 STRLENOF("issuer" )) == 0 ))
2573 x.bv_val += STRLENOF("issuer");
2574 x.bv_len -= STRLENOF("issuer");
2576 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2577 x.bv_val++; x.bv_len--;
2579 /* eat leading spaces */
2580 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2584 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2585 x.bv_val++; x.bv_len--;
2587 i.bv_val = x.bv_val;
2590 for( ; i.bv_len < x.bv_len; ) {
2591 if ( i.bv_val[i.bv_len] != '"' ) {
2595 if ( i.bv_val[i.bv_len+1] == '"' ) {
2602 x.bv_val += i.bv_len+1;
2603 x.bv_len -= i.bv_len+1;
2605 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2606 STRLENOF("serialNumber")) == 0 ))
2608 /* parse serialNumber */
2610 x.bv_val += STRLENOF("serialNumber");
2611 x.bv_len -= STRLENOF("serialNumber");
2613 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2614 x.bv_val++; x.bv_len--;
2616 /* eat leading spaces */
2617 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2621 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2622 x.bv_val++; x.bv_len--;
2624 sn.bv_val = x.bv_val;
2627 if( sn.bv_val[0] == '-' ) {
2632 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2633 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2636 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2637 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2638 return LDAP_INVALID_SYNTAX;
2641 x.bv_val += sn.bv_len;
2642 x.bv_len -= sn.bv_len;
2644 } else return LDAP_INVALID_SYNTAX;
2646 /* eat trailing spaces */
2647 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2651 /* should have no characters left... */
2652 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2655 /* validate DN -- doesn't handle double dquote */
2656 rc = dnValidate( NULL, &i );
2657 if( rc ) return LDAP_INVALID_SYNTAX;
2659 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2661 return LDAP_SUCCESS;
2665 serialNumberAndIssuerPretty(
2673 struct berval sn, i, ni;
2675 assert( in != NULL );
2676 assert( out != NULL );
2678 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2681 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2683 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2684 /* Parse old format */
2685 i.bv_val = ber_bvchr( in, '$' );
2686 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2688 sn.bv_val = in->bv_val;
2689 sn.bv_len = i.bv_val - in->bv_val;
2692 i.bv_len = in->bv_len - (sn.bv_len + 1);
2694 /* eat leading zeros */
2695 for( n=0; n < (sn.bv_len-1); n++ ) {
2696 if( sn.bv_val[n] != '0' ) break;
2701 for( n=0; n < sn.bv_len; n++ ) {
2702 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2706 /* Parse GSER format */
2707 int havesn=0,haveissuer=0;
2708 struct berval x = *in;
2712 /* eat leading spaces */
2713 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2717 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2718 return LDAP_INVALID_SYNTAX;
2721 /* should be at issuer or serialNumber NamedValue */
2722 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2724 x.bv_val += STRLENOF("issuer");
2725 x.bv_len -= STRLENOF("issuer");
2727 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2728 x.bv_val++; x.bv_len--;
2730 /* eat leading spaces */
2731 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2735 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2736 x.bv_val++; x.bv_len--;
2738 i.bv_val = x.bv_val;
2741 for( ; i.bv_len < x.bv_len; ) {
2742 if ( i.bv_val[i.bv_len] != '"' ) {
2746 if ( i.bv_val[i.bv_len+1] == '"' ) {
2753 x.bv_val += i.bv_len+1;
2754 x.bv_len -= i.bv_len+1;
2756 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2757 return LDAP_INVALID_SYNTAX;
2762 } else if( strncasecmp( x.bv_val, "serialNumber",
2763 STRLENOF("serialNumber")) == 0 )
2765 /* parse serialNumber */
2767 x.bv_val += STRLENOF("serialNumber");
2768 x.bv_len -= STRLENOF("serialNumber");
2770 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2771 x.bv_val++; x.bv_len--;
2773 /* eat leading spaces */
2774 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2778 sn.bv_val = x.bv_val;
2781 if( sn.bv_val[0] == '-' ) {
2786 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2787 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2790 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2791 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2792 return LDAP_INVALID_SYNTAX;
2795 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2797 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2798 return LDAP_INVALID_SYNTAX;
2803 } else return LDAP_INVALID_SYNTAX;
2805 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2806 x.bv_val++; x.bv_len--;
2809 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2813 /* should be at remaining NamedValue */
2814 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2815 STRLENOF("issuer" )) == 0 ))
2818 x.bv_val += STRLENOF("issuer");
2819 x.bv_len -= STRLENOF("issuer");
2821 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2822 x.bv_val++; x.bv_len--;
2824 /* eat leading spaces */
2825 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2829 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2830 x.bv_val++; x.bv_len--;
2832 i.bv_val = x.bv_val;
2835 for( ; i.bv_len < x.bv_len; ) {
2836 if ( i.bv_val[i.bv_len] != '"' ) {
2840 if ( i.bv_val[i.bv_len+1] == '"' ) {
2847 x.bv_val += i.bv_len+1;
2848 x.bv_len -= i.bv_len+1;
2850 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2851 STRLENOF("serialNumber")) == 0 ))
2853 /* parse serialNumber */
2855 x.bv_val += STRLENOF("serialNumber");
2856 x.bv_len -= STRLENOF("serialNumber");
2858 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2859 x.bv_val++; x.bv_len--;
2861 /* eat leading spaces */
2862 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2866 sn.bv_val = x.bv_val;
2869 if( sn.bv_val[0] == '-' ) {
2874 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2875 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2878 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2879 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2880 return LDAP_INVALID_SYNTAX;
2883 x.bv_val += sn.bv_len;
2884 x.bv_len -= sn.bv_len;
2886 } else return LDAP_INVALID_SYNTAX;
2888 /* eat trailing spaces */
2889 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2893 /* should have no characters left... */
2894 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2896 ber_dupbv_x( &ni, &i, ctx );
2899 /* need to handle double dquotes here */
2902 rc = dnPretty( syntax, &i, &ni, ctx );
2904 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2905 slap_sl_free( i.bv_val, ctx );
2908 if( rc ) return LDAP_INVALID_SYNTAX;
2910 /* make room from sn + "$" */
2911 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2912 + sn.bv_len + ni.bv_len;
2913 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2915 if( out->bv_val == NULL ) {
2917 slap_sl_free( ni.bv_val, ctx );
2922 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2923 STRLENOF("{ serialNumber "));
2924 n = STRLENOF("{ serialNumber ");
2926 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2929 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2930 n += STRLENOF(", issuer \"");
2932 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2935 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2936 n += STRLENOF("\" }");
2938 out->bv_val[n] = '\0';
2940 assert( n == out->bv_len );
2942 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2943 out->bv_val, 0, 0 );
2945 slap_sl_free( ni.bv_val, ctx );
2947 return LDAP_SUCCESS;
2951 * This routine is called by certificateExactNormalize when
2952 * certificateExactNormalize receives a search string instead of
2953 * a certificate. This routine checks if the search value is valid
2954 * and then returns the normalized value
2957 serialNumberAndIssuerNormalize(
2967 struct berval sn, i, ni;
2969 assert( in != NULL );
2970 assert( out != NULL );
2972 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2975 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2977 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2978 /* Parse old format */
2979 i.bv_val = ber_bvchr( in, '$' );
2980 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2982 sn.bv_val = in->bv_val;
2983 sn.bv_len = i.bv_val - in->bv_val;
2986 i.bv_len = in->bv_len - (sn.bv_len + 1);
2988 /* eat leading zeros */
2989 for( n=0; n < (sn.bv_len-1); n++ ) {
2990 if( sn.bv_val[n] != '0' ) break;
2995 for( n=0; n < sn.bv_len; n++ ) {
2996 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3000 /* Parse GSER format */
3001 int havesn=0,haveissuer=0;
3002 struct berval x = *in;
3006 /* eat leading spaces */
3007 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3011 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3012 return LDAP_INVALID_SYNTAX;
3015 /* should be at issuer or serialNumber NamedValue */
3016 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3018 x.bv_val += STRLENOF("issuer");
3019 x.bv_len -= STRLENOF("issuer");
3021 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3022 x.bv_val++; x.bv_len--;
3024 /* eat leading spaces */
3025 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3029 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3030 x.bv_val++; x.bv_len--;
3032 i.bv_val = x.bv_val;
3035 for( ; i.bv_len < x.bv_len; ) {
3036 if ( i.bv_val[i.bv_len] != '"' ) {
3040 if ( i.bv_val[i.bv_len+1] == '"' ) {
3047 x.bv_val += i.bv_len+1;
3048 x.bv_len -= i.bv_len+1;
3050 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3051 return LDAP_INVALID_SYNTAX;
3056 } else if( strncasecmp( x.bv_val, "serialNumber",
3057 STRLENOF("serialNumber")) == 0 )
3059 /* parse serialNumber */
3061 x.bv_val += STRLENOF("serialNumber");
3062 x.bv_len -= STRLENOF("serialNumber");
3064 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3065 x.bv_val++; x.bv_len--;
3067 /* eat leading spaces */
3068 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3072 sn.bv_val = x.bv_val;
3075 if( sn.bv_val[0] == '-' ) {
3080 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3081 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3084 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3085 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3086 return LDAP_INVALID_SYNTAX;
3089 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3091 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3092 return LDAP_INVALID_SYNTAX;
3097 } else return LDAP_INVALID_SYNTAX;
3099 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3100 x.bv_val++; x.bv_len--;
3103 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3107 /* should be at remaining NamedValue */
3108 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3109 STRLENOF("issuer" )) == 0 ))
3112 x.bv_val += STRLENOF("issuer");
3113 x.bv_len -= STRLENOF("issuer");
3115 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3116 x.bv_val++; x.bv_len--;
3118 /* eat leading spaces */
3119 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3123 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3124 x.bv_val++; x.bv_len--;
3126 i.bv_val = x.bv_val;
3129 for( ; i.bv_len < x.bv_len; ) {
3130 if ( i.bv_val[i.bv_len] != '"' ) {
3134 if ( i.bv_val[i.bv_len+1] == '"' ) {
3141 x.bv_val += i.bv_len+1;
3142 x.bv_len -= i.bv_len+1;
3144 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3145 STRLENOF("serialNumber")) == 0 ))
3147 /* parse serialNumber */
3149 x.bv_val += STRLENOF("serialNumber");
3150 x.bv_len -= STRLENOF("serialNumber");
3152 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3153 x.bv_val++; x.bv_len--;
3155 /* eat leading spaces */
3156 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3160 sn.bv_val = x.bv_val;
3163 if( sn.bv_val[0] == '-' ) {
3168 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3169 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3172 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3173 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3174 return LDAP_INVALID_SYNTAX;
3177 x.bv_val += sn.bv_len;
3178 x.bv_len -= sn.bv_len;
3180 } else return LDAP_INVALID_SYNTAX;
3182 /* eat trailing spaces */
3183 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3187 /* should have no characters left... */
3188 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3190 ber_dupbv_x( &ni, &i, ctx );
3193 /* need to handle double dquotes here */
3196 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3198 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3199 slap_sl_free( i.bv_val, ctx );
3202 if( rc ) return LDAP_INVALID_SYNTAX;
3204 /* make room from sn + "$" */
3205 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3206 + sn.bv_len + ni.bv_len;
3207 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3209 if( out->bv_val == NULL ) {
3211 slap_sl_free( ni.bv_val, ctx );
3216 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3217 STRLENOF( "{ serialNumber " ));
3218 n = STRLENOF( "{ serialNumber " );
3220 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3223 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3224 n += STRLENOF( ", issuer \"" );
3226 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3229 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3230 n += STRLENOF( "\" }" );
3232 out->bv_val[n] = '\0';
3234 assert( n == out->bv_len );
3236 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3237 out->bv_val, 0, 0 );
3239 slap_sl_free( ni.bv_val, ctx );
3241 return LDAP_SUCCESS;
3246 certificateExactNormalize(
3251 struct berval *normalized,
3254 int rc = LDAP_INVALID_SYNTAX;
3256 char *serial = NULL;
3257 ber_len_t seriallen;
3258 struct berval issuer_dn = BER_BVNULL;
3259 X509_NAME *name = NULL;
3260 ASN1_INTEGER *sn = NULL;
3263 if( BER_BVISEMPTY( val ) ) goto done;
3265 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3266 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3269 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3271 p = (unsigned char *)val->bv_val;
3272 xcert = d2i_X509( NULL, &p, val->bv_len);
3273 if( xcert == NULL ) goto done;
3275 sn=X509_get_serialNumber(xcert);
3276 if ( sn == NULL ) goto done;
3277 serial=i2s_ASN1_INTEGER(0, sn );
3278 if( serial == NULL ) goto done;
3279 seriallen=strlen(serial);
3281 name=X509_get_issuer_name(xcert);
3282 if( name == NULL ) goto done;
3283 rc = dnX509normalize( name, &issuer_dn );
3284 if( rc != LDAP_SUCCESS ) goto done;
3286 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3287 + seriallen + issuer_dn.bv_len;
3288 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3290 p = (unsigned char *)normalized->bv_val;
3292 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3293 p += STRLENOF( "{ serialNumber " );
3295 AC_MEMCPY(p, serial, seriallen);
3298 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3299 p += STRLENOF( ", issuer \"" );
3301 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3302 p += issuer_dn.bv_len;
3304 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3305 p += STRLENOF( "\" }" );
3309 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3310 normalized->bv_val, NULL, NULL );
3315 if (xcert) X509_free(xcert);
3316 if (serial) ch_free(serial);
3317 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3321 #endif /* HAVE_TLS */
3324 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3325 /* slight optimization - does not need the start parameter */
3326 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3331 check_time_syntax (struct berval *val,
3334 struct berval *fraction)
3337 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3338 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3339 * GeneralizedTime supports leap seconds, UTCTime does not.
3341 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3342 static const int mdays[2][12] = {
3343 /* non-leap years */
3344 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3346 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3349 int part, c, c1, c2, tzoffset, leapyear = 0;
3352 e = p + val->bv_len;
3354 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3355 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3357 for (part = start; part < 7 && p < e; part++) {
3359 if (!ASCII_DIGIT(c1)) {
3364 return LDAP_INVALID_SYNTAX;
3367 if (!ASCII_DIGIT(c)) {
3368 return LDAP_INVALID_SYNTAX;
3370 c += c1 * 10 - '0' * 11;
3371 if ((part | 1) == 3) {
3374 return LDAP_INVALID_SYNTAX;
3377 if (c >= ceiling[part]) {
3378 if (! (c == 60 && part == 6 && start == 0))
3379 return LDAP_INVALID_SYNTAX;
3383 if (part < 5 + start) {
3384 return LDAP_INVALID_SYNTAX;
3386 for (; part < 9; part++) {
3390 /* leapyear check for the Gregorian calendar (year>1581) */
3391 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3395 if (parts[3] >= mdays[leapyear][parts[2]]) {
3396 return LDAP_INVALID_SYNTAX;
3400 fraction->bv_val = p;
3401 fraction->bv_len = 0;
3402 if (p < e && (*p == '.' || *p == ',')) {
3404 while (++p < e && ASCII_DIGIT(*p)) {
3407 if (p - fraction->bv_val == 1) {
3408 return LDAP_INVALID_SYNTAX;
3410 for (end_num = p; end_num[-1] == '0'; --end_num) {
3413 c = end_num - fraction->bv_val;
3414 if (c != 1) fraction->bv_len = c;
3420 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3426 return LDAP_INVALID_SYNTAX;
3432 for (part = 7; part < 9 && p < e; part++) {
3434 if (!ASCII_DIGIT(c1)) {
3439 return LDAP_INVALID_SYNTAX;
3442 if (!ASCII_DIGIT(c2)) {
3443 return LDAP_INVALID_SYNTAX;
3445 parts[part] = c1 * 10 + c2 - '0' * 11;
3446 if (parts[part] >= ceiling[part]) {
3447 return LDAP_INVALID_SYNTAX;
3450 if (part < 8 + start) {
3451 return LDAP_INVALID_SYNTAX;
3454 if (tzoffset == '-') {
3455 /* negative offset to UTC, ie west of Greenwich */
3456 parts[4] += parts[7];
3457 parts[5] += parts[8];
3458 /* offset is just hhmm, no seconds */
3459 for (part = 6; --part >= 0; ) {
3463 c = mdays[leapyear][parts[2]];
3465 if (parts[part] >= c) {
3467 return LDAP_INVALID_SYNTAX;
3472 } else if (part != 5) {
3477 /* positive offset to UTC, ie east of Greenwich */
3478 parts[4] -= parts[7];
3479 parts[5] -= parts[8];
3480 for (part = 6; --part >= 0; ) {
3481 if (parts[part] < 0) {
3483 return LDAP_INVALID_SYNTAX;
3488 /* make first arg to % non-negative */
3489 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3494 } else if (part != 5) {
3501 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3504 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3511 struct berval *normalized )
3515 rc = check_time_syntax(val, 1, parts, NULL);
3516 if (rc != LDAP_SUCCESS) {
3520 normalized->bv_val = ch_malloc( 14 );
3521 if ( normalized->bv_val == NULL ) {
3522 return LBER_ERROR_MEMORY;
3525 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3526 parts[1], parts[2] + 1, parts[3] + 1,
3527 parts[4], parts[5], parts[6] );
3528 normalized->bv_len = 13;
3530 return LDAP_SUCCESS;
3540 return check_time_syntax(in, 1, parts, NULL);
3543 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3546 generalizedTimeValidate(
3551 struct berval fraction;
3552 return check_time_syntax(in, 0, parts, &fraction);
3556 generalizedTimeNormalize(
3561 struct berval *normalized,
3566 struct berval fraction;
3568 rc = check_time_syntax(val, 0, parts, &fraction);
3569 if (rc != LDAP_SUCCESS) {
3573 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3574 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3575 if ( BER_BVISNULL( normalized ) ) {
3576 return LBER_ERROR_MEMORY;
3579 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3580 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3581 parts[4], parts[5], parts[6] );
3582 if ( !BER_BVISEMPTY( &fraction ) ) {
3583 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3584 fraction.bv_val, fraction.bv_len );
3585 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3587 strcpy( normalized->bv_val + len-1, "Z" );
3588 normalized->bv_len = len;
3590 return LDAP_SUCCESS;
3594 generalizedTimeOrderingMatch(
3599 struct berval *value,
3600 void *assertedValue )
3602 struct berval *asserted = (struct berval *) assertedValue;
3603 ber_len_t v_len = value->bv_len;
3604 ber_len_t av_len = asserted->bv_len;
3606 /* ignore trailing 'Z' when comparing */
3607 int match = memcmp( value->bv_val, asserted->bv_val,
3608 (v_len < av_len ? v_len : av_len) - 1 );
3609 if ( match == 0 ) match = v_len - av_len;
3612 return LDAP_SUCCESS;
3615 /* Index generation function */
3616 int generalizedTimeIndexer(
3621 struct berval *prefix,
3629 BerValue bvtmp; /* 40 bit index */
3631 struct lutil_timet tt;
3633 bvtmp.bv_len = sizeof(tmp);
3635 for( i=0; values[i].bv_val != NULL; i++ ) {
3636 /* just count them */
3639 /* we should have at least one value at this point */
3642 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3644 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3645 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3646 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3647 /* Use 40 bits of time for key */
3648 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3649 lutil_tm2time( &tm, &tt );
3650 tmp[0] = tt.tt_gsec & 0xff;
3651 tmp[4] = tt.tt_sec & 0xff;
3653 tmp[3] = tt.tt_sec & 0xff;
3655 tmp[2] = tt.tt_sec & 0xff;
3657 tmp[1] = tt.tt_sec & 0xff;
3659 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3663 keys[j].bv_val = NULL;
3668 return LDAP_SUCCESS;
3671 /* Index generation function */
3672 int generalizedTimeFilter(
3677 struct berval *prefix,
3678 void * assertedValue,
3684 BerValue bvtmp; /* 40 bit index */
3685 BerValue *value = (BerValue *) assertedValue;
3687 struct lutil_timet tt;
3689 bvtmp.bv_len = sizeof(tmp);
3691 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3692 /* Use 40 bits of time for key */
3693 if ( value->bv_val && value->bv_len >= 10 &&
3694 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3696 lutil_tm2time( &tm, &tt );
3697 tmp[0] = tt.tt_gsec & 0xff;
3698 tmp[4] = tt.tt_sec & 0xff;
3700 tmp[3] = tt.tt_sec & 0xff;
3702 tmp[2] = tt.tt_sec & 0xff;
3704 tmp[1] = tt.tt_sec & 0xff;
3706 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3707 ber_dupbv_x(keys, &bvtmp, ctx );
3708 keys[1].bv_val = NULL;
3716 return LDAP_SUCCESS;
3720 deliveryMethodValidate(
3722 struct berval *val )
3725 #define LENOF(s) (sizeof(s)-1)
3726 struct berval tmp = *val;
3728 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3729 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3730 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3733 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3735 switch( tmp.bv_val[0] ) {
3738 if(( tmp.bv_len >= LENOF("any") ) &&
3739 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3741 tmp.bv_len -= LENOF("any");
3742 tmp.bv_val += LENOF("any");
3745 return LDAP_INVALID_SYNTAX;
3749 if(( tmp.bv_len >= LENOF("mhs") ) &&
3750 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3752 tmp.bv_len -= LENOF("mhs");
3753 tmp.bv_val += LENOF("mhs");
3756 return LDAP_INVALID_SYNTAX;
3760 if(( tmp.bv_len >= LENOF("physical") ) &&
3761 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3763 tmp.bv_len -= LENOF("physical");
3764 tmp.bv_val += LENOF("physical");
3767 return LDAP_INVALID_SYNTAX;
3770 case 'T': /* telex or teletex or telephone */
3771 if(( tmp.bv_len >= LENOF("telex") ) &&
3772 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3774 tmp.bv_len -= LENOF("telex");
3775 tmp.bv_val += LENOF("telex");
3778 if(( tmp.bv_len >= LENOF("teletex") ) &&
3779 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3781 tmp.bv_len -= LENOF("teletex");
3782 tmp.bv_val += LENOF("teletex");
3785 if(( tmp.bv_len >= LENOF("telephone") ) &&
3786 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3788 tmp.bv_len -= LENOF("telephone");
3789 tmp.bv_val += LENOF("telephone");
3792 return LDAP_INVALID_SYNTAX;
3795 case 'G': /* g3fax or g4fax */
3796 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3797 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3798 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3800 tmp.bv_len -= LENOF("g3fax");
3801 tmp.bv_val += LENOF("g3fax");
3804 return LDAP_INVALID_SYNTAX;
3808 if(( tmp.bv_len >= LENOF("ia5") ) &&
3809 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3811 tmp.bv_len -= LENOF("ia5");
3812 tmp.bv_val += LENOF("ia5");
3815 return LDAP_INVALID_SYNTAX;
3819 if(( tmp.bv_len >= LENOF("videotex") ) &&
3820 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3822 tmp.bv_len -= LENOF("videotex");
3823 tmp.bv_val += LENOF("videotex");
3826 return LDAP_INVALID_SYNTAX;
3829 return LDAP_INVALID_SYNTAX;
3832 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3834 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3838 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3842 return LDAP_INVALID_SYNTAX;
3844 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3853 nisNetgroupTripleValidate(
3855 struct berval *val )
3860 if ( BER_BVISEMPTY( val ) ) {
3861 return LDAP_INVALID_SYNTAX;
3864 p = (char *)val->bv_val;
3865 e = p + val->bv_len;
3867 if ( *p != '(' /*')'*/ ) {
3868 return LDAP_INVALID_SYNTAX;
3871 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3875 return LDAP_INVALID_SYNTAX;
3878 } else if ( !AD_CHAR( *p ) ) {
3879 return LDAP_INVALID_SYNTAX;
3883 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3884 return LDAP_INVALID_SYNTAX;
3890 return LDAP_INVALID_SYNTAX;
3893 return LDAP_SUCCESS;
3897 bootParameterValidate(
3899 struct berval *val )
3903 if ( BER_BVISEMPTY( val ) ) {
3904 return LDAP_INVALID_SYNTAX;
3907 p = (char *)val->bv_val;
3908 e = p + val->bv_len;
3911 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3912 if ( !AD_CHAR( *p ) ) {
3913 return LDAP_INVALID_SYNTAX;
3918 return LDAP_INVALID_SYNTAX;
3922 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3923 if ( !AD_CHAR( *p ) ) {
3924 return LDAP_INVALID_SYNTAX;
3929 return LDAP_INVALID_SYNTAX;
3933 for ( p++; p < e; p++ ) {
3934 if ( !SLAP_PRINTABLE( *p ) ) {
3935 return LDAP_INVALID_SYNTAX;
3939 return LDAP_SUCCESS;
3943 firstComponentNormalize(
3948 struct berval *normalized,
3955 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3956 ber_dupbv_x( normalized, val, ctx );
3957 return LDAP_SUCCESS;
3960 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3962 if( val->bv_val[0] != '(' /*')'*/ &&
3963 val->bv_val[0] != '{' /*'}'*/ )
3965 return LDAP_INVALID_SYNTAX;
3968 /* trim leading white space */
3970 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3976 /* grab next word */
3977 comp.bv_val = &val->bv_val[len];
3978 len = val->bv_len - len;
3979 for( comp.bv_len = 0;
3980 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3986 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3987 rc = numericoidValidate( NULL, &comp );
3988 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3989 rc = integerValidate( NULL, &comp );
3991 rc = LDAP_INVALID_SYNTAX;
3995 if( rc == LDAP_SUCCESS ) {
3996 ber_dupbv_x( normalized, &comp, ctx );
4003 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4004 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4006 static slap_syntax_defs_rec syntax_defs[] = {
4007 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4008 X_BINARY X_NOT_H_R ")",
4009 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
4010 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4012 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4014 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4016 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4017 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4019 SLAP_SYNTAX_BER, berValidate, NULL},
4020 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4021 0, bitStringValidate, NULL },
4022 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4023 0, booleanValidate, NULL},
4024 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4025 X_BINARY X_NOT_H_R ")",
4026 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
4027 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4028 X_BINARY X_NOT_H_R ")",
4029 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4030 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4031 X_BINARY X_NOT_H_R ")",
4032 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4033 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4034 0, countryStringValidate, NULL},
4035 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4036 0, dnValidate, dnPretty},
4037 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4038 0, rdnValidate, rdnPretty},
4039 #ifdef LDAP_COMP_MATCH
4040 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4041 0, allComponentsValidate, NULL},
4042 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4043 0, componentFilterValidate, NULL},
4045 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4047 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4048 0, deliveryMethodValidate, NULL},
4049 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4050 0, UTF8StringValidate, NULL},
4051 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4053 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4055 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4057 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4059 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4061 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4062 0, printablesStringValidate, NULL},
4063 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4064 SLAP_SYNTAX_BLOB, NULL, NULL},
4065 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4066 0, generalizedTimeValidate, NULL},
4067 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4069 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4070 0, IA5StringValidate, NULL},
4071 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4072 0, integerValidate, NULL},
4073 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4074 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4075 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4077 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4079 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4081 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4083 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4085 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4086 0, nameUIDValidate, nameUIDPretty },
4087 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4089 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4090 0, numericStringValidate, NULL},
4091 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4093 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4094 0, numericoidValidate, NULL},
4095 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4096 0, IA5StringValidate, NULL},
4097 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4098 0, blobValidate, NULL},
4099 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4100 0, UTF8StringValidate, NULL},
4101 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4103 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4105 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4106 0, printableStringValidate, NULL},
4107 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4108 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4109 0, subtreeSpecificationValidate, NULL},
4110 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4111 X_BINARY X_NOT_H_R ")",
4112 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
4113 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4114 0, printableStringValidate, NULL},
4115 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4117 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4118 0, printablesStringValidate, NULL},
4119 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4120 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4121 0, utcTimeValidate, NULL},
4123 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4125 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4127 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4129 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4131 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4134 /* RFC 2307 NIS Syntaxes */
4135 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4136 0, nisNetgroupTripleValidate, NULL},
4137 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4138 0, bootParameterValidate, NULL},
4140 /* draft-zeilenga-ldap-x509 */
4141 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4143 serialNumberAndIssuerValidate,
4144 serialNumberAndIssuerPretty},
4145 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4146 SLAP_SYNTAX_HIDE, NULL, NULL},
4147 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4148 SLAP_SYNTAX_HIDE, NULL, NULL},
4149 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4150 SLAP_SYNTAX_HIDE, NULL, NULL},
4151 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4152 SLAP_SYNTAX_HIDE, NULL, NULL},
4153 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4154 SLAP_SYNTAX_HIDE, NULL, NULL},
4155 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4156 SLAP_SYNTAX_HIDE, NULL, NULL},
4158 #ifdef SLAPD_AUTHPASSWD
4159 /* needs updating */
4160 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4161 SLAP_SYNTAX_HIDE, NULL, NULL},
4164 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4165 0, UUIDValidate, UUIDPretty},
4167 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4168 SLAP_SYNTAX_HIDE, csnValidate, NULL},
4170 /* OpenLDAP Void Syntax */
4171 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4172 SLAP_SYNTAX_HIDE, inValidate, NULL},
4174 /* FIXME: OID is unused, but not registered yet */
4175 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4176 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
4178 {NULL, 0, NULL, NULL}
4181 char *certificateExactMatchSyntaxes[] = {
4182 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4185 #ifdef LDAP_COMP_MATCH
4186 char *componentFilterMatchSyntaxes[] = {
4187 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4191 char *directoryStringSyntaxes[] = {
4192 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4195 char *integerFirstComponentMatchSyntaxes[] = {
4196 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4197 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
4200 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4201 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4202 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4203 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
4204 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4205 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4206 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4207 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4208 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4213 * Other matching rules in X.520 that we do not use (yet):
4215 * 2.5.13.25 uTCTimeMatch
4216 * 2.5.13.26 uTCTimeOrderingMatch
4217 * 2.5.13.31* directoryStringFirstComponentMatch
4218 * 2.5.13.32* wordMatch
4219 * 2.5.13.33* keywordMatch
4220 * 2.5.13.36+ certificatePairExactMatch
4221 * 2.5.13.37+ certificatePairMatch
4222 * 2.5.13.38+ certificateListExactMatch
4223 * 2.5.13.39+ certificateListMatch
4224 * 2.5.13.40+ algorithmIdentifierMatch
4225 * 2.5.13.41* storedPrefixMatch
4226 * 2.5.13.42 attributeCertificateMatch
4227 * 2.5.13.43 readerAndKeyIDMatch
4228 * 2.5.13.44 attributeIntegrityMatch
4230 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4231 * (+) described in draft-zeilenga-ldap-x509
4233 static slap_mrule_defs_rec mrule_defs[] = {
4235 * EQUALITY matching rules must be listed after associated APPROX
4236 * matching rules. So, we list all APPROX matching rules first.
4238 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4239 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4240 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4241 NULL, NULL, directoryStringApproxMatch,
4242 directoryStringApproxIndexer, directoryStringApproxFilter,
4245 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4246 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4247 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4248 NULL, NULL, IA5StringApproxMatch,
4249 IA5StringApproxIndexer, IA5StringApproxFilter,
4253 * Other matching rules
4256 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4257 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4258 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4259 NULL, NULL, octetStringMatch,
4260 octetStringIndexer, octetStringFilter,
4263 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4264 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4265 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4266 NULL, dnNormalize, dnMatch,
4267 octetStringIndexer, octetStringFilter,
4270 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4271 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4272 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4273 NULL, dnNormalize, dnRelativeMatch,
4277 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
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.10 NAME 'dnSubordinateMatch' "
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.11 NAME 'dnSuperiorMatch' "
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.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4299 "SYNTAX 1.2.36.79672281.1.5.0 )",
4300 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4301 NULL, rdnNormalize, rdnMatch,
4302 octetStringIndexer, octetStringFilter,
4305 #ifdef LDAP_COMP_MATCH
4306 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4307 "SYNTAX 1.2.36.79672281.1.5.2 )",
4308 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4309 NULL, NULL , componentFilterMatch,
4310 octetStringIndexer, octetStringFilter,
4313 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4314 "SYNTAX 1.2.36.79672281.1.5.3 )",
4315 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4316 NULL, NULL , allComponentsMatch,
4317 octetStringIndexer, octetStringFilter,
4320 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4321 "SYNTAX 1.2.36.79672281.1.5.3 )",
4322 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4323 NULL, NULL , directoryComponentsMatch,
4324 octetStringIndexer, octetStringFilter,
4328 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4329 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4330 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4331 NULL, UTF8StringNormalize, octetStringMatch,
4332 octetStringIndexer, octetStringFilter,
4333 directoryStringApproxMatchOID },
4335 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4336 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4337 SLAP_MR_ORDERING, directoryStringSyntaxes,
4338 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4340 "caseIgnoreMatch" },
4342 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4343 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4344 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4345 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4346 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4347 "caseIgnoreMatch" },
4349 {"( 2.5.13.5 NAME 'caseExactMatch' "
4350 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4351 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4352 NULL, UTF8StringNormalize, octetStringMatch,
4353 octetStringIndexer, octetStringFilter,
4354 directoryStringApproxMatchOID },
4356 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4357 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4358 SLAP_MR_ORDERING, directoryStringSyntaxes,
4359 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4363 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4364 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4365 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4366 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4367 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4370 {"( 2.5.13.8 NAME 'numericStringMatch' "
4371 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4372 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4373 NULL, numericStringNormalize, octetStringMatch,
4374 octetStringIndexer, octetStringFilter,
4377 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4378 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4379 SLAP_MR_ORDERING, NULL,
4380 NULL, numericStringNormalize, octetStringOrderingMatch,
4382 "numericStringMatch" },
4384 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4385 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4386 SLAP_MR_SUBSTR, NULL,
4387 NULL, numericStringNormalize, octetStringSubstringsMatch,
4388 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4389 "numericStringMatch" },
4391 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4392 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4393 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4394 NULL, NULL, NULL, NULL, NULL, NULL },
4396 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4397 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4398 SLAP_MR_SUBSTR, NULL,
4399 NULL, NULL, NULL, NULL, NULL,
4400 "caseIgnoreListMatch" },
4402 {"( 2.5.13.13 NAME 'booleanMatch' "
4403 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4404 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4405 NULL, NULL, booleanMatch,
4406 octetStringIndexer, octetStringFilter,
4409 {"( 2.5.13.14 NAME 'integerMatch' "
4410 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4411 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4412 NULL, NULL, integerMatch,
4413 octetStringIndexer, octetStringFilter,
4416 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4417 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4418 SLAP_MR_ORDERING, NULL,
4419 NULL, NULL, integerMatch,
4423 {"( 2.5.13.16 NAME 'bitStringMatch' "
4424 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4425 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4426 NULL, NULL, octetStringMatch,
4427 octetStringIndexer, octetStringFilter,
4430 {"( 2.5.13.17 NAME 'octetStringMatch' "
4431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4432 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4433 NULL, NULL, octetStringMatch,
4434 octetStringIndexer, octetStringFilter,
4437 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4438 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4439 SLAP_MR_ORDERING, NULL,
4440 NULL, NULL, octetStringOrderingMatch,
4442 "octetStringMatch" },
4444 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4445 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4446 SLAP_MR_SUBSTR, NULL,
4447 NULL, NULL, octetStringSubstringsMatch,
4448 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4449 "octetStringMatch" },
4451 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4453 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4455 telephoneNumberNormalize, octetStringMatch,
4456 octetStringIndexer, octetStringFilter,
4459 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4460 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4461 SLAP_MR_SUBSTR, NULL,
4462 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4463 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4464 "telephoneNumberMatch" },
4466 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4468 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4469 NULL, NULL, NULL, NULL, NULL, NULL },
4471 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4472 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4473 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4474 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4475 uniqueMemberIndexer, uniqueMemberFilter,
4478 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4480 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4481 NULL, NULL, NULL, NULL, NULL, NULL },
4483 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4484 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4485 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4486 NULL, generalizedTimeNormalize, octetStringMatch,
4487 generalizedTimeIndexer, generalizedTimeFilter,
4490 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4492 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4493 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4495 "generalizedTimeMatch" },
4497 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4498 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4499 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4500 integerFirstComponentMatchSyntaxes,
4501 NULL, firstComponentNormalize, integerMatch,
4502 octetStringIndexer, octetStringFilter,
4505 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4507 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4508 objectIdentifierFirstComponentMatchSyntaxes,
4509 NULL, firstComponentNormalize, octetStringMatch,
4510 octetStringIndexer, octetStringFilter,
4513 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4514 "SYNTAX 1.3.6.1.1.15.1 )",
4515 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4517 NULL, certificateExactNormalize, octetStringMatch,
4518 octetStringIndexer, octetStringFilter,
4520 NULL, NULL, NULL, NULL, NULL,
4524 {"( 2.5.13.35 NAME 'certificateMatch' "
4525 "SYNTAX 1.3.6.1.1.15.2 )",
4526 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4527 NULL, NULL, NULL, NULL, NULL,
4530 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4531 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4532 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4533 NULL, IA5StringNormalize, octetStringMatch,
4534 octetStringIndexer, octetStringFilter,
4535 IA5StringApproxMatchOID },
4537 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
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.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4546 SLAP_MR_SUBSTR, NULL,
4547 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4548 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4549 "caseIgnoreIA5Match" },
4551 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
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 "caseExactIA5Match" },
4558 #ifdef SLAPD_AUTHPASSWD
4559 /* needs updating */
4560 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4561 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4562 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4563 NULL, NULL, authPasswordMatch,
4568 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4571 NULL, NULL, integerBitAndMatch,
4575 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4578 NULL, NULL, integerBitOrMatch,
4582 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4583 "SYNTAX 1.3.6.1.1.16.1 )",
4584 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4585 NULL, UUIDNormalize, octetStringMatch,
4586 octetStringIndexer, octetStringFilter,
4589 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4590 "SYNTAX 1.3.6.1.1.16.1 )",
4591 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4592 NULL, UUIDNormalize, octetStringOrderingMatch,
4593 octetStringIndexer, octetStringFilter,
4596 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4597 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4598 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4599 NULL, NULL, csnMatch,
4600 csnIndexer, csnFilter,
4603 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4604 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4605 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4606 NULL, NULL, csnOrderingMatch,
4610 /* FIXME: OID is unused, but not registered yet */
4611 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4612 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4613 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4614 NULL, authzNormalize, authzMatch,
4618 {NULL, SLAP_MR_NONE, NULL,
4619 NULL, NULL, NULL, NULL, NULL,
4624 slap_schema_init( void )
4629 /* we should only be called once (from main) */
4630 assert( schema_init_done == 0 );
4632 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4633 res = register_syntax( &syntax_defs[i] );
4636 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4637 syntax_defs[i].sd_desc );
4642 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4643 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4644 mrule_defs[i].mrd_compat_syntaxes == NULL )
4647 "slap_schema_init: Ignoring unusable matching rule %s\n",
4648 mrule_defs[i].mrd_desc );
4652 res = register_matching_rule( &mrule_defs[i] );
4656 "slap_schema_init: Error registering matching rule %s\n",
4657 mrule_defs[i].mrd_desc );
4662 res = slap_schema_load();
4663 schema_init_done = 1;
4668 schema_destroy( void )
4677 if( schema_init_done ) {
4678 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4679 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );