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>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnValidate blobValidate
54 #define csnMatch octetStringMatch
55 #define csnOrderingMatch octetStringOrderingMatch
56 #define csnIndexer generalizedTimeIndexer
57 #define csnFilter generalizedTimeFilter
59 /* FIXME: temporary */
60 #define authzMatch octetStringMatch
62 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
63 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
64 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
65 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
67 ldap_pvt_thread_mutex_t ad_undef_mutex;
68 ldap_pvt_thread_mutex_t oc_undef_mutex;
75 /* no value allowed */
76 return LDAP_INVALID_SYNTAX;
84 /* any value allowed */
88 #define berValidate blobValidate
95 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
96 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
101 /* X.509 certificate validation */
102 static int certificateValidate( Syntax *syntax, struct berval *in )
104 BerElementBuffer berbuf;
105 BerElement *ber = (BerElement *)&berbuf;
108 ber_int_t i, version = 0;
110 ber_init2( ber, in, LBER_USE_DER );
111 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
112 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
113 tag = ber_skip_tag( ber, &len ); /* Sequence */
114 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
115 tag = ber_skip_tag( ber, &len );
116 if ( tag == 0xa0 ) { /* Optional version */
117 tag = ber_get_int( ber, &version );
118 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
120 tag = ber_get_int( ber, &i ); /* Serial */
121 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
122 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
123 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
124 ber_skip_data( ber, len );
125 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
126 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
127 ber_skip_data( ber, len );
128 tag = ber_skip_tag( ber, &len ); /* Validity */
129 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
130 ber_skip_data( ber, len );
131 tag = ber_skip_tag( ber, &len ); /* Subject DN */
132 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
133 ber_skip_data( ber, len );
134 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
135 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
136 ber_skip_data( ber, len );
137 tag = ber_skip_tag( ber, &len );
138 if ( tag == 0xa1 ) { /* issuerUniqueID */
139 if ( version < 1 ) return LDAP_INVALID_SYNTAX;
140 ber_skip_data( ber, len );
141 tag = ber_skip_tag( ber, &len );
143 if ( tag == 0xa2 ) { /* subjectUniqueID */
144 if ( version < 1 ) return LDAP_INVALID_SYNTAX;
145 ber_skip_data( ber, len );
146 tag = ber_skip_tag( ber, &len );
148 if ( tag == 0xa3 ) { /* Extensions */
149 if ( version < 2 ) return LDAP_INVALID_SYNTAX;
150 tag = ber_skip_tag( ber, &len );
151 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
152 ber_skip_data( ber, len );
153 tag = ber_skip_tag( ber, &len );
155 /* signatureAlgorithm */
156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
157 ber_skip_data( ber, len );
158 tag = ber_skip_tag( ber, &len );
160 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
161 ber_skip_data( ber, len );
162 tag = ber_skip_tag( ber, &len );
163 /* Must be at end now */
164 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
174 struct berval *value,
175 void *assertedValue )
177 struct berval *asserted = (struct berval *) assertedValue;
178 int match = value->bv_len - asserted->bv_len;
181 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
189 octetStringOrderingMatch(
194 struct berval *value,
195 void *assertedValue )
197 struct berval *asserted = (struct berval *) assertedValue;
198 ber_len_t v_len = value->bv_len;
199 ber_len_t av_len = asserted->bv_len;
201 int match = memcmp( value->bv_val, asserted->bv_val,
202 (v_len < av_len ? v_len : av_len) );
204 if( match == 0 ) match = v_len - av_len;
212 HASH_CONTEXT *HASHcontext,
213 struct berval *prefix,
218 HASH_Init(HASHcontext);
219 if(prefix && prefix->bv_len > 0) {
220 HASH_Update(HASHcontext,
221 (unsigned char *)prefix->bv_val, prefix->bv_len);
223 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
224 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
225 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
231 HASH_CONTEXT *HASHcontext,
232 unsigned char *HASHdigest,
233 unsigned char *value,
236 HASH_CONTEXT ctx = *HASHcontext;
237 HASH_Update( &ctx, value, len );
238 HASH_Final( HASHdigest, &ctx );
241 /* Index generation function */
242 int octetStringIndexer(
247 struct berval *prefix,
255 HASH_CONTEXT HASHcontext;
256 unsigned char HASHdigest[HASH_BYTES];
257 struct berval digest;
258 digest.bv_val = (char *)HASHdigest;
259 digest.bv_len = sizeof(HASHdigest);
261 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
262 /* just count them */
265 /* we should have at least one value at this point */
268 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
270 slen = syntax->ssyn_oidlen;
271 mlen = mr->smr_oidlen;
273 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
274 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
275 hashIter( &HASHcontext, HASHdigest,
276 (unsigned char *)values[i].bv_val, values[i].bv_len );
277 ber_dupbv_x( &keys[i], &digest, ctx );
280 BER_BVZERO( &keys[i] );
287 /* Index generation function */
288 int octetStringFilter(
293 struct berval *prefix,
294 void * assertedValue,
300 HASH_CONTEXT HASHcontext;
301 unsigned char HASHdigest[HASH_BYTES];
302 struct berval *value = (struct berval *) assertedValue;
303 struct berval digest;
304 digest.bv_val = (char *)HASHdigest;
305 digest.bv_len = sizeof(HASHdigest);
307 slen = syntax->ssyn_oidlen;
308 mlen = mr->smr_oidlen;
310 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
312 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
313 hashIter( &HASHcontext, HASHdigest,
314 (unsigned char *)value->bv_val, value->bv_len );
316 ber_dupbv_x( keys, &digest, ctx );
317 BER_BVZERO( &keys[1] );
325 octetStringSubstringsMatch(
330 struct berval *value,
331 void *assertedValue )
334 SubstringsAssertion *sub = assertedValue;
335 struct berval left = *value;
339 /* Add up asserted input length */
340 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
341 inlen += sub->sa_initial.bv_len;
344 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
345 inlen += sub->sa_any[i].bv_len;
348 if ( !BER_BVISNULL( &sub->sa_final ) ) {
349 inlen += sub->sa_final.bv_len;
352 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
353 if ( inlen > left.bv_len ) {
358 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
359 sub->sa_initial.bv_len );
365 left.bv_val += sub->sa_initial.bv_len;
366 left.bv_len -= sub->sa_initial.bv_len;
367 inlen -= sub->sa_initial.bv_len;
370 if ( !BER_BVISNULL( &sub->sa_final ) ) {
371 if ( inlen > left.bv_len ) {
376 match = memcmp( sub->sa_final.bv_val,
377 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
378 sub->sa_final.bv_len );
384 left.bv_len -= sub->sa_final.bv_len;
385 inlen -= sub->sa_final.bv_len;
389 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
394 if ( inlen > left.bv_len ) {
395 /* not enough length */
400 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
404 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
411 idx = p - left.bv_val;
413 if ( idx >= left.bv_len ) {
414 /* this shouldn't happen */
421 if ( sub->sa_any[i].bv_len > left.bv_len ) {
422 /* not enough left */
427 match = memcmp( left.bv_val,
428 sub->sa_any[i].bv_val,
429 sub->sa_any[i].bv_len );
437 left.bv_val += sub->sa_any[i].bv_len;
438 left.bv_len -= sub->sa_any[i].bv_len;
439 inlen -= sub->sa_any[i].bv_len;
448 /* Substrings Index generation function */
450 octetStringSubstringsIndexer(
455 struct berval *prefix,
464 HASH_CONTEXT HCany, HCini, HCfin;
465 unsigned char HASHdigest[HASH_BYTES];
466 struct berval digest;
467 digest.bv_val = (char *)HASHdigest;
468 digest.bv_len = sizeof(HASHdigest);
472 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
473 /* count number of indices to generate */
474 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
475 if( values[i].bv_len >= index_substr_if_maxlen ) {
476 nkeys += index_substr_if_maxlen -
477 (index_substr_if_minlen - 1);
478 } else if( values[i].bv_len >= index_substr_if_minlen ) {
479 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
483 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
484 if( values[i].bv_len >= index_substr_any_len ) {
485 nkeys += values[i].bv_len - (index_substr_any_len - 1);
489 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
490 if( values[i].bv_len >= index_substr_if_maxlen ) {
491 nkeys += index_substr_if_maxlen -
492 (index_substr_if_minlen - 1);
493 } else if( values[i].bv_len >= index_substr_if_minlen ) {
494 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
500 /* no keys to generate */
505 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
507 slen = syntax->ssyn_oidlen;
508 mlen = mr->smr_oidlen;
510 if ( flags & SLAP_INDEX_SUBSTR_ANY )
511 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
512 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
513 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
514 if( flags & SLAP_INDEX_SUBSTR_FINAL )
515 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
518 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
521 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
522 ( values[i].bv_len >= index_substr_any_len ) )
524 max = values[i].bv_len - (index_substr_any_len - 1);
526 for( j=0; j<max; j++ ) {
527 hashIter( &HCany, HASHdigest,
528 (unsigned char *)&values[i].bv_val[j],
529 index_substr_any_len );
530 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
534 /* skip if too short */
535 if( values[i].bv_len < index_substr_if_minlen ) continue;
537 max = index_substr_if_maxlen < values[i].bv_len
538 ? index_substr_if_maxlen : values[i].bv_len;
540 for( j=index_substr_if_minlen; j<=max; j++ ) {
542 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
543 hashIter( &HCini, HASHdigest,
544 (unsigned char *)values[i].bv_val, j );
545 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
548 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
549 hashIter( &HCfin, HASHdigest,
550 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
551 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
558 BER_BVZERO( &keys[nkeys] );
569 octetStringSubstringsFilter (
574 struct berval *prefix,
575 void * assertedValue,
579 SubstringsAssertion *sa;
582 size_t slen, mlen, klen;
584 HASH_CONTEXT HASHcontext;
585 unsigned char HASHdigest[HASH_BYTES];
586 struct berval *value;
587 struct berval digest;
589 sa = (SubstringsAssertion *) assertedValue;
591 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
592 !BER_BVISNULL( &sa->sa_initial ) &&
593 sa->sa_initial.bv_len >= index_substr_if_minlen )
596 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
597 ( flags & SLAP_INDEX_SUBSTR_ANY ))
599 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
603 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
605 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
606 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
607 /* don't bother accounting with stepping */
608 nkeys += sa->sa_any[i].bv_len -
609 ( index_substr_any_len - 1 );
614 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
615 !BER_BVISNULL( &sa->sa_final ) &&
616 sa->sa_final.bv_len >= index_substr_if_minlen )
619 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
620 ( flags & SLAP_INDEX_SUBSTR_ANY ))
622 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
631 digest.bv_val = (char *)HASHdigest;
632 digest.bv_len = sizeof(HASHdigest);
634 slen = syntax->ssyn_oidlen;
635 mlen = mr->smr_oidlen;
637 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
640 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
641 !BER_BVISNULL( &sa->sa_initial ) &&
642 sa->sa_initial.bv_len >= index_substr_if_minlen )
644 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
645 value = &sa->sa_initial;
647 klen = index_substr_if_maxlen < value->bv_len
648 ? index_substr_if_maxlen : value->bv_len;
650 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
651 hashIter( &HASHcontext, HASHdigest,
652 (unsigned char *)value->bv_val, klen );
653 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
655 /* If initial is too long and we have subany indexed, use it
656 * to match the excess...
658 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
661 pre = SLAP_INDEX_SUBSTR_PREFIX;
662 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
663 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
665 hashIter( &HASHcontext, HASHdigest,
666 (unsigned char *)&value->bv_val[j], index_substr_any_len );
667 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
672 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
674 pre = SLAP_INDEX_SUBSTR_PREFIX;
675 klen = index_substr_any_len;
677 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
678 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
682 value = &sa->sa_any[i];
684 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
686 j <= value->bv_len - index_substr_any_len;
687 j += index_substr_any_step )
689 hashIter( &HASHcontext, HASHdigest,
690 (unsigned char *)&value->bv_val[j], klen );
691 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
696 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
697 !BER_BVISNULL( &sa->sa_final ) &&
698 sa->sa_final.bv_len >= index_substr_if_minlen )
700 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
701 value = &sa->sa_final;
703 klen = index_substr_if_maxlen < value->bv_len
704 ? index_substr_if_maxlen : value->bv_len;
706 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
707 hashIter( &HASHcontext, HASHdigest,
708 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
709 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
711 /* If final is too long and we have subany indexed, use it
712 * to match the excess...
714 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
717 pre = SLAP_INDEX_SUBSTR_PREFIX;
718 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
719 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
721 hashIter( &HASHcontext, HASHdigest,
722 (unsigned char *)&value->bv_val[j], index_substr_any_len );
723 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
729 BER_BVZERO( &keys[nkeys] );
746 /* very unforgiving validation, requires no normalization
747 * before simplistic matching
749 if( in->bv_len < 3 ) {
750 return LDAP_INVALID_SYNTAX;
753 /* RFC 4517 Section 3.3.2 Bit String:
754 * BitString = SQUOTE *binary-digit SQUOTE "B"
755 * binary-digit = "0" / "1"
757 * where SQUOTE [RFC4512] is
758 * SQUOTE = %x27 ; single quote ("'")
760 * Example: '0101111101'B
763 if( in->bv_val[0] != '\'' ||
764 in->bv_val[in->bv_len - 2] != '\'' ||
765 in->bv_val[in->bv_len - 1] != 'B' )
767 return LDAP_INVALID_SYNTAX;
770 for( i = in->bv_len - 3; i > 0; i-- ) {
771 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
772 return LDAP_INVALID_SYNTAX;
780 * Syntaxes from RFC 4517
785 A value of the Bit String syntax is a sequence of binary digits. The
786 LDAP-specific encoding of a value of this syntax is defined by the
789 BitString = SQUOTE *binary-digit SQUOTE "B"
791 binary-digit = "0" / "1"
793 The <SQUOTE> rule is defined in [MODELS].
798 The LDAP definition for the Bit String syntax is:
800 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
802 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
806 3.3.21. Name and Optional UID
808 A value of the Name and Optional UID syntax is the distinguished name
809 [MODELS] of an entity optionally accompanied by a unique identifier
810 that serves to differentiate the entity from others with an identical
813 The LDAP-specific encoding of a value of this syntax is defined by
816 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
818 The <BitString> rule is defined in Section 3.3.2. The
819 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
822 Note that although the '#' character may occur in the string
823 representation of a distinguished name, no additional escaping of
824 this character is performed when a <distinguishedName> is encoded in
825 a <NameAndOptionalUID>.
828 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
830 The LDAP definition for the Name and Optional UID syntax is:
832 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
834 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
841 1.4. Common ABNF Productions
844 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
846 SQUOTE = %x27 ; single quote ("'")
850 * Note: normalization strips any leading "0"s, unless the
851 * bit string is exactly "'0'B", so the normalized example,
852 * in slapd, would result in
854 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
856 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
857 * be escaped except when at the beginning of a value, the
858 * definition of Name and Optional UID appears to be flawed,
859 * because there is no clear means to determine whether the
860 * UID part is present or not.
864 * cn=Someone,dc=example,dc=com#'1'B
866 * could be either a NameAndOptionalUID with trailing UID, i.e.
868 * DN = "cn=Someone,dc=example,dc=com"
871 * or a NameAndOptionalUID with no trailing UID, and the AVA
872 * in the last RDN made of
875 * attributeValue = com#'1'B
877 * in fact "com#'1'B" is a valid IA5 string.
879 * As a consequence, current slapd code assumes that the
880 * presence of portions of a BitString at the end of the string
881 * representation of a NameAndOptionalUID means a BitString
882 * is expected, and cause an error otherwise. This is quite
883 * arbitrary, and might change in the future.
893 struct berval dn, uid;
895 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
897 ber_dupbv( &dn, in );
898 if( !dn.bv_val ) return LDAP_OTHER;
900 /* if there's a "#", try bitStringValidate()... */
901 uid.bv_val = strrchr( dn.bv_val, '#' );
902 if ( !BER_BVISNULL( &uid ) ) {
904 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
906 rc = bitStringValidate( NULL, &uid );
907 if ( rc == LDAP_SUCCESS ) {
908 /* in case of success, trim the UID,
909 * otherwise treat it as part of the DN */
910 dn.bv_len -= uid.bv_len + 1;
911 uid.bv_val[-1] = '\0';
915 rc = dnValidate( NULL, &dn );
917 ber_memfree( dn.bv_val );
928 assert( val != NULL );
929 assert( out != NULL );
932 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
934 if( BER_BVISEMPTY( val ) ) {
935 ber_dupbv_x( out, val, ctx );
937 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
938 return LDAP_INVALID_SYNTAX;
942 struct berval dnval = *val;
943 struct berval uidval = BER_BVNULL;
945 uidval.bv_val = strrchr( val->bv_val, '#' );
946 if ( !BER_BVISNULL( &uidval ) ) {
948 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
950 rc = bitStringValidate( NULL, &uidval );
952 if ( rc == LDAP_SUCCESS ) {
953 ber_dupbv_x( &dnval, val, ctx );
954 dnval.bv_len -= uidval.bv_len + 1;
955 dnval.bv_val[dnval.bv_len] = '\0';
958 BER_BVZERO( &uidval );
962 rc = dnPretty( syntax, &dnval, out, ctx );
963 if ( dnval.bv_val != val->bv_val ) {
964 slap_sl_free( dnval.bv_val, ctx );
966 if( rc != LDAP_SUCCESS ) {
970 if( !BER_BVISNULL( &uidval ) ) {
974 tmp = slap_sl_realloc( out->bv_val, out->bv_len
975 + STRLENOF( "#" ) + uidval.bv_len + 1,
978 ber_memfree_x( out->bv_val, ctx );
982 out->bv_val[out->bv_len++] = '#';
983 out->bv_val[out->bv_len++] = '\'';
985 got1 = uidval.bv_len < sizeof("'0'B");
986 for( i = 1; i < uidval.bv_len - 2; i++ ) {
987 c = uidval.bv_val[i];
990 if( got1 ) out->bv_val[out->bv_len++] = c;
994 out->bv_val[out->bv_len++] = c;
999 out->bv_val[out->bv_len++] = '\'';
1000 out->bv_val[out->bv_len++] = 'B';
1001 out->bv_val[out->bv_len] = '\0';
1005 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1007 return LDAP_SUCCESS;
1011 uniqueMemberNormalize(
1016 struct berval *normalized,
1022 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1024 ber_dupbv_x( &out, val, ctx );
1025 if ( BER_BVISEMPTY( &out ) ) {
1029 struct berval uid = BER_BVNULL;
1031 uid.bv_val = strrchr( out.bv_val, '#' );
1032 if ( !BER_BVISNULL( &uid ) ) {
1034 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1036 rc = bitStringValidate( NULL, &uid );
1037 if ( rc == LDAP_SUCCESS ) {
1038 uid.bv_val[-1] = '\0';
1039 out.bv_len -= uid.bv_len + 1;
1045 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1047 if( rc != LDAP_SUCCESS ) {
1048 slap_sl_free( out.bv_val, ctx );
1049 return LDAP_INVALID_SYNTAX;
1052 if( !BER_BVISNULL( &uid ) ) {
1055 tmp = ch_realloc( normalized->bv_val,
1056 normalized->bv_len + uid.bv_len
1057 + STRLENOF("#") + 1 );
1058 if ( tmp == NULL ) {
1059 ber_memfree_x( normalized->bv_val, ctx );
1063 normalized->bv_val = tmp;
1065 /* insert the separator */
1066 normalized->bv_val[normalized->bv_len++] = '#';
1068 /* append the UID */
1069 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1070 uid.bv_val, uid.bv_len );
1071 normalized->bv_len += uid.bv_len;
1074 normalized->bv_val[normalized->bv_len] = '\0';
1077 slap_sl_free( out.bv_val, ctx );
1080 return LDAP_SUCCESS;
1089 struct berval *value,
1090 void *assertedValue )
1093 struct berval *asserted = (struct berval *) assertedValue;
1094 struct berval assertedDN = *asserted;
1095 struct berval assertedUID = BER_BVNULL;
1096 struct berval valueDN = *value;
1097 struct berval valueUID = BER_BVNULL;
1098 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1100 if ( !BER_BVISEMPTY( asserted ) ) {
1101 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1102 if ( !BER_BVISNULL( &assertedUID ) ) {
1103 assertedUID.bv_val++;
1104 assertedUID.bv_len = assertedDN.bv_len
1105 - ( assertedUID.bv_val - assertedDN.bv_val );
1107 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1108 assertedDN.bv_len -= assertedUID.bv_len + 1;
1111 BER_BVZERO( &assertedUID );
1116 if ( !BER_BVISEMPTY( value ) ) {
1118 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1119 if ( !BER_BVISNULL( &valueUID ) ) {
1121 valueUID.bv_len = valueDN.bv_len
1122 - ( valueUID.bv_val - valueDN.bv_val );
1124 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1125 valueDN.bv_len -= valueUID.bv_len + 1;
1128 BER_BVZERO( &valueUID );
1133 if( valueUID.bv_len && assertedUID.bv_len ) {
1134 match = valueUID.bv_len - assertedUID.bv_len;
1137 return LDAP_SUCCESS;
1140 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1143 return LDAP_SUCCESS;
1146 } else if ( !approx && valueUID.bv_len ) {
1149 return LDAP_SUCCESS;
1151 } else if ( !approx && assertedUID.bv_len ) {
1154 return LDAP_SUCCESS;
1157 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1161 uniqueMemberIndexer(
1166 struct berval *prefix,
1174 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1175 /* just count them */
1179 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1181 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1182 struct berval assertedDN = values[i];
1183 struct berval assertedUID = BER_BVNULL;
1185 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1186 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1187 if ( !BER_BVISNULL( &assertedUID ) ) {
1188 assertedUID.bv_val++;
1189 assertedUID.bv_len = assertedDN.bv_len
1190 - ( assertedUID.bv_val - assertedDN.bv_val );
1192 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1193 assertedDN.bv_len -= assertedUID.bv_len + 1;
1196 BER_BVZERO( &assertedUID );
1201 dnvalues[i] = assertedDN;
1203 BER_BVZERO( &dnvalues[i] );
1205 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1206 dnvalues, keysp, ctx );
1208 slap_sl_free( dnvalues, ctx );
1218 struct berval *prefix,
1219 void * assertedValue,
1223 struct berval *asserted = (struct berval *) assertedValue;
1224 struct berval assertedDN = *asserted;
1225 struct berval assertedUID = BER_BVNULL;
1227 if ( !BER_BVISEMPTY( asserted ) ) {
1228 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1229 if ( !BER_BVISNULL( &assertedUID ) ) {
1230 assertedUID.bv_val++;
1231 assertedUID.bv_len = assertedDN.bv_len
1232 - ( assertedUID.bv_val - assertedDN.bv_val );
1234 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1235 assertedDN.bv_len -= assertedUID.bv_len + 1;
1238 BER_BVZERO( &assertedUID );
1243 return octetStringFilter( use, flags, syntax, mr, prefix,
1244 &assertedDN, keysp, ctx );
1249 * Handling boolean syntax and matching is quite rigid.
1250 * A more flexible approach would be to allow a variety
1251 * of strings to be normalized and prettied into TRUE
1259 /* very unforgiving validation, requires no normalization
1260 * before simplistic matching
1263 if( in->bv_len == 4 ) {
1264 if( bvmatch( in, &slap_true_bv ) ) {
1265 return LDAP_SUCCESS;
1267 } else if( in->bv_len == 5 ) {
1268 if( bvmatch( in, &slap_false_bv ) ) {
1269 return LDAP_SUCCESS;
1273 return LDAP_INVALID_SYNTAX;
1282 struct berval *value,
1283 void *assertedValue )
1285 /* simplistic matching allowed by rigid validation */
1286 struct berval *asserted = (struct berval *) assertedValue;
1287 *matchp = value->bv_len != asserted->bv_len;
1288 return LDAP_SUCCESS;
1291 /*-------------------------------------------------------------------
1292 LDAP/X.500 string syntax / matching rules have a few oddities. This
1293 comment attempts to detail how slapd(8) treats them.
1296 StringSyntax X.500 LDAP Matching/Comments
1297 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1298 PrintableString subset subset i/e + ignore insignificant spaces
1299 PrintableString subset subset i/e + ignore insignificant spaces
1300 NumericString subset subset ignore all spaces
1301 IA5String ASCII ASCII i/e + ignore insignificant spaces
1302 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1304 TelephoneNumber subset subset i + ignore all spaces and "-"
1306 See RFC 4518 for details.
1310 In X.500(93), a directory string can be either a PrintableString,
1311 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1312 In later versions, more CHOICEs were added. In all cases the string
1315 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1316 A directory string cannot be zero length.
1318 For matching, there are both case ignore and exact rules. Both
1319 also require that "insignificant" spaces be ignored.
1320 spaces before the first non-space are ignored;
1321 spaces after the last non-space are ignored;
1322 spaces after a space are ignored.
1323 Note: by these rules (and as clarified in X.520), a string of only
1324 spaces is to be treated as if held one space, not empty (which
1325 would be a syntax error).
1328 In ASN.1, numeric string is just a string of digits and spaces
1329 and could be empty. However, in X.500, all attribute values of
1330 numeric string carry a non-empty constraint. For example:
1332 internationalISDNNumber ATTRIBUTE ::= {
1333 WITH SYNTAX InternationalISDNNumber
1334 EQUALITY MATCHING RULE numericStringMatch
1335 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1336 ID id-at-internationalISDNNumber }
1337 InternationalISDNNumber ::=
1338 NumericString (SIZE(1..ub-international-isdn-number))
1340 Unforunately, some assertion values are don't carry the same
1341 constraint (but its unclear how such an assertion could ever
1342 be true). In LDAP, there is one syntax (numericString) not two
1343 (numericString with constraint, numericString without constraint).
1344 This should be treated as numericString with non-empty constraint.
1345 Note that while someone may have no ISDN number, there are no ISDN
1346 numbers which are zero length.
1348 In matching, spaces are ignored.
1351 In ASN.1, Printable string is just a string of printable characters
1352 and can be empty. In X.500, semantics much like NumericString (see
1353 serialNumber for a like example) excepting uses insignificant space
1354 handling instead of ignore all spaces.
1357 Basically same as PrintableString. There are no examples in X.500,
1358 but same logic applies. So we require them to be non-empty as
1361 -------------------------------------------------------------------*/
1370 unsigned char *u = (unsigned char *)in->bv_val;
1372 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1373 /* directory strings cannot be empty */
1374 return LDAP_INVALID_SYNTAX;
1377 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1378 /* get the length indicated by the first byte */
1379 len = LDAP_UTF8_CHARLEN2( u, len );
1381 /* very basic checks */
1384 if( (u[5] & 0xC0) != 0x80 ) {
1385 return LDAP_INVALID_SYNTAX;
1388 if( (u[4] & 0xC0) != 0x80 ) {
1389 return LDAP_INVALID_SYNTAX;
1392 if( (u[3] & 0xC0) != 0x80 ) {
1393 return LDAP_INVALID_SYNTAX;
1396 if( (u[2] & 0xC0 )!= 0x80 ) {
1397 return LDAP_INVALID_SYNTAX;
1400 if( (u[1] & 0xC0) != 0x80 ) {
1401 return LDAP_INVALID_SYNTAX;
1404 /* CHARLEN already validated it */
1407 return LDAP_INVALID_SYNTAX;
1410 /* make sure len corresponds with the offset
1411 to the next character */
1412 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1416 return LDAP_INVALID_SYNTAX;
1419 return LDAP_SUCCESS;
1423 UTF8StringNormalize(
1428 struct berval *normalized,
1431 struct berval tmp, nvalue;
1435 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1437 if( BER_BVISNULL( val ) ) {
1438 /* assume we're dealing with a syntax (e.g., UTF8String)
1439 * which allows empty strings
1441 BER_BVZERO( normalized );
1442 return LDAP_SUCCESS;
1445 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1446 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1447 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1448 ? LDAP_UTF8_APPROX : 0;
1450 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1455 /* collapse spaces (in place) */
1457 nvalue.bv_val = tmp.bv_val;
1459 /* trim leading spaces? */
1460 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1461 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1463 for( i = 0; i < tmp.bv_len; i++) {
1464 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1465 if( wasspace++ == 0 ) {
1466 /* trim repeated spaces */
1467 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1471 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1475 if( !BER_BVISEMPTY( &nvalue ) ) {
1476 /* trim trailing space? */
1478 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1479 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1483 nvalue.bv_val[nvalue.bv_len] = '\0';
1486 /* string of all spaces is treated as one space */
1487 nvalue.bv_val[0] = ' ';
1488 nvalue.bv_val[1] = '\0';
1492 *normalized = nvalue;
1493 return LDAP_SUCCESS;
1497 directoryStringSubstringsMatch(
1502 struct berval *value,
1503 void *assertedValue )
1506 SubstringsAssertion *sub = assertedValue;
1507 struct berval left = *value;
1511 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1512 if ( sub->sa_initial.bv_len > left.bv_len ) {
1513 /* not enough left */
1518 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1519 sub->sa_initial.bv_len );
1525 left.bv_val += sub->sa_initial.bv_len;
1526 left.bv_len -= sub->sa_initial.bv_len;
1528 priorspace = ASCII_SPACE(
1529 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1532 if ( sub->sa_any ) {
1533 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1537 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1538 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1540 /* allow next space to match */
1547 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1551 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1552 /* not enough left */
1557 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1564 idx = p - left.bv_val;
1566 if ( idx >= left.bv_len ) {
1567 /* this shouldn't happen */
1574 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1575 /* not enough left */
1580 match = memcmp( left.bv_val,
1581 sub->sa_any[i].bv_val,
1582 sub->sa_any[i].bv_len );
1590 left.bv_val += sub->sa_any[i].bv_len;
1591 left.bv_len -= sub->sa_any[i].bv_len;
1593 priorspace = ASCII_SPACE(
1594 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1598 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1599 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1600 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1602 /* allow next space to match */
1607 if ( sub->sa_final.bv_len > left.bv_len ) {
1608 /* not enough left */
1613 match = memcmp( sub->sa_final.bv_val,
1614 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1615 sub->sa_final.bv_len );
1624 return LDAP_SUCCESS;
1627 #if defined(SLAPD_APPROX_INITIALS)
1628 # define SLAPD_APPROX_DELIMITER "._ "
1629 # define SLAPD_APPROX_WORDLEN 2
1631 # define SLAPD_APPROX_DELIMITER " "
1632 # define SLAPD_APPROX_WORDLEN 1
1641 struct berval *value,
1642 void *assertedValue )
1644 struct berval *nval, *assertv;
1645 char *val, **values, **words, *c;
1646 int i, count, len, nextchunk=0, nextavail=0;
1648 /* Yes, this is necessary */
1649 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1650 if( nval == NULL ) {
1652 return LDAP_SUCCESS;
1655 /* Yes, this is necessary */
1656 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1657 NULL, LDAP_UTF8_APPROX, NULL );
1658 if( assertv == NULL ) {
1661 return LDAP_SUCCESS;
1664 /* Isolate how many words there are */
1665 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1666 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1667 if ( c == NULL ) break;
1672 /* Get a phonetic copy of each word */
1673 words = (char **)ch_malloc( count * sizeof(char *) );
1674 values = (char **)ch_malloc( count * sizeof(char *) );
1675 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1677 values[i] = phonetic(c);
1680 /* Work through the asserted value's words, to see if at least some
1681 of the words are there, in the same order. */
1683 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1684 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1689 #if defined(SLAPD_APPROX_INITIALS)
1690 else if( len == 1 ) {
1691 /* Single letter words need to at least match one word's initial */
1692 for( i=nextavail; i<count; i++ )
1693 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1700 /* Isolate the next word in the asserted value and phonetic it */
1701 assertv->bv_val[nextchunk+len] = '\0';
1702 val = phonetic( assertv->bv_val + nextchunk );
1704 /* See if this phonetic chunk is in the remaining words of *value */
1705 for( i=nextavail; i<count; i++ ){
1706 if( !strcmp( val, values[i] ) ){
1714 /* This chunk in the asserted value was NOT within the *value. */
1720 /* Go on to the next word in the asserted value */
1724 /* If some of the words were seen, call it a match */
1725 if( nextavail > 0 ) {
1732 /* Cleanup allocs */
1733 ber_bvfree( assertv );
1734 for( i=0; i<count; i++ ) {
1735 ch_free( values[i] );
1741 return LDAP_SUCCESS;
1750 struct berval *prefix,
1756 int i,j, len, wordcount, keycount=0;
1757 struct berval *newkeys;
1758 BerVarray keys=NULL;
1760 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1761 struct berval val = BER_BVNULL;
1762 /* Yes, this is necessary */
1763 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1764 assert( !BER_BVISNULL( &val ) );
1766 /* Isolate how many words there are. There will be a key for each */
1767 for( wordcount = 0, c = val.bv_val; *c; c++) {
1768 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1769 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1771 if (*c == '\0') break;
1775 /* Allocate/increase storage to account for new keys */
1776 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1777 * sizeof(struct berval) );
1778 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1779 if( keys ) ch_free( keys );
1782 /* Get a phonetic copy of each word */
1783 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1785 if( len < SLAPD_APPROX_WORDLEN ) continue;
1786 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1791 ber_memfree( val.bv_val );
1793 BER_BVZERO( &keys[keycount] );
1796 return LDAP_SUCCESS;
1805 struct berval *prefix,
1806 void * assertedValue,
1815 /* Yes, this is necessary */
1816 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1817 NULL, LDAP_UTF8_APPROX, NULL );
1818 if( val == NULL || BER_BVISNULL( val ) ) {
1819 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1820 BER_BVZERO( &keys[0] );
1823 return LDAP_SUCCESS;
1826 /* Isolate how many words there are. There will be a key for each */
1827 for( count = 0,c = val->bv_val; *c; c++) {
1828 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1829 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1831 if (*c == '\0') break;
1835 /* Allocate storage for new keys */
1836 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1838 /* Get a phonetic copy of each word */
1839 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1841 if( len < SLAPD_APPROX_WORDLEN ) continue;
1842 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1848 BER_BVZERO( &keys[count] );
1851 return LDAP_SUCCESS;
1854 /* Remove all spaces and '-' characters */
1856 telephoneNumberNormalize(
1861 struct berval *normalized,
1866 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1868 /* validator should have refused an empty string */
1869 assert( !BER_BVISEMPTY( val ) );
1871 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1873 for( p = val->bv_val; *p; p++ ) {
1874 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1880 normalized->bv_len = q - normalized->bv_val;
1882 if( BER_BVISEMPTY( normalized ) ) {
1883 slap_sl_free( normalized->bv_val, ctx );
1884 BER_BVZERO( normalized );
1885 return LDAP_INVALID_SYNTAX;
1888 return LDAP_SUCCESS;
1896 struct berval val = *in;
1898 if( BER_BVISEMPTY( &val ) ) {
1899 /* disallow empty strings */
1900 return LDAP_INVALID_SYNTAX;
1903 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1904 if ( val.bv_len == 1 ) {
1905 return LDAP_SUCCESS;
1908 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1915 while ( OID_LEADCHAR( val.bv_val[0] )) {
1919 if ( val.bv_len == 0 ) {
1920 return LDAP_SUCCESS;
1924 if( !OID_SEPARATOR( val.bv_val[0] )) {
1932 return LDAP_INVALID_SYNTAX;
1941 struct berval val = *in;
1943 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1945 if ( val.bv_val[0] == '-' ) {
1949 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1950 return LDAP_INVALID_SYNTAX;
1953 if( val.bv_val[0] == '0' ) { /* "-0" */
1954 return LDAP_INVALID_SYNTAX;
1957 } else if ( val.bv_val[0] == '0' ) {
1958 if( val.bv_len > 1 ) { /* "0<more>" */
1959 return LDAP_INVALID_SYNTAX;
1962 return LDAP_SUCCESS;
1965 for( i=0; i < val.bv_len; i++ ) {
1966 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1967 return LDAP_INVALID_SYNTAX;
1971 return LDAP_SUCCESS;
1980 struct berval *value,
1981 void *assertedValue )
1983 struct berval *asserted = (struct berval *) assertedValue;
1984 int vsign = 1, asign = 1; /* default sign = '+' */
1989 if( v.bv_val[0] == '-' ) {
1995 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1998 if( a.bv_val[0] == '-' ) {
2004 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2006 match = vsign - asign;
2008 match = ( v.bv_len != a.bv_len
2009 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2010 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2011 if( vsign < 0 ) match = -match;
2015 return LDAP_SUCCESS;
2019 countryStringValidate(
2021 struct berval *val )
2023 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2025 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2026 return LDAP_INVALID_SYNTAX;
2028 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2029 return LDAP_INVALID_SYNTAX;
2032 return LDAP_SUCCESS;
2036 printableStringValidate(
2038 struct berval *val )
2042 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2044 for(i=0; i < val->bv_len; i++) {
2045 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2046 return LDAP_INVALID_SYNTAX;
2050 return LDAP_SUCCESS;
2054 printablesStringValidate(
2056 struct berval *val )
2060 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2062 for(i=0,len=0; i < val->bv_len; i++) {
2063 int c = val->bv_val[i];
2067 return LDAP_INVALID_SYNTAX;
2071 } else if ( SLAP_PRINTABLE(c) ) {
2074 return LDAP_INVALID_SYNTAX;
2079 return LDAP_INVALID_SYNTAX;
2082 return LDAP_SUCCESS;
2088 struct berval *val )
2092 for(i=0; i < val->bv_len; i++) {
2093 if( !LDAP_ASCII(val->bv_val[i]) ) {
2094 return LDAP_INVALID_SYNTAX;
2098 return LDAP_SUCCESS;
2107 struct berval *normalized,
2111 int casefold = !SLAP_MR_ASSOCIATED( mr,
2112 slap_schema.si_mr_caseExactIA5Match );
2114 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2118 /* Ignore initial whitespace */
2119 while ( ASCII_SPACE( *p ) ) p++;
2121 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2122 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2123 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2124 normalized->bv_val[normalized->bv_len] = '\0';
2126 p = q = normalized->bv_val;
2129 if ( ASCII_SPACE( *p ) ) {
2132 /* Ignore the extra whitespace */
2133 while ( ASCII_SPACE( *p ) ) {
2137 } else if ( casefold ) {
2138 /* Most IA5 rules require casefolding */
2139 *q++ = TOLOWER(*p); p++;
2146 assert( normalized->bv_val <= p );
2150 * If the string ended in space, backup the pointer one
2151 * position. One is enough because the above loop collapsed
2152 * all whitespace to a single space.
2154 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2156 /* null terminate */
2159 normalized->bv_len = q - normalized->bv_val;
2161 return LDAP_SUCCESS;
2170 if( in->bv_len != 36 ) {
2171 return LDAP_INVALID_SYNTAX;
2174 for( i=0; i<36; i++ ) {
2180 if( in->bv_val[i] != '-' ) {
2181 return LDAP_INVALID_SYNTAX;
2185 if( !ASCII_HEX( in->bv_val[i]) ) {
2186 return LDAP_INVALID_SYNTAX;
2191 return LDAP_SUCCESS;
2202 int rc=LDAP_INVALID_SYNTAX;
2204 assert( in != NULL );
2205 assert( out != NULL );
2207 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2210 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2212 for( i=0; i<36; i++ ) {
2218 if( in->bv_val[i] != '-' ) {
2221 out->bv_val[i] = '-';
2225 if( !ASCII_HEX( in->bv_val[i]) ) {
2228 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2233 out->bv_val[ out->bv_len ] = '\0';
2237 slap_sl_free( out->bv_val, ctx );
2250 struct berval *normalized,
2253 unsigned char octet = '\0';
2256 normalized->bv_len = 16;
2257 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2259 for( i=0, j=0; i<36; i++ ) {
2260 unsigned char nibble;
2261 if( val->bv_val[i] == '-' ) {
2264 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2265 nibble = val->bv_val[i] - '0';
2267 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2268 nibble = val->bv_val[i] - ('a'-10);
2270 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2271 nibble = val->bv_val[i] - ('A'-10);
2274 slap_sl_free( normalized->bv_val, ctx );
2275 return LDAP_INVALID_SYNTAX;
2280 normalized->bv_val[j>>1] = octet;
2282 octet = nibble << 4;
2287 normalized->bv_val[normalized->bv_len] = 0;
2288 return LDAP_SUCCESS;
2294 numericStringValidate(
2300 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2302 for(i=0; i < in->bv_len; i++) {
2303 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2304 return LDAP_INVALID_SYNTAX;
2308 return LDAP_SUCCESS;
2312 numericStringNormalize(
2317 struct berval *normalized,
2320 /* removal all spaces */
2323 assert( !BER_BVISEMPTY( val ) );
2325 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2328 q = normalized->bv_val;
2331 if ( ASCII_SPACE( *p ) ) {
2332 /* Ignore whitespace */
2339 /* we should have copied no more then is in val */
2340 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2342 /* null terminate */
2345 normalized->bv_len = q - normalized->bv_val;
2347 if( BER_BVISEMPTY( normalized ) ) {
2348 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2349 normalized->bv_val[0] = ' ';
2350 normalized->bv_val[1] = '\0';
2351 normalized->bv_len = 1;
2354 return LDAP_SUCCESS;
2358 * Integer conversion macros that will use the largest available
2361 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2362 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2363 # define SLAP_LONG long long
2365 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2366 # define SLAP_LONG long
2367 #endif /* HAVE_STRTOLL ... */
2375 struct berval *value,
2376 void *assertedValue )
2378 SLAP_LONG lValue, lAssertedValue;
2381 /* safe to assume integers are NUL terminated? */
2382 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2383 if( errno == ERANGE )
2385 return LDAP_CONSTRAINT_VIOLATION;
2388 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2390 if( errno == ERANGE )
2392 return LDAP_CONSTRAINT_VIOLATION;
2395 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2396 return LDAP_SUCCESS;
2405 struct berval *value,
2406 void *assertedValue )
2408 SLAP_LONG lValue, lAssertedValue;
2411 /* safe to assume integers are NUL terminated? */
2412 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2413 if( errno == ERANGE )
2415 return LDAP_CONSTRAINT_VIOLATION;
2418 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2420 if( errno == ERANGE )
2422 return LDAP_CONSTRAINT_VIOLATION;
2425 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2426 return LDAP_SUCCESS;
2430 serialNumberAndIssuerValidate(
2436 struct berval sn, i;
2438 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2441 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2443 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2444 /* Parse old format */
2445 i.bv_val = ber_bvchr( in, '$' );
2446 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2448 sn.bv_val = in->bv_val;
2449 sn.bv_len = i.bv_val - in->bv_val;
2452 i.bv_len = in->bv_len - (sn.bv_len + 1);
2454 /* eat leading zeros */
2455 for( n=0; n < (sn.bv_len-1); n++ ) {
2456 if( sn.bv_val[n] != '0' ) break;
2461 for( n=0; n < sn.bv_len; n++ ) {
2462 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2466 /* Parse GSER format */
2467 int havesn=0,haveissuer=0;
2468 struct berval x = *in;
2472 /* eat leading spaces */
2473 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2477 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2478 return LDAP_INVALID_SYNTAX;
2481 /* should be at issuer or serialNumber NamedValue */
2482 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2484 x.bv_val += STRLENOF("issuer");
2485 x.bv_len -= STRLENOF("issuer");
2487 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2488 x.bv_val++; x.bv_len--;
2490 /* eat leading spaces */
2491 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2495 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2496 x.bv_val++; x.bv_len--;
2498 i.bv_val = x.bv_val;
2501 for( ; i.bv_len < x.bv_len; ) {
2502 if ( i.bv_val[i.bv_len] != '"' ) {
2506 if ( i.bv_val[i.bv_len+1] == '"' ) {
2513 x.bv_val += i.bv_len+1;
2514 x.bv_len -= i.bv_len+1;
2516 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2517 return LDAP_INVALID_SYNTAX;
2522 } else if( strncasecmp( x.bv_val, "serialNumber",
2523 STRLENOF("serialNumber")) == 0 )
2525 /* parse serialNumber */
2527 x.bv_val += STRLENOF("serialNumber");
2528 x.bv_len -= STRLENOF("serialNumber");
2530 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2531 x.bv_val++; x.bv_len--;
2533 /* eat leading spaces */
2534 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2538 sn.bv_val = x.bv_val;
2541 if( sn.bv_val[0] == '-' ) {
2546 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2547 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2550 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2551 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2552 return LDAP_INVALID_SYNTAX;
2555 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2557 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2558 return LDAP_INVALID_SYNTAX;
2563 } else return LDAP_INVALID_SYNTAX;
2565 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2566 x.bv_val++; x.bv_len--;
2569 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2573 /* should be at remaining NamedValue */
2574 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2575 STRLENOF("issuer" )) == 0 ))
2578 x.bv_val += STRLENOF("issuer");
2579 x.bv_len -= STRLENOF("issuer");
2581 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2582 x.bv_val++; x.bv_len--;
2584 /* eat leading spaces */
2585 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2589 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2590 x.bv_val++; x.bv_len--;
2592 i.bv_val = x.bv_val;
2595 for( ; i.bv_len < x.bv_len; ) {
2596 if ( i.bv_val[i.bv_len] != '"' ) {
2600 if ( i.bv_val[i.bv_len+1] == '"' ) {
2607 x.bv_val += i.bv_len+1;
2608 x.bv_len -= i.bv_len+1;
2610 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2611 STRLENOF("serialNumber")) == 0 ))
2613 /* parse serialNumber */
2615 x.bv_val += STRLENOF("serialNumber");
2616 x.bv_len -= STRLENOF("serialNumber");
2618 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2619 x.bv_val++; x.bv_len--;
2621 /* eat leading spaces */
2622 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2626 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2627 x.bv_val++; x.bv_len--;
2629 sn.bv_val = x.bv_val;
2632 if( sn.bv_val[0] == '-' ) {
2637 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2638 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2641 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2642 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2643 return LDAP_INVALID_SYNTAX;
2646 x.bv_val += sn.bv_len;
2647 x.bv_len -= sn.bv_len;
2649 } else return LDAP_INVALID_SYNTAX;
2651 /* eat trailing spaces */
2652 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2656 /* should have no characters left... */
2657 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2660 /* validate DN -- doesn't handle double dquote */
2661 rc = dnValidate( NULL, &i );
2662 if( rc ) return LDAP_INVALID_SYNTAX;
2664 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2666 return LDAP_SUCCESS;
2670 serialNumberAndIssuerPretty(
2678 struct berval sn, i, ni;
2680 assert( in != NULL );
2681 assert( out != NULL );
2683 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2686 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2688 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2689 /* Parse old format */
2690 i.bv_val = ber_bvchr( in, '$' );
2691 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2693 sn.bv_val = in->bv_val;
2694 sn.bv_len = i.bv_val - in->bv_val;
2697 i.bv_len = in->bv_len - (sn.bv_len + 1);
2699 /* eat leading zeros */
2700 for( n=0; n < (sn.bv_len-1); n++ ) {
2701 if( sn.bv_val[n] != '0' ) break;
2706 for( n=0; n < sn.bv_len; n++ ) {
2707 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2711 /* Parse GSER format */
2712 int havesn=0,haveissuer=0;
2713 struct berval x = *in;
2717 /* eat leading spaces */
2718 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2722 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2723 return LDAP_INVALID_SYNTAX;
2726 /* should be at issuer or serialNumber NamedValue */
2727 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2729 x.bv_val += STRLENOF("issuer");
2730 x.bv_len -= STRLENOF("issuer");
2732 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2733 x.bv_val++; x.bv_len--;
2735 /* eat leading spaces */
2736 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2740 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2741 x.bv_val++; x.bv_len--;
2743 i.bv_val = x.bv_val;
2746 for( ; i.bv_len < x.bv_len; ) {
2747 if ( i.bv_val[i.bv_len] != '"' ) {
2751 if ( i.bv_val[i.bv_len+1] == '"' ) {
2758 x.bv_val += i.bv_len+1;
2759 x.bv_len -= i.bv_len+1;
2761 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2762 return LDAP_INVALID_SYNTAX;
2767 } else if( strncasecmp( x.bv_val, "serialNumber",
2768 STRLENOF("serialNumber")) == 0 )
2770 /* parse serialNumber */
2772 x.bv_val += STRLENOF("serialNumber");
2773 x.bv_len -= STRLENOF("serialNumber");
2775 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2776 x.bv_val++; x.bv_len--;
2778 /* eat leading spaces */
2779 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2783 sn.bv_val = x.bv_val;
2786 if( sn.bv_val[0] == '-' ) {
2791 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2792 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2795 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2796 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2797 return LDAP_INVALID_SYNTAX;
2800 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2802 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2803 return LDAP_INVALID_SYNTAX;
2808 } else return LDAP_INVALID_SYNTAX;
2810 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2811 x.bv_val++; x.bv_len--;
2814 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2818 /* should be at remaining NamedValue */
2819 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2820 STRLENOF("issuer" )) == 0 ))
2823 x.bv_val += STRLENOF("issuer");
2824 x.bv_len -= STRLENOF("issuer");
2826 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2827 x.bv_val++; x.bv_len--;
2829 /* eat leading spaces */
2830 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2834 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2835 x.bv_val++; x.bv_len--;
2837 i.bv_val = x.bv_val;
2840 for( ; i.bv_len < x.bv_len; ) {
2841 if ( i.bv_val[i.bv_len] != '"' ) {
2845 if ( i.bv_val[i.bv_len+1] == '"' ) {
2852 x.bv_val += i.bv_len+1;
2853 x.bv_len -= i.bv_len+1;
2855 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2856 STRLENOF("serialNumber")) == 0 ))
2858 /* parse serialNumber */
2860 x.bv_val += STRLENOF("serialNumber");
2861 x.bv_len -= STRLENOF("serialNumber");
2863 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2864 x.bv_val++; x.bv_len--;
2866 /* eat leading spaces */
2867 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2871 sn.bv_val = x.bv_val;
2874 if( sn.bv_val[0] == '-' ) {
2879 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2880 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2883 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2884 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2885 return LDAP_INVALID_SYNTAX;
2888 x.bv_val += sn.bv_len;
2889 x.bv_len -= sn.bv_len;
2891 } else return LDAP_INVALID_SYNTAX;
2893 /* eat trailing spaces */
2894 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2898 /* should have no characters left... */
2899 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2901 ber_dupbv_x( &ni, &i, ctx );
2904 /* need to handle double dquotes here */
2907 rc = dnPretty( syntax, &i, &ni, ctx );
2909 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2910 slap_sl_free( i.bv_val, ctx );
2913 if( rc ) return LDAP_INVALID_SYNTAX;
2915 /* make room from sn + "$" */
2916 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2917 + sn.bv_len + ni.bv_len;
2918 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2920 if( out->bv_val == NULL ) {
2922 slap_sl_free( ni.bv_val, ctx );
2927 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2928 STRLENOF("{ serialNumber "));
2929 n = STRLENOF("{ serialNumber ");
2931 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2934 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2935 n += STRLENOF(", issuer \"");
2937 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2940 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2941 n += STRLENOF("\" }");
2943 out->bv_val[n] = '\0';
2945 assert( n == out->bv_len );
2947 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2948 out->bv_val, 0, 0 );
2950 slap_sl_free( ni.bv_val, ctx );
2952 return LDAP_SUCCESS;
2956 * This routine is called by certificateExactNormalize when
2957 * certificateExactNormalize receives a search string instead of
2958 * a certificate. This routine checks if the search value is valid
2959 * and then returns the normalized value
2962 serialNumberAndIssuerNormalize(
2972 struct berval sn, i, ni;
2974 assert( in != NULL );
2975 assert( out != NULL );
2977 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2980 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2982 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2983 /* Parse old format */
2984 i.bv_val = ber_bvchr( in, '$' );
2985 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2987 sn.bv_val = in->bv_val;
2988 sn.bv_len = i.bv_val - in->bv_val;
2991 i.bv_len = in->bv_len - (sn.bv_len + 1);
2993 /* eat leading zeros */
2994 for( n=0; n < (sn.bv_len-1); n++ ) {
2995 if( sn.bv_val[n] != '0' ) break;
3000 for( n=0; n < sn.bv_len; n++ ) {
3001 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3005 /* Parse GSER format */
3006 int havesn=0,haveissuer=0;
3007 struct berval x = *in;
3011 /* eat leading spaces */
3012 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3016 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3017 return LDAP_INVALID_SYNTAX;
3020 /* should be at issuer or serialNumber NamedValue */
3021 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3023 x.bv_val += STRLENOF("issuer");
3024 x.bv_len -= STRLENOF("issuer");
3026 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3027 x.bv_val++; x.bv_len--;
3029 /* eat leading spaces */
3030 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3034 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3035 x.bv_val++; x.bv_len--;
3037 i.bv_val = x.bv_val;
3040 for( ; i.bv_len < x.bv_len; ) {
3041 if ( i.bv_val[i.bv_len] != '"' ) {
3045 if ( i.bv_val[i.bv_len+1] == '"' ) {
3052 x.bv_val += i.bv_len+1;
3053 x.bv_len -= i.bv_len+1;
3055 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3056 return LDAP_INVALID_SYNTAX;
3061 } else if( strncasecmp( x.bv_val, "serialNumber",
3062 STRLENOF("serialNumber")) == 0 )
3064 /* parse serialNumber */
3066 x.bv_val += STRLENOF("serialNumber");
3067 x.bv_len -= STRLENOF("serialNumber");
3069 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3070 x.bv_val++; x.bv_len--;
3072 /* eat leading spaces */
3073 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3077 sn.bv_val = x.bv_val;
3080 if( sn.bv_val[0] == '-' ) {
3085 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3086 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3089 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3090 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3091 return LDAP_INVALID_SYNTAX;
3094 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3096 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3097 return LDAP_INVALID_SYNTAX;
3102 } else return LDAP_INVALID_SYNTAX;
3104 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3105 x.bv_val++; x.bv_len--;
3108 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3112 /* should be at remaining NamedValue */
3113 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3114 STRLENOF("issuer" )) == 0 ))
3117 x.bv_val += STRLENOF("issuer");
3118 x.bv_len -= STRLENOF("issuer");
3120 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3121 x.bv_val++; x.bv_len--;
3123 /* eat leading spaces */
3124 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3128 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3129 x.bv_val++; x.bv_len--;
3131 i.bv_val = x.bv_val;
3134 for( ; i.bv_len < x.bv_len; ) {
3135 if ( i.bv_val[i.bv_len] != '"' ) {
3139 if ( i.bv_val[i.bv_len+1] == '"' ) {
3146 x.bv_val += i.bv_len+1;
3147 x.bv_len -= i.bv_len+1;
3149 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3150 STRLENOF("serialNumber")) == 0 ))
3152 /* parse serialNumber */
3154 x.bv_val += STRLENOF("serialNumber");
3155 x.bv_len -= STRLENOF("serialNumber");
3157 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3158 x.bv_val++; x.bv_len--;
3160 /* eat leading spaces */
3161 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3165 sn.bv_val = x.bv_val;
3168 if( sn.bv_val[0] == '-' ) {
3173 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3174 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3177 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3178 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3179 return LDAP_INVALID_SYNTAX;
3182 x.bv_val += sn.bv_len;
3183 x.bv_len -= sn.bv_len;
3185 } else return LDAP_INVALID_SYNTAX;
3187 /* eat trailing spaces */
3188 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3192 /* should have no characters left... */
3193 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3195 ber_dupbv_x( &ni, &i, ctx );
3198 /* need to handle double dquotes here */
3201 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3203 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3204 slap_sl_free( i.bv_val, ctx );
3207 if( rc ) return LDAP_INVALID_SYNTAX;
3209 /* make room from sn + "$" */
3210 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3211 + sn.bv_len + ni.bv_len;
3212 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3214 if( out->bv_val == NULL ) {
3216 slap_sl_free( ni.bv_val, ctx );
3221 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3222 STRLENOF( "{ serialNumber " ));
3223 n = STRLENOF( "{ serialNumber " );
3225 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3228 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3229 n += STRLENOF( ", issuer \"" );
3231 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3234 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3235 n += STRLENOF( "\" }" );
3237 out->bv_val[n] = '\0';
3239 assert( n == out->bv_len );
3241 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3242 out->bv_val, 0, 0 );
3244 slap_sl_free( ni.bv_val, ctx );
3246 return LDAP_SUCCESS;
3250 certificateExactNormalize(
3255 struct berval *normalized,
3258 BerElementBuffer berbuf;
3259 BerElement *ber = (BerElement *)&berbuf;
3264 ber_len_t seriallen;
3265 struct berval issuer_dn = BER_BVNULL, bvdn;
3267 int rc = LDAP_INVALID_SYNTAX;
3269 if( BER_BVISEMPTY( val ) ) goto done;
3271 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3272 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3275 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3277 ber_init2( ber, val, LBER_USE_DER );
3278 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3279 tag = ber_skip_tag( ber, &len ); /* Sequence */
3280 tag = ber_skip_tag( ber, &len ); /* Optional version? */
3282 tag = ber_get_int( ber, &i ); /* version */
3283 ber_get_int( ber, &i ); /* serial */
3285 seriallen = snprintf( serial, sizeof(serial), "%d", i );
3286 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3287 ber_skip_data( ber, len );
3288 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3289 len = ber_ptrlen( ber );
3290 bvdn.bv_val = val->bv_val + len;
3291 bvdn.bv_len = val->bv_len - len;
3293 rc = dnX509normalize( &bvdn, &issuer_dn );
3294 if( rc != LDAP_SUCCESS ) goto done;
3296 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3297 + seriallen + issuer_dn.bv_len;
3298 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3300 p = (unsigned char *)normalized->bv_val;
3302 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3303 p += STRLENOF( "{ serialNumber " );
3305 AC_MEMCPY(p, serial, seriallen);
3308 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3309 p += STRLENOF( ", issuer \"" );
3311 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3312 p += issuer_dn.bv_len;
3314 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3315 p += STRLENOF( "\" }" );
3319 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3320 normalized->bv_val, NULL, NULL );
3325 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3331 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3332 /* slight optimization - does not need the start parameter */
3333 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3338 check_time_syntax (struct berval *val,
3341 struct berval *fraction)
3344 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3345 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3346 * GeneralizedTime supports leap seconds, UTCTime does not.
3348 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3349 static const int mdays[2][12] = {
3350 /* non-leap years */
3351 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3353 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3356 int part, c, c1, c2, tzoffset, leapyear = 0;
3359 e = p + val->bv_len;
3361 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3362 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3364 for (part = start; part < 7 && p < e; part++) {
3366 if (!ASCII_DIGIT(c1)) {
3371 return LDAP_INVALID_SYNTAX;
3374 if (!ASCII_DIGIT(c)) {
3375 return LDAP_INVALID_SYNTAX;
3377 c += c1 * 10 - '0' * 11;
3378 if ((part | 1) == 3) {
3381 return LDAP_INVALID_SYNTAX;
3384 if (c >= ceiling[part]) {
3385 if (! (c == 60 && part == 6 && start == 0))
3386 return LDAP_INVALID_SYNTAX;
3390 if (part < 5 + start) {
3391 return LDAP_INVALID_SYNTAX;
3393 for (; part < 9; part++) {
3397 /* leapyear check for the Gregorian calendar (year>1581) */
3398 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3402 if (parts[3] >= mdays[leapyear][parts[2]]) {
3403 return LDAP_INVALID_SYNTAX;
3407 fraction->bv_val = p;
3408 fraction->bv_len = 0;
3409 if (p < e && (*p == '.' || *p == ',')) {
3411 while (++p < e && ASCII_DIGIT(*p)) {
3414 if (p - fraction->bv_val == 1) {
3415 return LDAP_INVALID_SYNTAX;
3417 for (end_num = p; end_num[-1] == '0'; --end_num) {
3420 c = end_num - fraction->bv_val;
3421 if (c != 1) fraction->bv_len = c;
3427 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3433 return LDAP_INVALID_SYNTAX;
3439 for (part = 7; part < 9 && p < e; part++) {
3441 if (!ASCII_DIGIT(c1)) {
3446 return LDAP_INVALID_SYNTAX;
3449 if (!ASCII_DIGIT(c2)) {
3450 return LDAP_INVALID_SYNTAX;
3452 parts[part] = c1 * 10 + c2 - '0' * 11;
3453 if (parts[part] >= ceiling[part]) {
3454 return LDAP_INVALID_SYNTAX;
3457 if (part < 8 + start) {
3458 return LDAP_INVALID_SYNTAX;
3461 if (tzoffset == '-') {
3462 /* negative offset to UTC, ie west of Greenwich */
3463 parts[4] += parts[7];
3464 parts[5] += parts[8];
3465 /* offset is just hhmm, no seconds */
3466 for (part = 6; --part >= 0; ) {
3470 c = mdays[leapyear][parts[2]];
3472 if (parts[part] >= c) {
3474 return LDAP_INVALID_SYNTAX;
3479 } else if (part != 5) {
3484 /* positive offset to UTC, ie east of Greenwich */
3485 parts[4] -= parts[7];
3486 parts[5] -= parts[8];
3487 for (part = 6; --part >= 0; ) {
3488 if (parts[part] < 0) {
3490 return LDAP_INVALID_SYNTAX;
3495 /* make first arg to % non-negative */
3496 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3501 } else if (part != 5) {
3508 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3511 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3518 struct berval *normalized )
3522 rc = check_time_syntax(val, 1, parts, NULL);
3523 if (rc != LDAP_SUCCESS) {
3527 normalized->bv_val = ch_malloc( 14 );
3528 if ( normalized->bv_val == NULL ) {
3529 return LBER_ERROR_MEMORY;
3532 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3533 parts[1], parts[2] + 1, parts[3] + 1,
3534 parts[4], parts[5], parts[6] );
3535 normalized->bv_len = 13;
3537 return LDAP_SUCCESS;
3547 return check_time_syntax(in, 1, parts, NULL);
3550 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3553 generalizedTimeValidate(
3558 struct berval fraction;
3559 return check_time_syntax(in, 0, parts, &fraction);
3563 generalizedTimeNormalize(
3568 struct berval *normalized,
3573 struct berval fraction;
3575 rc = check_time_syntax(val, 0, parts, &fraction);
3576 if (rc != LDAP_SUCCESS) {
3580 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3581 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3582 if ( BER_BVISNULL( normalized ) ) {
3583 return LBER_ERROR_MEMORY;
3586 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3587 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3588 parts[4], parts[5], parts[6] );
3589 if ( !BER_BVISEMPTY( &fraction ) ) {
3590 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3591 fraction.bv_val, fraction.bv_len );
3592 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3594 strcpy( normalized->bv_val + len-1, "Z" );
3595 normalized->bv_len = len;
3597 return LDAP_SUCCESS;
3601 generalizedTimeOrderingMatch(
3606 struct berval *value,
3607 void *assertedValue )
3609 struct berval *asserted = (struct berval *) assertedValue;
3610 ber_len_t v_len = value->bv_len;
3611 ber_len_t av_len = asserted->bv_len;
3613 /* ignore trailing 'Z' when comparing */
3614 int match = memcmp( value->bv_val, asserted->bv_val,
3615 (v_len < av_len ? v_len : av_len) - 1 );
3616 if ( match == 0 ) match = v_len - av_len;
3619 return LDAP_SUCCESS;
3622 /* Index generation function */
3623 int generalizedTimeIndexer(
3628 struct berval *prefix,
3636 BerValue bvtmp; /* 40 bit index */
3638 struct lutil_timet tt;
3640 bvtmp.bv_len = sizeof(tmp);
3642 for( i=0; values[i].bv_val != NULL; i++ ) {
3643 /* just count them */
3646 /* we should have at least one value at this point */
3649 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3651 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3652 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3653 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3654 /* Use 40 bits of time for key */
3655 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3656 lutil_tm2time( &tm, &tt );
3657 tmp[0] = tt.tt_gsec & 0xff;
3658 tmp[4] = tt.tt_sec & 0xff;
3660 tmp[3] = tt.tt_sec & 0xff;
3662 tmp[2] = tt.tt_sec & 0xff;
3664 tmp[1] = tt.tt_sec & 0xff;
3666 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3670 keys[j].bv_val = NULL;
3675 return LDAP_SUCCESS;
3678 /* Index generation function */
3679 int generalizedTimeFilter(
3684 struct berval *prefix,
3685 void * assertedValue,
3691 BerValue bvtmp; /* 40 bit index */
3692 BerValue *value = (BerValue *) assertedValue;
3694 struct lutil_timet tt;
3696 bvtmp.bv_len = sizeof(tmp);
3698 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3699 /* Use 40 bits of time for key */
3700 if ( value->bv_val && value->bv_len >= 10 &&
3701 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3703 lutil_tm2time( &tm, &tt );
3704 tmp[0] = tt.tt_gsec & 0xff;
3705 tmp[4] = tt.tt_sec & 0xff;
3707 tmp[3] = tt.tt_sec & 0xff;
3709 tmp[2] = tt.tt_sec & 0xff;
3711 tmp[1] = tt.tt_sec & 0xff;
3713 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3714 ber_dupbv_x(keys, &bvtmp, ctx );
3715 keys[1].bv_val = NULL;
3723 return LDAP_SUCCESS;
3727 deliveryMethodValidate(
3729 struct berval *val )
3732 #define LENOF(s) (sizeof(s)-1)
3733 struct berval tmp = *val;
3735 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3736 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3737 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3740 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3742 switch( tmp.bv_val[0] ) {
3745 if(( tmp.bv_len >= LENOF("any") ) &&
3746 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3748 tmp.bv_len -= LENOF("any");
3749 tmp.bv_val += LENOF("any");
3752 return LDAP_INVALID_SYNTAX;
3756 if(( tmp.bv_len >= LENOF("mhs") ) &&
3757 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3759 tmp.bv_len -= LENOF("mhs");
3760 tmp.bv_val += LENOF("mhs");
3763 return LDAP_INVALID_SYNTAX;
3767 if(( tmp.bv_len >= LENOF("physical") ) &&
3768 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3770 tmp.bv_len -= LENOF("physical");
3771 tmp.bv_val += LENOF("physical");
3774 return LDAP_INVALID_SYNTAX;
3777 case 'T': /* telex or teletex or telephone */
3778 if(( tmp.bv_len >= LENOF("telex") ) &&
3779 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3781 tmp.bv_len -= LENOF("telex");
3782 tmp.bv_val += LENOF("telex");
3785 if(( tmp.bv_len >= LENOF("teletex") ) &&
3786 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3788 tmp.bv_len -= LENOF("teletex");
3789 tmp.bv_val += LENOF("teletex");
3792 if(( tmp.bv_len >= LENOF("telephone") ) &&
3793 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3795 tmp.bv_len -= LENOF("telephone");
3796 tmp.bv_val += LENOF("telephone");
3799 return LDAP_INVALID_SYNTAX;
3802 case 'G': /* g3fax or g4fax */
3803 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3804 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3805 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3807 tmp.bv_len -= LENOF("g3fax");
3808 tmp.bv_val += LENOF("g3fax");
3811 return LDAP_INVALID_SYNTAX;
3815 if(( tmp.bv_len >= LENOF("ia5") ) &&
3816 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3818 tmp.bv_len -= LENOF("ia5");
3819 tmp.bv_val += LENOF("ia5");
3822 return LDAP_INVALID_SYNTAX;
3826 if(( tmp.bv_len >= LENOF("videotex") ) &&
3827 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3829 tmp.bv_len -= LENOF("videotex");
3830 tmp.bv_val += LENOF("videotex");
3833 return LDAP_INVALID_SYNTAX;
3836 return LDAP_INVALID_SYNTAX;
3839 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3841 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3845 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3849 return LDAP_INVALID_SYNTAX;
3851 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3860 nisNetgroupTripleValidate(
3862 struct berval *val )
3867 if ( BER_BVISEMPTY( val ) ) {
3868 return LDAP_INVALID_SYNTAX;
3871 p = (char *)val->bv_val;
3872 e = p + val->bv_len;
3874 if ( *p != '(' /*')'*/ ) {
3875 return LDAP_INVALID_SYNTAX;
3878 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3882 return LDAP_INVALID_SYNTAX;
3885 } else if ( !AD_CHAR( *p ) ) {
3886 return LDAP_INVALID_SYNTAX;
3890 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3891 return LDAP_INVALID_SYNTAX;
3897 return LDAP_INVALID_SYNTAX;
3900 return LDAP_SUCCESS;
3904 bootParameterValidate(
3906 struct berval *val )
3910 if ( BER_BVISEMPTY( val ) ) {
3911 return LDAP_INVALID_SYNTAX;
3914 p = (char *)val->bv_val;
3915 e = p + val->bv_len;
3918 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3919 if ( !AD_CHAR( *p ) ) {
3920 return LDAP_INVALID_SYNTAX;
3925 return LDAP_INVALID_SYNTAX;
3929 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3930 if ( !AD_CHAR( *p ) ) {
3931 return LDAP_INVALID_SYNTAX;
3936 return LDAP_INVALID_SYNTAX;
3940 for ( p++; p < e; p++ ) {
3941 if ( !SLAP_PRINTABLE( *p ) ) {
3942 return LDAP_INVALID_SYNTAX;
3946 return LDAP_SUCCESS;
3950 firstComponentNormalize(
3955 struct berval *normalized,
3962 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3963 ber_dupbv_x( normalized, val, ctx );
3964 return LDAP_SUCCESS;
3967 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3969 if( val->bv_val[0] != '(' /*')'*/ &&
3970 val->bv_val[0] != '{' /*'}'*/ )
3972 return LDAP_INVALID_SYNTAX;
3975 /* trim leading white space */
3977 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3983 /* grab next word */
3984 comp.bv_val = &val->bv_val[len];
3985 len = val->bv_len - len;
3986 for( comp.bv_len = 0;
3987 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3993 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3994 rc = numericoidValidate( NULL, &comp );
3995 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3996 rc = integerValidate( NULL, &comp );
3998 rc = LDAP_INVALID_SYNTAX;
4002 if( rc == LDAP_SUCCESS ) {
4003 ber_dupbv_x( normalized, &comp, ctx );
4009 static char *country_gen_syn[] = {
4010 "1.3.6.1.4.1.1466.115.121.1.15",
4011 "1.3.6.1.4.1.1466.115.121.1.26",
4012 "1.3.6.1.4.1.1466.115.121.1.44",
4016 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4017 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4019 static slap_syntax_defs_rec syntax_defs[] = {
4020 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4021 X_BINARY X_NOT_H_R ")",
4022 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4023 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4024 0, NULL, NULL, NULL},
4025 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4026 0, NULL, NULL, NULL},
4027 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4029 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4030 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4032 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4033 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4034 0, NULL, bitStringValidate, NULL },
4035 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4036 0, NULL, booleanValidate, NULL},
4037 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4038 X_BINARY X_NOT_H_R ")",
4039 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4040 NULL, certificateValidate, NULL},
4041 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4042 X_BINARY X_NOT_H_R ")",
4043 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4044 NULL, sequenceValidate, NULL},
4045 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4046 X_BINARY X_NOT_H_R ")",
4047 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4048 NULL, sequenceValidate, NULL},
4049 #if 0 /* need to go __after__ printableString */
4050 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4051 0, "1.3.6.1.4.1.1466.115.121.1.44",
4052 countryStringValidate, NULL},
4054 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4055 0, NULL, dnValidate, dnPretty},
4056 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4057 0, NULL, rdnValidate, rdnPretty},
4058 #ifdef LDAP_COMP_MATCH
4059 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4060 0, NULL, allComponentsValidate, NULL},
4061 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4062 0, NULL, componentFilterValidate, NULL},
4064 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4065 0, NULL, NULL, NULL},
4066 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4067 0, NULL, deliveryMethodValidate, NULL},
4068 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4069 0, NULL, UTF8StringValidate, NULL},
4070 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4071 0, NULL, NULL, NULL},
4072 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4073 0, NULL, NULL, NULL},
4074 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4075 0, NULL, NULL, NULL},
4076 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4077 0, NULL, NULL, NULL},
4078 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4079 0, NULL, NULL, NULL},
4080 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4081 0, NULL, printablesStringValidate, NULL},
4082 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4083 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4084 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4085 0, NULL, generalizedTimeValidate, NULL},
4086 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4087 0, NULL, NULL, NULL},
4088 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4089 0, NULL, IA5StringValidate, NULL},
4090 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4091 0, NULL, integerValidate, NULL},
4092 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4093 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4094 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4095 0, NULL, NULL, NULL},
4096 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4097 0, NULL, NULL, NULL},
4098 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4099 0, NULL, NULL, NULL},
4100 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4101 0, NULL, NULL, NULL},
4102 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4103 0, NULL, NULL, NULL},
4104 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4105 0, NULL, nameUIDValidate, nameUIDPretty },
4106 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4107 0, NULL, NULL, NULL},
4108 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4109 0, NULL, numericStringValidate, NULL},
4110 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4111 0, NULL, NULL, NULL},
4112 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4113 0, NULL, numericoidValidate, NULL},
4114 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4115 0, NULL, IA5StringValidate, NULL},
4116 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4117 0, NULL, blobValidate, NULL},
4118 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4119 0, NULL, UTF8StringValidate, NULL},
4120 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4121 0, NULL, NULL, NULL},
4122 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4123 0, NULL, NULL, NULL},
4124 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4125 0, NULL, printableStringValidate, NULL},
4126 /* moved here because now depends on Directory String, IA5 String
4127 * and Printable String */
4128 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4129 0, country_gen_syn, countryStringValidate, NULL},
4130 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4131 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4132 0, NULL, subtreeSpecificationValidate, NULL},
4133 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4134 X_BINARY X_NOT_H_R ")",
4135 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4136 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4137 0, NULL, printableStringValidate, NULL},
4138 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4139 0, NULL, NULL, NULL},
4140 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4141 0, NULL, printablesStringValidate, NULL},
4142 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4143 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4144 0, NULL, utcTimeValidate, NULL},
4146 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4147 0, NULL, NULL, NULL},
4148 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4149 0, NULL, NULL, NULL},
4150 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4151 0, NULL, NULL, NULL},
4152 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4153 0, NULL, NULL, NULL},
4154 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4155 0, NULL, NULL, NULL},
4157 /* RFC 2307 NIS Syntaxes */
4158 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4159 0, NULL, nisNetgroupTripleValidate, NULL},
4160 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4161 0, NULL, bootParameterValidate, NULL},
4163 /* draft-zeilenga-ldap-x509 */
4164 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4165 SLAP_SYNTAX_HIDE, NULL,
4166 serialNumberAndIssuerValidate,
4167 serialNumberAndIssuerPretty},
4168 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4169 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4170 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4171 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4172 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4173 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4174 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4175 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4176 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4177 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4178 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4179 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4181 #ifdef SLAPD_AUTHPASSWD
4182 /* needs updating */
4183 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4184 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4187 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4188 0, NULL, UUIDValidate, UUIDPretty},
4190 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4191 SLAP_SYNTAX_HIDE, NULL, csnValidate, NULL},
4193 /* OpenLDAP Void Syntax */
4194 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4195 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4197 /* FIXME: OID is unused, but not registered yet */
4198 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4199 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4201 {NULL, 0, NULL, NULL, NULL}
4204 char *certificateExactMatchSyntaxes[] = {
4205 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4208 #ifdef LDAP_COMP_MATCH
4209 char *componentFilterMatchSyntaxes[] = {
4210 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4214 char *directoryStringSyntaxes[] = {
4215 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4218 char *integerFirstComponentMatchSyntaxes[] = {
4219 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4220 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4223 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4224 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4225 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4226 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4227 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4228 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4229 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4230 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4231 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4236 * Other matching rules in X.520 that we do not use (yet):
4238 * 2.5.13.25 uTCTimeMatch
4239 * 2.5.13.26 uTCTimeOrderingMatch
4240 * 2.5.13.31* directoryStringFirstComponentMatch
4241 * 2.5.13.32* wordMatch
4242 * 2.5.13.33* keywordMatch
4243 * 2.5.13.36+ certificatePairExactMatch
4244 * 2.5.13.37+ certificatePairMatch
4245 * 2.5.13.38+ certificateListExactMatch
4246 * 2.5.13.39+ certificateListMatch
4247 * 2.5.13.40+ algorithmIdentifierMatch
4248 * 2.5.13.41* storedPrefixMatch
4249 * 2.5.13.42 attributeCertificateMatch
4250 * 2.5.13.43 readerAndKeyIDMatch
4251 * 2.5.13.44 attributeIntegrityMatch
4253 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4254 * (+) described in draft-zeilenga-ldap-x509
4256 static slap_mrule_defs_rec mrule_defs[] = {
4258 * EQUALITY matching rules must be listed after associated APPROX
4259 * matching rules. So, we list all APPROX matching rules first.
4261 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4262 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4263 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4264 NULL, NULL, directoryStringApproxMatch,
4265 directoryStringApproxIndexer, directoryStringApproxFilter,
4268 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4269 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4270 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4271 NULL, NULL, IA5StringApproxMatch,
4272 IA5StringApproxIndexer, IA5StringApproxFilter,
4276 * Other matching rules
4279 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4280 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4281 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4282 NULL, NULL, octetStringMatch,
4283 octetStringIndexer, octetStringFilter,
4286 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4287 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4288 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4289 NULL, dnNormalize, dnMatch,
4290 octetStringIndexer, octetStringFilter,
4293 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4294 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4295 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4296 NULL, dnNormalize, dnRelativeMatch,
4300 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4301 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4302 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4303 NULL, dnNormalize, dnRelativeMatch,
4307 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4308 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4309 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4310 NULL, dnNormalize, dnRelativeMatch,
4314 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4315 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4316 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4317 NULL, dnNormalize, dnRelativeMatch,
4321 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4322 "SYNTAX 1.2.36.79672281.1.5.0 )",
4323 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4324 NULL, rdnNormalize, rdnMatch,
4325 octetStringIndexer, octetStringFilter,
4328 #ifdef LDAP_COMP_MATCH
4329 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4330 "SYNTAX 1.2.36.79672281.1.5.2 )",
4331 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4332 NULL, NULL , componentFilterMatch,
4333 octetStringIndexer, octetStringFilter,
4336 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4337 "SYNTAX 1.2.36.79672281.1.5.3 )",
4338 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4339 NULL, NULL , allComponentsMatch,
4340 octetStringIndexer, octetStringFilter,
4343 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4344 "SYNTAX 1.2.36.79672281.1.5.3 )",
4345 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4346 NULL, NULL , directoryComponentsMatch,
4347 octetStringIndexer, octetStringFilter,
4351 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4352 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4353 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4354 NULL, UTF8StringNormalize, octetStringMatch,
4355 octetStringIndexer, octetStringFilter,
4356 directoryStringApproxMatchOID },
4358 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4359 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4360 SLAP_MR_ORDERING, directoryStringSyntaxes,
4361 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4363 "caseIgnoreMatch" },
4365 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4366 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4367 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4368 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4369 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4370 "caseIgnoreMatch" },
4372 {"( 2.5.13.5 NAME 'caseExactMatch' "
4373 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4374 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4375 NULL, UTF8StringNormalize, octetStringMatch,
4376 octetStringIndexer, octetStringFilter,
4377 directoryStringApproxMatchOID },
4379 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4380 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4381 SLAP_MR_ORDERING, directoryStringSyntaxes,
4382 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4386 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4387 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4388 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4389 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4390 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4393 {"( 2.5.13.8 NAME 'numericStringMatch' "
4394 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4395 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4396 NULL, numericStringNormalize, octetStringMatch,
4397 octetStringIndexer, octetStringFilter,
4400 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4401 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4402 SLAP_MR_ORDERING, NULL,
4403 NULL, numericStringNormalize, octetStringOrderingMatch,
4405 "numericStringMatch" },
4407 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4408 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4409 SLAP_MR_SUBSTR, NULL,
4410 NULL, numericStringNormalize, octetStringSubstringsMatch,
4411 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4412 "numericStringMatch" },
4414 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4415 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4416 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4417 NULL, NULL, NULL, NULL, NULL, NULL },
4419 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4420 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4421 SLAP_MR_SUBSTR, NULL,
4422 NULL, NULL, NULL, NULL, NULL,
4423 "caseIgnoreListMatch" },
4425 {"( 2.5.13.13 NAME 'booleanMatch' "
4426 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4427 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4428 NULL, NULL, booleanMatch,
4429 octetStringIndexer, octetStringFilter,
4432 {"( 2.5.13.14 NAME 'integerMatch' "
4433 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4434 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4435 NULL, NULL, integerMatch,
4436 octetStringIndexer, octetStringFilter,
4439 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4440 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4441 SLAP_MR_ORDERING, NULL,
4442 NULL, NULL, integerMatch,
4446 {"( 2.5.13.16 NAME 'bitStringMatch' "
4447 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4448 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4449 NULL, NULL, octetStringMatch,
4450 octetStringIndexer, octetStringFilter,
4453 {"( 2.5.13.17 NAME 'octetStringMatch' "
4454 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4455 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4456 NULL, NULL, octetStringMatch,
4457 octetStringIndexer, octetStringFilter,
4460 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4461 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4462 SLAP_MR_ORDERING, NULL,
4463 NULL, NULL, octetStringOrderingMatch,
4465 "octetStringMatch" },
4467 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4468 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4469 SLAP_MR_SUBSTR, NULL,
4470 NULL, NULL, octetStringSubstringsMatch,
4471 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4472 "octetStringMatch" },
4474 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4475 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4476 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4478 telephoneNumberNormalize, octetStringMatch,
4479 octetStringIndexer, octetStringFilter,
4482 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4483 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4484 SLAP_MR_SUBSTR, NULL,
4485 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4486 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4487 "telephoneNumberMatch" },
4489 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4490 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4491 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4492 NULL, NULL, NULL, NULL, NULL, NULL },
4494 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4495 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4496 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4497 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4498 uniqueMemberIndexer, uniqueMemberFilter,
4501 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4503 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4504 NULL, NULL, NULL, NULL, NULL, NULL },
4506 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4507 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4508 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4509 NULL, generalizedTimeNormalize, octetStringMatch,
4510 generalizedTimeIndexer, generalizedTimeFilter,
4513 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4514 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4515 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4516 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4518 "generalizedTimeMatch" },
4520 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4521 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4522 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4523 integerFirstComponentMatchSyntaxes,
4524 NULL, firstComponentNormalize, integerMatch,
4525 octetStringIndexer, octetStringFilter,
4528 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4529 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4530 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4531 objectIdentifierFirstComponentMatchSyntaxes,
4532 NULL, firstComponentNormalize, octetStringMatch,
4533 octetStringIndexer, octetStringFilter,
4536 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4537 "SYNTAX 1.3.6.1.1.15.1 )",
4538 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4540 NULL, certificateExactNormalize, octetStringMatch,
4541 octetStringIndexer, octetStringFilter,
4543 NULL, NULL, NULL, NULL, NULL,
4547 {"( 2.5.13.35 NAME 'certificateMatch' "
4548 "SYNTAX 1.3.6.1.1.15.2 )",
4549 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4550 NULL, NULL, NULL, NULL, NULL,
4553 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4555 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4556 NULL, IA5StringNormalize, octetStringMatch,
4557 octetStringIndexer, octetStringFilter,
4558 IA5StringApproxMatchOID },
4560 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4561 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4562 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4563 NULL, IA5StringNormalize, octetStringMatch,
4564 octetStringIndexer, octetStringFilter,
4565 IA5StringApproxMatchOID },
4567 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4568 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4569 SLAP_MR_SUBSTR, NULL,
4570 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4571 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4572 "caseIgnoreIA5Match" },
4574 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4575 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4576 SLAP_MR_SUBSTR, NULL,
4577 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4578 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4579 "caseExactIA5Match" },
4581 #ifdef SLAPD_AUTHPASSWD
4582 /* needs updating */
4583 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4584 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4585 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4586 NULL, NULL, authPasswordMatch,
4591 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4592 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4594 NULL, NULL, integerBitAndMatch,
4598 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4599 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4601 NULL, NULL, integerBitOrMatch,
4605 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4606 "SYNTAX 1.3.6.1.1.16.1 )",
4607 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4608 NULL, UUIDNormalize, octetStringMatch,
4609 octetStringIndexer, octetStringFilter,
4612 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4613 "SYNTAX 1.3.6.1.1.16.1 )",
4614 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4615 NULL, UUIDNormalize, octetStringOrderingMatch,
4616 octetStringIndexer, octetStringFilter,
4619 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4620 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4621 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4622 NULL, NULL, csnMatch,
4623 csnIndexer, csnFilter,
4626 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4627 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4628 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4629 NULL, NULL, csnOrderingMatch,
4633 /* FIXME: OID is unused, but not registered yet */
4634 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4635 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4636 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4637 NULL, authzNormalize, authzMatch,
4641 {NULL, SLAP_MR_NONE, NULL,
4642 NULL, NULL, NULL, NULL, NULL,
4647 slap_schema_init( void )
4652 /* we should only be called once (from main) */
4653 assert( schema_init_done == 0 );
4655 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4656 res = register_syntax( &syntax_defs[i] );
4659 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4660 syntax_defs[i].sd_desc );
4665 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4666 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4667 mrule_defs[i].mrd_compat_syntaxes == NULL )
4670 "slap_schema_init: Ignoring unusable matching rule %s\n",
4671 mrule_defs[i].mrd_desc );
4675 res = register_matching_rule( &mrule_defs[i] );
4679 "slap_schema_init: Error registering matching rule %s\n",
4680 mrule_defs[i].mrd_desc );
4685 res = slap_schema_load();
4686 schema_init_done = 1;
4691 schema_destroy( void )
4700 if( schema_init_done ) {
4701 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
4702 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );