1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 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 for(i=0; i < val->bv_len; i++) {
2053 if( !LDAP_ASCII(val->bv_val[i]) ) {
2054 return LDAP_INVALID_SYNTAX;
2058 return LDAP_SUCCESS;
2067 struct berval *normalized,
2071 int casefold = !SLAP_MR_ASSOCIATED( mr,
2072 slap_schema.si_mr_caseExactIA5Match );
2074 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2078 /* Ignore initial whitespace */
2079 while ( ASCII_SPACE( *p ) ) p++;
2081 normalized->bv_val = ber_strdup_x( p, ctx );
2082 p = q = normalized->bv_val;
2085 if ( ASCII_SPACE( *p ) ) {
2088 /* Ignore the extra whitespace */
2089 while ( ASCII_SPACE( *p ) ) {
2093 } else if ( casefold ) {
2094 /* Most IA5 rules require casefolding */
2095 *q++ = TOLOWER(*p); p++;
2102 assert( normalized->bv_val <= p );
2106 * If the string ended in space, backup the pointer one
2107 * position. One is enough because the above loop collapsed
2108 * all whitespace to a single space.
2110 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2112 /* null terminate */
2115 normalized->bv_len = q - normalized->bv_val;
2117 return LDAP_SUCCESS;
2126 if( in->bv_len != 36 ) {
2127 return LDAP_INVALID_SYNTAX;
2130 for( i=0; i<36; i++ ) {
2136 if( in->bv_val[i] != '-' ) {
2137 return LDAP_INVALID_SYNTAX;
2141 if( !ASCII_HEX( in->bv_val[i]) ) {
2142 return LDAP_INVALID_SYNTAX;
2147 return LDAP_SUCCESS;
2158 int rc=LDAP_INVALID_SYNTAX;
2160 assert( in != NULL );
2161 assert( out != NULL );
2163 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2166 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2168 for( i=0; i<36; i++ ) {
2174 if( in->bv_val[i] != '-' ) {
2177 out->bv_val[i] = '-';
2181 if( !ASCII_HEX( in->bv_val[i]) ) {
2184 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2189 out->bv_val[ out->bv_len ] = '\0';
2193 slap_sl_free( out->bv_val, ctx );
2206 struct berval *normalized,
2209 unsigned char octet = '\0';
2212 normalized->bv_len = 16;
2213 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2215 for( i=0, j=0; i<36; i++ ) {
2216 unsigned char nibble;
2217 if( val->bv_val[i] == '-' ) {
2220 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2221 nibble = val->bv_val[i] - '0';
2223 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2224 nibble = val->bv_val[i] - ('a'-10);
2226 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2227 nibble = val->bv_val[i] - ('A'-10);
2230 slap_sl_free( normalized->bv_val, ctx );
2231 return LDAP_INVALID_SYNTAX;
2236 normalized->bv_val[j>>1] = octet;
2238 octet = nibble << 4;
2243 normalized->bv_val[normalized->bv_len] = 0;
2244 return LDAP_SUCCESS;
2250 numericStringValidate(
2256 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2258 for(i=0; i < in->bv_len; i++) {
2259 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2260 return LDAP_INVALID_SYNTAX;
2264 return LDAP_SUCCESS;
2268 numericStringNormalize(
2273 struct berval *normalized,
2276 /* removal all spaces */
2279 assert( !BER_BVISEMPTY( val ) );
2281 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2284 q = normalized->bv_val;
2287 if ( ASCII_SPACE( *p ) ) {
2288 /* Ignore whitespace */
2295 /* we should have copied no more then is in val */
2296 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2298 /* null terminate */
2301 normalized->bv_len = q - normalized->bv_val;
2303 if( BER_BVISEMPTY( normalized ) ) {
2304 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2305 normalized->bv_val[0] = ' ';
2306 normalized->bv_val[1] = '\0';
2307 normalized->bv_len = 1;
2310 return LDAP_SUCCESS;
2314 * Integer conversion macros that will use the largest available
2317 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2318 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2319 # define SLAP_LONG long long
2321 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2322 # define SLAP_LONG long
2323 #endif /* HAVE_STRTOLL ... */
2331 struct berval *value,
2332 void *assertedValue )
2334 SLAP_LONG lValue, lAssertedValue;
2337 /* safe to assume integers are NUL terminated? */
2338 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2339 if( errno == ERANGE )
2341 return LDAP_CONSTRAINT_VIOLATION;
2344 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2346 if( errno == ERANGE )
2348 return LDAP_CONSTRAINT_VIOLATION;
2351 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2352 return LDAP_SUCCESS;
2361 struct berval *value,
2362 void *assertedValue )
2364 SLAP_LONG lValue, lAssertedValue;
2367 /* safe to assume integers are NUL terminated? */
2368 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2369 if( errno == ERANGE )
2371 return LDAP_CONSTRAINT_VIOLATION;
2374 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2376 if( errno == ERANGE )
2378 return LDAP_CONSTRAINT_VIOLATION;
2381 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2382 return LDAP_SUCCESS;
2386 serialNumberAndIssuerValidate(
2392 struct berval sn, i;
2394 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2397 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2399 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2400 /* Parse old format */
2401 i.bv_val = ber_bvchr( in, '$' );
2402 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2404 sn.bv_val = in->bv_val;
2405 sn.bv_len = i.bv_val - in->bv_val;
2408 i.bv_len = in->bv_len - (sn.bv_len + 1);
2410 /* eat leading zeros */
2411 for( n=0; n < (sn.bv_len-1); n++ ) {
2412 if( sn.bv_val[n] != '0' ) break;
2417 for( n=0; n < sn.bv_len; n++ ) {
2418 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2422 /* Parse GSER format */
2423 int havesn=0,haveissuer=0;
2424 struct berval x = *in;
2428 /* eat leading spaces */
2429 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2433 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2434 return LDAP_INVALID_SYNTAX;
2437 /* should be at issuer or serialNumber NamedValue */
2438 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2440 x.bv_val += STRLENOF("issuer");
2441 x.bv_len -= STRLENOF("issuer");
2443 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2444 x.bv_val++; x.bv_len--;
2446 /* eat leading spaces */
2447 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2451 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2452 x.bv_val++; x.bv_len--;
2454 i.bv_val = x.bv_val;
2457 for( ; i.bv_len < x.bv_len; ) {
2458 if ( i.bv_val[i.bv_len] != '"' ) {
2462 if ( i.bv_val[i.bv_len+1] == '"' ) {
2469 x.bv_val += i.bv_len+1;
2470 x.bv_len -= i.bv_len+1;
2472 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2473 return LDAP_INVALID_SYNTAX;
2478 } else if( strncasecmp( x.bv_val, "serialNumber",
2479 STRLENOF("serialNumber")) == 0 )
2481 /* parse serialNumber */
2483 x.bv_val += STRLENOF("serialNumber");
2484 x.bv_len -= STRLENOF("serialNumber");
2486 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2487 x.bv_val++; x.bv_len--;
2489 /* eat leading spaces */
2490 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2494 sn.bv_val = x.bv_val;
2497 if( sn.bv_val[0] == '-' ) {
2502 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2503 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2506 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2507 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2508 return LDAP_INVALID_SYNTAX;
2511 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2513 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2514 return LDAP_INVALID_SYNTAX;
2519 } else return LDAP_INVALID_SYNTAX;
2521 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2522 x.bv_val++; x.bv_len--;
2525 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2529 /* should be at remaining NamedValue */
2530 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2531 STRLENOF("issuer" )) == 0 ))
2534 x.bv_val += STRLENOF("issuer");
2535 x.bv_len -= STRLENOF("issuer");
2537 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2538 x.bv_val++; x.bv_len--;
2540 /* eat leading spaces */
2541 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2545 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2546 x.bv_val++; x.bv_len--;
2548 i.bv_val = x.bv_val;
2551 for( ; i.bv_len < x.bv_len; ) {
2552 if ( i.bv_val[i.bv_len] != '"' ) {
2556 if ( i.bv_val[i.bv_len+1] == '"' ) {
2563 x.bv_val += i.bv_len+1;
2564 x.bv_len -= i.bv_len+1;
2566 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2567 STRLENOF("serialNumber")) == 0 ))
2569 /* parse serialNumber */
2571 x.bv_val += STRLENOF("serialNumber");
2572 x.bv_len -= STRLENOF("serialNumber");
2574 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2575 x.bv_val++; x.bv_len--;
2577 /* eat leading spaces */
2578 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2582 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2583 x.bv_val++; x.bv_len--;
2585 sn.bv_val = x.bv_val;
2588 if( sn.bv_val[0] == '-' ) {
2593 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2594 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2597 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2598 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2599 return LDAP_INVALID_SYNTAX;
2602 x.bv_val += sn.bv_len;
2603 x.bv_len -= sn.bv_len;
2605 } else return LDAP_INVALID_SYNTAX;
2607 /* eat trailing spaces */
2608 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2612 /* should have no characters left... */
2613 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2616 /* validate DN -- doesn't handle double dquote */
2617 rc = dnValidate( NULL, &i );
2618 if( rc ) return LDAP_INVALID_SYNTAX;
2620 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2622 return LDAP_SUCCESS;
2626 serialNumberAndIssuerPretty(
2634 struct berval sn, i, ni;
2636 assert( in != NULL );
2637 assert( out != NULL );
2639 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2642 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2644 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2645 /* Parse old format */
2646 i.bv_val = ber_bvchr( in, '$' );
2647 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2649 sn.bv_val = in->bv_val;
2650 sn.bv_len = i.bv_val - in->bv_val;
2653 i.bv_len = in->bv_len - (sn.bv_len + 1);
2655 /* eat leading zeros */
2656 for( n=0; n < (sn.bv_len-1); n++ ) {
2657 if( sn.bv_val[n] != '0' ) break;
2662 for( n=0; n < sn.bv_len; n++ ) {
2663 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2667 /* Parse GSER format */
2668 int havesn=0,haveissuer=0;
2669 struct berval x = *in;
2673 /* eat leading spaces */
2674 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2678 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2679 return LDAP_INVALID_SYNTAX;
2682 /* should be at issuer or serialNumber NamedValue */
2683 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2685 x.bv_val += STRLENOF("issuer");
2686 x.bv_len -= STRLENOF("issuer");
2688 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2689 x.bv_val++; x.bv_len--;
2691 /* eat leading spaces */
2692 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2696 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2697 x.bv_val++; x.bv_len--;
2699 i.bv_val = x.bv_val;
2702 for( ; i.bv_len < x.bv_len; ) {
2703 if ( i.bv_val[i.bv_len] != '"' ) {
2707 if ( i.bv_val[i.bv_len+1] == '"' ) {
2714 x.bv_val += i.bv_len+1;
2715 x.bv_len -= i.bv_len+1;
2717 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2718 return LDAP_INVALID_SYNTAX;
2723 } else if( strncasecmp( x.bv_val, "serialNumber",
2724 STRLENOF("serialNumber")) == 0 )
2726 /* parse serialNumber */
2728 x.bv_val += STRLENOF("serialNumber");
2729 x.bv_len -= STRLENOF("serialNumber");
2731 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2732 x.bv_val++; x.bv_len--;
2734 /* eat leading spaces */
2735 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2739 sn.bv_val = x.bv_val;
2742 if( sn.bv_val[0] == '-' ) {
2747 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2748 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2751 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2752 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2753 return LDAP_INVALID_SYNTAX;
2756 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2758 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2759 return LDAP_INVALID_SYNTAX;
2764 } else return LDAP_INVALID_SYNTAX;
2766 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2767 x.bv_val++; x.bv_len--;
2770 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2774 /* should be at remaining NamedValue */
2775 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2776 STRLENOF("issuer" )) == 0 ))
2779 x.bv_val += STRLENOF("issuer");
2780 x.bv_len -= STRLENOF("issuer");
2782 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2783 x.bv_val++; x.bv_len--;
2785 /* eat leading spaces */
2786 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2790 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2791 x.bv_val++; x.bv_len--;
2793 i.bv_val = x.bv_val;
2796 for( ; i.bv_len < x.bv_len; ) {
2797 if ( i.bv_val[i.bv_len] != '"' ) {
2801 if ( i.bv_val[i.bv_len+1] == '"' ) {
2808 x.bv_val += i.bv_len+1;
2809 x.bv_len -= i.bv_len+1;
2811 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2812 STRLENOF("serialNumber")) == 0 ))
2814 /* parse serialNumber */
2816 x.bv_val += STRLENOF("serialNumber");
2817 x.bv_len -= STRLENOF("serialNumber");
2819 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2820 x.bv_val++; x.bv_len--;
2822 /* eat leading spaces */
2823 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2827 sn.bv_val = x.bv_val;
2830 if( sn.bv_val[0] == '-' ) {
2835 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2836 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2839 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2840 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2841 return LDAP_INVALID_SYNTAX;
2844 x.bv_val += sn.bv_len;
2845 x.bv_len -= sn.bv_len;
2847 } else return LDAP_INVALID_SYNTAX;
2849 /* eat trailing spaces */
2850 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2854 /* should have no characters left... */
2855 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2857 ber_dupbv_x( &ni, &i, ctx );
2860 /* need to handle double dquotes here */
2863 rc = dnPretty( syntax, &i, &ni, ctx );
2865 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2866 slap_sl_free( i.bv_val, ctx );
2869 if( rc ) return LDAP_INVALID_SYNTAX;
2871 /* make room from sn + "$" */
2872 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2873 + sn.bv_len + ni.bv_len;
2874 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2876 if( out->bv_val == NULL ) {
2878 slap_sl_free( ni.bv_val, ctx );
2883 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2884 STRLENOF("{ serialNumber "));
2885 n = STRLENOF("{ serialNumber ");
2887 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2890 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2891 n += STRLENOF(", issuer \"");
2893 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2896 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2897 n += STRLENOF("\" }");
2899 out->bv_val[n] = '\0';
2901 assert( n == out->bv_len );
2903 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2904 out->bv_val, 0, 0 );
2906 slap_sl_free( ni.bv_val, ctx );
2908 return LDAP_SUCCESS;
2912 * This routine is called by certificateExactNormalize when
2913 * certificateExactNormalize receives a search string instead of
2914 * a certificate. This routine checks if the search value is valid
2915 * and then returns the normalized value
2918 serialNumberAndIssuerNormalize(
2928 struct berval sn, i, ni;
2930 assert( in != NULL );
2931 assert( out != NULL );
2933 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2936 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2938 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2939 /* Parse old format */
2940 i.bv_val = ber_bvchr( in, '$' );
2941 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2943 sn.bv_val = in->bv_val;
2944 sn.bv_len = i.bv_val - in->bv_val;
2947 i.bv_len = in->bv_len - (sn.bv_len + 1);
2949 /* eat leading zeros */
2950 for( n=0; n < (sn.bv_len-1); n++ ) {
2951 if( sn.bv_val[n] != '0' ) break;
2956 for( n=0; n < sn.bv_len; n++ ) {
2957 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2961 /* Parse GSER format */
2962 int havesn=0,haveissuer=0;
2963 struct berval x = *in;
2967 /* eat leading spaces */
2968 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2972 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2973 return LDAP_INVALID_SYNTAX;
2976 /* should be at issuer or serialNumber NamedValue */
2977 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2979 x.bv_val += STRLENOF("issuer");
2980 x.bv_len -= STRLENOF("issuer");
2982 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2983 x.bv_val++; x.bv_len--;
2985 /* eat leading spaces */
2986 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2990 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2991 x.bv_val++; x.bv_len--;
2993 i.bv_val = x.bv_val;
2996 for( ; i.bv_len < x.bv_len; ) {
2997 if ( i.bv_val[i.bv_len] != '"' ) {
3001 if ( i.bv_val[i.bv_len+1] == '"' ) {
3008 x.bv_val += i.bv_len+1;
3009 x.bv_len -= i.bv_len+1;
3011 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3012 return LDAP_INVALID_SYNTAX;
3017 } else if( strncasecmp( x.bv_val, "serialNumber",
3018 STRLENOF("serialNumber")) == 0 )
3020 /* parse serialNumber */
3022 x.bv_val += STRLENOF("serialNumber");
3023 x.bv_len -= STRLENOF("serialNumber");
3025 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3026 x.bv_val++; x.bv_len--;
3028 /* eat leading spaces */
3029 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3033 sn.bv_val = x.bv_val;
3036 if( sn.bv_val[0] == '-' ) {
3041 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3042 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3045 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3046 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3047 return LDAP_INVALID_SYNTAX;
3050 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3052 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3053 return LDAP_INVALID_SYNTAX;
3058 } else return LDAP_INVALID_SYNTAX;
3060 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3061 x.bv_val++; x.bv_len--;
3064 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3068 /* should be at remaining NamedValue */
3069 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3070 STRLENOF("issuer" )) == 0 ))
3073 x.bv_val += STRLENOF("issuer");
3074 x.bv_len -= STRLENOF("issuer");
3076 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3077 x.bv_val++; x.bv_len--;
3079 /* eat leading spaces */
3080 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3084 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3085 x.bv_val++; x.bv_len--;
3087 i.bv_val = x.bv_val;
3090 for( ; i.bv_len < x.bv_len; ) {
3091 if ( i.bv_val[i.bv_len] != '"' ) {
3095 if ( i.bv_val[i.bv_len+1] == '"' ) {
3102 x.bv_val += i.bv_len+1;
3103 x.bv_len -= i.bv_len+1;
3105 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3106 STRLENOF("serialNumber")) == 0 ))
3108 /* parse serialNumber */
3110 x.bv_val += STRLENOF("serialNumber");
3111 x.bv_len -= STRLENOF("serialNumber");
3113 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3114 x.bv_val++; x.bv_len--;
3116 /* eat leading spaces */
3117 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3121 sn.bv_val = x.bv_val;
3124 if( sn.bv_val[0] == '-' ) {
3129 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3130 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3133 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3134 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3135 return LDAP_INVALID_SYNTAX;
3138 x.bv_val += sn.bv_len;
3139 x.bv_len -= sn.bv_len;
3141 } else return LDAP_INVALID_SYNTAX;
3143 /* eat trailing spaces */
3144 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3148 /* should have no characters left... */
3149 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3151 ber_dupbv_x( &ni, &i, ctx );
3154 /* need to handle double dquotes here */
3157 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3159 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3160 slap_sl_free( i.bv_val, ctx );
3163 if( rc ) return LDAP_INVALID_SYNTAX;
3165 /* make room from sn + "$" */
3166 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3167 + sn.bv_len + ni.bv_len;
3168 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3170 if( out->bv_val == NULL ) {
3172 slap_sl_free( ni.bv_val, ctx );
3177 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3178 STRLENOF( "{ serialNumber " ));
3179 n = STRLENOF( "{ serialNumber " );
3181 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3184 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3185 n += STRLENOF( ", issuer \"" );
3187 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3190 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3191 n += STRLENOF( "\" }" );
3193 out->bv_val[n] = '\0';
3195 assert( n == out->bv_len );
3197 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3198 out->bv_val, 0, 0 );
3200 slap_sl_free( ni.bv_val, ctx );
3202 return LDAP_SUCCESS;
3207 certificateExactNormalize(
3212 struct berval *normalized,
3215 int rc = LDAP_INVALID_SYNTAX;
3217 char *serial = NULL;
3218 ber_len_t seriallen;
3219 struct berval issuer_dn = BER_BVNULL;
3220 X509_NAME *name = NULL;
3221 ASN1_INTEGER *sn = NULL;
3224 if( BER_BVISEMPTY( val ) ) goto done;
3226 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3227 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3230 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3232 p = (unsigned char *)val->bv_val;
3233 xcert = d2i_X509( NULL, &p, val->bv_len);
3234 if( xcert == NULL ) goto done;
3236 sn=X509_get_serialNumber(xcert);
3237 if ( sn == NULL ) goto done;
3238 serial=i2s_ASN1_INTEGER(0, sn );
3239 if( serial == NULL ) goto done;
3240 seriallen=strlen(serial);
3242 name=X509_get_issuer_name(xcert);
3243 if( name == NULL ) goto done;
3244 rc = dnX509normalize( name, &issuer_dn );
3245 if( rc != LDAP_SUCCESS ) goto done;
3247 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3248 + seriallen + issuer_dn.bv_len;
3249 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3251 p = (unsigned char *)normalized->bv_val;
3253 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3254 p += STRLENOF( "{ serialNumber " );
3256 AC_MEMCPY(p, serial, seriallen);
3259 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3260 p += STRLENOF( ", issuer \"" );
3262 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3263 p += issuer_dn.bv_len;
3265 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3266 p += STRLENOF( "\" }" );
3270 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3271 normalized->bv_val, NULL, NULL );
3276 if (xcert) X509_free(xcert);
3277 if (serial) ch_free(serial);
3278 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3282 #endif /* HAVE_TLS */
3285 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3286 /* slight optimization - does not need the start parameter */
3287 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3292 check_time_syntax (struct berval *val,
3295 struct berval *fraction)
3298 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3299 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3300 * GeneralizedTime supports leap seconds, UTCTime does not.
3302 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3303 static const int mdays[2][12] = {
3304 /* non-leap years */
3305 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3307 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3310 int part, c, c1, c2, tzoffset, leapyear = 0;
3313 e = p + val->bv_len;
3315 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3316 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3318 for (part = start; part < 7 && p < e; part++) {
3320 if (!ASCII_DIGIT(c1)) {
3325 return LDAP_INVALID_SYNTAX;
3328 if (!ASCII_DIGIT(c)) {
3329 return LDAP_INVALID_SYNTAX;
3331 c += c1 * 10 - '0' * 11;
3332 if ((part | 1) == 3) {
3335 return LDAP_INVALID_SYNTAX;
3338 if (c >= ceiling[part]) {
3339 if (! (c == 60 && part == 6 && start == 0))
3340 return LDAP_INVALID_SYNTAX;
3344 if (part < 5 + start) {
3345 return LDAP_INVALID_SYNTAX;
3347 for (; part < 9; part++) {
3351 /* leapyear check for the Gregorian calendar (year>1581) */
3352 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3356 if (parts[3] >= mdays[leapyear][parts[2]]) {
3357 return LDAP_INVALID_SYNTAX;
3361 fraction->bv_val = p;
3362 fraction->bv_len = 0;
3363 if (p < e && (*p == '.' || *p == ',')) {
3365 while (++p < e && ASCII_DIGIT(*p)) {
3368 if (p - fraction->bv_val == 1) {
3369 return LDAP_INVALID_SYNTAX;
3371 for (end_num = p; end_num[-1] == '0'; --end_num) {
3374 c = end_num - fraction->bv_val;
3375 if (c != 1) fraction->bv_len = c;
3381 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3387 return LDAP_INVALID_SYNTAX;
3393 for (part = 7; part < 9 && p < e; part++) {
3395 if (!ASCII_DIGIT(c1)) {
3400 return LDAP_INVALID_SYNTAX;
3403 if (!ASCII_DIGIT(c2)) {
3404 return LDAP_INVALID_SYNTAX;
3406 parts[part] = c1 * 10 + c2 - '0' * 11;
3407 if (parts[part] >= ceiling[part]) {
3408 return LDAP_INVALID_SYNTAX;
3411 if (part < 8 + start) {
3412 return LDAP_INVALID_SYNTAX;
3415 if (tzoffset == '-') {
3416 /* negative offset to UTC, ie west of Greenwich */
3417 parts[4] += parts[7];
3418 parts[5] += parts[8];
3419 /* offset is just hhmm, no seconds */
3420 for (part = 6; --part >= 0; ) {
3424 c = mdays[leapyear][parts[2]];
3426 if (parts[part] >= c) {
3428 return LDAP_INVALID_SYNTAX;
3433 } else if (part != 5) {
3438 /* positive offset to UTC, ie east of Greenwich */
3439 parts[4] -= parts[7];
3440 parts[5] -= parts[8];
3441 for (part = 6; --part >= 0; ) {
3442 if (parts[part] < 0) {
3444 return LDAP_INVALID_SYNTAX;
3449 /* make first arg to % non-negative */
3450 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3455 } else if (part != 5) {
3462 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3465 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3472 struct berval *normalized )
3476 rc = check_time_syntax(val, 1, parts, NULL);
3477 if (rc != LDAP_SUCCESS) {
3481 normalized->bv_val = ch_malloc( 14 );
3482 if ( normalized->bv_val == NULL ) {
3483 return LBER_ERROR_MEMORY;
3486 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3487 parts[1], parts[2] + 1, parts[3] + 1,
3488 parts[4], parts[5], parts[6] );
3489 normalized->bv_len = 13;
3491 return LDAP_SUCCESS;
3501 return check_time_syntax(in, 1, parts, NULL);
3504 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3507 generalizedTimeValidate(
3512 struct berval fraction;
3513 return check_time_syntax(in, 0, parts, &fraction);
3517 generalizedTimeNormalize(
3522 struct berval *normalized,
3527 struct berval fraction;
3529 rc = check_time_syntax(val, 0, parts, &fraction);
3530 if (rc != LDAP_SUCCESS) {
3534 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3535 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3536 if ( BER_BVISNULL( normalized ) ) {
3537 return LBER_ERROR_MEMORY;
3540 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3541 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3542 parts[4], parts[5], parts[6] );
3543 if ( !BER_BVISEMPTY( &fraction ) ) {
3544 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3545 fraction.bv_val, fraction.bv_len );
3546 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3548 strcpy( normalized->bv_val + len-1, "Z" );
3549 normalized->bv_len = len;
3551 return LDAP_SUCCESS;
3555 generalizedTimeOrderingMatch(
3560 struct berval *value,
3561 void *assertedValue )
3563 struct berval *asserted = (struct berval *) assertedValue;
3564 ber_len_t v_len = value->bv_len;
3565 ber_len_t av_len = asserted->bv_len;
3567 /* ignore trailing 'Z' when comparing */
3568 int match = memcmp( value->bv_val, asserted->bv_val,
3569 (v_len < av_len ? v_len : av_len) - 1 );
3570 if ( match == 0 ) match = v_len - av_len;
3573 return LDAP_SUCCESS;
3576 /* Index generation function */
3577 int generalizedTimeIndexer(
3582 struct berval *prefix,
3590 BerValue bvtmp; /* 40 bit index */
3592 struct lutil_timet tt;
3594 bvtmp.bv_len = sizeof(tmp);
3596 for( i=0; values[i].bv_val != NULL; i++ ) {
3597 /* just count them */
3600 /* we should have at least one value at this point */
3603 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3605 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3606 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3607 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3608 /* Use 40 bits of time for key */
3609 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3610 lutil_tm2time( &tm, &tt );
3611 tmp[0] = tt.tt_gsec & 0xff;
3612 tmp[4] = tt.tt_sec & 0xff;
3614 tmp[3] = tt.tt_sec & 0xff;
3616 tmp[2] = tt.tt_sec & 0xff;
3618 tmp[1] = tt.tt_sec & 0xff;
3620 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3624 keys[j].bv_val = NULL;
3629 return LDAP_SUCCESS;
3632 /* Index generation function */
3633 int generalizedTimeFilter(
3638 struct berval *prefix,
3639 void * assertedValue,
3645 BerValue bvtmp; /* 40 bit index */
3646 BerValue *value = (BerValue *) assertedValue;
3648 struct lutil_timet tt;
3650 bvtmp.bv_len = sizeof(tmp);
3652 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3653 /* Use 40 bits of time for key */
3654 if ( value->bv_val && value->bv_len >= 10 &&
3655 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3657 lutil_tm2time( &tm, &tt );
3658 tmp[0] = tt.tt_gsec & 0xff;
3659 tmp[4] = tt.tt_sec & 0xff;
3661 tmp[3] = tt.tt_sec & 0xff;
3663 tmp[2] = tt.tt_sec & 0xff;
3665 tmp[1] = tt.tt_sec & 0xff;
3667 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3668 ber_dupbv_x(keys, &bvtmp, ctx );
3669 keys[1].bv_val = NULL;
3677 return LDAP_SUCCESS;
3681 deliveryMethodValidate(
3683 struct berval *val )
3686 #define LENOF(s) (sizeof(s)-1)
3687 struct berval tmp = *val;
3689 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3690 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3691 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3694 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3696 switch( tmp.bv_val[0] ) {
3699 if(( tmp.bv_len >= LENOF("any") ) &&
3700 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3702 tmp.bv_len -= LENOF("any");
3703 tmp.bv_val += LENOF("any");
3706 return LDAP_INVALID_SYNTAX;
3710 if(( tmp.bv_len >= LENOF("mhs") ) &&
3711 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3713 tmp.bv_len -= LENOF("mhs");
3714 tmp.bv_val += LENOF("mhs");
3717 return LDAP_INVALID_SYNTAX;
3721 if(( tmp.bv_len >= LENOF("physical") ) &&
3722 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3724 tmp.bv_len -= LENOF("physical");
3725 tmp.bv_val += LENOF("physical");
3728 return LDAP_INVALID_SYNTAX;
3731 case 'T': /* telex or teletex or telephone */
3732 if(( tmp.bv_len >= LENOF("telex") ) &&
3733 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3735 tmp.bv_len -= LENOF("telex");
3736 tmp.bv_val += LENOF("telex");
3739 if(( tmp.bv_len >= LENOF("teletex") ) &&
3740 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3742 tmp.bv_len -= LENOF("teletex");
3743 tmp.bv_val += LENOF("teletex");
3746 if(( tmp.bv_len >= LENOF("telephone") ) &&
3747 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3749 tmp.bv_len -= LENOF("telephone");
3750 tmp.bv_val += LENOF("telephone");
3753 return LDAP_INVALID_SYNTAX;
3756 case 'G': /* g3fax or g4fax */
3757 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3758 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3759 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3761 tmp.bv_len -= LENOF("g3fax");
3762 tmp.bv_val += LENOF("g3fax");
3765 return LDAP_INVALID_SYNTAX;
3769 if(( tmp.bv_len >= LENOF("ia5") ) &&
3770 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3772 tmp.bv_len -= LENOF("ia5");
3773 tmp.bv_val += LENOF("ia5");
3776 return LDAP_INVALID_SYNTAX;
3780 if(( tmp.bv_len >= LENOF("videotex") ) &&
3781 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3783 tmp.bv_len -= LENOF("videotex");
3784 tmp.bv_val += LENOF("videotex");
3787 return LDAP_INVALID_SYNTAX;
3790 return LDAP_INVALID_SYNTAX;
3793 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3795 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3799 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3803 return LDAP_INVALID_SYNTAX;
3805 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3814 nisNetgroupTripleValidate(
3816 struct berval *val )
3821 if ( BER_BVISEMPTY( val ) ) {
3822 return LDAP_INVALID_SYNTAX;
3825 p = (char *)val->bv_val;
3826 e = p + val->bv_len;
3828 if ( *p != '(' /*')'*/ ) {
3829 return LDAP_INVALID_SYNTAX;
3832 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3836 return LDAP_INVALID_SYNTAX;
3839 } else if ( !AD_CHAR( *p ) ) {
3840 return LDAP_INVALID_SYNTAX;
3844 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3845 return LDAP_INVALID_SYNTAX;
3851 return LDAP_INVALID_SYNTAX;
3854 return LDAP_SUCCESS;
3858 bootParameterValidate(
3860 struct berval *val )
3864 if ( BER_BVISEMPTY( val ) ) {
3865 return LDAP_INVALID_SYNTAX;
3868 p = (char *)val->bv_val;
3869 e = p + val->bv_len;
3872 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3873 if ( !AD_CHAR( *p ) ) {
3874 return LDAP_INVALID_SYNTAX;
3879 return LDAP_INVALID_SYNTAX;
3883 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3884 if ( !AD_CHAR( *p ) ) {
3885 return LDAP_INVALID_SYNTAX;
3890 return LDAP_INVALID_SYNTAX;
3894 for ( p++; p < e; p++ ) {
3895 if ( !SLAP_PRINTABLE( *p ) ) {
3896 return LDAP_INVALID_SYNTAX;
3900 return LDAP_SUCCESS;
3904 firstComponentNormalize(
3909 struct berval *normalized,
3916 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3917 ber_dupbv_x( normalized, val, ctx );
3918 return LDAP_SUCCESS;
3921 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3923 if( val->bv_val[0] != '(' /*')'*/ &&
3924 val->bv_val[0] != '{' /*'}'*/ )
3926 return LDAP_INVALID_SYNTAX;
3929 /* trim leading white space */
3931 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3937 /* grab next word */
3938 comp.bv_val = &val->bv_val[len];
3939 len = val->bv_len - len;
3940 for( comp.bv_len = 0;
3941 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3947 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3948 rc = numericoidValidate( NULL, &comp );
3949 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3950 rc = integerValidate( NULL, &comp );
3952 rc = LDAP_INVALID_SYNTAX;
3956 if( rc == LDAP_SUCCESS ) {
3957 ber_dupbv_x( normalized, &comp, ctx );
3964 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3965 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3967 static slap_syntax_defs_rec syntax_defs[] = {
3968 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3969 X_BINARY X_NOT_H_R ")",
3970 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3971 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3973 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3975 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3977 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3978 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3980 SLAP_SYNTAX_BER, berValidate, NULL},
3981 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3982 0, bitStringValidate, NULL },
3983 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3984 0, booleanValidate, NULL},
3985 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3986 X_BINARY X_NOT_H_R ")",
3987 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3988 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3989 X_BINARY X_NOT_H_R ")",
3990 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3991 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3992 X_BINARY X_NOT_H_R ")",
3993 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3994 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3995 0, countryStringValidate, NULL},
3996 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3997 0, dnValidate, dnPretty},
3998 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3999 0, rdnValidate, rdnPretty},
4000 #ifdef LDAP_COMP_MATCH
4001 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4002 0, allComponentsValidate, NULL},
4003 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4004 0, componentFilterValidate, NULL},
4006 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4008 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4009 0, deliveryMethodValidate, NULL},
4010 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4011 0, UTF8StringValidate, NULL},
4012 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4014 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4016 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4018 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4020 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4022 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4023 0, printablesStringValidate, NULL},
4024 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4025 SLAP_SYNTAX_BLOB, NULL, NULL},
4026 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4027 0, generalizedTimeValidate, NULL},
4028 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4030 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4031 0, IA5StringValidate, NULL},
4032 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4033 0, integerValidate, NULL},
4034 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4035 SLAP_SYNTAX_BLOB, blobValidate, NULL},
4036 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4038 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4040 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4042 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4044 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4046 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4047 0, nameUIDValidate, nameUIDPretty },
4048 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4050 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4051 0, numericStringValidate, NULL},
4052 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4054 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4055 0, numericoidValidate, NULL},
4056 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4057 0, IA5StringValidate, NULL},
4058 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4059 0, blobValidate, NULL},
4060 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4061 0, UTF8StringValidate, NULL},
4062 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4064 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4066 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4067 0, printableStringValidate, NULL},
4068 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4069 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4070 0, subtreeSpecificationValidate, NULL},
4071 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4072 X_BINARY X_NOT_H_R ")",
4073 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
4074 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4075 0, printableStringValidate, NULL},
4076 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4078 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4079 0, printablesStringValidate, NULL},
4080 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4081 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4082 0, utcTimeValidate, NULL},
4084 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4086 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4088 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4090 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4092 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4095 /* RFC 2307 NIS Syntaxes */
4096 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4097 0, nisNetgroupTripleValidate, NULL},
4098 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4099 0, bootParameterValidate, NULL},
4101 /* draft-zeilenga-ldap-x509 */
4102 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4104 serialNumberAndIssuerValidate,
4105 serialNumberAndIssuerPretty},
4106 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4107 SLAP_SYNTAX_HIDE, NULL, NULL},
4108 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4109 SLAP_SYNTAX_HIDE, NULL, NULL},
4110 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4111 SLAP_SYNTAX_HIDE, NULL, NULL},
4112 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4113 SLAP_SYNTAX_HIDE, NULL, NULL},
4114 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4115 SLAP_SYNTAX_HIDE, NULL, NULL},
4116 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4117 SLAP_SYNTAX_HIDE, NULL, NULL},
4119 #ifdef SLAPD_AUTHPASSWD
4120 /* needs updating */
4121 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4122 SLAP_SYNTAX_HIDE, NULL, NULL},
4125 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4126 0, UUIDValidate, UUIDPretty},
4128 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4129 SLAP_SYNTAX_HIDE, csnValidate, NULL},
4131 /* OpenLDAP Void Syntax */
4132 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4133 SLAP_SYNTAX_HIDE, inValidate, NULL},
4135 /* FIXME: OID is unused, but not registered yet */
4136 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4137 SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
4139 {NULL, 0, NULL, NULL}
4142 char *certificateExactMatchSyntaxes[] = {
4143 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4146 #ifdef LDAP_COMP_MATCH
4147 char *componentFilterMatchSyntaxes[] = {
4148 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4152 char *directoryStringSyntaxes[] = {
4153 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4156 char *integerFirstComponentMatchSyntaxes[] = {
4157 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4158 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4161 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4162 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4163 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4164 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4165 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4166 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4167 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4168 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4169 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4174 * Other matching rules in X.520 that we do not use (yet):
4176 * 2.5.13.25 uTCTimeMatch
4177 * 2.5.13.26 uTCTimeOrderingMatch
4178 * 2.5.13.31* directoryStringFirstComponentMatch
4179 * 2.5.13.32* wordMatch
4180 * 2.5.13.33* keywordMatch
4181 * 2.5.13.36+ certificatePairExactMatch
4182 * 2.5.13.37+ certificatePairMatch
4183 * 2.5.13.38+ certificateListExactMatch
4184 * 2.5.13.39+ certificateListMatch
4185 * 2.5.13.40+ algorithmIdentifierMatch
4186 * 2.5.13.41* storedPrefixMatch
4187 * 2.5.13.42 attributeCertificateMatch
4188 * 2.5.13.43 readerAndKeyIDMatch
4189 * 2.5.13.44 attributeIntegrityMatch
4191 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4192 * (+) described in draft-zeilenga-ldap-x509
4194 static slap_mrule_defs_rec mrule_defs[] = {
4196 * EQUALITY matching rules must be listed after associated APPROX
4197 * matching rules. So, we list all APPROX matching rules first.
4199 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4200 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4201 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4202 NULL, NULL, directoryStringApproxMatch,
4203 directoryStringApproxIndexer, directoryStringApproxFilter,
4206 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4207 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4208 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4209 NULL, NULL, IA5StringApproxMatch,
4210 IA5StringApproxIndexer, IA5StringApproxFilter,
4214 * Other matching rules
4217 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4218 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4219 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4220 NULL, NULL, octetStringMatch,
4221 octetStringIndexer, octetStringFilter,
4224 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4225 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4226 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4227 NULL, dnNormalize, dnMatch,
4228 octetStringIndexer, octetStringFilter,
4231 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4232 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4233 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4234 NULL, dnNormalize, dnRelativeMatch,
4238 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4239 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4240 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4241 NULL, dnNormalize, dnRelativeMatch,
4245 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4246 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4247 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4248 NULL, dnNormalize, dnRelativeMatch,
4252 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4253 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4254 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4255 NULL, dnNormalize, dnRelativeMatch,
4259 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4260 "SYNTAX 1.2.36.79672281.1.5.0 )",
4261 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4262 NULL, rdnNormalize, rdnMatch,
4263 octetStringIndexer, octetStringFilter,
4266 #ifdef LDAP_COMP_MATCH
4267 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4268 "SYNTAX 1.2.36.79672281.1.5.2 )",
4269 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4270 NULL, NULL , componentFilterMatch,
4271 octetStringIndexer, octetStringFilter,
4274 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4275 "SYNTAX 1.2.36.79672281.1.5.3 )",
4276 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4277 NULL, NULL , allComponentsMatch,
4278 octetStringIndexer, octetStringFilter,
4281 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4282 "SYNTAX 1.2.36.79672281.1.5.3 )",
4283 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4284 NULL, NULL , directoryComponentsMatch,
4285 octetStringIndexer, octetStringFilter,
4289 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4290 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4291 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4292 NULL, UTF8StringNormalize, octetStringMatch,
4293 octetStringIndexer, octetStringFilter,
4294 directoryStringApproxMatchOID },
4296 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4297 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4298 SLAP_MR_ORDERING, directoryStringSyntaxes,
4299 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4301 "caseIgnoreMatch" },
4303 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4304 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4305 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4306 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4307 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4308 "caseIgnoreMatch" },
4310 {"( 2.5.13.5 NAME 'caseExactMatch' "
4311 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4312 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4313 NULL, UTF8StringNormalize, octetStringMatch,
4314 octetStringIndexer, octetStringFilter,
4315 directoryStringApproxMatchOID },
4317 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4318 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4319 SLAP_MR_ORDERING, directoryStringSyntaxes,
4320 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4324 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4325 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4326 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4327 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4328 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4331 {"( 2.5.13.8 NAME 'numericStringMatch' "
4332 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4333 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4334 NULL, numericStringNormalize, octetStringMatch,
4335 octetStringIndexer, octetStringFilter,
4338 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4339 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4340 SLAP_MR_ORDERING, NULL,
4341 NULL, numericStringNormalize, octetStringOrderingMatch,
4343 "numericStringMatch" },
4345 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4346 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4347 SLAP_MR_SUBSTR, NULL,
4348 NULL, numericStringNormalize, octetStringSubstringsMatch,
4349 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4350 "numericStringMatch" },
4352 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4353 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4354 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4355 NULL, NULL, NULL, NULL, NULL, NULL },
4357 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4358 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4359 SLAP_MR_SUBSTR, NULL,
4360 NULL, NULL, NULL, NULL, NULL,
4361 "caseIgnoreListMatch" },
4363 {"( 2.5.13.13 NAME 'booleanMatch' "
4364 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4365 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4366 NULL, NULL, booleanMatch,
4367 octetStringIndexer, octetStringFilter,
4370 {"( 2.5.13.14 NAME 'integerMatch' "
4371 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4372 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4373 NULL, NULL, integerMatch,
4374 octetStringIndexer, octetStringFilter,
4377 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4378 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4379 SLAP_MR_ORDERING, NULL,
4380 NULL, NULL, integerMatch,
4384 {"( 2.5.13.16 NAME 'bitStringMatch' "
4385 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4386 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4387 NULL, NULL, octetStringMatch,
4388 octetStringIndexer, octetStringFilter,
4391 {"( 2.5.13.17 NAME 'octetStringMatch' "
4392 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4393 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4394 NULL, NULL, octetStringMatch,
4395 octetStringIndexer, octetStringFilter,
4398 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4400 SLAP_MR_ORDERING, NULL,
4401 NULL, NULL, octetStringOrderingMatch,
4403 "octetStringMatch" },
4405 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4406 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4407 SLAP_MR_SUBSTR, NULL,
4408 NULL, NULL, octetStringSubstringsMatch,
4409 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4410 "octetStringMatch" },
4412 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4413 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4414 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4416 telephoneNumberNormalize, octetStringMatch,
4417 octetStringIndexer, octetStringFilter,
4420 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4421 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4422 SLAP_MR_SUBSTR, NULL,
4423 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4424 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4425 "telephoneNumberMatch" },
4427 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4428 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4429 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4430 NULL, NULL, NULL, NULL, NULL, NULL },
4432 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4433 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4434 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4435 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4436 uniqueMemberIndexer, uniqueMemberFilter,
4439 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4440 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4441 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4442 NULL, NULL, NULL, NULL, NULL, NULL },
4444 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4445 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4446 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4447 NULL, generalizedTimeNormalize, octetStringMatch,
4448 generalizedTimeIndexer, generalizedTimeFilter,
4451 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4453 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4454 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4456 "generalizedTimeMatch" },
4458 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4460 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4461 integerFirstComponentMatchSyntaxes,
4462 NULL, firstComponentNormalize, integerMatch,
4463 octetStringIndexer, octetStringFilter,
4466 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4468 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4469 objectIdentifierFirstComponentMatchSyntaxes,
4470 NULL, firstComponentNormalize, octetStringMatch,
4471 octetStringIndexer, octetStringFilter,
4474 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4475 "SYNTAX 1.3.6.1.1.15.1 )",
4476 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4478 NULL, certificateExactNormalize, octetStringMatch,
4479 octetStringIndexer, octetStringFilter,
4481 NULL, NULL, NULL, NULL, NULL,
4485 {"( 2.5.13.35 NAME 'certificateMatch' "
4486 "SYNTAX 1.3.6.1.1.15.2 )",
4487 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4488 NULL, NULL, NULL, NULL, NULL,
4491 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4492 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4493 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4494 NULL, IA5StringNormalize, octetStringMatch,
4495 octetStringIndexer, octetStringFilter,
4496 IA5StringApproxMatchOID },
4498 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4499 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4500 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4501 NULL, IA5StringNormalize, octetStringMatch,
4502 octetStringIndexer, octetStringFilter,
4503 IA5StringApproxMatchOID },
4505 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4507 SLAP_MR_SUBSTR, NULL,
4508 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4509 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4510 "caseIgnoreIA5Match" },
4512 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4514 SLAP_MR_SUBSTR, NULL,
4515 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4516 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4517 "caseExactIA5Match" },
4519 #ifdef SLAPD_AUTHPASSWD
4520 /* needs updating */
4521 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4522 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4523 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4524 NULL, NULL, authPasswordMatch,
4529 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4530 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4532 NULL, NULL, integerBitAndMatch,
4536 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4539 NULL, NULL, integerBitOrMatch,
4543 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4544 "SYNTAX 1.3.6.1.1.16.1 )",
4545 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4546 NULL, UUIDNormalize, octetStringMatch,
4547 octetStringIndexer, octetStringFilter,
4550 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4551 "SYNTAX 1.3.6.1.1.16.1 )",
4552 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4553 NULL, UUIDNormalize, octetStringOrderingMatch,
4554 octetStringIndexer, octetStringFilter,
4557 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4558 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4559 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4560 NULL, NULL, csnMatch,
4561 csnIndexer, csnFilter,
4564 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4565 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4566 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4567 NULL, NULL, csnOrderingMatch,
4571 /* FIXME: OID is unused, but not registered yet */
4572 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4573 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4574 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4575 NULL, authzNormalize, authzMatch,
4579 {NULL, SLAP_MR_NONE, NULL,
4580 NULL, NULL, NULL, NULL, NULL,
4585 slap_schema_init( void )
4590 /* we should only be called once (from main) */
4591 assert( schema_init_done == 0 );
4593 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4594 res = register_syntax( &syntax_defs[i] );
4597 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4598 syntax_defs[i].sd_desc );
4603 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4604 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4605 mrule_defs[i].mrd_compat_syntaxes == NULL )
4608 "slap_schema_init: Ignoring unusable matching rule %s\n",
4609 mrule_defs[i].mrd_desc );
4613 res = register_matching_rule( &mrule_defs[i] );
4617 "slap_schema_init: Error registering matching rule %s\n",
4618 mrule_defs[i].mrd_desc );
4623 res = slap_schema_load();
4624 schema_init_done = 1;
4629 schema_destroy( void )
4638 if( schema_init_done ) {
4639 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4640 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );