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_peek_tag( ber, &len );
116 /* Optional version */
118 tag = ber_skip_tag( ber, &len );
119 tag = ber_get_int( ber, &version );
120 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
122 tag = ber_get_int( ber, &i ); /* Serial */
123 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
124 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
125 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
126 ber_skip_data( ber, len );
127 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
128 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
129 ber_skip_data( ber, len );
130 tag = ber_skip_tag( ber, &len ); /* Validity */
131 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
132 ber_skip_data( ber, len );
133 tag = ber_skip_tag( ber, &len ); /* Subject DN */
134 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
135 ber_skip_data( ber, len );
136 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
137 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
138 ber_skip_data( ber, len );
139 tag = ber_skip_tag( ber, &len );
140 if ( tag == 0xa1 ) { /* issuerUniqueID */
141 if ( version < 1 ) return LDAP_INVALID_SYNTAX;
142 ber_skip_data( ber, len );
143 tag = ber_skip_tag( ber, &len );
145 if ( tag == 0xa2 ) { /* subjectUniqueID */
146 if ( version < 1 ) return LDAP_INVALID_SYNTAX;
147 ber_skip_data( ber, len );
148 tag = ber_skip_tag( ber, &len );
150 if ( tag == 0xa3 ) { /* Extensions */
151 if ( version < 2 ) return LDAP_INVALID_SYNTAX;
152 tag = ber_skip_tag( ber, &len );
153 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
154 ber_skip_data( ber, len );
155 tag = ber_skip_tag( ber, &len );
157 /* signatureAlgorithm */
158 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
159 ber_skip_data( ber, len );
160 tag = ber_skip_tag( ber, &len );
162 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
163 ber_skip_data( ber, len );
164 tag = ber_skip_tag( ber, &len );
165 /* Must be at end now */
166 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
176 struct berval *value,
177 void *assertedValue )
179 struct berval *asserted = (struct berval *) assertedValue;
180 int match = value->bv_len - asserted->bv_len;
183 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
191 octetStringOrderingMatch(
196 struct berval *value,
197 void *assertedValue )
199 struct berval *asserted = (struct berval *) assertedValue;
200 ber_len_t v_len = value->bv_len;
201 ber_len_t av_len = asserted->bv_len;
203 int match = memcmp( value->bv_val, asserted->bv_val,
204 (v_len < av_len ? v_len : av_len) );
206 if( match == 0 ) match = v_len - av_len;
214 HASH_CONTEXT *HASHcontext,
215 struct berval *prefix,
220 HASH_Init(HASHcontext);
221 if(prefix && prefix->bv_len > 0) {
222 HASH_Update(HASHcontext,
223 (unsigned char *)prefix->bv_val, prefix->bv_len);
225 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
226 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
227 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
233 HASH_CONTEXT *HASHcontext,
234 unsigned char *HASHdigest,
235 unsigned char *value,
238 HASH_CONTEXT ctx = *HASHcontext;
239 HASH_Update( &ctx, value, len );
240 HASH_Final( HASHdigest, &ctx );
243 /* Index generation function */
244 int octetStringIndexer(
249 struct berval *prefix,
257 HASH_CONTEXT HASHcontext;
258 unsigned char HASHdigest[HASH_BYTES];
259 struct berval digest;
260 digest.bv_val = (char *)HASHdigest;
261 digest.bv_len = sizeof(HASHdigest);
263 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
264 /* just count them */
267 /* we should have at least one value at this point */
270 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
272 slen = syntax->ssyn_oidlen;
273 mlen = mr->smr_oidlen;
275 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
276 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
277 hashIter( &HASHcontext, HASHdigest,
278 (unsigned char *)values[i].bv_val, values[i].bv_len );
279 ber_dupbv_x( &keys[i], &digest, ctx );
282 BER_BVZERO( &keys[i] );
289 /* Index generation function */
290 int octetStringFilter(
295 struct berval *prefix,
296 void * assertedValue,
302 HASH_CONTEXT HASHcontext;
303 unsigned char HASHdigest[HASH_BYTES];
304 struct berval *value = (struct berval *) assertedValue;
305 struct berval digest;
306 digest.bv_val = (char *)HASHdigest;
307 digest.bv_len = sizeof(HASHdigest);
309 slen = syntax->ssyn_oidlen;
310 mlen = mr->smr_oidlen;
312 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
314 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
315 hashIter( &HASHcontext, HASHdigest,
316 (unsigned char *)value->bv_val, value->bv_len );
318 ber_dupbv_x( keys, &digest, ctx );
319 BER_BVZERO( &keys[1] );
327 octetStringSubstringsMatch(
332 struct berval *value,
333 void *assertedValue )
336 SubstringsAssertion *sub = assertedValue;
337 struct berval left = *value;
341 /* Add up asserted input length */
342 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
343 inlen += sub->sa_initial.bv_len;
346 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
347 inlen += sub->sa_any[i].bv_len;
350 if ( !BER_BVISNULL( &sub->sa_final ) ) {
351 inlen += sub->sa_final.bv_len;
354 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
355 if ( inlen > left.bv_len ) {
360 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
361 sub->sa_initial.bv_len );
367 left.bv_val += sub->sa_initial.bv_len;
368 left.bv_len -= sub->sa_initial.bv_len;
369 inlen -= sub->sa_initial.bv_len;
372 if ( !BER_BVISNULL( &sub->sa_final ) ) {
373 if ( inlen > left.bv_len ) {
378 match = memcmp( sub->sa_final.bv_val,
379 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
380 sub->sa_final.bv_len );
386 left.bv_len -= sub->sa_final.bv_len;
387 inlen -= sub->sa_final.bv_len;
391 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
396 if ( inlen > left.bv_len ) {
397 /* not enough length */
402 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
406 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
413 idx = p - left.bv_val;
415 if ( idx >= left.bv_len ) {
416 /* this shouldn't happen */
423 if ( sub->sa_any[i].bv_len > left.bv_len ) {
424 /* not enough left */
429 match = memcmp( left.bv_val,
430 sub->sa_any[i].bv_val,
431 sub->sa_any[i].bv_len );
439 left.bv_val += sub->sa_any[i].bv_len;
440 left.bv_len -= sub->sa_any[i].bv_len;
441 inlen -= sub->sa_any[i].bv_len;
450 /* Substrings Index generation function */
452 octetStringSubstringsIndexer(
457 struct berval *prefix,
466 HASH_CONTEXT HCany, HCini, HCfin;
467 unsigned char HASHdigest[HASH_BYTES];
468 struct berval digest;
469 digest.bv_val = (char *)HASHdigest;
470 digest.bv_len = sizeof(HASHdigest);
474 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
475 /* count number of indices to generate */
476 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
477 if( values[i].bv_len >= index_substr_if_maxlen ) {
478 nkeys += index_substr_if_maxlen -
479 (index_substr_if_minlen - 1);
480 } else if( values[i].bv_len >= index_substr_if_minlen ) {
481 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
485 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
486 if( values[i].bv_len >= index_substr_any_len ) {
487 nkeys += values[i].bv_len - (index_substr_any_len - 1);
491 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
492 if( values[i].bv_len >= index_substr_if_maxlen ) {
493 nkeys += index_substr_if_maxlen -
494 (index_substr_if_minlen - 1);
495 } else if( values[i].bv_len >= index_substr_if_minlen ) {
496 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
502 /* no keys to generate */
507 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
509 slen = syntax->ssyn_oidlen;
510 mlen = mr->smr_oidlen;
512 if ( flags & SLAP_INDEX_SUBSTR_ANY )
513 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
514 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
515 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
516 if( flags & SLAP_INDEX_SUBSTR_FINAL )
517 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
520 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
523 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
524 ( values[i].bv_len >= index_substr_any_len ) )
526 max = values[i].bv_len - (index_substr_any_len - 1);
528 for( j=0; j<max; j++ ) {
529 hashIter( &HCany, HASHdigest,
530 (unsigned char *)&values[i].bv_val[j],
531 index_substr_any_len );
532 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
536 /* skip if too short */
537 if( values[i].bv_len < index_substr_if_minlen ) continue;
539 max = index_substr_if_maxlen < values[i].bv_len
540 ? index_substr_if_maxlen : values[i].bv_len;
542 for( j=index_substr_if_minlen; j<=max; j++ ) {
544 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
545 hashIter( &HCini, HASHdigest,
546 (unsigned char *)values[i].bv_val, j );
547 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
550 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
551 hashIter( &HCfin, HASHdigest,
552 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
553 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
560 BER_BVZERO( &keys[nkeys] );
571 octetStringSubstringsFilter (
576 struct berval *prefix,
577 void * assertedValue,
581 SubstringsAssertion *sa;
584 size_t slen, mlen, klen;
586 HASH_CONTEXT HASHcontext;
587 unsigned char HASHdigest[HASH_BYTES];
588 struct berval *value;
589 struct berval digest;
591 sa = (SubstringsAssertion *) assertedValue;
593 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
594 !BER_BVISNULL( &sa->sa_initial ) &&
595 sa->sa_initial.bv_len >= index_substr_if_minlen )
598 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
599 ( flags & SLAP_INDEX_SUBSTR_ANY ))
601 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
605 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
607 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
608 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
609 /* don't bother accounting with stepping */
610 nkeys += sa->sa_any[i].bv_len -
611 ( index_substr_any_len - 1 );
616 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
617 !BER_BVISNULL( &sa->sa_final ) &&
618 sa->sa_final.bv_len >= index_substr_if_minlen )
621 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
622 ( flags & SLAP_INDEX_SUBSTR_ANY ))
624 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
633 digest.bv_val = (char *)HASHdigest;
634 digest.bv_len = sizeof(HASHdigest);
636 slen = syntax->ssyn_oidlen;
637 mlen = mr->smr_oidlen;
639 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
642 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
643 !BER_BVISNULL( &sa->sa_initial ) &&
644 sa->sa_initial.bv_len >= index_substr_if_minlen )
646 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
647 value = &sa->sa_initial;
649 klen = index_substr_if_maxlen < value->bv_len
650 ? index_substr_if_maxlen : value->bv_len;
652 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
653 hashIter( &HASHcontext, HASHdigest,
654 (unsigned char *)value->bv_val, klen );
655 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
657 /* If initial is too long and we have subany indexed, use it
658 * to match the excess...
660 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
663 pre = SLAP_INDEX_SUBSTR_PREFIX;
664 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
665 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
667 hashIter( &HASHcontext, HASHdigest,
668 (unsigned char *)&value->bv_val[j], index_substr_any_len );
669 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
674 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
676 pre = SLAP_INDEX_SUBSTR_PREFIX;
677 klen = index_substr_any_len;
679 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
680 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
684 value = &sa->sa_any[i];
686 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
688 j <= value->bv_len - index_substr_any_len;
689 j += index_substr_any_step )
691 hashIter( &HASHcontext, HASHdigest,
692 (unsigned char *)&value->bv_val[j], klen );
693 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
698 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
699 !BER_BVISNULL( &sa->sa_final ) &&
700 sa->sa_final.bv_len >= index_substr_if_minlen )
702 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
703 value = &sa->sa_final;
705 klen = index_substr_if_maxlen < value->bv_len
706 ? index_substr_if_maxlen : value->bv_len;
708 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
709 hashIter( &HASHcontext, HASHdigest,
710 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
711 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
713 /* If final is too long and we have subany indexed, use it
714 * to match the excess...
716 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
719 pre = SLAP_INDEX_SUBSTR_PREFIX;
720 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
721 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
723 hashIter( &HASHcontext, HASHdigest,
724 (unsigned char *)&value->bv_val[j], index_substr_any_len );
725 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
731 BER_BVZERO( &keys[nkeys] );
748 /* very unforgiving validation, requires no normalization
749 * before simplistic matching
751 if( in->bv_len < 3 ) {
752 return LDAP_INVALID_SYNTAX;
755 /* RFC 4517 Section 3.3.2 Bit String:
756 * BitString = SQUOTE *binary-digit SQUOTE "B"
757 * binary-digit = "0" / "1"
759 * where SQUOTE [RFC4512] is
760 * SQUOTE = %x27 ; single quote ("'")
762 * Example: '0101111101'B
765 if( in->bv_val[0] != '\'' ||
766 in->bv_val[in->bv_len - 2] != '\'' ||
767 in->bv_val[in->bv_len - 1] != 'B' )
769 return LDAP_INVALID_SYNTAX;
772 for( i = in->bv_len - 3; i > 0; i-- ) {
773 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
774 return LDAP_INVALID_SYNTAX;
782 * Syntaxes from RFC 4517
787 A value of the Bit String syntax is a sequence of binary digits. The
788 LDAP-specific encoding of a value of this syntax is defined by the
791 BitString = SQUOTE *binary-digit SQUOTE "B"
793 binary-digit = "0" / "1"
795 The <SQUOTE> rule is defined in [MODELS].
800 The LDAP definition for the Bit String syntax is:
802 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
804 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
808 3.3.21. Name and Optional UID
810 A value of the Name and Optional UID syntax is the distinguished name
811 [MODELS] of an entity optionally accompanied by a unique identifier
812 that serves to differentiate the entity from others with an identical
815 The LDAP-specific encoding of a value of this syntax is defined by
818 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
820 The <BitString> rule is defined in Section 3.3.2. The
821 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
824 Note that although the '#' character may occur in the string
825 representation of a distinguished name, no additional escaping of
826 this character is performed when a <distinguishedName> is encoded in
827 a <NameAndOptionalUID>.
830 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
832 The LDAP definition for the Name and Optional UID syntax is:
834 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
836 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
843 1.4. Common ABNF Productions
846 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
848 SQUOTE = %x27 ; single quote ("'")
852 * Note: normalization strips any leading "0"s, unless the
853 * bit string is exactly "'0'B", so the normalized example,
854 * in slapd, would result in
856 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
858 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
859 * be escaped except when at the beginning of a value, the
860 * definition of Name and Optional UID appears to be flawed,
861 * because there is no clear means to determine whether the
862 * UID part is present or not.
866 * cn=Someone,dc=example,dc=com#'1'B
868 * could be either a NameAndOptionalUID with trailing UID, i.e.
870 * DN = "cn=Someone,dc=example,dc=com"
873 * or a NameAndOptionalUID with no trailing UID, and the AVA
874 * in the last RDN made of
877 * attributeValue = com#'1'B
879 * in fact "com#'1'B" is a valid IA5 string.
881 * As a consequence, current slapd code assumes that the
882 * presence of portions of a BitString at the end of the string
883 * representation of a NameAndOptionalUID means a BitString
884 * is expected, and cause an error otherwise. This is quite
885 * arbitrary, and might change in the future.
895 struct berval dn, uid;
897 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
899 ber_dupbv( &dn, in );
900 if( !dn.bv_val ) return LDAP_OTHER;
902 /* if there's a "#", try bitStringValidate()... */
903 uid.bv_val = strrchr( dn.bv_val, '#' );
904 if ( !BER_BVISNULL( &uid ) ) {
906 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
908 rc = bitStringValidate( NULL, &uid );
909 if ( rc == LDAP_SUCCESS ) {
910 /* in case of success, trim the UID,
911 * otherwise treat it as part of the DN */
912 dn.bv_len -= uid.bv_len + 1;
913 uid.bv_val[-1] = '\0';
917 rc = dnValidate( NULL, &dn );
919 ber_memfree( dn.bv_val );
930 assert( val != NULL );
931 assert( out != NULL );
934 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
936 if( BER_BVISEMPTY( val ) ) {
937 ber_dupbv_x( out, val, ctx );
939 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
940 return LDAP_INVALID_SYNTAX;
944 struct berval dnval = *val;
945 struct berval uidval = BER_BVNULL;
947 uidval.bv_val = strrchr( val->bv_val, '#' );
948 if ( !BER_BVISNULL( &uidval ) ) {
950 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
952 rc = bitStringValidate( NULL, &uidval );
954 if ( rc == LDAP_SUCCESS ) {
955 ber_dupbv_x( &dnval, val, ctx );
956 dnval.bv_len -= uidval.bv_len + 1;
957 dnval.bv_val[dnval.bv_len] = '\0';
960 BER_BVZERO( &uidval );
964 rc = dnPretty( syntax, &dnval, out, ctx );
965 if ( dnval.bv_val != val->bv_val ) {
966 slap_sl_free( dnval.bv_val, ctx );
968 if( rc != LDAP_SUCCESS ) {
972 if( !BER_BVISNULL( &uidval ) ) {
976 tmp = slap_sl_realloc( out->bv_val, out->bv_len
977 + STRLENOF( "#" ) + uidval.bv_len + 1,
980 ber_memfree_x( out->bv_val, ctx );
984 out->bv_val[out->bv_len++] = '#';
985 out->bv_val[out->bv_len++] = '\'';
987 got1 = uidval.bv_len < sizeof("'0'B");
988 for( i = 1; i < uidval.bv_len - 2; i++ ) {
989 c = uidval.bv_val[i];
992 if( got1 ) out->bv_val[out->bv_len++] = c;
996 out->bv_val[out->bv_len++] = c;
1001 out->bv_val[out->bv_len++] = '\'';
1002 out->bv_val[out->bv_len++] = 'B';
1003 out->bv_val[out->bv_len] = '\0';
1007 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1009 return LDAP_SUCCESS;
1013 uniqueMemberNormalize(
1018 struct berval *normalized,
1024 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1026 ber_dupbv_x( &out, val, ctx );
1027 if ( BER_BVISEMPTY( &out ) ) {
1031 struct berval uid = BER_BVNULL;
1033 uid.bv_val = strrchr( out.bv_val, '#' );
1034 if ( !BER_BVISNULL( &uid ) ) {
1036 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1038 rc = bitStringValidate( NULL, &uid );
1039 if ( rc == LDAP_SUCCESS ) {
1040 uid.bv_val[-1] = '\0';
1041 out.bv_len -= uid.bv_len + 1;
1047 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1049 if( rc != LDAP_SUCCESS ) {
1050 slap_sl_free( out.bv_val, ctx );
1051 return LDAP_INVALID_SYNTAX;
1054 if( !BER_BVISNULL( &uid ) ) {
1057 tmp = ch_realloc( normalized->bv_val,
1058 normalized->bv_len + uid.bv_len
1059 + STRLENOF("#") + 1 );
1060 if ( tmp == NULL ) {
1061 ber_memfree_x( normalized->bv_val, ctx );
1065 normalized->bv_val = tmp;
1067 /* insert the separator */
1068 normalized->bv_val[normalized->bv_len++] = '#';
1070 /* append the UID */
1071 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1072 uid.bv_val, uid.bv_len );
1073 normalized->bv_len += uid.bv_len;
1076 normalized->bv_val[normalized->bv_len] = '\0';
1079 slap_sl_free( out.bv_val, ctx );
1082 return LDAP_SUCCESS;
1091 struct berval *value,
1092 void *assertedValue )
1095 struct berval *asserted = (struct berval *) assertedValue;
1096 struct berval assertedDN = *asserted;
1097 struct berval assertedUID = BER_BVNULL;
1098 struct berval valueDN = *value;
1099 struct berval valueUID = BER_BVNULL;
1100 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1102 if ( !BER_BVISEMPTY( asserted ) ) {
1103 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1104 if ( !BER_BVISNULL( &assertedUID ) ) {
1105 assertedUID.bv_val++;
1106 assertedUID.bv_len = assertedDN.bv_len
1107 - ( assertedUID.bv_val - assertedDN.bv_val );
1109 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1110 assertedDN.bv_len -= assertedUID.bv_len + 1;
1113 BER_BVZERO( &assertedUID );
1118 if ( !BER_BVISEMPTY( value ) ) {
1120 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1121 if ( !BER_BVISNULL( &valueUID ) ) {
1123 valueUID.bv_len = valueDN.bv_len
1124 - ( valueUID.bv_val - valueDN.bv_val );
1126 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1127 valueDN.bv_len -= valueUID.bv_len + 1;
1130 BER_BVZERO( &valueUID );
1135 if( valueUID.bv_len && assertedUID.bv_len ) {
1136 match = valueUID.bv_len - assertedUID.bv_len;
1139 return LDAP_SUCCESS;
1142 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1145 return LDAP_SUCCESS;
1148 } else if ( !approx && valueUID.bv_len ) {
1151 return LDAP_SUCCESS;
1153 } else if ( !approx && assertedUID.bv_len ) {
1156 return LDAP_SUCCESS;
1159 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1163 uniqueMemberIndexer(
1168 struct berval *prefix,
1176 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1177 /* just count them */
1181 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1183 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1184 struct berval assertedDN = values[i];
1185 struct berval assertedUID = BER_BVNULL;
1187 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1188 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1189 if ( !BER_BVISNULL( &assertedUID ) ) {
1190 assertedUID.bv_val++;
1191 assertedUID.bv_len = assertedDN.bv_len
1192 - ( assertedUID.bv_val - assertedDN.bv_val );
1194 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1195 assertedDN.bv_len -= assertedUID.bv_len + 1;
1198 BER_BVZERO( &assertedUID );
1203 dnvalues[i] = assertedDN;
1205 BER_BVZERO( &dnvalues[i] );
1207 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1208 dnvalues, keysp, ctx );
1210 slap_sl_free( dnvalues, ctx );
1220 struct berval *prefix,
1221 void * assertedValue,
1225 struct berval *asserted = (struct berval *) assertedValue;
1226 struct berval assertedDN = *asserted;
1227 struct berval assertedUID = BER_BVNULL;
1229 if ( !BER_BVISEMPTY( asserted ) ) {
1230 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1231 if ( !BER_BVISNULL( &assertedUID ) ) {
1232 assertedUID.bv_val++;
1233 assertedUID.bv_len = assertedDN.bv_len
1234 - ( assertedUID.bv_val - assertedDN.bv_val );
1236 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1237 assertedDN.bv_len -= assertedUID.bv_len + 1;
1240 BER_BVZERO( &assertedUID );
1245 return octetStringFilter( use, flags, syntax, mr, prefix,
1246 &assertedDN, keysp, ctx );
1251 * Handling boolean syntax and matching is quite rigid.
1252 * A more flexible approach would be to allow a variety
1253 * of strings to be normalized and prettied into TRUE
1261 /* very unforgiving validation, requires no normalization
1262 * before simplistic matching
1265 if( in->bv_len == 4 ) {
1266 if( bvmatch( in, &slap_true_bv ) ) {
1267 return LDAP_SUCCESS;
1269 } else if( in->bv_len == 5 ) {
1270 if( bvmatch( in, &slap_false_bv ) ) {
1271 return LDAP_SUCCESS;
1275 return LDAP_INVALID_SYNTAX;
1284 struct berval *value,
1285 void *assertedValue )
1287 /* simplistic matching allowed by rigid validation */
1288 struct berval *asserted = (struct berval *) assertedValue;
1289 *matchp = value->bv_len != asserted->bv_len;
1290 return LDAP_SUCCESS;
1293 /*-------------------------------------------------------------------
1294 LDAP/X.500 string syntax / matching rules have a few oddities. This
1295 comment attempts to detail how slapd(8) treats them.
1298 StringSyntax X.500 LDAP Matching/Comments
1299 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1300 PrintableString subset subset i/e + ignore insignificant spaces
1301 PrintableString subset subset i/e + ignore insignificant spaces
1302 NumericString subset subset ignore all spaces
1303 IA5String ASCII ASCII i/e + ignore insignificant spaces
1304 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1306 TelephoneNumber subset subset i + ignore all spaces and "-"
1308 See RFC 4518 for details.
1312 In X.500(93), a directory string can be either a PrintableString,
1313 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1314 In later versions, more CHOICEs were added. In all cases the string
1317 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1318 A directory string cannot be zero length.
1320 For matching, there are both case ignore and exact rules. Both
1321 also require that "insignificant" spaces be ignored.
1322 spaces before the first non-space are ignored;
1323 spaces after the last non-space are ignored;
1324 spaces after a space are ignored.
1325 Note: by these rules (and as clarified in X.520), a string of only
1326 spaces is to be treated as if held one space, not empty (which
1327 would be a syntax error).
1330 In ASN.1, numeric string is just a string of digits and spaces
1331 and could be empty. However, in X.500, all attribute values of
1332 numeric string carry a non-empty constraint. For example:
1334 internationalISDNNumber ATTRIBUTE ::= {
1335 WITH SYNTAX InternationalISDNNumber
1336 EQUALITY MATCHING RULE numericStringMatch
1337 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1338 ID id-at-internationalISDNNumber }
1339 InternationalISDNNumber ::=
1340 NumericString (SIZE(1..ub-international-isdn-number))
1342 Unforunately, some assertion values are don't carry the same
1343 constraint (but its unclear how such an assertion could ever
1344 be true). In LDAP, there is one syntax (numericString) not two
1345 (numericString with constraint, numericString without constraint).
1346 This should be treated as numericString with non-empty constraint.
1347 Note that while someone may have no ISDN number, there are no ISDN
1348 numbers which are zero length.
1350 In matching, spaces are ignored.
1353 In ASN.1, Printable string is just a string of printable characters
1354 and can be empty. In X.500, semantics much like NumericString (see
1355 serialNumber for a like example) excepting uses insignificant space
1356 handling instead of ignore all spaces.
1359 Basically same as PrintableString. There are no examples in X.500,
1360 but same logic applies. So we require them to be non-empty as
1363 -------------------------------------------------------------------*/
1372 unsigned char *u = (unsigned char *)in->bv_val;
1374 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1375 /* directory strings cannot be empty */
1376 return LDAP_INVALID_SYNTAX;
1379 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1380 /* get the length indicated by the first byte */
1381 len = LDAP_UTF8_CHARLEN2( u, len );
1383 /* very basic checks */
1386 if( (u[5] & 0xC0) != 0x80 ) {
1387 return LDAP_INVALID_SYNTAX;
1390 if( (u[4] & 0xC0) != 0x80 ) {
1391 return LDAP_INVALID_SYNTAX;
1394 if( (u[3] & 0xC0) != 0x80 ) {
1395 return LDAP_INVALID_SYNTAX;
1398 if( (u[2] & 0xC0 )!= 0x80 ) {
1399 return LDAP_INVALID_SYNTAX;
1402 if( (u[1] & 0xC0) != 0x80 ) {
1403 return LDAP_INVALID_SYNTAX;
1406 /* CHARLEN already validated it */
1409 return LDAP_INVALID_SYNTAX;
1412 /* make sure len corresponds with the offset
1413 to the next character */
1414 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1418 return LDAP_INVALID_SYNTAX;
1421 return LDAP_SUCCESS;
1425 UTF8StringNormalize(
1430 struct berval *normalized,
1433 struct berval tmp, nvalue;
1437 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1439 if( BER_BVISNULL( val ) ) {
1440 /* assume we're dealing with a syntax (e.g., UTF8String)
1441 * which allows empty strings
1443 BER_BVZERO( normalized );
1444 return LDAP_SUCCESS;
1447 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1448 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1449 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1450 ? LDAP_UTF8_APPROX : 0;
1452 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1457 /* collapse spaces (in place) */
1459 nvalue.bv_val = tmp.bv_val;
1461 /* trim leading spaces? */
1462 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1463 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1465 for( i = 0; i < tmp.bv_len; i++) {
1466 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1467 if( wasspace++ == 0 ) {
1468 /* trim repeated spaces */
1469 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1473 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1477 if( !BER_BVISEMPTY( &nvalue ) ) {
1478 /* trim trailing space? */
1480 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1481 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1485 nvalue.bv_val[nvalue.bv_len] = '\0';
1488 /* string of all spaces is treated as one space */
1489 nvalue.bv_val[0] = ' ';
1490 nvalue.bv_val[1] = '\0';
1494 *normalized = nvalue;
1495 return LDAP_SUCCESS;
1499 directoryStringSubstringsMatch(
1504 struct berval *value,
1505 void *assertedValue )
1508 SubstringsAssertion *sub = assertedValue;
1509 struct berval left = *value;
1513 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1514 if ( sub->sa_initial.bv_len > left.bv_len ) {
1515 /* not enough left */
1520 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1521 sub->sa_initial.bv_len );
1527 left.bv_val += sub->sa_initial.bv_len;
1528 left.bv_len -= sub->sa_initial.bv_len;
1530 priorspace = ASCII_SPACE(
1531 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1534 if ( sub->sa_any ) {
1535 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1539 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1540 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1542 /* allow next space to match */
1549 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1553 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1554 /* not enough left */
1559 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1566 idx = p - left.bv_val;
1568 if ( idx >= left.bv_len ) {
1569 /* this shouldn't happen */
1576 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1577 /* not enough left */
1582 match = memcmp( left.bv_val,
1583 sub->sa_any[i].bv_val,
1584 sub->sa_any[i].bv_len );
1592 left.bv_val += sub->sa_any[i].bv_len;
1593 left.bv_len -= sub->sa_any[i].bv_len;
1595 priorspace = ASCII_SPACE(
1596 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1600 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1601 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1602 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1604 /* allow next space to match */
1609 if ( sub->sa_final.bv_len > left.bv_len ) {
1610 /* not enough left */
1615 match = memcmp( sub->sa_final.bv_val,
1616 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1617 sub->sa_final.bv_len );
1626 return LDAP_SUCCESS;
1629 #if defined(SLAPD_APPROX_INITIALS)
1630 # define SLAPD_APPROX_DELIMITER "._ "
1631 # define SLAPD_APPROX_WORDLEN 2
1633 # define SLAPD_APPROX_DELIMITER " "
1634 # define SLAPD_APPROX_WORDLEN 1
1643 struct berval *value,
1644 void *assertedValue )
1646 struct berval *nval, *assertv;
1647 char *val, **values, **words, *c;
1648 int i, count, len, nextchunk=0, nextavail=0;
1650 /* Yes, this is necessary */
1651 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1652 if( nval == NULL ) {
1654 return LDAP_SUCCESS;
1657 /* Yes, this is necessary */
1658 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1659 NULL, LDAP_UTF8_APPROX, NULL );
1660 if( assertv == NULL ) {
1663 return LDAP_SUCCESS;
1666 /* Isolate how many words there are */
1667 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1668 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1669 if ( c == NULL ) break;
1674 /* Get a phonetic copy of each word */
1675 words = (char **)ch_malloc( count * sizeof(char *) );
1676 values = (char **)ch_malloc( count * sizeof(char *) );
1677 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1679 values[i] = phonetic(c);
1682 /* Work through the asserted value's words, to see if at least some
1683 of the words are there, in the same order. */
1685 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1686 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1691 #if defined(SLAPD_APPROX_INITIALS)
1692 else if( len == 1 ) {
1693 /* Single letter words need to at least match one word's initial */
1694 for( i=nextavail; i<count; i++ )
1695 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1702 /* Isolate the next word in the asserted value and phonetic it */
1703 assertv->bv_val[nextchunk+len] = '\0';
1704 val = phonetic( assertv->bv_val + nextchunk );
1706 /* See if this phonetic chunk is in the remaining words of *value */
1707 for( i=nextavail; i<count; i++ ){
1708 if( !strcmp( val, values[i] ) ){
1716 /* This chunk in the asserted value was NOT within the *value. */
1722 /* Go on to the next word in the asserted value */
1726 /* If some of the words were seen, call it a match */
1727 if( nextavail > 0 ) {
1734 /* Cleanup allocs */
1735 ber_bvfree( assertv );
1736 for( i=0; i<count; i++ ) {
1737 ch_free( values[i] );
1743 return LDAP_SUCCESS;
1752 struct berval *prefix,
1758 int i,j, len, wordcount, keycount=0;
1759 struct berval *newkeys;
1760 BerVarray keys=NULL;
1762 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1763 struct berval val = BER_BVNULL;
1764 /* Yes, this is necessary */
1765 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1766 assert( !BER_BVISNULL( &val ) );
1768 /* Isolate how many words there are. There will be a key for each */
1769 for( wordcount = 0, c = val.bv_val; *c; c++) {
1770 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1771 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1773 if (*c == '\0') break;
1777 /* Allocate/increase storage to account for new keys */
1778 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1779 * sizeof(struct berval) );
1780 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1781 if( keys ) ch_free( keys );
1784 /* Get a phonetic copy of each word */
1785 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1787 if( len < SLAPD_APPROX_WORDLEN ) continue;
1788 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1793 ber_memfree( val.bv_val );
1795 BER_BVZERO( &keys[keycount] );
1798 return LDAP_SUCCESS;
1807 struct berval *prefix,
1808 void * assertedValue,
1817 /* Yes, this is necessary */
1818 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1819 NULL, LDAP_UTF8_APPROX, NULL );
1820 if( val == NULL || BER_BVISNULL( val ) ) {
1821 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1822 BER_BVZERO( &keys[0] );
1825 return LDAP_SUCCESS;
1828 /* Isolate how many words there are. There will be a key for each */
1829 for( count = 0,c = val->bv_val; *c; c++) {
1830 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1831 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1833 if (*c == '\0') break;
1837 /* Allocate storage for new keys */
1838 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1840 /* Get a phonetic copy of each word */
1841 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1843 if( len < SLAPD_APPROX_WORDLEN ) continue;
1844 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1850 BER_BVZERO( &keys[count] );
1853 return LDAP_SUCCESS;
1856 /* Remove all spaces and '-' characters */
1858 telephoneNumberNormalize(
1863 struct berval *normalized,
1868 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1870 /* validator should have refused an empty string */
1871 assert( !BER_BVISEMPTY( val ) );
1873 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1875 for( p = val->bv_val; *p; p++ ) {
1876 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1882 normalized->bv_len = q - normalized->bv_val;
1884 if( BER_BVISEMPTY( normalized ) ) {
1885 slap_sl_free( normalized->bv_val, ctx );
1886 BER_BVZERO( normalized );
1887 return LDAP_INVALID_SYNTAX;
1890 return LDAP_SUCCESS;
1898 struct berval val = *in;
1900 if( BER_BVISEMPTY( &val ) ) {
1901 /* disallow empty strings */
1902 return LDAP_INVALID_SYNTAX;
1905 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1906 if ( val.bv_len == 1 ) {
1907 return LDAP_SUCCESS;
1910 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1917 while ( OID_LEADCHAR( val.bv_val[0] )) {
1921 if ( val.bv_len == 0 ) {
1922 return LDAP_SUCCESS;
1926 if( !OID_SEPARATOR( val.bv_val[0] )) {
1934 return LDAP_INVALID_SYNTAX;
1943 struct berval val = *in;
1945 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1947 if ( val.bv_val[0] == '-' ) {
1951 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1952 return LDAP_INVALID_SYNTAX;
1955 if( val.bv_val[0] == '0' ) { /* "-0" */
1956 return LDAP_INVALID_SYNTAX;
1959 } else if ( val.bv_val[0] == '0' ) {
1960 if( val.bv_len > 1 ) { /* "0<more>" */
1961 return LDAP_INVALID_SYNTAX;
1964 return LDAP_SUCCESS;
1967 for( i=0; i < val.bv_len; i++ ) {
1968 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1969 return LDAP_INVALID_SYNTAX;
1973 return LDAP_SUCCESS;
1982 struct berval *value,
1983 void *assertedValue )
1985 struct berval *asserted = (struct berval *) assertedValue;
1986 int vsign = 1, asign = 1; /* default sign = '+' */
1991 if( v.bv_val[0] == '-' ) {
1997 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2000 if( a.bv_val[0] == '-' ) {
2006 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2008 match = vsign - asign;
2010 match = ( v.bv_len != a.bv_len
2011 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2012 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2013 if( vsign < 0 ) match = -match;
2017 return LDAP_SUCCESS;
2021 countryStringValidate(
2023 struct berval *val )
2025 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2027 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2028 return LDAP_INVALID_SYNTAX;
2030 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2031 return LDAP_INVALID_SYNTAX;
2034 return LDAP_SUCCESS;
2038 printableStringValidate(
2040 struct berval *val )
2044 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2046 for(i=0; i < val->bv_len; i++) {
2047 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2048 return LDAP_INVALID_SYNTAX;
2052 return LDAP_SUCCESS;
2056 printablesStringValidate(
2058 struct berval *val )
2062 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2064 for(i=0,len=0; i < val->bv_len; i++) {
2065 int c = val->bv_val[i];
2069 return LDAP_INVALID_SYNTAX;
2073 } else if ( SLAP_PRINTABLE(c) ) {
2076 return LDAP_INVALID_SYNTAX;
2081 return LDAP_INVALID_SYNTAX;
2084 return LDAP_SUCCESS;
2090 struct berval *val )
2094 for(i=0; i < val->bv_len; i++) {
2095 if( !LDAP_ASCII(val->bv_val[i]) ) {
2096 return LDAP_INVALID_SYNTAX;
2100 return LDAP_SUCCESS;
2109 struct berval *normalized,
2113 int casefold = !SLAP_MR_ASSOCIATED( mr,
2114 slap_schema.si_mr_caseExactIA5Match );
2116 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2120 /* Ignore initial whitespace */
2121 while ( ASCII_SPACE( *p ) ) p++;
2123 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2124 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2125 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2126 normalized->bv_val[normalized->bv_len] = '\0';
2128 p = q = normalized->bv_val;
2131 if ( ASCII_SPACE( *p ) ) {
2134 /* Ignore the extra whitespace */
2135 while ( ASCII_SPACE( *p ) ) {
2139 } else if ( casefold ) {
2140 /* Most IA5 rules require casefolding */
2141 *q++ = TOLOWER(*p); p++;
2148 assert( normalized->bv_val <= p );
2152 * If the string ended in space, backup the pointer one
2153 * position. One is enough because the above loop collapsed
2154 * all whitespace to a single space.
2156 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2158 /* null terminate */
2161 normalized->bv_len = q - normalized->bv_val;
2163 return LDAP_SUCCESS;
2172 if( in->bv_len != 36 ) {
2173 return LDAP_INVALID_SYNTAX;
2176 for( i=0; i<36; i++ ) {
2182 if( in->bv_val[i] != '-' ) {
2183 return LDAP_INVALID_SYNTAX;
2187 if( !ASCII_HEX( in->bv_val[i]) ) {
2188 return LDAP_INVALID_SYNTAX;
2193 return LDAP_SUCCESS;
2204 int rc=LDAP_INVALID_SYNTAX;
2206 assert( in != NULL );
2207 assert( out != NULL );
2209 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2212 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2214 for( i=0; i<36; i++ ) {
2220 if( in->bv_val[i] != '-' ) {
2223 out->bv_val[i] = '-';
2227 if( !ASCII_HEX( in->bv_val[i]) ) {
2230 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2235 out->bv_val[ out->bv_len ] = '\0';
2239 slap_sl_free( out->bv_val, ctx );
2252 struct berval *normalized,
2255 unsigned char octet = '\0';
2258 normalized->bv_len = 16;
2259 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2261 for( i=0, j=0; i<36; i++ ) {
2262 unsigned char nibble;
2263 if( val->bv_val[i] == '-' ) {
2266 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2267 nibble = val->bv_val[i] - '0';
2269 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2270 nibble = val->bv_val[i] - ('a'-10);
2272 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2273 nibble = val->bv_val[i] - ('A'-10);
2276 slap_sl_free( normalized->bv_val, ctx );
2277 return LDAP_INVALID_SYNTAX;
2282 normalized->bv_val[j>>1] = octet;
2284 octet = nibble << 4;
2289 normalized->bv_val[normalized->bv_len] = 0;
2290 return LDAP_SUCCESS;
2296 numericStringValidate(
2302 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2304 for(i=0; i < in->bv_len; i++) {
2305 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2306 return LDAP_INVALID_SYNTAX;
2310 return LDAP_SUCCESS;
2314 numericStringNormalize(
2319 struct berval *normalized,
2322 /* removal all spaces */
2325 assert( !BER_BVISEMPTY( val ) );
2327 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2330 q = normalized->bv_val;
2333 if ( ASCII_SPACE( *p ) ) {
2334 /* Ignore whitespace */
2341 /* we should have copied no more then is in val */
2342 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2344 /* null terminate */
2347 normalized->bv_len = q - normalized->bv_val;
2349 if( BER_BVISEMPTY( normalized ) ) {
2350 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2351 normalized->bv_val[0] = ' ';
2352 normalized->bv_val[1] = '\0';
2353 normalized->bv_len = 1;
2356 return LDAP_SUCCESS;
2360 * Integer conversion macros that will use the largest available
2363 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2364 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2365 # define SLAP_LONG long long
2367 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2368 # define SLAP_LONG long
2369 #endif /* HAVE_STRTOLL ... */
2377 struct berval *value,
2378 void *assertedValue )
2380 SLAP_LONG lValue, lAssertedValue;
2383 /* safe to assume integers are NUL terminated? */
2384 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2385 if( errno == ERANGE )
2387 return LDAP_CONSTRAINT_VIOLATION;
2390 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2392 if( errno == ERANGE )
2394 return LDAP_CONSTRAINT_VIOLATION;
2397 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2398 return LDAP_SUCCESS;
2407 struct berval *value,
2408 void *assertedValue )
2410 SLAP_LONG lValue, lAssertedValue;
2413 /* safe to assume integers are NUL terminated? */
2414 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2415 if( errno == ERANGE )
2417 return LDAP_CONSTRAINT_VIOLATION;
2420 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2422 if( errno == ERANGE )
2424 return LDAP_CONSTRAINT_VIOLATION;
2427 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2428 return LDAP_SUCCESS;
2432 serialNumberAndIssuerValidate(
2438 struct berval sn, i;
2440 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2443 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2445 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2446 /* Parse old format */
2447 i.bv_val = ber_bvchr( in, '$' );
2448 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2450 sn.bv_val = in->bv_val;
2451 sn.bv_len = i.bv_val - in->bv_val;
2454 i.bv_len = in->bv_len - (sn.bv_len + 1);
2456 /* eat leading zeros */
2457 for( n=0; n < (sn.bv_len-1); n++ ) {
2458 if( sn.bv_val[n] != '0' ) break;
2463 for( n=0; n < sn.bv_len; n++ ) {
2464 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2468 /* Parse GSER format */
2469 int havesn=0,haveissuer=0;
2470 struct berval x = *in;
2474 /* eat leading spaces */
2475 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2479 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2480 return LDAP_INVALID_SYNTAX;
2483 /* should be at issuer or serialNumber NamedValue */
2484 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2486 x.bv_val += STRLENOF("issuer");
2487 x.bv_len -= STRLENOF("issuer");
2489 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2490 x.bv_val++; x.bv_len--;
2492 /* eat leading spaces */
2493 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2497 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2498 x.bv_val++; x.bv_len--;
2500 i.bv_val = x.bv_val;
2503 for( ; i.bv_len < x.bv_len; ) {
2504 if ( i.bv_val[i.bv_len] != '"' ) {
2508 if ( i.bv_val[i.bv_len+1] == '"' ) {
2515 x.bv_val += i.bv_len+1;
2516 x.bv_len -= i.bv_len+1;
2518 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2519 return LDAP_INVALID_SYNTAX;
2524 } else if( strncasecmp( x.bv_val, "serialNumber",
2525 STRLENOF("serialNumber")) == 0 )
2527 /* parse serialNumber */
2529 x.bv_val += STRLENOF("serialNumber");
2530 x.bv_len -= STRLENOF("serialNumber");
2532 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2533 x.bv_val++; x.bv_len--;
2535 /* eat leading spaces */
2536 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2540 sn.bv_val = x.bv_val;
2543 if( sn.bv_val[0] == '-' ) {
2548 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2549 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2552 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2553 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2554 return LDAP_INVALID_SYNTAX;
2557 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2559 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2560 return LDAP_INVALID_SYNTAX;
2565 } else return LDAP_INVALID_SYNTAX;
2567 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2568 x.bv_val++; x.bv_len--;
2571 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2575 /* should be at remaining NamedValue */
2576 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2577 STRLENOF("issuer" )) == 0 ))
2580 x.bv_val += STRLENOF("issuer");
2581 x.bv_len -= STRLENOF("issuer");
2583 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2584 x.bv_val++; x.bv_len--;
2586 /* eat leading spaces */
2587 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2591 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2592 x.bv_val++; x.bv_len--;
2594 i.bv_val = x.bv_val;
2597 for( ; i.bv_len < x.bv_len; ) {
2598 if ( i.bv_val[i.bv_len] != '"' ) {
2602 if ( i.bv_val[i.bv_len+1] == '"' ) {
2609 x.bv_val += i.bv_len+1;
2610 x.bv_len -= i.bv_len+1;
2612 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2613 STRLENOF("serialNumber")) == 0 ))
2615 /* parse serialNumber */
2617 x.bv_val += STRLENOF("serialNumber");
2618 x.bv_len -= STRLENOF("serialNumber");
2620 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2621 x.bv_val++; x.bv_len--;
2623 /* eat leading spaces */
2624 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2628 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2629 x.bv_val++; x.bv_len--;
2631 sn.bv_val = x.bv_val;
2634 if( sn.bv_val[0] == '-' ) {
2639 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2640 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2643 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2644 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2645 return LDAP_INVALID_SYNTAX;
2648 x.bv_val += sn.bv_len;
2649 x.bv_len -= sn.bv_len;
2651 } else return LDAP_INVALID_SYNTAX;
2653 /* eat trailing spaces */
2654 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2658 /* should have no characters left... */
2659 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2662 /* validate DN -- doesn't handle double dquote */
2663 rc = dnValidate( NULL, &i );
2664 if( rc ) return LDAP_INVALID_SYNTAX;
2666 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2668 return LDAP_SUCCESS;
2672 serialNumberAndIssuerPretty(
2680 struct berval sn, i, ni;
2682 assert( in != NULL );
2683 assert( out != NULL );
2685 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2688 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2690 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2691 /* Parse old format */
2692 i.bv_val = ber_bvchr( in, '$' );
2693 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2695 sn.bv_val = in->bv_val;
2696 sn.bv_len = i.bv_val - in->bv_val;
2699 i.bv_len = in->bv_len - (sn.bv_len + 1);
2701 /* eat leading zeros */
2702 for( n=0; n < (sn.bv_len-1); n++ ) {
2703 if( sn.bv_val[n] != '0' ) break;
2708 for( n=0; n < sn.bv_len; n++ ) {
2709 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2713 /* Parse GSER format */
2714 int havesn=0,haveissuer=0;
2715 struct berval x = *in;
2719 /* eat leading spaces */
2720 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2724 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2725 return LDAP_INVALID_SYNTAX;
2728 /* should be at issuer or serialNumber NamedValue */
2729 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2731 x.bv_val += STRLENOF("issuer");
2732 x.bv_len -= STRLENOF("issuer");
2734 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2735 x.bv_val++; x.bv_len--;
2737 /* eat leading spaces */
2738 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2742 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2743 x.bv_val++; x.bv_len--;
2745 i.bv_val = x.bv_val;
2748 for( ; i.bv_len < x.bv_len; ) {
2749 if ( i.bv_val[i.bv_len] != '"' ) {
2753 if ( i.bv_val[i.bv_len+1] == '"' ) {
2760 x.bv_val += i.bv_len+1;
2761 x.bv_len -= i.bv_len+1;
2763 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2764 return LDAP_INVALID_SYNTAX;
2769 } else if( strncasecmp( x.bv_val, "serialNumber",
2770 STRLENOF("serialNumber")) == 0 )
2772 /* parse serialNumber */
2774 x.bv_val += STRLENOF("serialNumber");
2775 x.bv_len -= STRLENOF("serialNumber");
2777 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2778 x.bv_val++; x.bv_len--;
2780 /* eat leading spaces */
2781 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2785 sn.bv_val = x.bv_val;
2788 if( sn.bv_val[0] == '-' ) {
2793 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2794 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2797 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2798 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2799 return LDAP_INVALID_SYNTAX;
2802 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2804 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2805 return LDAP_INVALID_SYNTAX;
2810 } else return LDAP_INVALID_SYNTAX;
2812 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2813 x.bv_val++; x.bv_len--;
2816 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2820 /* should be at remaining NamedValue */
2821 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2822 STRLENOF("issuer" )) == 0 ))
2825 x.bv_val += STRLENOF("issuer");
2826 x.bv_len -= STRLENOF("issuer");
2828 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2829 x.bv_val++; x.bv_len--;
2831 /* eat leading spaces */
2832 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2836 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2837 x.bv_val++; x.bv_len--;
2839 i.bv_val = x.bv_val;
2842 for( ; i.bv_len < x.bv_len; ) {
2843 if ( i.bv_val[i.bv_len] != '"' ) {
2847 if ( i.bv_val[i.bv_len+1] == '"' ) {
2854 x.bv_val += i.bv_len+1;
2855 x.bv_len -= i.bv_len+1;
2857 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2858 STRLENOF("serialNumber")) == 0 ))
2860 /* parse serialNumber */
2862 x.bv_val += STRLENOF("serialNumber");
2863 x.bv_len -= STRLENOF("serialNumber");
2865 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2866 x.bv_val++; x.bv_len--;
2868 /* eat leading spaces */
2869 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2873 sn.bv_val = x.bv_val;
2876 if( sn.bv_val[0] == '-' ) {
2881 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2882 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2885 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2886 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2887 return LDAP_INVALID_SYNTAX;
2890 x.bv_val += sn.bv_len;
2891 x.bv_len -= sn.bv_len;
2893 } else return LDAP_INVALID_SYNTAX;
2895 /* eat trailing spaces */
2896 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2900 /* should have no characters left... */
2901 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2903 ber_dupbv_x( &ni, &i, ctx );
2906 /* need to handle double dquotes here */
2909 rc = dnPretty( syntax, &i, &ni, ctx );
2911 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2912 slap_sl_free( i.bv_val, ctx );
2915 if( rc ) return LDAP_INVALID_SYNTAX;
2917 /* make room from sn + "$" */
2918 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
2919 + sn.bv_len + ni.bv_len;
2920 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2922 if( out->bv_val == NULL ) {
2924 slap_sl_free( ni.bv_val, ctx );
2929 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
2930 STRLENOF("{ serialNumber "));
2931 n = STRLENOF("{ serialNumber ");
2933 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
2936 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
2937 n += STRLENOF(", issuer \"");
2939 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
2942 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
2943 n += STRLENOF("\" }");
2945 out->bv_val[n] = '\0';
2947 assert( n == out->bv_len );
2949 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2950 out->bv_val, 0, 0 );
2952 slap_sl_free( ni.bv_val, ctx );
2954 return LDAP_SUCCESS;
2958 * This routine is called by certificateExactNormalize when
2959 * certificateExactNormalize receives a search string instead of
2960 * a certificate. This routine checks if the search value is valid
2961 * and then returns the normalized value
2964 serialNumberAndIssuerNormalize(
2974 struct berval sn, i, ni;
2976 assert( in != NULL );
2977 assert( out != NULL );
2979 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2982 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2984 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2985 /* Parse old format */
2986 i.bv_val = ber_bvchr( in, '$' );
2987 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2989 sn.bv_val = in->bv_val;
2990 sn.bv_len = i.bv_val - in->bv_val;
2993 i.bv_len = in->bv_len - (sn.bv_len + 1);
2995 /* eat leading zeros */
2996 for( n=0; n < (sn.bv_len-1); n++ ) {
2997 if( sn.bv_val[n] != '0' ) break;
3002 for( n=0; n < sn.bv_len; n++ ) {
3003 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3007 /* Parse GSER format */
3008 int havesn=0,haveissuer=0;
3009 struct berval x = *in;
3013 /* eat leading spaces */
3014 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3018 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3019 return LDAP_INVALID_SYNTAX;
3022 /* should be at issuer or serialNumber NamedValue */
3023 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3025 x.bv_val += STRLENOF("issuer");
3026 x.bv_len -= STRLENOF("issuer");
3028 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3029 x.bv_val++; x.bv_len--;
3031 /* eat leading spaces */
3032 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3036 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3037 x.bv_val++; x.bv_len--;
3039 i.bv_val = x.bv_val;
3042 for( ; i.bv_len < x.bv_len; ) {
3043 if ( i.bv_val[i.bv_len] != '"' ) {
3047 if ( i.bv_val[i.bv_len+1] == '"' ) {
3054 x.bv_val += i.bv_len+1;
3055 x.bv_len -= i.bv_len+1;
3057 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3058 return LDAP_INVALID_SYNTAX;
3063 } else if( strncasecmp( x.bv_val, "serialNumber",
3064 STRLENOF("serialNumber")) == 0 )
3066 /* parse serialNumber */
3068 x.bv_val += STRLENOF("serialNumber");
3069 x.bv_len -= STRLENOF("serialNumber");
3071 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3072 x.bv_val++; x.bv_len--;
3074 /* eat leading spaces */
3075 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3079 sn.bv_val = x.bv_val;
3082 if( sn.bv_val[0] == '-' ) {
3087 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3088 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3091 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3092 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3093 return LDAP_INVALID_SYNTAX;
3096 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3098 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3099 return LDAP_INVALID_SYNTAX;
3104 } else return LDAP_INVALID_SYNTAX;
3106 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3107 x.bv_val++; x.bv_len--;
3110 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3114 /* should be at remaining NamedValue */
3115 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3116 STRLENOF("issuer" )) == 0 ))
3119 x.bv_val += STRLENOF("issuer");
3120 x.bv_len -= STRLENOF("issuer");
3122 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3123 x.bv_val++; x.bv_len--;
3125 /* eat leading spaces */
3126 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3130 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3131 x.bv_val++; x.bv_len--;
3133 i.bv_val = x.bv_val;
3136 for( ; i.bv_len < x.bv_len; ) {
3137 if ( i.bv_val[i.bv_len] != '"' ) {
3141 if ( i.bv_val[i.bv_len+1] == '"' ) {
3148 x.bv_val += i.bv_len+1;
3149 x.bv_len -= i.bv_len+1;
3151 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3152 STRLENOF("serialNumber")) == 0 ))
3154 /* parse serialNumber */
3156 x.bv_val += STRLENOF("serialNumber");
3157 x.bv_len -= STRLENOF("serialNumber");
3159 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3160 x.bv_val++; x.bv_len--;
3162 /* eat leading spaces */
3163 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3167 sn.bv_val = x.bv_val;
3170 if( sn.bv_val[0] == '-' ) {
3175 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3176 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3179 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3180 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3181 return LDAP_INVALID_SYNTAX;
3184 x.bv_val += sn.bv_len;
3185 x.bv_len -= sn.bv_len;
3187 } else return LDAP_INVALID_SYNTAX;
3189 /* eat trailing spaces */
3190 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3194 /* should have no characters left... */
3195 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3197 ber_dupbv_x( &ni, &i, ctx );
3200 /* need to handle double dquotes here */
3203 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3205 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3206 slap_sl_free( i.bv_val, ctx );
3209 if( rc ) return LDAP_INVALID_SYNTAX;
3211 /* make room from sn + "$" */
3212 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3213 + sn.bv_len + ni.bv_len;
3214 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3216 if( out->bv_val == NULL ) {
3218 slap_sl_free( ni.bv_val, ctx );
3223 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3224 STRLENOF( "{ serialNumber " ));
3225 n = STRLENOF( "{ serialNumber " );
3227 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3230 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3231 n += STRLENOF( ", issuer \"" );
3233 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3236 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3237 n += STRLENOF( "\" }" );
3239 out->bv_val[n] = '\0';
3241 assert( n == out->bv_len );
3243 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3244 out->bv_val, 0, 0 );
3246 slap_sl_free( ni.bv_val, ctx );
3248 return LDAP_SUCCESS;
3252 certificateExactNormalize(
3257 struct berval *normalized,
3260 BerElementBuffer berbuf;
3261 BerElement *ber = (BerElement *)&berbuf;
3266 ber_len_t seriallen;
3267 struct berval issuer_dn = BER_BVNULL, bvdn;
3269 int rc = LDAP_INVALID_SYNTAX;
3271 if( BER_BVISEMPTY( val ) ) goto done;
3273 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3274 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3277 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3279 ber_init2( ber, val, LBER_USE_DER );
3280 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3281 tag = ber_skip_tag( ber, &len ); /* Sequence */
3282 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3283 if ( tag == 0xa0 ) {
3284 tag = ber_skip_tag( ber, &len );
3285 tag = ber_get_int( ber, &i ); /* version */
3287 ber_get_int( ber, &i ); /* serial */
3289 seriallen = snprintf( serial, sizeof(serial), "%d", i );
3290 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3291 ber_skip_data( ber, len );
3292 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3293 len = ber_ptrlen( ber );
3294 bvdn.bv_val = val->bv_val + len;
3295 bvdn.bv_len = val->bv_len - len;
3297 rc = dnX509normalize( &bvdn, &issuer_dn );
3298 if( rc != LDAP_SUCCESS ) goto done;
3300 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3301 + seriallen + issuer_dn.bv_len;
3302 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3304 p = (unsigned char *)normalized->bv_val;
3306 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3307 p += STRLENOF( "{ serialNumber " );
3309 AC_MEMCPY(p, serial, seriallen);
3312 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3313 p += STRLENOF( ", issuer \"" );
3315 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3316 p += issuer_dn.bv_len;
3318 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3319 p += STRLENOF( "\" }" );
3323 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3324 normalized->bv_val, NULL, NULL );
3329 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
3335 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3336 /* slight optimization - does not need the start parameter */
3337 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3342 check_time_syntax (struct berval *val,
3345 struct berval *fraction)
3348 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3349 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3350 * GeneralizedTime supports leap seconds, UTCTime does not.
3352 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3353 static const int mdays[2][12] = {
3354 /* non-leap years */
3355 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3357 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3360 int part, c, c1, c2, tzoffset, leapyear = 0;
3363 e = p + val->bv_len;
3365 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3366 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3368 for (part = start; part < 7 && p < e; part++) {
3370 if (!ASCII_DIGIT(c1)) {
3375 return LDAP_INVALID_SYNTAX;
3378 if (!ASCII_DIGIT(c)) {
3379 return LDAP_INVALID_SYNTAX;
3381 c += c1 * 10 - '0' * 11;
3382 if ((part | 1) == 3) {
3385 return LDAP_INVALID_SYNTAX;
3388 if (c >= ceiling[part]) {
3389 if (! (c == 60 && part == 6 && start == 0))
3390 return LDAP_INVALID_SYNTAX;
3394 if (part < 5 + start) {
3395 return LDAP_INVALID_SYNTAX;
3397 for (; part < 9; part++) {
3401 /* leapyear check for the Gregorian calendar (year>1581) */
3402 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3406 if (parts[3] >= mdays[leapyear][parts[2]]) {
3407 return LDAP_INVALID_SYNTAX;
3411 fraction->bv_val = p;
3412 fraction->bv_len = 0;
3413 if (p < e && (*p == '.' || *p == ',')) {
3415 while (++p < e && ASCII_DIGIT(*p)) {
3418 if (p - fraction->bv_val == 1) {
3419 return LDAP_INVALID_SYNTAX;
3421 for (end_num = p; end_num[-1] == '0'; --end_num) {
3424 c = end_num - fraction->bv_val;
3425 if (c != 1) fraction->bv_len = c;
3431 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3437 return LDAP_INVALID_SYNTAX;
3443 for (part = 7; part < 9 && p < e; part++) {
3445 if (!ASCII_DIGIT(c1)) {
3450 return LDAP_INVALID_SYNTAX;
3453 if (!ASCII_DIGIT(c2)) {
3454 return LDAP_INVALID_SYNTAX;
3456 parts[part] = c1 * 10 + c2 - '0' * 11;
3457 if (parts[part] >= ceiling[part]) {
3458 return LDAP_INVALID_SYNTAX;
3461 if (part < 8 + start) {
3462 return LDAP_INVALID_SYNTAX;
3465 if (tzoffset == '-') {
3466 /* negative offset to UTC, ie west of Greenwich */
3467 parts[4] += parts[7];
3468 parts[5] += parts[8];
3469 /* offset is just hhmm, no seconds */
3470 for (part = 6; --part >= 0; ) {
3474 c = mdays[leapyear][parts[2]];
3476 if (parts[part] >= c) {
3478 return LDAP_INVALID_SYNTAX;
3483 } else if (part != 5) {
3488 /* positive offset to UTC, ie east of Greenwich */
3489 parts[4] -= parts[7];
3490 parts[5] -= parts[8];
3491 for (part = 6; --part >= 0; ) {
3492 if (parts[part] < 0) {
3494 return LDAP_INVALID_SYNTAX;
3499 /* make first arg to % non-negative */
3500 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3505 } else if (part != 5) {
3512 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3515 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3522 struct berval *normalized )
3526 rc = check_time_syntax(val, 1, parts, NULL);
3527 if (rc != LDAP_SUCCESS) {
3531 normalized->bv_val = ch_malloc( 14 );
3532 if ( normalized->bv_val == NULL ) {
3533 return LBER_ERROR_MEMORY;
3536 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3537 parts[1], parts[2] + 1, parts[3] + 1,
3538 parts[4], parts[5], parts[6] );
3539 normalized->bv_len = 13;
3541 return LDAP_SUCCESS;
3551 return check_time_syntax(in, 1, parts, NULL);
3554 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3557 generalizedTimeValidate(
3562 struct berval fraction;
3563 return check_time_syntax(in, 0, parts, &fraction);
3567 generalizedTimeNormalize(
3572 struct berval *normalized,
3577 struct berval fraction;
3579 rc = check_time_syntax(val, 0, parts, &fraction);
3580 if (rc != LDAP_SUCCESS) {
3584 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3585 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3586 if ( BER_BVISNULL( normalized ) ) {
3587 return LBER_ERROR_MEMORY;
3590 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3591 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3592 parts[4], parts[5], parts[6] );
3593 if ( !BER_BVISEMPTY( &fraction ) ) {
3594 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3595 fraction.bv_val, fraction.bv_len );
3596 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3598 strcpy( normalized->bv_val + len-1, "Z" );
3599 normalized->bv_len = len;
3601 return LDAP_SUCCESS;
3605 generalizedTimeOrderingMatch(
3610 struct berval *value,
3611 void *assertedValue )
3613 struct berval *asserted = (struct berval *) assertedValue;
3614 ber_len_t v_len = value->bv_len;
3615 ber_len_t av_len = asserted->bv_len;
3617 /* ignore trailing 'Z' when comparing */
3618 int match = memcmp( value->bv_val, asserted->bv_val,
3619 (v_len < av_len ? v_len : av_len) - 1 );
3620 if ( match == 0 ) match = v_len - av_len;
3623 return LDAP_SUCCESS;
3626 /* Index generation function */
3627 int generalizedTimeIndexer(
3632 struct berval *prefix,
3640 BerValue bvtmp; /* 40 bit index */
3642 struct lutil_timet tt;
3644 bvtmp.bv_len = sizeof(tmp);
3646 for( i=0; values[i].bv_val != NULL; i++ ) {
3647 /* just count them */
3650 /* we should have at least one value at this point */
3653 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
3655 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3656 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
3657 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
3658 /* Use 40 bits of time for key */
3659 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
3660 lutil_tm2time( &tm, &tt );
3661 tmp[0] = tt.tt_gsec & 0xff;
3662 tmp[4] = tt.tt_sec & 0xff;
3664 tmp[3] = tt.tt_sec & 0xff;
3666 tmp[2] = tt.tt_sec & 0xff;
3668 tmp[1] = tt.tt_sec & 0xff;
3670 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
3674 keys[j].bv_val = NULL;
3679 return LDAP_SUCCESS;
3682 /* Index generation function */
3683 int generalizedTimeFilter(
3688 struct berval *prefix,
3689 void * assertedValue,
3695 BerValue bvtmp; /* 40 bit index */
3696 BerValue *value = (BerValue *) assertedValue;
3698 struct lutil_timet tt;
3700 bvtmp.bv_len = sizeof(tmp);
3702 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
3703 /* Use 40 bits of time for key */
3704 if ( value->bv_val && value->bv_len >= 10 &&
3705 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
3707 lutil_tm2time( &tm, &tt );
3708 tmp[0] = tt.tt_gsec & 0xff;
3709 tmp[4] = tt.tt_sec & 0xff;
3711 tmp[3] = tt.tt_sec & 0xff;
3713 tmp[2] = tt.tt_sec & 0xff;
3715 tmp[1] = tt.tt_sec & 0xff;
3717 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
3718 ber_dupbv_x(keys, &bvtmp, ctx );
3719 keys[1].bv_val = NULL;
3727 return LDAP_SUCCESS;
3731 deliveryMethodValidate(
3733 struct berval *val )
3736 #define LENOF(s) (sizeof(s)-1)
3737 struct berval tmp = *val;
3739 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
3740 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
3741 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
3744 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3746 switch( tmp.bv_val[0] ) {
3749 if(( tmp.bv_len >= LENOF("any") ) &&
3750 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
3752 tmp.bv_len -= LENOF("any");
3753 tmp.bv_val += LENOF("any");
3756 return LDAP_INVALID_SYNTAX;
3760 if(( tmp.bv_len >= LENOF("mhs") ) &&
3761 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
3763 tmp.bv_len -= LENOF("mhs");
3764 tmp.bv_val += LENOF("mhs");
3767 return LDAP_INVALID_SYNTAX;
3771 if(( tmp.bv_len >= LENOF("physical") ) &&
3772 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
3774 tmp.bv_len -= LENOF("physical");
3775 tmp.bv_val += LENOF("physical");
3778 return LDAP_INVALID_SYNTAX;
3781 case 'T': /* telex or teletex or telephone */
3782 if(( tmp.bv_len >= LENOF("telex") ) &&
3783 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
3785 tmp.bv_len -= LENOF("telex");
3786 tmp.bv_val += LENOF("telex");
3789 if(( tmp.bv_len >= LENOF("teletex") ) &&
3790 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
3792 tmp.bv_len -= LENOF("teletex");
3793 tmp.bv_val += LENOF("teletex");
3796 if(( tmp.bv_len >= LENOF("telephone") ) &&
3797 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
3799 tmp.bv_len -= LENOF("telephone");
3800 tmp.bv_val += LENOF("telephone");
3803 return LDAP_INVALID_SYNTAX;
3806 case 'G': /* g3fax or g4fax */
3807 if(( tmp.bv_len >= LENOF("g3fax") ) && (
3808 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
3809 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
3811 tmp.bv_len -= LENOF("g3fax");
3812 tmp.bv_val += LENOF("g3fax");
3815 return LDAP_INVALID_SYNTAX;
3819 if(( tmp.bv_len >= LENOF("ia5") ) &&
3820 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
3822 tmp.bv_len -= LENOF("ia5");
3823 tmp.bv_val += LENOF("ia5");
3826 return LDAP_INVALID_SYNTAX;
3830 if(( tmp.bv_len >= LENOF("videotex") ) &&
3831 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
3833 tmp.bv_len -= LENOF("videotex");
3834 tmp.bv_val += LENOF("videotex");
3837 return LDAP_INVALID_SYNTAX;
3840 return LDAP_INVALID_SYNTAX;
3843 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3845 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3849 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3853 return LDAP_INVALID_SYNTAX;
3855 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3864 nisNetgroupTripleValidate(
3866 struct berval *val )
3871 if ( BER_BVISEMPTY( val ) ) {
3872 return LDAP_INVALID_SYNTAX;
3875 p = (char *)val->bv_val;
3876 e = p + val->bv_len;
3878 if ( *p != '(' /*')'*/ ) {
3879 return LDAP_INVALID_SYNTAX;
3882 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3886 return LDAP_INVALID_SYNTAX;
3889 } else if ( !AD_CHAR( *p ) ) {
3890 return LDAP_INVALID_SYNTAX;
3894 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3895 return LDAP_INVALID_SYNTAX;
3901 return LDAP_INVALID_SYNTAX;
3904 return LDAP_SUCCESS;
3908 bootParameterValidate(
3910 struct berval *val )
3914 if ( BER_BVISEMPTY( val ) ) {
3915 return LDAP_INVALID_SYNTAX;
3918 p = (char *)val->bv_val;
3919 e = p + val->bv_len;
3922 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3923 if ( !AD_CHAR( *p ) ) {
3924 return LDAP_INVALID_SYNTAX;
3929 return LDAP_INVALID_SYNTAX;
3933 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3934 if ( !AD_CHAR( *p ) ) {
3935 return LDAP_INVALID_SYNTAX;
3940 return LDAP_INVALID_SYNTAX;
3944 for ( p++; p < e; p++ ) {
3945 if ( !SLAP_PRINTABLE( *p ) ) {
3946 return LDAP_INVALID_SYNTAX;
3950 return LDAP_SUCCESS;
3954 firstComponentNormalize(
3959 struct berval *normalized,
3966 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3967 ber_dupbv_x( normalized, val, ctx );
3968 return LDAP_SUCCESS;
3971 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3973 if( val->bv_val[0] != '(' /*')'*/ &&
3974 val->bv_val[0] != '{' /*'}'*/ )
3976 return LDAP_INVALID_SYNTAX;
3979 /* trim leading white space */
3981 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3987 /* grab next word */
3988 comp.bv_val = &val->bv_val[len];
3989 len = val->bv_len - len;
3990 for( comp.bv_len = 0;
3991 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3997 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3998 rc = numericoidValidate( NULL, &comp );
3999 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4000 rc = integerValidate( NULL, &comp );
4002 rc = LDAP_INVALID_SYNTAX;
4006 if( rc == LDAP_SUCCESS ) {
4007 ber_dupbv_x( normalized, &comp, ctx );
4013 static char *country_gen_syn[] = {
4014 "1.3.6.1.4.1.1466.115.121.1.15",
4015 "1.3.6.1.4.1.1466.115.121.1.26",
4016 "1.3.6.1.4.1.1466.115.121.1.44",
4020 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4021 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4023 static slap_syntax_defs_rec syntax_defs[] = {
4024 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4025 X_BINARY X_NOT_H_R ")",
4026 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4027 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4028 0, NULL, NULL, NULL},
4029 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4030 0, NULL, NULL, NULL},
4031 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4033 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4034 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4036 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4037 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4038 0, NULL, bitStringValidate, NULL },
4039 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4040 0, NULL, booleanValidate, NULL},
4041 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4042 X_BINARY X_NOT_H_R ")",
4043 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4044 NULL, certificateValidate, NULL},
4045 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4046 X_BINARY X_NOT_H_R ")",
4047 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4048 NULL, sequenceValidate, NULL},
4049 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4050 X_BINARY X_NOT_H_R ")",
4051 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4052 NULL, sequenceValidate, NULL},
4053 #if 0 /* need to go __after__ printableString */
4054 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4055 0, "1.3.6.1.4.1.1466.115.121.1.44",
4056 countryStringValidate, NULL},
4058 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4059 0, NULL, dnValidate, dnPretty},
4060 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4061 0, NULL, rdnValidate, rdnPretty},
4062 #ifdef LDAP_COMP_MATCH
4063 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4064 0, NULL, allComponentsValidate, NULL},
4065 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4066 0, NULL, componentFilterValidate, NULL},
4068 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4069 0, NULL, NULL, NULL},
4070 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4071 0, NULL, deliveryMethodValidate, NULL},
4072 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4073 0, NULL, UTF8StringValidate, NULL},
4074 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4075 0, NULL, NULL, NULL},
4076 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4077 0, NULL, NULL, NULL},
4078 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4079 0, NULL, NULL, NULL},
4080 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4081 0, NULL, NULL, NULL},
4082 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4083 0, NULL, NULL, NULL},
4084 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4085 0, NULL, printablesStringValidate, NULL},
4086 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4087 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4088 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4089 0, NULL, generalizedTimeValidate, NULL},
4090 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4091 0, NULL, NULL, NULL},
4092 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4093 0, NULL, IA5StringValidate, NULL},
4094 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4095 0, NULL, integerValidate, NULL},
4096 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4097 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4098 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4099 0, NULL, NULL, NULL},
4100 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4101 0, NULL, NULL, NULL},
4102 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4103 0, NULL, NULL, NULL},
4104 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4105 0, NULL, NULL, NULL},
4106 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4107 0, NULL, NULL, NULL},
4108 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4109 0, NULL, nameUIDValidate, nameUIDPretty },
4110 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4111 0, NULL, NULL, NULL},
4112 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4113 0, NULL, numericStringValidate, NULL},
4114 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4115 0, NULL, NULL, NULL},
4116 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4117 0, NULL, numericoidValidate, NULL},
4118 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4119 0, NULL, IA5StringValidate, NULL},
4120 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4121 0, NULL, blobValidate, NULL},
4122 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4123 0, NULL, UTF8StringValidate, NULL},
4124 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4125 0, NULL, NULL, NULL},
4126 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4127 0, NULL, NULL, NULL},
4128 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4129 0, NULL, printableStringValidate, NULL},
4130 /* moved here because now depends on Directory String, IA5 String
4131 * and Printable String */
4132 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4133 0, country_gen_syn, countryStringValidate, NULL},
4134 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4135 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4136 0, NULL, subtreeSpecificationValidate, NULL},
4137 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4138 X_BINARY X_NOT_H_R ")",
4139 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4140 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4141 0, NULL, printableStringValidate, NULL},
4142 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4143 0, NULL, NULL, NULL},
4144 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4145 0, NULL, printablesStringValidate, NULL},
4146 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4147 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4148 0, NULL, utcTimeValidate, NULL},
4150 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4151 0, NULL, NULL, NULL},
4152 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4153 0, NULL, NULL, NULL},
4154 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4155 0, NULL, NULL, NULL},
4156 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4157 0, NULL, NULL, NULL},
4158 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4159 0, NULL, NULL, NULL},
4161 /* RFC 2307 NIS Syntaxes */
4162 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4163 0, NULL, nisNetgroupTripleValidate, NULL},
4164 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4165 0, NULL, bootParameterValidate, NULL},
4167 /* draft-zeilenga-ldap-x509 */
4168 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4169 SLAP_SYNTAX_HIDE, NULL,
4170 serialNumberAndIssuerValidate,
4171 serialNumberAndIssuerPretty},
4172 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4173 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4174 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4175 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4176 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4177 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4178 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4179 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4180 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4181 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4182 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4183 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4185 #ifdef SLAPD_AUTHPASSWD
4186 /* needs updating */
4187 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4188 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4191 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4192 0, NULL, UUIDValidate, UUIDPretty},
4194 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4195 SLAP_SYNTAX_HIDE, NULL, csnValidate, NULL},
4197 /* OpenLDAP Void Syntax */
4198 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4199 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4201 /* FIXME: OID is unused, but not registered yet */
4202 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4203 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4205 {NULL, 0, NULL, NULL, NULL}
4208 char *certificateExactMatchSyntaxes[] = {
4209 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4212 #ifdef LDAP_COMP_MATCH
4213 char *componentFilterMatchSyntaxes[] = {
4214 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4218 char *directoryStringSyntaxes[] = {
4219 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4222 char *integerFirstComponentMatchSyntaxes[] = {
4223 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4224 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4227 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4228 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4229 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4230 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4231 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4232 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4233 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4234 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4235 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4240 * Other matching rules in X.520 that we do not use (yet):
4242 * 2.5.13.25 uTCTimeMatch
4243 * 2.5.13.26 uTCTimeOrderingMatch
4244 * 2.5.13.31* directoryStringFirstComponentMatch
4245 * 2.5.13.32* wordMatch
4246 * 2.5.13.33* keywordMatch
4247 * 2.5.13.36+ certificatePairExactMatch
4248 * 2.5.13.37+ certificatePairMatch
4249 * 2.5.13.38+ certificateListExactMatch
4250 * 2.5.13.39+ certificateListMatch
4251 * 2.5.13.40+ algorithmIdentifierMatch
4252 * 2.5.13.41* storedPrefixMatch
4253 * 2.5.13.42 attributeCertificateMatch
4254 * 2.5.13.43 readerAndKeyIDMatch
4255 * 2.5.13.44 attributeIntegrityMatch
4257 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4258 * (+) described in draft-zeilenga-ldap-x509
4260 static slap_mrule_defs_rec mrule_defs[] = {
4262 * EQUALITY matching rules must be listed after associated APPROX
4263 * matching rules. So, we list all APPROX matching rules first.
4265 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4266 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4267 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4268 NULL, NULL, directoryStringApproxMatch,
4269 directoryStringApproxIndexer, directoryStringApproxFilter,
4272 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4273 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4274 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4275 NULL, NULL, IA5StringApproxMatch,
4276 IA5StringApproxIndexer, IA5StringApproxFilter,
4280 * Other matching rules
4283 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4284 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4285 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4286 NULL, NULL, octetStringMatch,
4287 octetStringIndexer, octetStringFilter,
4290 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4291 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4292 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4293 NULL, dnNormalize, dnMatch,
4294 octetStringIndexer, octetStringFilter,
4297 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4298 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4299 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4300 NULL, dnNormalize, dnRelativeMatch,
4304 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4305 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4306 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4307 NULL, dnNormalize, dnRelativeMatch,
4311 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4312 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4313 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4314 NULL, dnNormalize, dnRelativeMatch,
4318 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4319 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4320 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4321 NULL, dnNormalize, dnRelativeMatch,
4325 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4326 "SYNTAX 1.2.36.79672281.1.5.0 )",
4327 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4328 NULL, rdnNormalize, rdnMatch,
4329 octetStringIndexer, octetStringFilter,
4332 #ifdef LDAP_COMP_MATCH
4333 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4334 "SYNTAX 1.2.36.79672281.1.5.2 )",
4335 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4336 NULL, NULL , componentFilterMatch,
4337 octetStringIndexer, octetStringFilter,
4340 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4341 "SYNTAX 1.2.36.79672281.1.5.3 )",
4342 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4343 NULL, NULL , allComponentsMatch,
4344 octetStringIndexer, octetStringFilter,
4347 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4348 "SYNTAX 1.2.36.79672281.1.5.3 )",
4349 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4350 NULL, NULL , directoryComponentsMatch,
4351 octetStringIndexer, octetStringFilter,
4355 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4356 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4357 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4358 NULL, UTF8StringNormalize, octetStringMatch,
4359 octetStringIndexer, octetStringFilter,
4360 directoryStringApproxMatchOID },
4362 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4363 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4364 SLAP_MR_ORDERING, directoryStringSyntaxes,
4365 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4367 "caseIgnoreMatch" },
4369 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4370 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4371 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4372 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4373 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4374 "caseIgnoreMatch" },
4376 {"( 2.5.13.5 NAME 'caseExactMatch' "
4377 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4378 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4379 NULL, UTF8StringNormalize, octetStringMatch,
4380 octetStringIndexer, octetStringFilter,
4381 directoryStringApproxMatchOID },
4383 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4384 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4385 SLAP_MR_ORDERING, directoryStringSyntaxes,
4386 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4390 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4391 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4392 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4393 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4394 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4397 {"( 2.5.13.8 NAME 'numericStringMatch' "
4398 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4399 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4400 NULL, numericStringNormalize, octetStringMatch,
4401 octetStringIndexer, octetStringFilter,
4404 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4405 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4406 SLAP_MR_ORDERING, NULL,
4407 NULL, numericStringNormalize, octetStringOrderingMatch,
4409 "numericStringMatch" },
4411 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4412 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4413 SLAP_MR_SUBSTR, NULL,
4414 NULL, numericStringNormalize, octetStringSubstringsMatch,
4415 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4416 "numericStringMatch" },
4418 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4419 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4420 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4421 NULL, NULL, NULL, NULL, NULL, NULL },
4423 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4424 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4425 SLAP_MR_SUBSTR, NULL,
4426 NULL, NULL, NULL, NULL, NULL,
4427 "caseIgnoreListMatch" },
4429 {"( 2.5.13.13 NAME 'booleanMatch' "
4430 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4431 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4432 NULL, NULL, booleanMatch,
4433 octetStringIndexer, octetStringFilter,
4436 {"( 2.5.13.14 NAME 'integerMatch' "
4437 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4438 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4439 NULL, NULL, integerMatch,
4440 octetStringIndexer, octetStringFilter,
4443 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4444 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4445 SLAP_MR_ORDERING, NULL,
4446 NULL, NULL, integerMatch,
4450 {"( 2.5.13.16 NAME 'bitStringMatch' "
4451 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4452 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4453 NULL, NULL, octetStringMatch,
4454 octetStringIndexer, octetStringFilter,
4457 {"( 2.5.13.17 NAME 'octetStringMatch' "
4458 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4459 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4460 NULL, NULL, octetStringMatch,
4461 octetStringIndexer, octetStringFilter,
4464 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4465 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4466 SLAP_MR_ORDERING, NULL,
4467 NULL, NULL, octetStringOrderingMatch,
4469 "octetStringMatch" },
4471 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4472 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4473 SLAP_MR_SUBSTR, NULL,
4474 NULL, NULL, octetStringSubstringsMatch,
4475 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4476 "octetStringMatch" },
4478 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4480 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4482 telephoneNumberNormalize, octetStringMatch,
4483 octetStringIndexer, octetStringFilter,
4486 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4487 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4488 SLAP_MR_SUBSTR, NULL,
4489 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4490 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4491 "telephoneNumberMatch" },
4493 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4495 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4496 NULL, NULL, NULL, NULL, NULL, NULL },
4498 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4499 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4500 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4501 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4502 uniqueMemberIndexer, uniqueMemberFilter,
4505 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4507 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4508 NULL, NULL, NULL, NULL, NULL, NULL },
4510 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4511 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4512 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4513 NULL, generalizedTimeNormalize, octetStringMatch,
4514 generalizedTimeIndexer, generalizedTimeFilter,
4517 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4518 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4519 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4520 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4522 "generalizedTimeMatch" },
4524 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4525 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4526 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4527 integerFirstComponentMatchSyntaxes,
4528 NULL, firstComponentNormalize, integerMatch,
4529 octetStringIndexer, octetStringFilter,
4532 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4534 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4535 objectIdentifierFirstComponentMatchSyntaxes,
4536 NULL, firstComponentNormalize, octetStringMatch,
4537 octetStringIndexer, octetStringFilter,
4540 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4541 "SYNTAX 1.3.6.1.1.15.1 )",
4542 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4543 NULL, certificateExactNormalize, octetStringMatch,
4544 octetStringIndexer, octetStringFilter,
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 );