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;
713 /* RFC 4517 Section 3.3.2 Bit String:
714 * BitString = SQUOTE *binary-digit SQUOTE "B"
715 * binary-digit = "0" / "1"
717 * where SQUOTE [RFC4512] is
718 * SQUOTE = %x27 ; single quote ("'")
720 * Example: '0101111101'B
723 if( in->bv_val[0] != '\'' ||
724 in->bv_val[in->bv_len - 2] != '\'' ||
725 in->bv_val[in->bv_len - 1] != 'B' )
727 return LDAP_INVALID_SYNTAX;
730 for( i = in->bv_len - 3; i > 0; i-- ) {
731 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
732 return LDAP_INVALID_SYNTAX;
740 * Syntaxes from RFC 4517
745 A value of the Bit String syntax is a sequence of binary digits. The
746 LDAP-specific encoding of a value of this syntax is defined by the
749 BitString = SQUOTE *binary-digit SQUOTE "B"
751 binary-digit = "0" / "1"
753 The <SQUOTE> rule is defined in [MODELS].
758 The LDAP definition for the Bit String syntax is:
760 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
762 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
766 3.3.21. Name and Optional UID
768 A value of the Name and Optional UID syntax is the distinguished name
769 [MODELS] of an entity optionally accompanied by a unique identifier
770 that serves to differentiate the entity from others with an identical
773 The LDAP-specific encoding of a value of this syntax is defined by
776 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
778 The <BitString> rule is defined in Section 3.3.2. The
779 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
782 Note that although the '#' character may occur in the string
783 representation of a distinguished name, no additional escaping of
784 this character is performed when a <distinguishedName> is encoded in
785 a <NameAndOptionalUID>.
788 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
790 The LDAP definition for the Name and Optional UID syntax is:
792 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
794 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
801 1.4. Common ABNF Productions
804 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
806 SQUOTE = %x27 ; single quote ("'")
810 * Note: normalization strips any leading "0"s, unless the
811 * bit string is exactly "'0'B", so the normalized example,
812 * in slapd, would result in
814 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
816 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
817 * be escaped except when at the beginning of a value, the
818 * definition of Name and Optional UID appears to be flawed,
819 * because there is no clear means to determine whether the
820 * UID part is present or not.
824 * cn=Someone,dc=example,dc=com#'1'B
826 * could be either a NameAndOptionalUID with trailing UID, i.e.
828 * DN = "cn=Someone,dc=example,dc=com"
831 * or a NameAndOptionalUID with no trailing UID, and the AVA
832 * in the last RDN made of
835 * attributeValue = com#'1'B
837 * in fact "com#'1'B" is a valid IA5 string.
839 * As a consequence, current slapd code assumes that the
840 * presence of portions of a BitString at the end of the string
841 * representation of a NameAndOptionalUID means a BitString
842 * is expected, and cause an error otherwise. This is quite
843 * arbitrary, and might change in the future.
853 struct berval dn, uid;
855 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
857 ber_dupbv( &dn, in );
858 if( !dn.bv_val ) return LDAP_OTHER;
860 /* if there's a "#", try bitStringValidate()... */
861 uid.bv_val = strrchr( dn.bv_val, '#' );
862 if ( !BER_BVISNULL( &uid ) ) {
864 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
866 rc = bitStringValidate( NULL, &uid );
867 if ( rc == LDAP_SUCCESS ) {
868 /* in case of success, trim the UID,
869 * otherwise treat it as part of the DN */
870 dn.bv_len -= uid.bv_len + 1;
871 uid.bv_val[-1] = '\0';
875 rc = dnValidate( NULL, &dn );
877 ber_memfree( dn.bv_val );
888 assert( val != NULL );
889 assert( out != NULL );
892 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
894 if( BER_BVISEMPTY( val ) ) {
895 ber_dupbv_x( out, val, ctx );
897 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
898 return LDAP_INVALID_SYNTAX;
902 struct berval dnval = *val;
903 struct berval uidval = BER_BVNULL;
905 uidval.bv_val = strrchr( val->bv_val, '#' );
906 if ( !BER_BVISNULL( &uidval ) ) {
908 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
910 rc = bitStringValidate( NULL, &uidval );
912 if ( rc == LDAP_SUCCESS ) {
913 ber_dupbv_x( &dnval, val, ctx );
914 dnval.bv_len -= uidval.bv_len + 1;
915 dnval.bv_val[dnval.bv_len] = '\0';
918 BER_BVZERO( &uidval );
922 rc = dnPretty( syntax, &dnval, out, ctx );
923 if ( dnval.bv_val != val->bv_val ) {
924 slap_sl_free( dnval.bv_val, ctx );
926 if( rc != LDAP_SUCCESS ) {
930 if( !BER_BVISNULL( &uidval ) ) {
934 tmp = slap_sl_realloc( out->bv_val, out->bv_len
935 + STRLENOF( "#" ) + uidval.bv_len + 1,
938 ber_memfree_x( out->bv_val, ctx );
942 out->bv_val[out->bv_len++] = '#';
943 out->bv_val[out->bv_len++] = '\'';
945 got1 = uidval.bv_len < sizeof("'0'B");
946 for( i = 1; i < uidval.bv_len - 2; i++ ) {
947 c = uidval.bv_val[i];
950 if( got1 ) out->bv_val[out->bv_len++] = c;
954 out->bv_val[out->bv_len++] = c;
959 out->bv_val[out->bv_len++] = '\'';
960 out->bv_val[out->bv_len++] = 'B';
961 out->bv_val[out->bv_len] = '\0';
965 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
971 uniqueMemberNormalize(
976 struct berval *normalized,
982 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
984 ber_dupbv_x( &out, val, ctx );
985 if ( BER_BVISEMPTY( &out ) ) {
989 struct berval uid = BER_BVNULL;
991 uid.bv_val = strrchr( out.bv_val, '#' );
992 if ( !BER_BVISNULL( &uid ) ) {
994 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
996 rc = bitStringValidate( NULL, &uid );
997 if ( rc == LDAP_SUCCESS ) {
998 uid.bv_val[-1] = '\0';
999 out.bv_len -= uid.bv_len + 1;
1005 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1007 if( rc != LDAP_SUCCESS ) {
1008 slap_sl_free( out.bv_val, ctx );
1009 return LDAP_INVALID_SYNTAX;
1012 if( !BER_BVISNULL( &uid ) ) {
1015 tmp = ch_realloc( normalized->bv_val,
1016 normalized->bv_len + uid.bv_len
1017 + STRLENOF("#") + 1 );
1018 if ( tmp == NULL ) {
1019 ber_memfree_x( normalized->bv_val, ctx );
1023 normalized->bv_val = tmp;
1025 /* insert the separator */
1026 normalized->bv_val[normalized->bv_len++] = '#';
1028 /* append the UID */
1029 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1030 uid.bv_val, uid.bv_len );
1031 normalized->bv_len += uid.bv_len;
1034 normalized->bv_val[normalized->bv_len] = '\0';
1037 slap_sl_free( out.bv_val, ctx );
1040 return LDAP_SUCCESS;
1049 struct berval *value,
1050 void *assertedValue )
1053 struct berval *asserted = (struct berval *) assertedValue;
1054 struct berval assertedDN = *asserted;
1055 struct berval assertedUID = BER_BVNULL;
1056 struct berval valueDN = *value;
1057 struct berval valueUID = BER_BVNULL;
1058 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1060 if ( !BER_BVISEMPTY( asserted ) ) {
1061 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1062 if ( !BER_BVISNULL( &assertedUID ) ) {
1063 assertedUID.bv_val++;
1064 assertedUID.bv_len = assertedDN.bv_len
1065 - ( assertedUID.bv_val - assertedDN.bv_val );
1067 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1068 assertedDN.bv_len -= assertedUID.bv_len + 1;
1071 BER_BVZERO( &assertedUID );
1076 if ( !BER_BVISEMPTY( value ) ) {
1078 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1079 if ( !BER_BVISNULL( &valueUID ) ) {
1081 valueUID.bv_len = valueDN.bv_len
1082 - ( valueUID.bv_val - valueDN.bv_val );
1084 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1085 valueDN.bv_len -= valueUID.bv_len + 1;
1088 BER_BVZERO( &valueUID );
1093 if( valueUID.bv_len && assertedUID.bv_len ) {
1094 match = valueUID.bv_len - assertedUID.bv_len;
1097 return LDAP_SUCCESS;
1100 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1103 return LDAP_SUCCESS;
1106 } else if ( !approx && valueUID.bv_len ) {
1109 return LDAP_SUCCESS;
1111 } else if ( !approx && assertedUID.bv_len ) {
1114 return LDAP_SUCCESS;
1117 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1121 uniqueMemberIndexer(
1126 struct berval *prefix,
1134 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1135 /* just count them */
1139 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1141 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1142 struct berval assertedDN = values[i];
1143 struct berval assertedUID = BER_BVNULL;
1145 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1146 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1147 if ( !BER_BVISNULL( &assertedUID ) ) {
1148 assertedUID.bv_val++;
1149 assertedUID.bv_len = assertedDN.bv_len
1150 - ( assertedUID.bv_val - assertedDN.bv_val );
1152 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1153 assertedDN.bv_len -= assertedUID.bv_len + 1;
1156 BER_BVZERO( &assertedUID );
1161 dnvalues[i] = assertedDN;
1163 BER_BVZERO( &dnvalues[i] );
1165 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1166 dnvalues, keysp, ctx );
1168 slap_sl_free( dnvalues, ctx );
1178 struct berval *prefix,
1179 void * assertedValue,
1183 struct berval *asserted = (struct berval *) assertedValue;
1184 struct berval assertedDN = *asserted;
1185 struct berval assertedUID = BER_BVNULL;
1187 if ( !BER_BVISEMPTY( asserted ) ) {
1188 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1189 if ( !BER_BVISNULL( &assertedUID ) ) {
1190 assertedUID.bv_val++;
1191 assertedUID.bv_len = assertedDN.bv_len
1192 - ( assertedUID.bv_val - assertedDN.bv_val );
1194 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1195 assertedDN.bv_len -= assertedUID.bv_len + 1;
1198 BER_BVZERO( &assertedUID );
1203 return octetStringFilter( use, flags, syntax, mr, prefix,
1204 &assertedDN, keysp, ctx );
1209 * Handling boolean syntax and matching is quite rigid.
1210 * A more flexible approach would be to allow a variety
1211 * of strings to be normalized and prettied into TRUE
1219 /* very unforgiving validation, requires no normalization
1220 * before simplistic matching
1223 if( in->bv_len == 4 ) {
1224 if( bvmatch( in, &slap_true_bv ) ) {
1225 return LDAP_SUCCESS;
1227 } else if( in->bv_len == 5 ) {
1228 if( bvmatch( in, &slap_false_bv ) ) {
1229 return LDAP_SUCCESS;
1233 return LDAP_INVALID_SYNTAX;
1242 struct berval *value,
1243 void *assertedValue )
1245 /* simplistic matching allowed by rigid validation */
1246 struct berval *asserted = (struct berval *) assertedValue;
1247 *matchp = value->bv_len != asserted->bv_len;
1248 return LDAP_SUCCESS;
1251 /*-------------------------------------------------------------------
1252 LDAP/X.500 string syntax / matching rules have a few oddities. This
1253 comment attempts to detail how slapd(8) treats them.
1256 StringSyntax X.500 LDAP Matching/Comments
1257 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1258 PrintableString subset subset i/e + ignore insignificant spaces
1259 PrintableString subset subset i/e + ignore insignificant spaces
1260 NumericString subset subset ignore all spaces
1261 IA5String ASCII ASCII i/e + ignore insignificant spaces
1262 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1264 TelephoneNumber subset subset i + ignore all spaces and "-"
1266 See RFC 4518 for details.
1270 In X.500(93), a directory string can be either a PrintableString,
1271 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1272 In later versions, more CHOICEs were added. In all cases the string
1275 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1276 A directory string cannot be zero length.
1278 For matching, there are both case ignore and exact rules. Both
1279 also require that "insignificant" spaces be ignored.
1280 spaces before the first non-space are ignored;
1281 spaces after the last non-space are ignored;
1282 spaces after a space are ignored.
1283 Note: by these rules (and as clarified in X.520), a string of only
1284 spaces is to be treated as if held one space, not empty (which
1285 would be a syntax error).
1288 In ASN.1, numeric string is just a string of digits and spaces
1289 and could be empty. However, in X.500, all attribute values of
1290 numeric string carry a non-empty constraint. For example:
1292 internationalISDNNumber ATTRIBUTE ::= {
1293 WITH SYNTAX InternationalISDNNumber
1294 EQUALITY MATCHING RULE numericStringMatch
1295 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1296 ID id-at-internationalISDNNumber }
1297 InternationalISDNNumber ::=
1298 NumericString (SIZE(1..ub-international-isdn-number))
1300 Unforunately, some assertion values are don't carry the same
1301 constraint (but its unclear how such an assertion could ever
1302 be true). In LDAP, there is one syntax (numericString) not two
1303 (numericString with constraint, numericString without constraint).
1304 This should be treated as numericString with non-empty constraint.
1305 Note that while someone may have no ISDN number, there are no ISDN
1306 numbers which are zero length.
1308 In matching, spaces are ignored.
1311 In ASN.1, Printable string is just a string of printable characters
1312 and can be empty. In X.500, semantics much like NumericString (see
1313 serialNumber for a like example) excepting uses insignificant space
1314 handling instead of ignore all spaces.
1317 Basically same as PrintableString. There are no examples in X.500,
1318 but same logic applies. So we require them to be non-empty as
1321 -------------------------------------------------------------------*/
1330 unsigned char *u = (unsigned char *)in->bv_val;
1332 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1333 /* directory strings cannot be empty */
1334 return LDAP_INVALID_SYNTAX;
1337 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1338 /* get the length indicated by the first byte */
1339 len = LDAP_UTF8_CHARLEN2( u, len );
1341 /* very basic checks */
1344 if( (u[5] & 0xC0) != 0x80 ) {
1345 return LDAP_INVALID_SYNTAX;
1348 if( (u[4] & 0xC0) != 0x80 ) {
1349 return LDAP_INVALID_SYNTAX;
1352 if( (u[3] & 0xC0) != 0x80 ) {
1353 return LDAP_INVALID_SYNTAX;
1356 if( (u[2] & 0xC0 )!= 0x80 ) {
1357 return LDAP_INVALID_SYNTAX;
1360 if( (u[1] & 0xC0) != 0x80 ) {
1361 return LDAP_INVALID_SYNTAX;
1364 /* CHARLEN already validated it */
1367 return LDAP_INVALID_SYNTAX;
1370 /* make sure len corresponds with the offset
1371 to the next character */
1372 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1376 return LDAP_INVALID_SYNTAX;
1379 return LDAP_SUCCESS;
1383 UTF8StringNormalize(
1388 struct berval *normalized,
1391 struct berval tmp, nvalue;
1395 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1397 if( BER_BVISNULL( val ) ) {
1398 /* assume we're dealing with a syntax (e.g., UTF8String)
1399 * which allows empty strings
1401 BER_BVZERO( normalized );
1402 return LDAP_SUCCESS;
1405 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1406 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1407 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1408 ? LDAP_UTF8_APPROX : 0;
1410 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1415 /* collapse spaces (in place) */
1417 nvalue.bv_val = tmp.bv_val;
1419 /* trim leading spaces? */
1420 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1421 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1423 for( i = 0; i < tmp.bv_len; i++) {
1424 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1425 if( wasspace++ == 0 ) {
1426 /* trim repeated spaces */
1427 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1431 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1435 if( !BER_BVISEMPTY( &nvalue ) ) {
1436 /* trim trailing space? */
1438 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1439 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1443 nvalue.bv_val[nvalue.bv_len] = '\0';
1446 /* string of all spaces is treated as one space */
1447 nvalue.bv_val[0] = ' ';
1448 nvalue.bv_val[1] = '\0';
1452 *normalized = nvalue;
1453 return LDAP_SUCCESS;
1457 directoryStringSubstringsMatch(
1462 struct berval *value,
1463 void *assertedValue )
1466 SubstringsAssertion *sub = assertedValue;
1467 struct berval left = *value;
1471 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1472 if ( sub->sa_initial.bv_len > left.bv_len ) {
1473 /* not enough left */
1478 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1479 sub->sa_initial.bv_len );
1485 left.bv_val += sub->sa_initial.bv_len;
1486 left.bv_len -= sub->sa_initial.bv_len;
1488 priorspace = ASCII_SPACE(
1489 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1492 if ( sub->sa_any ) {
1493 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1497 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1498 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1500 /* allow next space to match */
1507 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1511 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1512 /* not enough left */
1517 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1524 idx = p - left.bv_val;
1526 if ( idx >= left.bv_len ) {
1527 /* this shouldn't happen */
1534 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1535 /* not enough left */
1540 match = memcmp( left.bv_val,
1541 sub->sa_any[i].bv_val,
1542 sub->sa_any[i].bv_len );
1550 left.bv_val += sub->sa_any[i].bv_len;
1551 left.bv_len -= sub->sa_any[i].bv_len;
1553 priorspace = ASCII_SPACE(
1554 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1558 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1559 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1560 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1562 /* allow next space to match */
1567 if ( sub->sa_final.bv_len > left.bv_len ) {
1568 /* not enough left */
1573 match = memcmp( sub->sa_final.bv_val,
1574 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1575 sub->sa_final.bv_len );
1584 return LDAP_SUCCESS;
1587 #if defined(SLAPD_APPROX_INITIALS)
1588 # define SLAPD_APPROX_DELIMITER "._ "
1589 # define SLAPD_APPROX_WORDLEN 2
1591 # define SLAPD_APPROX_DELIMITER " "
1592 # define SLAPD_APPROX_WORDLEN 1
1601 struct berval *value,
1602 void *assertedValue )
1604 struct berval *nval, *assertv;
1605 char *val, **values, **words, *c;
1606 int i, count, len, nextchunk=0, nextavail=0;
1608 /* Yes, this is necessary */
1609 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1610 if( nval == NULL ) {
1612 return LDAP_SUCCESS;
1615 /* Yes, this is necessary */
1616 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1617 NULL, LDAP_UTF8_APPROX, NULL );
1618 if( assertv == NULL ) {
1621 return LDAP_SUCCESS;
1624 /* Isolate how many words there are */
1625 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1626 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1627 if ( c == NULL ) break;
1632 /* Get a phonetic copy of each word */
1633 words = (char **)ch_malloc( count * sizeof(char *) );
1634 values = (char **)ch_malloc( count * sizeof(char *) );
1635 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1637 values[i] = phonetic(c);
1640 /* Work through the asserted value's words, to see if at least some
1641 of the words are there, in the same order. */
1643 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1644 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1649 #if defined(SLAPD_APPROX_INITIALS)
1650 else if( len == 1 ) {
1651 /* Single letter words need to at least match one word's initial */
1652 for( i=nextavail; i<count; i++ )
1653 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1660 /* Isolate the next word in the asserted value and phonetic it */
1661 assertv->bv_val[nextchunk+len] = '\0';
1662 val = phonetic( assertv->bv_val + nextchunk );
1664 /* See if this phonetic chunk is in the remaining words of *value */
1665 for( i=nextavail; i<count; i++ ){
1666 if( !strcmp( val, values[i] ) ){
1674 /* This chunk in the asserted value was NOT within the *value. */
1680 /* Go on to the next word in the asserted value */
1684 /* If some of the words were seen, call it a match */
1685 if( nextavail > 0 ) {
1692 /* Cleanup allocs */
1693 ber_bvfree( assertv );
1694 for( i=0; i<count; i++ ) {
1695 ch_free( values[i] );
1701 return LDAP_SUCCESS;
1710 struct berval *prefix,
1716 int i,j, len, wordcount, keycount=0;
1717 struct berval *newkeys;
1718 BerVarray keys=NULL;
1720 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1721 struct berval val = BER_BVNULL;
1722 /* Yes, this is necessary */
1723 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1724 assert( !BER_BVISNULL( &val ) );
1726 /* Isolate how many words there are. There will be a key for each */
1727 for( wordcount = 0, c = val.bv_val; *c; c++) {
1728 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1729 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1731 if (*c == '\0') break;
1735 /* Allocate/increase storage to account for new keys */
1736 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1737 * sizeof(struct berval) );
1738 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1739 if( keys ) ch_free( keys );
1742 /* Get a phonetic copy of each word */
1743 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1745 if( len < SLAPD_APPROX_WORDLEN ) continue;
1746 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1751 ber_memfree( val.bv_val );
1753 BER_BVZERO( &keys[keycount] );
1756 return LDAP_SUCCESS;
1765 struct berval *prefix,
1766 void * assertedValue,
1775 /* Yes, this is necessary */
1776 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1777 NULL, LDAP_UTF8_APPROX, NULL );
1778 if( val == NULL || BER_BVISNULL( val ) ) {
1779 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1780 BER_BVZERO( &keys[0] );
1783 return LDAP_SUCCESS;
1786 /* Isolate how many words there are. There will be a key for each */
1787 for( count = 0,c = val->bv_val; *c; c++) {
1788 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1789 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1791 if (*c == '\0') break;
1795 /* Allocate storage for new keys */
1796 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1798 /* Get a phonetic copy of each word */
1799 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1801 if( len < SLAPD_APPROX_WORDLEN ) continue;
1802 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1808 BER_BVZERO( &keys[count] );
1811 return LDAP_SUCCESS;
1814 /* Remove all spaces and '-' characters */
1816 telephoneNumberNormalize(
1821 struct berval *normalized,
1826 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1828 /* validator should have refused an empty string */
1829 assert( !BER_BVISEMPTY( val ) );
1831 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1833 for( p = val->bv_val; *p; p++ ) {
1834 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1840 normalized->bv_len = q - normalized->bv_val;
1842 if( BER_BVISEMPTY( normalized ) ) {
1843 slap_sl_free( normalized->bv_val, ctx );
1844 BER_BVZERO( normalized );
1845 return LDAP_INVALID_SYNTAX;
1848 return LDAP_SUCCESS;
1856 struct berval val = *in;
1858 if( BER_BVISEMPTY( &val ) ) {
1859 /* disallow empty strings */
1860 return LDAP_INVALID_SYNTAX;
1863 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1864 if ( val.bv_len == 1 ) {
1865 return LDAP_SUCCESS;
1868 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1875 while ( OID_LEADCHAR( val.bv_val[0] )) {
1879 if ( val.bv_len == 0 ) {
1880 return LDAP_SUCCESS;
1884 if( !OID_SEPARATOR( val.bv_val[0] )) {
1892 return LDAP_INVALID_SYNTAX;
1901 struct berval val = *in;
1903 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1905 if ( val.bv_val[0] == '-' ) {
1909 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1910 return LDAP_INVALID_SYNTAX;
1913 if( val.bv_val[0] == '0' ) { /* "-0" */
1914 return LDAP_INVALID_SYNTAX;
1917 } else if ( val.bv_val[0] == '0' ) {
1918 if( val.bv_len > 1 ) { /* "0<more>" */
1919 return LDAP_INVALID_SYNTAX;
1922 return LDAP_SUCCESS;
1925 for( i=0; i < val.bv_len; i++ ) {
1926 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1927 return LDAP_INVALID_SYNTAX;
1931 return LDAP_SUCCESS;
1940 struct berval *value,
1941 void *assertedValue )
1943 struct berval *asserted = (struct berval *) assertedValue;
1944 int vsign = 1, asign = 1; /* default sign = '+' */
1949 if( v.bv_val[0] == '-' ) {
1955 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1958 if( a.bv_val[0] == '-' ) {
1964 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1966 match = vsign - asign;
1968 match = ( v.bv_len != a.bv_len
1969 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1970 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1971 if( vsign < 0 ) match = -match;
1975 return LDAP_SUCCESS;
1979 countryStringValidate(
1981 struct berval *val )
1983 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1985 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1986 return LDAP_INVALID_SYNTAX;
1988 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1989 return LDAP_INVALID_SYNTAX;
1992 return LDAP_SUCCESS;
1996 printableStringValidate(
1998 struct berval *val )
2002 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2004 for(i=0; i < val->bv_len; i++) {
2005 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2006 return LDAP_INVALID_SYNTAX;
2010 return LDAP_SUCCESS;
2014 printablesStringValidate(
2016 struct berval *val )
2020 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2022 for(i=0,len=0; i < val->bv_len; i++) {
2023 int c = val->bv_val[i];
2027 return LDAP_INVALID_SYNTAX;
2031 } else if ( SLAP_PRINTABLE(c) ) {
2034 return LDAP_INVALID_SYNTAX;
2039 return LDAP_INVALID_SYNTAX;
2042 return LDAP_SUCCESS;
2048 struct berval *val )
2052 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2054 for(i=0; i < val->bv_len; i++) {
2055 if( !LDAP_ASCII(val->bv_val[i]) ) {
2056 return LDAP_INVALID_SYNTAX;
2060 return LDAP_SUCCESS;
2069 struct berval *normalized,
2073 int casefold = !SLAP_MR_ASSOCIATED( mr,
2074 slap_schema.si_mr_caseExactIA5Match );
2076 assert( !BER_BVISEMPTY( val ) );
2078 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2082 /* Ignore initial whitespace */
2083 while ( ASCII_SPACE( *p ) ) p++;
2085 normalized->bv_val = ber_strdup_x( p, ctx );
2086 p = q = normalized->bv_val;
2089 if ( ASCII_SPACE( *p ) ) {
2092 /* Ignore the extra whitespace */
2093 while ( ASCII_SPACE( *p ) ) {
2097 } else if ( casefold ) {
2098 /* Most IA5 rules require casefolding */
2099 *q++ = TOLOWER(*p); p++;
2106 assert( normalized->bv_val <= p );
2110 * If the string ended in space, backup the pointer one
2111 * position. One is enough because the above loop collapsed
2112 * all whitespace to a single space.
2114 if ( ASCII_SPACE( q[-1] ) ) --q;
2116 /* null terminate */
2119 normalized->bv_len = q - normalized->bv_val;
2120 if( BER_BVISEMPTY( normalized ) ) {
2121 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2122 normalized->bv_val[0] = ' ';
2123 normalized->bv_val[1] = '\0';
2124 normalized->bv_len = 1;
2127 return LDAP_SUCCESS;
2136 if( in->bv_len != 36 ) {
2137 return LDAP_INVALID_SYNTAX;
2140 for( i=0; i<36; i++ ) {
2146 if( in->bv_val[i] != '-' ) {
2147 return LDAP_INVALID_SYNTAX;
2151 if( !ASCII_HEX( in->bv_val[i]) ) {
2152 return LDAP_INVALID_SYNTAX;
2157 return LDAP_SUCCESS;
2168 int rc=LDAP_INVALID_SYNTAX;
2170 assert( in != NULL );
2171 assert( out != NULL );
2173 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2176 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2178 for( i=0; i<36; i++ ) {
2184 if( in->bv_val[i] != '-' ) {
2187 out->bv_val[i] = '-';
2191 if( !ASCII_HEX( in->bv_val[i]) ) {
2194 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2199 out->bv_val[ out->bv_len ] = '\0';
2203 slap_sl_free( out->bv_val, ctx );
2216 struct berval *normalized,
2219 unsigned char octet = '\0';
2222 normalized->bv_len = 16;
2223 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2225 for( i=0, j=0; i<36; i++ ) {
2226 unsigned char nibble;
2227 if( val->bv_val[i] == '-' ) {
2230 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2231 nibble = val->bv_val[i] - '0';
2233 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2234 nibble = val->bv_val[i] - ('a'-10);
2236 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2237 nibble = val->bv_val[i] - ('A'-10);
2240 slap_sl_free( normalized->bv_val, ctx );
2241 return LDAP_INVALID_SYNTAX;
2246 normalized->bv_val[j>>1] = octet;
2248 octet = nibble << 4;
2253 normalized->bv_val[normalized->bv_len] = 0;
2254 return LDAP_SUCCESS;
2260 numericStringValidate(
2266 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2268 for(i=0; i < in->bv_len; i++) {
2269 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2270 return LDAP_INVALID_SYNTAX;
2274 return LDAP_SUCCESS;
2278 numericStringNormalize(
2283 struct berval *normalized,
2286 /* removal all spaces */
2289 assert( !BER_BVISEMPTY( val ) );
2291 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2294 q = normalized->bv_val;
2297 if ( ASCII_SPACE( *p ) ) {
2298 /* Ignore whitespace */
2305 /* we should have copied no more then is in val */
2306 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2308 /* null terminate */
2311 normalized->bv_len = q - normalized->bv_val;
2313 if( BER_BVISEMPTY( normalized ) ) {
2314 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2315 normalized->bv_val[0] = ' ';
2316 normalized->bv_val[1] = '\0';
2317 normalized->bv_len = 1;
2320 return LDAP_SUCCESS;
2324 * Integer conversion macros that will use the largest available
2327 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2328 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2329 # define SLAP_LONG long long
2331 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2332 # define SLAP_LONG long
2333 #endif /* HAVE_STRTOLL ... */
2341 struct berval *value,
2342 void *assertedValue )
2344 SLAP_LONG lValue, lAssertedValue;
2347 /* safe to assume integers are NUL terminated? */
2348 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2349 if( errno == ERANGE )
2351 return LDAP_CONSTRAINT_VIOLATION;
2354 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2356 if( errno == ERANGE )
2358 return LDAP_CONSTRAINT_VIOLATION;
2361 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2362 return LDAP_SUCCESS;
2371 struct berval *value,
2372 void *assertedValue )
2374 SLAP_LONG lValue, lAssertedValue;
2377 /* safe to assume integers are NUL terminated? */
2378 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2379 if( errno == ERANGE )
2381 return LDAP_CONSTRAINT_VIOLATION;
2384 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2386 if( errno == ERANGE )
2388 return LDAP_CONSTRAINT_VIOLATION;
2391 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2392 return LDAP_SUCCESS;
2396 serialNumberAndIssuerValidate(
2402 struct berval sn, i;
2404 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2407 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2409 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2410 /* Parse old format */
2411 i.bv_val = ber_bvchr( in, '$' );
2412 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2414 sn.bv_val = in->bv_val;
2415 sn.bv_len = i.bv_val - in->bv_val;
2418 i.bv_len = in->bv_len - (sn.bv_len + 1);
2420 /* eat leading zeros */
2421 for( n=0; n < (sn.bv_len-1); n++ ) {
2422 if( sn.bv_val[n] != '0' ) break;
2427 for( n=0; n < sn.bv_len; n++ ) {
2428 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2432 /* Parse GSER format */
2433 int havesn=0,haveissuer=0;
2434 struct berval x = *in;
2438 /* eat leading spaces */
2439 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2443 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2444 return LDAP_INVALID_SYNTAX;
2447 /* should be at issuer or serialNumber NamedValue */
2448 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2450 x.bv_val += STRLENOF("issuer");
2451 x.bv_len -= STRLENOF("issuer");
2453 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2454 x.bv_val++; x.bv_len--;
2456 /* eat leading spaces */
2457 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2461 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2462 x.bv_val++; x.bv_len--;
2464 i.bv_val = x.bv_val;
2467 for( ; i.bv_len < x.bv_len; ) {
2468 if ( i.bv_val[i.bv_len] != '"' ) {
2472 if ( i.bv_val[i.bv_len+1] == '"' ) {
2479 x.bv_val += i.bv_len+1;
2480 x.bv_len -= i.bv_len+1;
2482 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2483 return LDAP_INVALID_SYNTAX;
2488 } else if( strncasecmp( x.bv_val, "serialNumber",
2489 STRLENOF("serialNumber")) == 0 )
2491 /* parse serialNumber */
2493 x.bv_val += STRLENOF("serialNumber");
2494 x.bv_len -= STRLENOF("serialNumber");
2496 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2497 x.bv_val++; x.bv_len--;
2499 /* eat leading spaces */
2500 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2504 sn.bv_val = x.bv_val;
2507 if( sn.bv_val[0] == '-' ) {
2512 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2513 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2516 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2517 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2518 return LDAP_INVALID_SYNTAX;
2521 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2523 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2524 return LDAP_INVALID_SYNTAX;
2529 } else return LDAP_INVALID_SYNTAX;
2531 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2532 x.bv_val++; x.bv_len--;
2535 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2539 /* should be at remaining NamedValue */
2540 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2541 STRLENOF("issuer" )) == 0 ))
2544 x.bv_val += STRLENOF("issuer");
2545 x.bv_len -= STRLENOF("issuer");
2547 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2548 x.bv_val++; x.bv_len--;
2550 /* eat leading spaces */
2551 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2555 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2556 x.bv_val++; x.bv_len--;
2558 i.bv_val = x.bv_val;
2561 for( ; i.bv_len < x.bv_len; ) {
2562 if ( i.bv_val[i.bv_len] != '"' ) {
2566 if ( i.bv_val[i.bv_len+1] == '"' ) {
2573 x.bv_val += i.bv_len+1;
2574 x.bv_len -= i.bv_len+1;
2576 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2577 STRLENOF("serialNumber")) == 0 ))
2579 /* parse serialNumber */
2581 x.bv_val += STRLENOF("serialNumber");
2582 x.bv_len -= STRLENOF("serialNumber");
2584 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2585 x.bv_val++; x.bv_len--;
2587 /* eat leading spaces */
2588 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2592 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2593 x.bv_val++; x.bv_len--;
2595 sn.bv_val = x.bv_val;
2598 if( sn.bv_val[0] == '-' ) {
2603 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2604 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2607 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2608 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2609 return LDAP_INVALID_SYNTAX;
2612 x.bv_val += sn.bv_len;
2613 x.bv_len -= sn.bv_len;
2615 } else return LDAP_INVALID_SYNTAX;
2617 /* eat trailing spaces */
2618 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2622 /* should have no characters left... */
2623 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2626 /* validate DN -- doesn't handle double dquote */
2627 rc = dnValidate( NULL, &i );
2628 if( rc ) return LDAP_INVALID_SYNTAX;
2630 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2632 return LDAP_SUCCESS;
2636 serialNumberAndIssuerPretty(
2644 struct berval sn, i, ni;
2646 assert( in != NULL );
2647 assert( out != NULL );
2649 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2652 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2654 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2655 /* Parse old format */
2656 i.bv_val = ber_bvchr( in, '$' );
2657 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2659 sn.bv_val = in->bv_val;
2660 sn.bv_len = i.bv_val - in->bv_val;
2663 i.bv_len = in->bv_len - (sn.bv_len + 1);
2665 /* eat leading zeros */
2666 for( n=0; n < (sn.bv_len-1); n++ ) {
2667 if( sn.bv_val[n] != '0' ) break;
2672 for( n=0; n < sn.bv_len; n++ ) {
2673 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2677 /* Parse GSER format */
2678 int havesn=0,haveissuer=0;
2679 struct berval x = *in;
2683 /* eat leading spaces */
2684 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2688 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2689 return LDAP_INVALID_SYNTAX;
2692 /* should be at issuer or serialNumber NamedValue */
2693 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2695 x.bv_val += STRLENOF("issuer");
2696 x.bv_len -= STRLENOF("issuer");
2698 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2699 x.bv_val++; x.bv_len--;
2701 /* eat leading spaces */
2702 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2706 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2707 x.bv_val++; x.bv_len--;
2709 i.bv_val = x.bv_val;
2712 for( ; i.bv_len < x.bv_len; ) {
2713 if ( i.bv_val[i.bv_len] != '"' ) {
2717 if ( i.bv_val[i.bv_len+1] == '"' ) {
2724 x.bv_val += i.bv_len+1;
2725 x.bv_len -= i.bv_len+1;
2727 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2728 return LDAP_INVALID_SYNTAX;
2733 } else if( strncasecmp( x.bv_val, "serialNumber",
2734 STRLENOF("serialNumber")) == 0 )
2736 /* parse serialNumber */
2738 x.bv_val += STRLENOF("serialNumber");
2739 x.bv_len -= STRLENOF("serialNumber");
2741 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2742 x.bv_val++; x.bv_len--;
2744 /* eat leading spaces */
2745 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2749 sn.bv_val = x.bv_val;
2752 if( sn.bv_val[0] == '-' ) {
2757 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2758 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2761 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2762 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2763 return LDAP_INVALID_SYNTAX;
2766 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2768 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2769 return LDAP_INVALID_SYNTAX;
2774 } else return LDAP_INVALID_SYNTAX;
2776 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2777 x.bv_val++; x.bv_len--;
2780 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2784 /* should be at remaining NamedValue */
2785 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2786 STRLENOF("issuer" )) == 0 ))
2789 x.bv_val += STRLENOF("issuer");
2790 x.bv_len -= STRLENOF("issuer");
2792 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2793 x.bv_val++; x.bv_len--;
2795 /* eat leading spaces */
2796 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2800 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2801 x.bv_val++; x.bv_len--;
2803 i.bv_val = x.bv_val;
2806 for( ; i.bv_len < x.bv_len; ) {
2807 if ( i.bv_val[i.bv_len] != '"' ) {
2811 if ( i.bv_val[i.bv_len+1] == '"' ) {
2818 x.bv_val += i.bv_len+1;
2819 x.bv_len -= i.bv_len+1;
2821 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2822 STRLENOF("serialNumber")) == 0 ))
2824 /* parse serialNumber */
2826 x.bv_val += STRLENOF("serialNumber");
2827 x.bv_len -= STRLENOF("serialNumber");
2829 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2830 x.bv_val++; x.bv_len--;
2832 /* eat leading spaces */
2833 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2837 sn.bv_val = x.bv_val;
2840 if( sn.bv_val[0] == '-' ) {
2845 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2846 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2849 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2850 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2851 return LDAP_INVALID_SYNTAX;
2854 x.bv_val += sn.bv_len;
2855 x.bv_len -= sn.bv_len;
2857 } else return LDAP_INVALID_SYNTAX;
2859 /* eat trailing spaces */
2860 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2864 /* should have no characters left... */
2865 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2867 ber_dupbv_x( &ni, &i, ctx );
2870 /* need to handle double dquotes here */
2873 rc = dnPretty( syntax, &i, &ni, ctx );
2875 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2876 slap_sl_free( i.bv_val, ctx );
2879 if( rc ) return LDAP_INVALID_SYNTAX;
2881 /* make room from sn + "$" */
2882 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2883 + sn.bv_len + ni.bv_len;
2884 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2886 if( out->bv_val == NULL ) {
2888 slap_sl_free( ni.bv_val, ctx );
2893 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2894 STRLENOF("{ serialNumber "));
2895 n = STRLENOF("{ serialNumber ");
2897 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2900 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2901 n += STRLENOF(", issuer \"");
2903 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2906 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2907 n += STRLENOF("\" }");
2909 out->bv_val[n] = '\0';
2911 assert( n == out->bv_len );
2913 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2914 out->bv_val, 0, 0 );
2916 slap_sl_free( ni.bv_val, ctx );
2918 return LDAP_SUCCESS;
2922 * This routine is called by certificateExactNormalize when
2923 * certificateExactNormalize receives a search string instead of
2924 * a certificate. This routine checks if the search value is valid
2925 * and then returns the normalized value
2928 serialNumberAndIssuerNormalize(
2938 struct berval sn, i, ni;
2940 assert( in != NULL );
2941 assert( out != NULL );
2943 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2946 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2948 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2949 /* Parse old format */
2950 i.bv_val = ber_bvchr( in, '$' );
2951 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2953 sn.bv_val = in->bv_val;
2954 sn.bv_len = i.bv_val - in->bv_val;
2957 i.bv_len = in->bv_len - (sn.bv_len + 1);
2959 /* eat leading zeros */
2960 for( n=0; n < (sn.bv_len-1); n++ ) {
2961 if( sn.bv_val[n] != '0' ) break;
2966 for( n=0; n < sn.bv_len; n++ ) {
2967 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2971 /* Parse GSER format */
2972 int havesn=0,haveissuer=0;
2973 struct berval x = *in;
2977 /* eat leading spaces */
2978 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2982 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2983 return LDAP_INVALID_SYNTAX;
2986 /* should be at issuer or serialNumber NamedValue */
2987 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2989 x.bv_val += STRLENOF("issuer");
2990 x.bv_len -= STRLENOF("issuer");
2992 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2993 x.bv_val++; x.bv_len--;
2995 /* eat leading spaces */
2996 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3000 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3001 x.bv_val++; x.bv_len--;
3003 i.bv_val = x.bv_val;
3006 for( ; i.bv_len < x.bv_len; ) {
3007 if ( i.bv_val[i.bv_len] != '"' ) {
3011 if ( i.bv_val[i.bv_len+1] == '"' ) {
3018 x.bv_val += i.bv_len+1;
3019 x.bv_len -= i.bv_len+1;
3021 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3022 return LDAP_INVALID_SYNTAX;
3027 } else if( strncasecmp( x.bv_val, "serialNumber",
3028 STRLENOF("serialNumber")) == 0 )
3030 /* parse serialNumber */
3032 x.bv_val += STRLENOF("serialNumber");
3033 x.bv_len -= STRLENOF("serialNumber");
3035 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3036 x.bv_val++; x.bv_len--;
3038 /* eat leading spaces */
3039 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3043 sn.bv_val = x.bv_val;
3046 if( sn.bv_val[0] == '-' ) {
3051 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3052 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3055 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3056 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3057 return LDAP_INVALID_SYNTAX;
3060 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3062 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3063 return LDAP_INVALID_SYNTAX;
3068 } else return LDAP_INVALID_SYNTAX;
3070 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3071 x.bv_val++; x.bv_len--;
3074 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3078 /* should be at remaining NamedValue */
3079 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3080 STRLENOF("issuer" )) == 0 ))
3083 x.bv_val += STRLENOF("issuer");
3084 x.bv_len -= STRLENOF("issuer");
3086 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3087 x.bv_val++; x.bv_len--;
3089 /* eat leading spaces */
3090 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3094 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3095 x.bv_val++; x.bv_len--;
3097 i.bv_val = x.bv_val;
3100 for( ; i.bv_len < x.bv_len; ) {
3101 if ( i.bv_val[i.bv_len] != '"' ) {
3105 if ( i.bv_val[i.bv_len+1] == '"' ) {
3112 x.bv_val += i.bv_len+1;
3113 x.bv_len -= i.bv_len+1;
3115 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3116 STRLENOF("serialNumber")) == 0 ))
3118 /* parse serialNumber */
3120 x.bv_val += STRLENOF("serialNumber");
3121 x.bv_len -= STRLENOF("serialNumber");
3123 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3124 x.bv_val++; x.bv_len--;
3126 /* eat leading spaces */
3127 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3131 sn.bv_val = x.bv_val;
3134 if( sn.bv_val[0] == '-' ) {
3139 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3140 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3143 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3144 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3145 return LDAP_INVALID_SYNTAX;
3148 x.bv_val += sn.bv_len;
3149 x.bv_len -= sn.bv_len;
3151 } else return LDAP_INVALID_SYNTAX;
3153 /* eat trailing spaces */
3154 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3158 /* should have no characters left... */
3159 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3161 ber_dupbv_x( &ni, &i, ctx );
3164 /* need to handle double dquotes here */
3167 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3169 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3170 slap_sl_free( i.bv_val, ctx );
3173 if( rc ) return LDAP_INVALID_SYNTAX;
3175 /* make room from sn + "$" */
3176 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3177 + sn.bv_len + ni.bv_len;
3178 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3180 if( out->bv_val == NULL ) {
3182 slap_sl_free( ni.bv_val, ctx );
3187 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3188 STRLENOF( "{ serialNumber " ));
3189 n = STRLENOF( "{ serialNumber " );
3191 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3194 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3195 n += STRLENOF( ", issuer \"" );
3197 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3200 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3201 n += STRLENOF( "\" }" );
3203 out->bv_val[n] = '\0';
3205 assert( n == out->bv_len );
3207 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3208 out->bv_val, 0, 0 );
3210 slap_sl_free( ni.bv_val, ctx );
3212 return LDAP_SUCCESS;
3217 certificateExactNormalize(
3222 struct berval *normalized,
3225 int rc = LDAP_INVALID_SYNTAX;
3227 char *serial = NULL;
3228 ber_len_t seriallen;
3229 struct berval issuer_dn = BER_BVNULL;
3230 X509_NAME *name = NULL;
3231 ASN1_INTEGER *sn = NULL;
3234 if( BER_BVISEMPTY( val ) ) goto done;
3236 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3237 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3240 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3242 p = (unsigned char *)val->bv_val;
3243 xcert = d2i_X509( NULL, &p, val->bv_len);
3244 if( xcert == NULL ) goto done;
3246 sn=X509_get_serialNumber(xcert);
3247 if ( sn == NULL ) goto done;
3248 serial=i2s_ASN1_INTEGER(0, sn );
3249 if( serial == NULL ) goto done;
3250 seriallen=strlen(serial);
3252 name=X509_get_issuer_name(xcert);
3253 if( name == NULL ) goto done;
3254 rc = dnX509normalize( name, &issuer_dn );
3255 if( rc != LDAP_SUCCESS ) goto done;
3257 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3258 + seriallen + issuer_dn.bv_len;
3259 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3261 p = (unsigned char *)normalized->bv_val;
3263 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3264 p += STRLENOF( "{ serialNumber " );
3266 AC_MEMCPY(p, serial, seriallen);
3269 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3270 p += STRLENOF( ", issuer \"" );
3272 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3273 p += issuer_dn.bv_len;
3275 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3276 p += STRLENOF( "\" }" );
3280 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3281 normalized->bv_val, NULL, NULL );
3286 if (xcert) X509_free(xcert);
3287 if (serial) ch_free(serial);
3288 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3292 #endif /* HAVE_TLS */
3295 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3296 /* slight optimization - does not need the start parameter */
3297 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3302 check_time_syntax (struct berval *val,
3305 struct berval *fraction)
3308 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3309 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3310 * GeneralizedTime supports leap seconds, UTCTime does not.
3312 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3313 static const int mdays[2][12] = {
3314 /* non-leap years */
3315 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3317 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3320 int part, c, c1, c2, tzoffset, leapyear = 0;
3323 e = p + val->bv_len;
3325 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3326 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3328 for (part = start; part < 7 && p < e; part++) {
3330 if (!ASCII_DIGIT(c1)) {
3335 return LDAP_INVALID_SYNTAX;
3338 if (!ASCII_DIGIT(c)) {
3339 return LDAP_INVALID_SYNTAX;
3341 c += c1 * 10 - '0' * 11;
3342 if ((part | 1) == 3) {
3345 return LDAP_INVALID_SYNTAX;
3348 if (c >= ceiling[part]) {
3349 if (! (c == 60 && part == 6 && start == 0))
3350 return LDAP_INVALID_SYNTAX;
3354 if (part < 5 + start) {
3355 return LDAP_INVALID_SYNTAX;
3357 for (; part < 9; part++) {
3361 /* leapyear check for the Gregorian calendar (year>1581) */
3362 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3366 if (parts[3] >= mdays[leapyear][parts[2]]) {
3367 return LDAP_INVALID_SYNTAX;
3371 fraction->bv_val = p;
3372 fraction->bv_len = 0;
3373 if (p < e && (*p == '.' || *p == ',')) {
3375 while (++p < e && ASCII_DIGIT(*p)) {
3378 if (p - fraction->bv_val == 1) {
3379 return LDAP_INVALID_SYNTAX;
3381 for (end_num = p; end_num[-1] == '0'; --end_num) {
3384 c = end_num - fraction->bv_val;
3385 if (c != 1) fraction->bv_len = c;
3391 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3397 return LDAP_INVALID_SYNTAX;
3403 for (part = 7; part < 9 && p < e; part++) {
3405 if (!ASCII_DIGIT(c1)) {
3410 return LDAP_INVALID_SYNTAX;
3413 if (!ASCII_DIGIT(c2)) {
3414 return LDAP_INVALID_SYNTAX;
3416 parts[part] = c1 * 10 + c2 - '0' * 11;
3417 if (parts[part] >= ceiling[part]) {
3418 return LDAP_INVALID_SYNTAX;
3421 if (part < 8 + start) {
3422 return LDAP_INVALID_SYNTAX;
3425 if (tzoffset == '-') {
3426 /* negative offset to UTC, ie west of Greenwich */
3427 parts[4] += parts[7];
3428 parts[5] += parts[8];
3429 /* offset is just hhmm, no seconds */
3430 for (part = 6; --part >= 0; ) {
3434 c = mdays[leapyear][parts[2]];
3436 if (parts[part] >= c) {
3438 return LDAP_INVALID_SYNTAX;
3443 } else if (part != 5) {
3448 /* positive offset to UTC, ie east of Greenwich */
3449 parts[4] -= parts[7];
3450 parts[5] -= parts[8];
3451 for (part = 6; --part >= 0; ) {
3452 if (parts[part] < 0) {
3454 return LDAP_INVALID_SYNTAX;
3459 /* make first arg to % non-negative */
3460 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3465 } else if (part != 5) {
3472 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3475 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3482 struct berval *normalized )
3486 rc = check_time_syntax(val, 1, parts, NULL);
3487 if (rc != LDAP_SUCCESS) {
3491 normalized->bv_val = ch_malloc( 14 );
3492 if ( normalized->bv_val == NULL ) {
3493 return LBER_ERROR_MEMORY;
3496 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3497 parts[1], parts[2] + 1, parts[3] + 1,
3498 parts[4], parts[5], parts[6] );
3499 normalized->bv_len = 13;
3501 return LDAP_SUCCESS;
3511 return check_time_syntax(in, 1, parts, NULL);
3514 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3517 generalizedTimeValidate(
3522 struct berval fraction;
3523 return check_time_syntax(in, 0, parts, &fraction);
3527 generalizedTimeNormalize(
3532 struct berval *normalized,
3537 struct berval fraction;
3539 rc = check_time_syntax(val, 0, parts, &fraction);
3540 if (rc != LDAP_SUCCESS) {
3544 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3545 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3546 if ( BER_BVISNULL( normalized ) ) {
3547 return LBER_ERROR_MEMORY;
3550 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3551 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3552 parts[4], parts[5], parts[6] );
3553 if ( !BER_BVISEMPTY( &fraction ) ) {
3554 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3555 fraction.bv_val, fraction.bv_len );
3556 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3558 strcpy( normalized->bv_val + len-1, "Z" );
3559 normalized->bv_len = len;
3561 return LDAP_SUCCESS;
3565 generalizedTimeOrderingMatch(
3570 struct berval *value,
3571 void *assertedValue )
3573 struct berval *asserted = (struct berval *) assertedValue;
3574 ber_len_t v_len = value->bv_len;
3575 ber_len_t av_len = asserted->bv_len;
3577 /* ignore trailing 'Z' when comparing */
3578 int match = memcmp( value->bv_val, asserted->bv_val,
3579 (v_len < av_len ? v_len : av_len) - 1 );
3580 if ( match == 0 ) match = v_len - av_len;
3583 return LDAP_SUCCESS;
3586 /* Index generation function */
3587 int generalizedTimeIndexer(
3592 struct berval *prefix,
3600 BerValue bvtmp; /* 40 bit index */
3602 struct lutil_timet tt;
3604 bvtmp.bv_len = sizeof(tmp);
3606 for( i=0; values[i].bv_val != NULL; i++ ) {
3607 /* just count them */
3610 /* we should have at least one value at this point */
3613 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3615 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3616 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3617 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3618 /* Use 40 bits of time for key */
3619 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3620 lutil_tm2time( &tm, &tt );
3621 tmp[0] = tt.tt_gsec & 0xff;
3622 tmp[4] = tt.tt_sec & 0xff;
3624 tmp[3] = tt.tt_sec & 0xff;
3626 tmp[2] = tt.tt_sec & 0xff;
3628 tmp[1] = tt.tt_sec & 0xff;
3630 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3634 keys[j].bv_val = NULL;
3639 return LDAP_SUCCESS;
3642 /* Index generation function */
3643 int generalizedTimeFilter(
3648 struct berval *prefix,
3649 void * assertedValue,
3655 BerValue bvtmp; /* 40 bit index */
3656 BerValue *value = (BerValue *) assertedValue;
3658 struct lutil_timet tt;
3660 bvtmp.bv_len = sizeof(tmp);
3662 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3663 /* Use 40 bits of time for key */
3664 if ( value->bv_val && value->bv_len >= 10 &&
3665 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3667 lutil_tm2time( &tm, &tt );
3668 tmp[0] = tt.tt_gsec & 0xff;
3669 tmp[4] = tt.tt_sec & 0xff;
3671 tmp[3] = tt.tt_sec & 0xff;
3673 tmp[2] = tt.tt_sec & 0xff;
3675 tmp[1] = tt.tt_sec & 0xff;
3677 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3678 ber_dupbv_x(keys, &bvtmp, ctx );
3679 keys[1].bv_val = NULL;
3687 return LDAP_SUCCESS;
3691 deliveryMethodValidate(
3693 struct berval *val )
3696 #define LENOF(s) (sizeof(s)-1)
3697 struct berval tmp = *val;
3699 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3700 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3701 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3704 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3706 switch( tmp.bv_val[0] ) {
3709 if(( tmp.bv_len >= LENOF("any") ) &&
3710 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3712 tmp.bv_len -= LENOF("any");
3713 tmp.bv_val += LENOF("any");
3716 return LDAP_INVALID_SYNTAX;
3720 if(( tmp.bv_len >= LENOF("mhs") ) &&
3721 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3723 tmp.bv_len -= LENOF("mhs");
3724 tmp.bv_val += LENOF("mhs");
3727 return LDAP_INVALID_SYNTAX;
3731 if(( tmp.bv_len >= LENOF("physical") ) &&
3732 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3734 tmp.bv_len -= LENOF("physical");
3735 tmp.bv_val += LENOF("physical");
3738 return LDAP_INVALID_SYNTAX;
3741 case 'T': /* telex or teletex or telephone */
3742 if(( tmp.bv_len >= LENOF("telex") ) &&
3743 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3745 tmp.bv_len -= LENOF("telex");
3746 tmp.bv_val += LENOF("telex");
3749 if(( tmp.bv_len >= LENOF("teletex") ) &&
3750 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3752 tmp.bv_len -= LENOF("teletex");
3753 tmp.bv_val += LENOF("teletex");
3756 if(( tmp.bv_len >= LENOF("telephone") ) &&
3757 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3759 tmp.bv_len -= LENOF("telephone");
3760 tmp.bv_val += LENOF("telephone");
3763 return LDAP_INVALID_SYNTAX;
3766 case 'G': /* g3fax or g4fax */
3767 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3768 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3769 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3771 tmp.bv_len -= LENOF("g3fax");
3772 tmp.bv_val += LENOF("g3fax");
3775 return LDAP_INVALID_SYNTAX;
3779 if(( tmp.bv_len >= LENOF("ia5") ) &&
3780 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3782 tmp.bv_len -= LENOF("ia5");
3783 tmp.bv_val += LENOF("ia5");
3786 return LDAP_INVALID_SYNTAX;
3790 if(( tmp.bv_len >= LENOF("videotex") ) &&
3791 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3793 tmp.bv_len -= LENOF("videotex");
3794 tmp.bv_val += LENOF("videotex");
3797 return LDAP_INVALID_SYNTAX;
3800 return LDAP_INVALID_SYNTAX;
3803 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3805 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3809 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3813 return LDAP_INVALID_SYNTAX;
3815 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3824 nisNetgroupTripleValidate(
3826 struct berval *val )
3831 if ( BER_BVISEMPTY( val ) ) {
3832 return LDAP_INVALID_SYNTAX;
3835 p = (char *)val->bv_val;
3836 e = p + val->bv_len;
3838 if ( *p != '(' /*')'*/ ) {
3839 return LDAP_INVALID_SYNTAX;
3842 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3846 return LDAP_INVALID_SYNTAX;
3849 } else if ( !AD_CHAR( *p ) ) {
3850 return LDAP_INVALID_SYNTAX;
3854 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3855 return LDAP_INVALID_SYNTAX;
3861 return LDAP_INVALID_SYNTAX;
3864 return LDAP_SUCCESS;
3868 bootParameterValidate(
3870 struct berval *val )
3874 if ( BER_BVISEMPTY( val ) ) {
3875 return LDAP_INVALID_SYNTAX;
3878 p = (char *)val->bv_val;
3879 e = p + val->bv_len;
3882 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3883 if ( !AD_CHAR( *p ) ) {
3884 return LDAP_INVALID_SYNTAX;
3889 return LDAP_INVALID_SYNTAX;
3893 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3894 if ( !AD_CHAR( *p ) ) {
3895 return LDAP_INVALID_SYNTAX;
3900 return LDAP_INVALID_SYNTAX;
3904 for ( p++; p < e; p++ ) {
3905 if ( !SLAP_PRINTABLE( *p ) ) {
3906 return LDAP_INVALID_SYNTAX;
3910 return LDAP_SUCCESS;
3914 firstComponentNormalize(
3919 struct berval *normalized,
3926 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3927 ber_dupbv_x( normalized, val, ctx );
3928 return LDAP_SUCCESS;
3931 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3933 if( val->bv_val[0] != '(' /*')'*/ &&
3934 val->bv_val[0] != '{' /*'}'*/ )
3936 return LDAP_INVALID_SYNTAX;
3939 /* trim leading white space */
3941 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3947 /* grab next word */
3948 comp.bv_val = &val->bv_val[len];
3949 len = val->bv_len - len;
3950 for( comp.bv_len = 0;
3951 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3957 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3958 rc = numericoidValidate( NULL, &comp );
3959 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3960 rc = integerValidate( NULL, &comp );
3962 rc = LDAP_INVALID_SYNTAX;
3966 if( rc == LDAP_SUCCESS ) {
3967 ber_dupbv_x( normalized, &comp, ctx );
3974 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3975 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3977 static slap_syntax_defs_rec syntax_defs[] = {
3978 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3979 X_BINARY X_NOT_H_R ")",
3980 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3981 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3983 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3985 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3987 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3988 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3990 SLAP_SYNTAX_BER, berValidate, NULL},
3991 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3992 0, bitStringValidate, NULL },
3993 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3994 0, booleanValidate, NULL},
3995 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3996 X_BINARY X_NOT_H_R ")",
3997 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3998 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3999 X_BINARY X_NOT_H_R ")",
4000 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4001 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4002 X_BINARY X_NOT_H_R ")",
4003 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
4004 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4005 0, countryStringValidate, NULL},
4006 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4007 0, dnValidate, dnPretty},
4008 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4009 0, rdnValidate, rdnPretty},
4010 #ifdef LDAP_COMP_MATCH
4011 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4012 0, allComponentsValidate, NULL},
4013 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4014 0, componentFilterValidate, NULL},
4016 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4018 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4019 0, deliveryMethodValidate, NULL},
4020 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4021 0, UTF8StringValidate, NULL},
4022 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4024 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4026 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4028 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4030 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4032 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4033 0, printablesStringValidate, NULL},
4034 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4035 SLAP_SYNTAX_BLOB, NULL, NULL},
4036 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4037 0, generalizedTimeValidate, NULL},
4038 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4040 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4041 0, IA5StringValidate, NULL},
4042 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4043 0, integerValidate, NULL},
4044 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4045 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4046 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4048 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4050 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4052 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4054 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4056 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4057 0, nameUIDValidate, nameUIDPretty },
4058 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4060 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4061 0, numericStringValidate, NULL},
4062 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4064 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4065 0, numericoidValidate, NULL},
4066 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4067 0, IA5StringValidate, NULL},
4068 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4069 0, blobValidate, NULL},
4070 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4071 0, UTF8StringValidate, NULL},
4072 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4074 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4076 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4077 0, printableStringValidate, NULL},
4078 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4079 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4080 0, subtreeSpecificationValidate, NULL},
4081 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4082 X_BINARY X_NOT_H_R ")",
4083 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
4084 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4085 0, printableStringValidate, NULL},
4086 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4088 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4089 0, printablesStringValidate, NULL},
4090 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4091 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4092 0, utcTimeValidate, NULL},
4094 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4096 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4098 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4100 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4102 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4105 /* RFC 2307 NIS Syntaxes */
4106 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4107 0, nisNetgroupTripleValidate, NULL},
4108 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4109 0, bootParameterValidate, NULL},
4111 /* draft-zeilenga-ldap-x509 */
4112 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4114 serialNumberAndIssuerValidate,
4115 serialNumberAndIssuerPretty},
4116 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4117 SLAP_SYNTAX_HIDE, NULL, NULL},
4118 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4119 SLAP_SYNTAX_HIDE, NULL, NULL},
4120 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4121 SLAP_SYNTAX_HIDE, NULL, NULL},
4122 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4123 SLAP_SYNTAX_HIDE, NULL, NULL},
4124 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4125 SLAP_SYNTAX_HIDE, NULL, NULL},
4126 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4127 SLAP_SYNTAX_HIDE, NULL, NULL},
4129 #ifdef SLAPD_AUTHPASSWD
4130 /* needs updating */
4131 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4132 SLAP_SYNTAX_HIDE, NULL, NULL},
4135 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4136 0, UUIDValidate, UUIDPretty},
4138 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4139 SLAP_SYNTAX_HIDE, csnValidate, NULL},
4141 /* OpenLDAP Void Syntax */
4142 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4143 SLAP_SYNTAX_HIDE, inValidate, NULL},
4145 /* FIXME: OID is unused, but not registered yet */
4146 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4147 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
4149 {NULL, 0, NULL, NULL}
4152 char *certificateExactMatchSyntaxes[] = {
4153 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4156 #ifdef LDAP_COMP_MATCH
4157 char *componentFilterMatchSyntaxes[] = {
4158 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4162 char *directoryStringSyntaxes[] = {
4163 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4166 char *integerFirstComponentMatchSyntaxes[] = {
4167 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4168 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4171 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4172 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4173 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4174 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4175 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4176 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4177 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4178 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4179 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4184 * Other matching rules in X.520 that we do not use (yet):
4186 * 2.5.13.25 uTCTimeMatch
4187 * 2.5.13.26 uTCTimeOrderingMatch
4188 * 2.5.13.31* directoryStringFirstComponentMatch
4189 * 2.5.13.32* wordMatch
4190 * 2.5.13.33* keywordMatch
4191 * 2.5.13.36+ certificatePairExactMatch
4192 * 2.5.13.37+ certificatePairMatch
4193 * 2.5.13.38+ certificateListExactMatch
4194 * 2.5.13.39+ certificateListMatch
4195 * 2.5.13.40+ algorithmIdentifierMatch
4196 * 2.5.13.41* storedPrefixMatch
4197 * 2.5.13.42 attributeCertificateMatch
4198 * 2.5.13.43 readerAndKeyIDMatch
4199 * 2.5.13.44 attributeIntegrityMatch
4201 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4202 * (+) described in draft-zeilenga-ldap-x509
4204 static slap_mrule_defs_rec mrule_defs[] = {
4206 * EQUALITY matching rules must be listed after associated APPROX
4207 * matching rules. So, we list all APPROX matching rules first.
4209 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4210 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4211 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4212 NULL, NULL, directoryStringApproxMatch,
4213 directoryStringApproxIndexer, directoryStringApproxFilter,
4216 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4217 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4218 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4219 NULL, NULL, IA5StringApproxMatch,
4220 IA5StringApproxIndexer, IA5StringApproxFilter,
4224 * Other matching rules
4227 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4228 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4229 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4230 NULL, NULL, octetStringMatch,
4231 octetStringIndexer, octetStringFilter,
4234 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4235 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4236 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4237 NULL, dnNormalize, dnMatch,
4238 octetStringIndexer, octetStringFilter,
4241 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4242 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4243 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4244 NULL, dnNormalize, dnRelativeMatch,
4248 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4249 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4250 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4251 NULL, dnNormalize, dnRelativeMatch,
4255 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4256 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4257 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4258 NULL, dnNormalize, dnRelativeMatch,
4262 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4263 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4264 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4265 NULL, dnNormalize, dnRelativeMatch,
4269 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4270 "SYNTAX 1.2.36.79672281.1.5.0 )",
4271 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4272 NULL, rdnNormalize, rdnMatch,
4273 octetStringIndexer, octetStringFilter,
4276 #ifdef LDAP_COMP_MATCH
4277 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4278 "SYNTAX 1.2.36.79672281.1.5.2 )",
4279 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4280 NULL, NULL , componentFilterMatch,
4281 octetStringIndexer, octetStringFilter,
4284 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4285 "SYNTAX 1.2.36.79672281.1.5.3 )",
4286 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4287 NULL, NULL , allComponentsMatch,
4288 octetStringIndexer, octetStringFilter,
4291 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4292 "SYNTAX 1.2.36.79672281.1.5.3 )",
4293 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4294 NULL, NULL , directoryComponentsMatch,
4295 octetStringIndexer, octetStringFilter,
4299 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4300 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4301 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4302 NULL, UTF8StringNormalize, octetStringMatch,
4303 octetStringIndexer, octetStringFilter,
4304 directoryStringApproxMatchOID },
4306 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4307 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4308 SLAP_MR_ORDERING, directoryStringSyntaxes,
4309 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4311 "caseIgnoreMatch" },
4313 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4314 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4315 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4316 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4317 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4318 "caseIgnoreMatch" },
4320 {"( 2.5.13.5 NAME 'caseExactMatch' "
4321 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4322 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4323 NULL, UTF8StringNormalize, octetStringMatch,
4324 octetStringIndexer, octetStringFilter,
4325 directoryStringApproxMatchOID },
4327 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4328 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4329 SLAP_MR_ORDERING, directoryStringSyntaxes,
4330 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4334 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4335 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4336 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4337 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4338 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4341 {"( 2.5.13.8 NAME 'numericStringMatch' "
4342 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4343 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4344 NULL, numericStringNormalize, octetStringMatch,
4345 octetStringIndexer, octetStringFilter,
4348 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4349 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4350 SLAP_MR_ORDERING, NULL,
4351 NULL, numericStringNormalize, octetStringOrderingMatch,
4353 "numericStringMatch" },
4355 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4356 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4357 SLAP_MR_SUBSTR, NULL,
4358 NULL, numericStringNormalize, octetStringSubstringsMatch,
4359 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4360 "numericStringMatch" },
4362 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4363 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4364 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4365 NULL, NULL, NULL, NULL, NULL, NULL },
4367 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4368 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4369 SLAP_MR_SUBSTR, NULL,
4370 NULL, NULL, NULL, NULL, NULL,
4371 "caseIgnoreListMatch" },
4373 {"( 2.5.13.13 NAME 'booleanMatch' "
4374 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4375 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4376 NULL, NULL, booleanMatch,
4377 octetStringIndexer, octetStringFilter,
4380 {"( 2.5.13.14 NAME 'integerMatch' "
4381 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4382 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4383 NULL, NULL, integerMatch,
4384 octetStringIndexer, octetStringFilter,
4387 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4388 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4389 SLAP_MR_ORDERING, NULL,
4390 NULL, NULL, integerMatch,
4394 {"( 2.5.13.16 NAME 'bitStringMatch' "
4395 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4396 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4397 NULL, NULL, octetStringMatch,
4398 octetStringIndexer, octetStringFilter,
4401 {"( 2.5.13.17 NAME 'octetStringMatch' "
4402 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4403 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4404 NULL, NULL, octetStringMatch,
4405 octetStringIndexer, octetStringFilter,
4408 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4409 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4410 SLAP_MR_ORDERING, NULL,
4411 NULL, NULL, octetStringOrderingMatch,
4413 "octetStringMatch" },
4415 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4416 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4417 SLAP_MR_SUBSTR, NULL,
4418 NULL, NULL, octetStringSubstringsMatch,
4419 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4420 "octetStringMatch" },
4422 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4423 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4424 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4426 telephoneNumberNormalize, octetStringMatch,
4427 octetStringIndexer, octetStringFilter,
4430 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4432 SLAP_MR_SUBSTR, NULL,
4433 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4434 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4435 "telephoneNumberMatch" },
4437 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4438 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4439 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4440 NULL, NULL, NULL, NULL, NULL, NULL },
4442 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4443 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4444 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4445 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4446 uniqueMemberIndexer, uniqueMemberFilter,
4449 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4450 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4451 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4452 NULL, NULL, NULL, NULL, NULL, NULL },
4454 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4455 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4456 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4457 NULL, generalizedTimeNormalize, octetStringMatch,
4458 generalizedTimeIndexer, generalizedTimeFilter,
4461 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4462 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4463 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4464 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4466 "generalizedTimeMatch" },
4468 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4470 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4471 integerFirstComponentMatchSyntaxes,
4472 NULL, firstComponentNormalize, integerMatch,
4473 octetStringIndexer, octetStringFilter,
4476 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4477 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4478 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4479 objectIdentifierFirstComponentMatchSyntaxes,
4480 NULL, firstComponentNormalize, octetStringMatch,
4481 octetStringIndexer, octetStringFilter,
4484 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4485 "SYNTAX 1.3.6.1.1.15.1 )",
4486 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4488 NULL, certificateExactNormalize, octetStringMatch,
4489 octetStringIndexer, octetStringFilter,
4491 NULL, NULL, NULL, NULL, NULL,
4495 {"( 2.5.13.35 NAME 'certificateMatch' "
4496 "SYNTAX 1.3.6.1.1.15.2 )",
4497 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4498 NULL, NULL, NULL, NULL, NULL,
4501 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4503 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4504 NULL, IA5StringNormalize, octetStringMatch,
4505 octetStringIndexer, octetStringFilter,
4506 IA5StringApproxMatchOID },
4508 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4510 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4511 NULL, IA5StringNormalize, octetStringMatch,
4512 octetStringIndexer, octetStringFilter,
4513 IA5StringApproxMatchOID },
4515 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4517 SLAP_MR_SUBSTR, NULL,
4518 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4519 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4520 "caseIgnoreIA5Match" },
4522 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4524 SLAP_MR_SUBSTR, NULL,
4525 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4526 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4527 "caseExactIA5Match" },
4529 #ifdef SLAPD_AUTHPASSWD
4530 /* needs updating */
4531 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4532 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4533 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4534 NULL, NULL, authPasswordMatch,
4539 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4540 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4542 NULL, NULL, integerBitAndMatch,
4546 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4547 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4549 NULL, NULL, integerBitOrMatch,
4553 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4554 "SYNTAX 1.3.6.1.1.16.1 )",
4555 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4556 NULL, UUIDNormalize, octetStringMatch,
4557 octetStringIndexer, octetStringFilter,
4560 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4561 "SYNTAX 1.3.6.1.1.16.1 )",
4562 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4563 NULL, UUIDNormalize, octetStringOrderingMatch,
4564 octetStringIndexer, octetStringFilter,
4567 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4568 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4569 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4570 NULL, NULL, csnMatch,
4571 csnIndexer, csnFilter,
4574 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4575 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4576 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4577 NULL, NULL, csnOrderingMatch,
4581 /* FIXME: OID is unused, but not registered yet */
4582 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4583 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4584 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4585 NULL, authzNormalize, authzMatch,
4589 {NULL, SLAP_MR_NONE, NULL,
4590 NULL, NULL, NULL, NULL, NULL,
4595 slap_schema_init( void )
4600 /* we should only be called once (from main) */
4601 assert( schema_init_done == 0 );
4603 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4604 res = register_syntax( &syntax_defs[i] );
4607 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4608 syntax_defs[i].sd_desc );
4613 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4614 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4615 mrule_defs[i].mrd_compat_syntaxes == NULL )
4618 "slap_schema_init: Ignoring unusable matching rule %s\n",
4619 mrule_defs[i].mrd_desc );
4623 res = register_matching_rule( &mrule_defs[i] );
4627 "slap_schema_init: Error registering matching rule %s\n",
4628 mrule_defs[i].mrd_desc );
4633 res = slap_schema_load();
4634 schema_init_done = 1;
4639 schema_destroy( void )
4648 if( schema_init_done ) {
4649 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4650 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );