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 csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 /* Default to no ordered integer indexing */
66 unsigned int index_intlen = 0;
68 ldap_pvt_thread_mutex_t ad_undef_mutex;
69 ldap_pvt_thread_mutex_t oc_undef_mutex;
72 generalizedTimeValidate(
81 /* no value allowed */
82 return LDAP_INVALID_SYNTAX;
90 /* any value allowed */
94 #define berValidate blobValidate
101 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
102 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
107 /* X.509 related stuff */
115 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
118 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
119 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
120 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
121 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
125 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
128 /* X.509 certificate validation */
129 static int certificateValidate( Syntax *syntax, struct berval *in )
131 BerElementBuffer berbuf;
132 BerElement *ber = (BerElement *)&berbuf;
135 ber_int_t version = SLAP_X509_V1;
137 ber_init2( ber, in, LBER_USE_DER );
138 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
139 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
140 tag = ber_skip_tag( ber, &len ); /* Sequence */
141 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
142 tag = ber_peek_tag( ber, &len );
143 /* Optional version */
144 if ( tag == SLAP_X509_OPT_C_VERSION ) {
145 tag = ber_skip_tag( ber, &len );
146 tag = ber_get_int( ber, &version );
147 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
149 /* NOTE: don't try to parse Serial, because it might be longer
150 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
151 tag = ber_skip_tag( ber, &len ); /* Serial */
152 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
153 ber_skip_data( ber, len );
154 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
155 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
156 ber_skip_data( ber, len );
157 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
158 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
159 ber_skip_data( ber, len );
160 tag = ber_skip_tag( ber, &len ); /* Validity */
161 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
162 ber_skip_data( ber, len );
163 tag = ber_skip_tag( ber, &len ); /* Subject DN */
164 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
165 ber_skip_data( ber, len );
166 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
167 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
168 ber_skip_data( ber, len );
169 tag = ber_skip_tag( ber, &len );
170 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
171 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
172 ber_skip_data( ber, len );
173 tag = ber_skip_tag( ber, &len );
175 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
176 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
177 ber_skip_data( ber, len );
178 tag = ber_skip_tag( ber, &len );
180 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
181 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
182 tag = ber_skip_tag( ber, &len );
183 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
184 ber_skip_data( ber, len );
185 tag = ber_skip_tag( ber, &len );
187 /* signatureAlgorithm */
188 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
189 ber_skip_data( ber, len );
190 tag = ber_skip_tag( ber, &len );
192 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
193 ber_skip_data( ber, len );
194 tag = ber_skip_tag( ber, &len );
195 /* Must be at end now */
196 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
200 /* X.509 certificate list validation */
201 static int certificateListValidate( Syntax *syntax, struct berval *in )
203 BerElementBuffer berbuf;
204 BerElement *ber = (BerElement *)&berbuf;
207 ber_int_t version = SLAP_X509_V1;
209 ber_init2( ber, in, LBER_USE_DER );
210 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
211 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
212 tag = ber_skip_tag( ber, &len ); /* Sequence */
213 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
214 tag = ber_peek_tag( ber, &len );
215 /* Optional version */
216 if ( tag == LBER_INTEGER ) {
217 tag = ber_get_int( ber, &version );
218 assert( tag == LBER_INTEGER );
219 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
221 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
222 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
223 ber_skip_data( ber, len );
224 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
225 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
226 ber_skip_data( ber, len );
227 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
228 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
229 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
230 ber_skip_data( ber, len );
231 /* Optional nextUpdate */
232 tag = ber_skip_tag( ber, &len );
233 if ( tag == 0x17U || tag == 0x18U ) {
234 ber_skip_data( ber, len );
235 tag = ber_skip_tag( ber, &len );
237 /* revokedCertificates - Sequence of Sequence, Optional */
238 if ( tag == LBER_SEQUENCE ) {
240 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
241 /* Should NOT be empty */
242 ber_skip_data( ber, len );
243 tag = ber_skip_tag( ber, &len );
246 /* Optional Extensions */
247 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
248 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
249 tag = ber_skip_tag( ber, &len );
250 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
251 ber_skip_data( ber, len );
252 tag = ber_skip_tag( ber, &len );
254 /* signatureAlgorithm */
255 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
256 ber_skip_data( ber, len );
257 tag = ber_skip_tag( ber, &len );
259 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
260 ber_skip_data( ber, len );
261 tag = ber_skip_tag( ber, &len );
262 /* Must be at end now */
263 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
273 struct berval *value,
274 void *assertedValue )
276 struct berval *asserted = (struct berval *) assertedValue;
277 int match = value->bv_len - asserted->bv_len;
280 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
288 octetStringOrderingMatch(
293 struct berval *value,
294 void *assertedValue )
296 struct berval *asserted = (struct berval *) assertedValue;
297 ber_len_t v_len = value->bv_len;
298 ber_len_t av_len = asserted->bv_len;
300 int match = memcmp( value->bv_val, asserted->bv_val,
301 (v_len < av_len ? v_len : av_len) );
303 if( match == 0 ) match = v_len - av_len;
311 HASH_CONTEXT *HASHcontext,
312 struct berval *prefix,
317 HASH_Init(HASHcontext);
318 if(prefix && prefix->bv_len > 0) {
319 HASH_Update(HASHcontext,
320 (unsigned char *)prefix->bv_val, prefix->bv_len);
322 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
323 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
324 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
330 HASH_CONTEXT *HASHcontext,
331 unsigned char *HASHdigest,
332 unsigned char *value,
335 HASH_CONTEXT ctx = *HASHcontext;
336 HASH_Update( &ctx, value, len );
337 HASH_Final( HASHdigest, &ctx );
340 /* Index generation function */
341 int octetStringIndexer(
346 struct berval *prefix,
354 HASH_CONTEXT HASHcontext;
355 unsigned char HASHdigest[HASH_BYTES];
356 struct berval digest;
357 digest.bv_val = (char *)HASHdigest;
358 digest.bv_len = sizeof(HASHdigest);
360 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
361 /* just count them */
364 /* we should have at least one value at this point */
367 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
369 slen = syntax->ssyn_oidlen;
370 mlen = mr->smr_oidlen;
372 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
373 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
374 hashIter( &HASHcontext, HASHdigest,
375 (unsigned char *)values[i].bv_val, values[i].bv_len );
376 ber_dupbv_x( &keys[i], &digest, ctx );
379 BER_BVZERO( &keys[i] );
386 /* Index generation function */
387 int octetStringFilter(
392 struct berval *prefix,
393 void * assertedValue,
399 HASH_CONTEXT HASHcontext;
400 unsigned char HASHdigest[HASH_BYTES];
401 struct berval *value = (struct berval *) assertedValue;
402 struct berval digest;
403 digest.bv_val = (char *)HASHdigest;
404 digest.bv_len = sizeof(HASHdigest);
406 slen = syntax->ssyn_oidlen;
407 mlen = mr->smr_oidlen;
409 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
411 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
412 hashIter( &HASHcontext, HASHdigest,
413 (unsigned char *)value->bv_val, value->bv_len );
415 ber_dupbv_x( keys, &digest, ctx );
416 BER_BVZERO( &keys[1] );
424 octetStringSubstringsMatch(
429 struct berval *value,
430 void *assertedValue )
433 SubstringsAssertion *sub = assertedValue;
434 struct berval left = *value;
438 /* Add up asserted input length */
439 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
440 inlen += sub->sa_initial.bv_len;
443 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
444 inlen += sub->sa_any[i].bv_len;
447 if ( !BER_BVISNULL( &sub->sa_final ) ) {
448 inlen += sub->sa_final.bv_len;
451 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
452 if ( inlen > left.bv_len ) {
457 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
458 sub->sa_initial.bv_len );
464 left.bv_val += sub->sa_initial.bv_len;
465 left.bv_len -= sub->sa_initial.bv_len;
466 inlen -= sub->sa_initial.bv_len;
469 if ( !BER_BVISNULL( &sub->sa_final ) ) {
470 if ( inlen > left.bv_len ) {
475 match = memcmp( sub->sa_final.bv_val,
476 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
477 sub->sa_final.bv_len );
483 left.bv_len -= sub->sa_final.bv_len;
484 inlen -= sub->sa_final.bv_len;
488 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
493 if ( inlen > left.bv_len ) {
494 /* not enough length */
499 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
503 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
510 idx = p - left.bv_val;
512 if ( idx >= left.bv_len ) {
513 /* this shouldn't happen */
520 if ( sub->sa_any[i].bv_len > left.bv_len ) {
521 /* not enough left */
526 match = memcmp( left.bv_val,
527 sub->sa_any[i].bv_val,
528 sub->sa_any[i].bv_len );
536 left.bv_val += sub->sa_any[i].bv_len;
537 left.bv_len -= sub->sa_any[i].bv_len;
538 inlen -= sub->sa_any[i].bv_len;
547 /* Substrings Index generation function */
549 octetStringSubstringsIndexer(
554 struct berval *prefix,
563 HASH_CONTEXT HCany, HCini, HCfin;
564 unsigned char HASHdigest[HASH_BYTES];
565 struct berval digest;
566 digest.bv_val = (char *)HASHdigest;
567 digest.bv_len = sizeof(HASHdigest);
571 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
572 /* count number of indices to generate */
573 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
574 if( values[i].bv_len >= index_substr_if_maxlen ) {
575 nkeys += index_substr_if_maxlen -
576 (index_substr_if_minlen - 1);
577 } else if( values[i].bv_len >= index_substr_if_minlen ) {
578 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
582 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
583 if( values[i].bv_len >= index_substr_any_len ) {
584 nkeys += values[i].bv_len - (index_substr_any_len - 1);
588 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
589 if( values[i].bv_len >= index_substr_if_maxlen ) {
590 nkeys += index_substr_if_maxlen -
591 (index_substr_if_minlen - 1);
592 } else if( values[i].bv_len >= index_substr_if_minlen ) {
593 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
599 /* no keys to generate */
604 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
606 slen = syntax->ssyn_oidlen;
607 mlen = mr->smr_oidlen;
609 if ( flags & SLAP_INDEX_SUBSTR_ANY )
610 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
611 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
612 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
613 if( flags & SLAP_INDEX_SUBSTR_FINAL )
614 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
617 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
620 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
621 ( values[i].bv_len >= index_substr_any_len ) )
623 max = values[i].bv_len - (index_substr_any_len - 1);
625 for( j=0; j<max; j++ ) {
626 hashIter( &HCany, HASHdigest,
627 (unsigned char *)&values[i].bv_val[j],
628 index_substr_any_len );
629 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
633 /* skip if too short */
634 if( values[i].bv_len < index_substr_if_minlen ) continue;
636 max = index_substr_if_maxlen < values[i].bv_len
637 ? index_substr_if_maxlen : values[i].bv_len;
639 for( j=index_substr_if_minlen; j<=max; j++ ) {
641 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
642 hashIter( &HCini, HASHdigest,
643 (unsigned char *)values[i].bv_val, j );
644 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
647 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
648 hashIter( &HCfin, HASHdigest,
649 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
650 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
657 BER_BVZERO( &keys[nkeys] );
668 octetStringSubstringsFilter (
673 struct berval *prefix,
674 void * assertedValue,
678 SubstringsAssertion *sa;
681 size_t slen, mlen, klen;
683 HASH_CONTEXT HASHcontext;
684 unsigned char HASHdigest[HASH_BYTES];
685 struct berval *value;
686 struct berval digest;
688 sa = (SubstringsAssertion *) assertedValue;
690 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
691 !BER_BVISNULL( &sa->sa_initial ) &&
692 sa->sa_initial.bv_len >= index_substr_if_minlen )
695 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
696 ( flags & SLAP_INDEX_SUBSTR_ANY ))
698 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
702 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
704 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
705 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
706 /* don't bother accounting with stepping */
707 nkeys += sa->sa_any[i].bv_len -
708 ( index_substr_any_len - 1 );
713 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
714 !BER_BVISNULL( &sa->sa_final ) &&
715 sa->sa_final.bv_len >= index_substr_if_minlen )
718 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
719 ( flags & SLAP_INDEX_SUBSTR_ANY ))
721 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
730 digest.bv_val = (char *)HASHdigest;
731 digest.bv_len = sizeof(HASHdigest);
733 slen = syntax->ssyn_oidlen;
734 mlen = mr->smr_oidlen;
736 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
739 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
740 !BER_BVISNULL( &sa->sa_initial ) &&
741 sa->sa_initial.bv_len >= index_substr_if_minlen )
743 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
744 value = &sa->sa_initial;
746 klen = index_substr_if_maxlen < value->bv_len
747 ? index_substr_if_maxlen : value->bv_len;
749 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
750 hashIter( &HASHcontext, HASHdigest,
751 (unsigned char *)value->bv_val, klen );
752 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
754 /* If initial is too long and we have subany indexed, use it
755 * to match the excess...
757 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
760 pre = SLAP_INDEX_SUBSTR_PREFIX;
761 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
762 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
764 hashIter( &HASHcontext, HASHdigest,
765 (unsigned char *)&value->bv_val[j], index_substr_any_len );
766 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
771 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
773 pre = SLAP_INDEX_SUBSTR_PREFIX;
774 klen = index_substr_any_len;
776 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
777 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
781 value = &sa->sa_any[i];
783 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
785 j <= value->bv_len - index_substr_any_len;
786 j += index_substr_any_step )
788 hashIter( &HASHcontext, HASHdigest,
789 (unsigned char *)&value->bv_val[j], klen );
790 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
795 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
796 !BER_BVISNULL( &sa->sa_final ) &&
797 sa->sa_final.bv_len >= index_substr_if_minlen )
799 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
800 value = &sa->sa_final;
802 klen = index_substr_if_maxlen < value->bv_len
803 ? index_substr_if_maxlen : value->bv_len;
805 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
806 hashIter( &HASHcontext, HASHdigest,
807 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
808 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
810 /* If final is too long and we have subany indexed, use it
811 * to match the excess...
813 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
816 pre = SLAP_INDEX_SUBSTR_PREFIX;
817 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
818 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
820 hashIter( &HASHcontext, HASHdigest,
821 (unsigned char *)&value->bv_val[j], index_substr_any_len );
822 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
828 BER_BVZERO( &keys[nkeys] );
845 /* very unforgiving validation, requires no normalization
846 * before simplistic matching
848 if( in->bv_len < 3 ) {
849 return LDAP_INVALID_SYNTAX;
852 /* RFC 4517 Section 3.3.2 Bit String:
853 * BitString = SQUOTE *binary-digit SQUOTE "B"
854 * binary-digit = "0" / "1"
856 * where SQUOTE [RFC4512] is
857 * SQUOTE = %x27 ; single quote ("'")
859 * Example: '0101111101'B
862 if( in->bv_val[0] != '\'' ||
863 in->bv_val[in->bv_len - 2] != '\'' ||
864 in->bv_val[in->bv_len - 1] != 'B' )
866 return LDAP_INVALID_SYNTAX;
869 for( i = in->bv_len - 3; i > 0; i-- ) {
870 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
871 return LDAP_INVALID_SYNTAX;
879 * Syntaxes from RFC 4517
884 A value of the Bit String syntax is a sequence of binary digits. The
885 LDAP-specific encoding of a value of this syntax is defined by the
888 BitString = SQUOTE *binary-digit SQUOTE "B"
890 binary-digit = "0" / "1"
892 The <SQUOTE> rule is defined in [MODELS].
897 The LDAP definition for the Bit String syntax is:
899 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
901 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
905 3.3.21. Name and Optional UID
907 A value of the Name and Optional UID syntax is the distinguished name
908 [MODELS] of an entity optionally accompanied by a unique identifier
909 that serves to differentiate the entity from others with an identical
912 The LDAP-specific encoding of a value of this syntax is defined by
915 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
917 The <BitString> rule is defined in Section 3.3.2. The
918 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
921 Note that although the '#' character may occur in the string
922 representation of a distinguished name, no additional escaping of
923 this character is performed when a <distinguishedName> is encoded in
924 a <NameAndOptionalUID>.
927 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
929 The LDAP definition for the Name and Optional UID syntax is:
931 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
933 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
940 1.4. Common ABNF Productions
943 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
945 SQUOTE = %x27 ; single quote ("'")
949 * Note: normalization strips any leading "0"s, unless the
950 * bit string is exactly "'0'B", so the normalized example,
951 * in slapd, would result in
953 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
955 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
956 * be escaped except when at the beginning of a value, the
957 * definition of Name and Optional UID appears to be flawed,
958 * because there is no clear means to determine whether the
959 * UID part is present or not.
963 * cn=Someone,dc=example,dc=com#'1'B
965 * could be either a NameAndOptionalUID with trailing UID, i.e.
967 * DN = "cn=Someone,dc=example,dc=com"
970 * or a NameAndOptionalUID with no trailing UID, and the AVA
971 * in the last RDN made of
974 * attributeValue = com#'1'B
976 * in fact "com#'1'B" is a valid IA5 string.
978 * As a consequence, current slapd code assumes that the
979 * presence of portions of a BitString at the end of the string
980 * representation of a NameAndOptionalUID means a BitString
981 * is expected, and cause an error otherwise. This is quite
982 * arbitrary, and might change in the future.
992 struct berval dn, uid;
994 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
996 ber_dupbv( &dn, in );
997 if( !dn.bv_val ) return LDAP_OTHER;
999 /* if there's a "#", try bitStringValidate()... */
1000 uid.bv_val = strrchr( dn.bv_val, '#' );
1001 if ( !BER_BVISNULL( &uid ) ) {
1003 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1005 rc = bitStringValidate( NULL, &uid );
1006 if ( rc == LDAP_SUCCESS ) {
1007 /* in case of success, trim the UID,
1008 * otherwise treat it as part of the DN */
1009 dn.bv_len -= uid.bv_len + 1;
1010 uid.bv_val[-1] = '\0';
1014 rc = dnValidate( NULL, &dn );
1016 ber_memfree( dn.bv_val );
1027 assert( val != NULL );
1028 assert( out != NULL );
1031 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1033 if( BER_BVISEMPTY( val ) ) {
1034 ber_dupbv_x( out, val, ctx );
1036 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1037 return LDAP_INVALID_SYNTAX;
1041 struct berval dnval = *val;
1042 struct berval uidval = BER_BVNULL;
1044 uidval.bv_val = strrchr( val->bv_val, '#' );
1045 if ( !BER_BVISNULL( &uidval ) ) {
1047 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1049 rc = bitStringValidate( NULL, &uidval );
1051 if ( rc == LDAP_SUCCESS ) {
1052 ber_dupbv_x( &dnval, val, ctx );
1053 dnval.bv_len -= uidval.bv_len + 1;
1054 dnval.bv_val[dnval.bv_len] = '\0';
1057 BER_BVZERO( &uidval );
1061 rc = dnPretty( syntax, &dnval, out, ctx );
1062 if ( dnval.bv_val != val->bv_val ) {
1063 slap_sl_free( dnval.bv_val, ctx );
1065 if( rc != LDAP_SUCCESS ) {
1069 if( !BER_BVISNULL( &uidval ) ) {
1073 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1074 + STRLENOF( "#" ) + uidval.bv_len + 1,
1077 ber_memfree_x( out->bv_val, ctx );
1081 out->bv_val[out->bv_len++] = '#';
1082 out->bv_val[out->bv_len++] = '\'';
1084 got1 = uidval.bv_len < sizeof("'0'B");
1085 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1086 c = uidval.bv_val[i];
1089 if( got1 ) out->bv_val[out->bv_len++] = c;
1093 out->bv_val[out->bv_len++] = c;
1098 out->bv_val[out->bv_len++] = '\'';
1099 out->bv_val[out->bv_len++] = 'B';
1100 out->bv_val[out->bv_len] = '\0';
1104 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1106 return LDAP_SUCCESS;
1110 uniqueMemberNormalize(
1115 struct berval *normalized,
1121 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1123 ber_dupbv_x( &out, val, ctx );
1124 if ( BER_BVISEMPTY( &out ) ) {
1128 struct berval uid = BER_BVNULL;
1130 uid.bv_val = strrchr( out.bv_val, '#' );
1131 if ( !BER_BVISNULL( &uid ) ) {
1133 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1135 rc = bitStringValidate( NULL, &uid );
1136 if ( rc == LDAP_SUCCESS ) {
1137 uid.bv_val[-1] = '\0';
1138 out.bv_len -= uid.bv_len + 1;
1144 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1146 if( rc != LDAP_SUCCESS ) {
1147 slap_sl_free( out.bv_val, ctx );
1148 return LDAP_INVALID_SYNTAX;
1151 if( !BER_BVISNULL( &uid ) ) {
1154 tmp = ch_realloc( normalized->bv_val,
1155 normalized->bv_len + uid.bv_len
1156 + STRLENOF("#") + 1 );
1157 if ( tmp == NULL ) {
1158 ber_memfree_x( normalized->bv_val, ctx );
1162 normalized->bv_val = tmp;
1164 /* insert the separator */
1165 normalized->bv_val[normalized->bv_len++] = '#';
1167 /* append the UID */
1168 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1169 uid.bv_val, uid.bv_len );
1170 normalized->bv_len += uid.bv_len;
1173 normalized->bv_val[normalized->bv_len] = '\0';
1176 slap_sl_free( out.bv_val, ctx );
1179 return LDAP_SUCCESS;
1188 struct berval *value,
1189 void *assertedValue )
1192 struct berval *asserted = (struct berval *) assertedValue;
1193 struct berval assertedDN = *asserted;
1194 struct berval assertedUID = BER_BVNULL;
1195 struct berval valueDN = *value;
1196 struct berval valueUID = BER_BVNULL;
1197 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1199 if ( !BER_BVISEMPTY( asserted ) ) {
1200 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1201 if ( !BER_BVISNULL( &assertedUID ) ) {
1202 assertedUID.bv_val++;
1203 assertedUID.bv_len = assertedDN.bv_len
1204 - ( assertedUID.bv_val - assertedDN.bv_val );
1206 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1207 assertedDN.bv_len -= assertedUID.bv_len + 1;
1210 BER_BVZERO( &assertedUID );
1215 if ( !BER_BVISEMPTY( value ) ) {
1217 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1218 if ( !BER_BVISNULL( &valueUID ) ) {
1220 valueUID.bv_len = valueDN.bv_len
1221 - ( valueUID.bv_val - valueDN.bv_val );
1223 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1224 valueDN.bv_len -= valueUID.bv_len + 1;
1227 BER_BVZERO( &valueUID );
1232 if( valueUID.bv_len && assertedUID.bv_len ) {
1233 match = valueUID.bv_len - assertedUID.bv_len;
1236 return LDAP_SUCCESS;
1239 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1242 return LDAP_SUCCESS;
1245 } else if ( !approx && valueUID.bv_len ) {
1248 return LDAP_SUCCESS;
1250 } else if ( !approx && assertedUID.bv_len ) {
1253 return LDAP_SUCCESS;
1256 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1260 uniqueMemberIndexer(
1265 struct berval *prefix,
1273 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1274 /* just count them */
1278 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1280 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1281 struct berval assertedDN = values[i];
1282 struct berval assertedUID = BER_BVNULL;
1284 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1285 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1286 if ( !BER_BVISNULL( &assertedUID ) ) {
1287 assertedUID.bv_val++;
1288 assertedUID.bv_len = assertedDN.bv_len
1289 - ( assertedUID.bv_val - assertedDN.bv_val );
1291 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1292 assertedDN.bv_len -= assertedUID.bv_len + 1;
1295 BER_BVZERO( &assertedUID );
1300 dnvalues[i] = assertedDN;
1302 BER_BVZERO( &dnvalues[i] );
1304 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1305 dnvalues, keysp, ctx );
1307 slap_sl_free( dnvalues, ctx );
1317 struct berval *prefix,
1318 void * assertedValue,
1322 struct berval *asserted = (struct berval *) assertedValue;
1323 struct berval assertedDN = *asserted;
1324 struct berval assertedUID = BER_BVNULL;
1326 if ( !BER_BVISEMPTY( asserted ) ) {
1327 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1328 if ( !BER_BVISNULL( &assertedUID ) ) {
1329 assertedUID.bv_val++;
1330 assertedUID.bv_len = assertedDN.bv_len
1331 - ( assertedUID.bv_val - assertedDN.bv_val );
1333 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1334 assertedDN.bv_len -= assertedUID.bv_len + 1;
1337 BER_BVZERO( &assertedUID );
1342 return octetStringFilter( use, flags, syntax, mr, prefix,
1343 &assertedDN, keysp, ctx );
1348 * Handling boolean syntax and matching is quite rigid.
1349 * A more flexible approach would be to allow a variety
1350 * of strings to be normalized and prettied into TRUE
1358 /* very unforgiving validation, requires no normalization
1359 * before simplistic matching
1362 if( in->bv_len == 4 ) {
1363 if( bvmatch( in, &slap_true_bv ) ) {
1364 return LDAP_SUCCESS;
1366 } else if( in->bv_len == 5 ) {
1367 if( bvmatch( in, &slap_false_bv ) ) {
1368 return LDAP_SUCCESS;
1372 return LDAP_INVALID_SYNTAX;
1381 struct berval *value,
1382 void *assertedValue )
1384 /* simplistic matching allowed by rigid validation */
1385 struct berval *asserted = (struct berval *) assertedValue;
1386 *matchp = value->bv_len != asserted->bv_len;
1387 return LDAP_SUCCESS;
1390 /*-------------------------------------------------------------------
1391 LDAP/X.500 string syntax / matching rules have a few oddities. This
1392 comment attempts to detail how slapd(8) treats them.
1395 StringSyntax X.500 LDAP Matching/Comments
1396 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1397 PrintableString subset subset i/e + ignore insignificant spaces
1398 PrintableString subset subset i/e + ignore insignificant spaces
1399 NumericString subset subset ignore all spaces
1400 IA5String ASCII ASCII i/e + ignore insignificant spaces
1401 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1403 TelephoneNumber subset subset i + ignore all spaces and "-"
1405 See RFC 4518 for details.
1409 In X.500(93), a directory string can be either a PrintableString,
1410 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1411 In later versions, more CHOICEs were added. In all cases the string
1414 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1415 A directory string cannot be zero length.
1417 For matching, there are both case ignore and exact rules. Both
1418 also require that "insignificant" spaces be ignored.
1419 spaces before the first non-space are ignored;
1420 spaces after the last non-space are ignored;
1421 spaces after a space are ignored.
1422 Note: by these rules (and as clarified in X.520), a string of only
1423 spaces is to be treated as if held one space, not empty (which
1424 would be a syntax error).
1427 In ASN.1, numeric string is just a string of digits and spaces
1428 and could be empty. However, in X.500, all attribute values of
1429 numeric string carry a non-empty constraint. For example:
1431 internationalISDNNumber ATTRIBUTE ::= {
1432 WITH SYNTAX InternationalISDNNumber
1433 EQUALITY MATCHING RULE numericStringMatch
1434 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1435 ID id-at-internationalISDNNumber }
1436 InternationalISDNNumber ::=
1437 NumericString (SIZE(1..ub-international-isdn-number))
1439 Unforunately, some assertion values are don't carry the same
1440 constraint (but its unclear how such an assertion could ever
1441 be true). In LDAP, there is one syntax (numericString) not two
1442 (numericString with constraint, numericString without constraint).
1443 This should be treated as numericString with non-empty constraint.
1444 Note that while someone may have no ISDN number, there are no ISDN
1445 numbers which are zero length.
1447 In matching, spaces are ignored.
1450 In ASN.1, Printable string is just a string of printable characters
1451 and can be empty. In X.500, semantics much like NumericString (see
1452 serialNumber for a like example) excepting uses insignificant space
1453 handling instead of ignore all spaces. They must be non-empty.
1456 Basically same as PrintableString. There are no examples in X.500,
1457 but same logic applies. Empty strings are allowed.
1459 -------------------------------------------------------------------*/
1468 unsigned char *u = (unsigned char *)in->bv_val;
1470 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1471 /* directory strings cannot be empty */
1472 return LDAP_INVALID_SYNTAX;
1475 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1476 /* get the length indicated by the first byte */
1477 len = LDAP_UTF8_CHARLEN2( u, len );
1479 /* very basic checks */
1482 if( (u[5] & 0xC0) != 0x80 ) {
1483 return LDAP_INVALID_SYNTAX;
1486 if( (u[4] & 0xC0) != 0x80 ) {
1487 return LDAP_INVALID_SYNTAX;
1490 if( (u[3] & 0xC0) != 0x80 ) {
1491 return LDAP_INVALID_SYNTAX;
1494 if( (u[2] & 0xC0 )!= 0x80 ) {
1495 return LDAP_INVALID_SYNTAX;
1498 if( (u[1] & 0xC0) != 0x80 ) {
1499 return LDAP_INVALID_SYNTAX;
1502 /* CHARLEN already validated it */
1505 return LDAP_INVALID_SYNTAX;
1508 /* make sure len corresponds with the offset
1509 to the next character */
1510 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1514 return LDAP_INVALID_SYNTAX;
1517 return LDAP_SUCCESS;
1521 UTF8StringNormalize(
1526 struct berval *normalized,
1529 struct berval tmp, nvalue;
1533 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1535 if( BER_BVISNULL( val ) ) {
1536 /* assume we're dealing with a syntax (e.g., UTF8String)
1537 * which allows empty strings
1539 BER_BVZERO( normalized );
1540 return LDAP_SUCCESS;
1543 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1544 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1545 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1546 ? LDAP_UTF8_APPROX : 0;
1548 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1553 /* collapse spaces (in place) */
1555 nvalue.bv_val = tmp.bv_val;
1557 /* trim leading spaces? */
1558 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1559 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1561 for( i = 0; i < tmp.bv_len; i++) {
1562 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1563 if( wasspace++ == 0 ) {
1564 /* trim repeated spaces */
1565 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1569 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1573 if( !BER_BVISEMPTY( &nvalue ) ) {
1574 /* trim trailing space? */
1576 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1577 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1581 nvalue.bv_val[nvalue.bv_len] = '\0';
1584 /* string of all spaces is treated as one space */
1585 nvalue.bv_val[0] = ' ';
1586 nvalue.bv_val[1] = '\0';
1590 *normalized = nvalue;
1591 return LDAP_SUCCESS;
1595 directoryStringSubstringsMatch(
1600 struct berval *value,
1601 void *assertedValue )
1604 SubstringsAssertion *sub = assertedValue;
1605 struct berval left = *value;
1609 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1610 if ( sub->sa_initial.bv_len > left.bv_len ) {
1611 /* not enough left */
1616 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1617 sub->sa_initial.bv_len );
1623 left.bv_val += sub->sa_initial.bv_len;
1624 left.bv_len -= sub->sa_initial.bv_len;
1626 priorspace = ASCII_SPACE(
1627 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1630 if ( sub->sa_any ) {
1631 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1635 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1636 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1638 /* allow next space to match */
1645 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1649 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1650 /* not enough left */
1655 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1662 idx = p - left.bv_val;
1664 if ( idx >= left.bv_len ) {
1665 /* this shouldn't happen */
1672 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1673 /* not enough left */
1678 match = memcmp( left.bv_val,
1679 sub->sa_any[i].bv_val,
1680 sub->sa_any[i].bv_len );
1688 left.bv_val += sub->sa_any[i].bv_len;
1689 left.bv_len -= sub->sa_any[i].bv_len;
1691 priorspace = ASCII_SPACE(
1692 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1696 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1697 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1698 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1700 /* allow next space to match */
1705 if ( sub->sa_final.bv_len > left.bv_len ) {
1706 /* not enough left */
1711 match = memcmp( sub->sa_final.bv_val,
1712 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1713 sub->sa_final.bv_len );
1722 return LDAP_SUCCESS;
1725 #if defined(SLAPD_APPROX_INITIALS)
1726 # define SLAPD_APPROX_DELIMITER "._ "
1727 # define SLAPD_APPROX_WORDLEN 2
1729 # define SLAPD_APPROX_DELIMITER " "
1730 # define SLAPD_APPROX_WORDLEN 1
1739 struct berval *value,
1740 void *assertedValue )
1742 struct berval *nval, *assertv;
1743 char *val, **values, **words, *c;
1744 int i, count, len, nextchunk=0, nextavail=0;
1746 /* Yes, this is necessary */
1747 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1748 if( nval == NULL ) {
1750 return LDAP_SUCCESS;
1753 /* Yes, this is necessary */
1754 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1755 NULL, LDAP_UTF8_APPROX, NULL );
1756 if( assertv == NULL ) {
1759 return LDAP_SUCCESS;
1762 /* Isolate how many words there are */
1763 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1764 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1765 if ( c == NULL ) break;
1770 /* Get a phonetic copy of each word */
1771 words = (char **)ch_malloc( count * sizeof(char *) );
1772 values = (char **)ch_malloc( count * sizeof(char *) );
1773 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1775 values[i] = phonetic(c);
1778 /* Work through the asserted value's words, to see if at least some
1779 of the words are there, in the same order. */
1781 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1782 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1787 #if defined(SLAPD_APPROX_INITIALS)
1788 else if( len == 1 ) {
1789 /* Single letter words need to at least match one word's initial */
1790 for( i=nextavail; i<count; i++ )
1791 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1798 /* Isolate the next word in the asserted value and phonetic it */
1799 assertv->bv_val[nextchunk+len] = '\0';
1800 val = phonetic( assertv->bv_val + nextchunk );
1802 /* See if this phonetic chunk is in the remaining words of *value */
1803 for( i=nextavail; i<count; i++ ){
1804 if( !strcmp( val, values[i] ) ){
1812 /* This chunk in the asserted value was NOT within the *value. */
1818 /* Go on to the next word in the asserted value */
1822 /* If some of the words were seen, call it a match */
1823 if( nextavail > 0 ) {
1830 /* Cleanup allocs */
1831 ber_bvfree( assertv );
1832 for( i=0; i<count; i++ ) {
1833 ch_free( values[i] );
1839 return LDAP_SUCCESS;
1848 struct berval *prefix,
1854 int i,j, len, wordcount, keycount=0;
1855 struct berval *newkeys;
1856 BerVarray keys=NULL;
1858 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1859 struct berval val = BER_BVNULL;
1860 /* Yes, this is necessary */
1861 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1862 assert( !BER_BVISNULL( &val ) );
1864 /* Isolate how many words there are. There will be a key for each */
1865 for( wordcount = 0, c = val.bv_val; *c; c++) {
1866 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1867 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1869 if (*c == '\0') break;
1873 /* Allocate/increase storage to account for new keys */
1874 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1875 * sizeof(struct berval) );
1876 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1877 if( keys ) ch_free( keys );
1880 /* Get a phonetic copy of each word */
1881 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1883 if( len < SLAPD_APPROX_WORDLEN ) continue;
1884 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1889 ber_memfree( val.bv_val );
1891 BER_BVZERO( &keys[keycount] );
1894 return LDAP_SUCCESS;
1903 struct berval *prefix,
1904 void * assertedValue,
1913 /* Yes, this is necessary */
1914 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1915 NULL, LDAP_UTF8_APPROX, NULL );
1916 if( val == NULL || BER_BVISNULL( val ) ) {
1917 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1918 BER_BVZERO( &keys[0] );
1921 return LDAP_SUCCESS;
1924 /* Isolate how many words there are. There will be a key for each */
1925 for( count = 0,c = val->bv_val; *c; c++) {
1926 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1927 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1929 if (*c == '\0') break;
1933 /* Allocate storage for new keys */
1934 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1936 /* Get a phonetic copy of each word */
1937 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1939 if( len < SLAPD_APPROX_WORDLEN ) continue;
1940 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1946 BER_BVZERO( &keys[count] );
1949 return LDAP_SUCCESS;
1952 /* Remove all spaces and '-' characters */
1954 telephoneNumberNormalize(
1959 struct berval *normalized,
1964 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1966 /* validator should have refused an empty string */
1967 assert( !BER_BVISEMPTY( val ) );
1969 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1971 for( p = val->bv_val; *p; p++ ) {
1972 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1978 normalized->bv_len = q - normalized->bv_val;
1980 if( BER_BVISEMPTY( normalized ) ) {
1981 slap_sl_free( normalized->bv_val, ctx );
1982 BER_BVZERO( normalized );
1983 return LDAP_INVALID_SYNTAX;
1986 return LDAP_SUCCESS;
1994 struct berval val = *in;
1996 if( BER_BVISEMPTY( &val ) ) {
1997 /* disallow empty strings */
1998 return LDAP_INVALID_SYNTAX;
2001 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2002 if ( val.bv_len == 1 ) {
2003 return LDAP_SUCCESS;
2006 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2013 while ( OID_LEADCHAR( val.bv_val[0] )) {
2017 if ( val.bv_len == 0 ) {
2018 return LDAP_SUCCESS;
2022 if( !OID_SEPARATOR( val.bv_val[0] )) {
2030 return LDAP_INVALID_SYNTAX;
2039 struct berval val = *in;
2041 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2043 if ( val.bv_val[0] == '-' ) {
2047 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2048 return LDAP_INVALID_SYNTAX;
2051 if( val.bv_val[0] == '0' ) { /* "-0" */
2052 return LDAP_INVALID_SYNTAX;
2055 } else if ( val.bv_val[0] == '0' ) {
2056 if( val.bv_len > 1 ) { /* "0<more>" */
2057 return LDAP_INVALID_SYNTAX;
2060 return LDAP_SUCCESS;
2063 for( i=0; i < val.bv_len; i++ ) {
2064 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2065 return LDAP_INVALID_SYNTAX;
2069 return LDAP_SUCCESS;
2078 struct berval *value,
2079 void *assertedValue )
2081 struct berval *asserted = (struct berval *) assertedValue;
2082 int vsign = 1, asign = 1; /* default sign = '+' */
2087 if( v.bv_val[0] == '-' ) {
2093 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2096 if( a.bv_val[0] == '-' ) {
2102 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2104 match = vsign - asign;
2106 match = ( v.bv_len != a.bv_len
2107 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2108 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2109 if( vsign < 0 ) match = -match;
2113 return LDAP_SUCCESS;
2116 /* Index generation function */
2123 struct berval *prefix,
2129 struct berval iv, itmp;
2133 if ( !index_intlen ) {
2134 return octetStringIndexer( use, flags, syntax, mr,
2135 prefix, values, keysp, ctx );
2138 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2139 /* just count them */
2142 /* we should have at least one value at this point */
2145 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2146 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2147 keys[i].bv_len = index_intlen+1;
2148 keys[i].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2151 keys[i].bv_val = NULL;
2154 itmp.bv_len = sizeof(ibuf);
2156 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2157 if ( values[i].bv_len > itmp.bv_len ) {
2158 itmp.bv_len = values[i].bv_len;
2159 if ( itmp.bv_val == ibuf ) {
2160 itmp.bv_val = slap_sl_malloc( itmp.bv_len, ctx );
2162 itmp.bv_val = slap_sl_realloc( itmp.bv_val, itmp.bv_len, ctx );
2166 if ( lutil_str2bin( &values[i], &iv )) {
2167 rc = LDAP_INVALID_SYNTAX;
2170 /* If too small, pad with zeros */
2171 if ( iv.bv_len < index_intlen ) {
2173 keys[i].bv_val[0] = index_intlen;
2174 k = index_intlen - iv.bv_len + 1;
2175 for ( j=1; j<k; j++)
2176 keys[i].bv_val[j] = 0;
2177 for ( j = 0; j<iv.bv_len; j++ )
2178 keys[i].bv_val[j+k] = iv.bv_val[j];
2180 keys[i].bv_val[0] = iv.bv_len;
2181 memcpy( keys[i].bv_val+1, iv.bv_val, index_intlen );
2183 /* convert signed to unsigned */
2184 keys[i].bv_val[1] ^= 0x80;
2189 if ( itmp.bv_val != ibuf ) {
2190 slap_sl_free( itmp.bv_val, ctx );
2195 /* Index generation function */
2202 struct berval *prefix,
2203 void * assertedValue,
2210 struct berval *value;
2213 if ( !index_intlen ) {
2214 return octetStringFilter( use, flags, syntax, mr,
2215 prefix, assertedValue, keysp, ctx );
2218 value = (struct berval *) assertedValue;
2220 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2222 keys[0].bv_len = index_intlen + 1;
2223 keys[0].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2225 if ( value->bv_len > sizeof( ibuf )) {
2226 iv.bv_val = slap_sl_malloc( value->bv_len, ctx );
2227 iv.bv_len = value->bv_len;
2230 iv.bv_len = sizeof(ibuf);
2233 if ( lutil_str2bin( value, &iv )) {
2234 rc = LDAP_INVALID_SYNTAX;
2237 /* If too small, pad with zeros */
2238 if ( iv.bv_len < index_intlen ) {
2240 keys[0].bv_val[0] = index_intlen;
2241 k = index_intlen - iv.bv_len + 1;
2242 for ( j=1; j<k; j++)
2243 keys[0].bv_val[j] = 0;
2244 for ( j = 0; j<iv.bv_len; j++ )
2245 keys[0].bv_val[j+k] = iv.bv_val[j];
2247 keys[0].bv_val[0] = iv.bv_len;
2248 memcpy( keys[0].bv_val+1, iv.bv_val, index_intlen );
2250 /* convert signed to unsigned */
2251 keys[0].bv_val[1] ^= 0x80;
2256 if ( iv.bv_val != ibuf ) {
2257 slap_sl_free( iv.bv_val, ctx );
2263 countryStringValidate(
2265 struct berval *val )
2267 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2269 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2270 return LDAP_INVALID_SYNTAX;
2272 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2273 return LDAP_INVALID_SYNTAX;
2276 return LDAP_SUCCESS;
2280 printableStringValidate(
2282 struct berval *val )
2286 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2288 for(i=0; i < val->bv_len; i++) {
2289 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2290 return LDAP_INVALID_SYNTAX;
2294 return LDAP_SUCCESS;
2298 printablesStringValidate(
2300 struct berval *val )
2304 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2306 for(i=0,len=0; i < val->bv_len; i++) {
2307 int c = val->bv_val[i];
2311 return LDAP_INVALID_SYNTAX;
2315 } else if ( SLAP_PRINTABLE(c) ) {
2318 return LDAP_INVALID_SYNTAX;
2323 return LDAP_INVALID_SYNTAX;
2326 return LDAP_SUCCESS;
2332 struct berval *val )
2336 for(i=0; i < val->bv_len; i++) {
2337 if( !LDAP_ASCII(val->bv_val[i]) ) {
2338 return LDAP_INVALID_SYNTAX;
2342 return LDAP_SUCCESS;
2351 struct berval *normalized,
2355 int casefold = !SLAP_MR_ASSOCIATED( mr,
2356 slap_schema.si_mr_caseExactIA5Match );
2358 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2362 /* Ignore initial whitespace */
2363 while ( ASCII_SPACE( *p ) ) p++;
2365 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2366 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2367 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2368 normalized->bv_val[normalized->bv_len] = '\0';
2370 p = q = normalized->bv_val;
2373 if ( ASCII_SPACE( *p ) ) {
2376 /* Ignore the extra whitespace */
2377 while ( ASCII_SPACE( *p ) ) {
2381 } else if ( casefold ) {
2382 /* Most IA5 rules require casefolding */
2383 *q++ = TOLOWER(*p); p++;
2390 assert( normalized->bv_val <= p );
2394 * If the string ended in space, backup the pointer one
2395 * position. One is enough because the above loop collapsed
2396 * all whitespace to a single space.
2398 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2400 /* null terminate */
2403 normalized->bv_len = q - normalized->bv_val;
2405 return LDAP_SUCCESS;
2414 if( in->bv_len != 36 ) {
2415 return LDAP_INVALID_SYNTAX;
2418 for( i=0; i<36; i++ ) {
2424 if( in->bv_val[i] != '-' ) {
2425 return LDAP_INVALID_SYNTAX;
2429 if( !ASCII_HEX( in->bv_val[i]) ) {
2430 return LDAP_INVALID_SYNTAX;
2435 return LDAP_SUCCESS;
2446 int rc=LDAP_INVALID_SYNTAX;
2448 assert( in != NULL );
2449 assert( out != NULL );
2451 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2454 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2456 for( i=0; i<36; i++ ) {
2462 if( in->bv_val[i] != '-' ) {
2465 out->bv_val[i] = '-';
2469 if( !ASCII_HEX( in->bv_val[i]) ) {
2472 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2477 out->bv_val[ out->bv_len ] = '\0';
2481 slap_sl_free( out->bv_val, ctx );
2494 struct berval *normalized,
2497 unsigned char octet = '\0';
2501 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2502 /* NOTE: must be a normalized UUID */
2503 assert( val->bv_len == 16 );
2505 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2506 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2507 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2508 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2510 return LDAP_SUCCESS;
2513 normalized->bv_len = 16;
2514 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2516 for( i=0, j=0; i<36; i++ ) {
2517 unsigned char nibble;
2518 if( val->bv_val[i] == '-' ) {
2521 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2522 nibble = val->bv_val[i] - '0';
2524 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2525 nibble = val->bv_val[i] - ('a'-10);
2527 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2528 nibble = val->bv_val[i] - ('A'-10);
2531 slap_sl_free( normalized->bv_val, ctx );
2532 return LDAP_INVALID_SYNTAX;
2537 normalized->bv_val[j>>1] = octet;
2539 octet = nibble << 4;
2544 normalized->bv_val[normalized->bv_len] = 0;
2545 return LDAP_SUCCESS;
2551 numericStringValidate(
2557 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2559 for(i=0; i < in->bv_len; i++) {
2560 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2561 return LDAP_INVALID_SYNTAX;
2565 return LDAP_SUCCESS;
2569 numericStringNormalize(
2574 struct berval *normalized,
2577 /* removal all spaces */
2580 assert( !BER_BVISEMPTY( val ) );
2582 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2585 q = normalized->bv_val;
2588 if ( ASCII_SPACE( *p ) ) {
2589 /* Ignore whitespace */
2596 /* we should have copied no more than is in val */
2597 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2599 /* null terminate */
2602 normalized->bv_len = q - normalized->bv_val;
2604 if( BER_BVISEMPTY( normalized ) ) {
2605 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2606 normalized->bv_val[0] = ' ';
2607 normalized->bv_val[1] = '\0';
2608 normalized->bv_len = 1;
2611 return LDAP_SUCCESS;
2615 * Integer conversion macros that will use the largest available
2618 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2619 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2620 # define SLAP_LONG long long
2622 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2623 # define SLAP_LONG long
2624 #endif /* HAVE_STRTOLL ... */
2632 struct berval *value,
2633 void *assertedValue )
2635 SLAP_LONG lValue, lAssertedValue;
2638 /* safe to assume integers are NUL terminated? */
2639 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2640 if( errno == ERANGE )
2642 return LDAP_CONSTRAINT_VIOLATION;
2645 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2647 if( errno == ERANGE )
2649 return LDAP_CONSTRAINT_VIOLATION;
2652 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2653 return LDAP_SUCCESS;
2662 struct berval *value,
2663 void *assertedValue )
2665 SLAP_LONG lValue, lAssertedValue;
2668 /* safe to assume integers are NUL terminated? */
2669 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2670 if( errno == ERANGE )
2672 return LDAP_CONSTRAINT_VIOLATION;
2675 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2677 if( errno == ERANGE )
2679 return LDAP_CONSTRAINT_VIOLATION;
2682 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2683 return LDAP_SUCCESS;
2687 serialNumberAndIssuerCheck(
2696 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2698 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2699 /* Parse old format */
2700 is->bv_val = ber_bvchr( in, '$' );
2701 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2703 sn->bv_val = in->bv_val;
2704 sn->bv_len = is->bv_val - in->bv_val;
2707 is->bv_len = in->bv_len - (sn->bv_len + 1);
2709 /* eat leading zeros */
2710 for( n=0; n < (sn->bv_len-1); n++ ) {
2711 if( sn->bv_val[n] != '0' ) break;
2716 for( n=0; n < sn->bv_len; n++ ) {
2717 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2721 /* Parse GSER format */
2722 int havesn=0,haveissuer=0;
2723 struct berval x = *in;
2728 /* eat leading spaces */
2729 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2733 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2734 return LDAP_INVALID_SYNTAX;
2737 /* should be at issuer or serialNumber NamedValue */
2738 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2740 x.bv_val += STRLENOF("issuer");
2741 x.bv_len -= STRLENOF("issuer");
2743 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2744 x.bv_val++; x.bv_len--;
2746 /* eat leading spaces */
2747 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2751 /* For backward compatibility, this part is optional */
2752 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2753 x.bv_val += STRLENOF("rdnSequence:");
2754 x.bv_len -= STRLENOF("rdnSequence:");
2757 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2758 x.bv_val++; x.bv_len--;
2760 is->bv_val = x.bv_val;
2763 for( ; is->bv_len < x.bv_len; ) {
2764 if ( is->bv_val[is->bv_len] != '"' ) {
2768 if ( is->bv_val[is->bv_len+1] == '"' ) {
2775 x.bv_val += is->bv_len+1;
2776 x.bv_len -= is->bv_len+1;
2778 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2779 return LDAP_INVALID_SYNTAX;
2784 } else if( strncasecmp( x.bv_val, "serialNumber",
2785 STRLENOF("serialNumber")) == 0 )
2787 /* parse serialNumber */
2789 x.bv_val += STRLENOF("serialNumber");
2790 x.bv_len -= STRLENOF("serialNumber");
2792 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2793 x.bv_val++; x.bv_len--;
2795 /* eat leading spaces */
2796 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2800 sn->bv_val = x.bv_val;
2803 if( sn->bv_val[0] == '-' ) {
2808 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2809 sn->bv_val[1] == 'X' )) {
2811 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2812 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2814 } else if ( sn->bv_val[0] == '\'' ) {
2815 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2816 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2818 if ( sn->bv_val[sn->bv_len] == '\'' &&
2819 sn->bv_val[sn->bv_len+1] == 'H' )
2822 return LDAP_INVALID_SYNTAX;
2825 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2826 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2830 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2831 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2832 return LDAP_INVALID_SYNTAX;
2835 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2837 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2838 return LDAP_INVALID_SYNTAX;
2843 } else return LDAP_INVALID_SYNTAX;
2845 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2846 x.bv_val++; x.bv_len--;
2849 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2853 /* should be at remaining NamedValue */
2854 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2855 STRLENOF("issuer" )) == 0 ))
2858 x.bv_val += STRLENOF("issuer");
2859 x.bv_len -= STRLENOF("issuer");
2861 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2862 x.bv_val++; x.bv_len--;
2864 /* eat leading spaces */
2865 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2869 /* For backward compatibility, this part is optional */
2870 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2871 x.bv_val += STRLENOF("rdnSequence:");
2872 x.bv_len -= STRLENOF("rdnSequence:");
2875 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2876 x.bv_val++; x.bv_len--;
2878 is->bv_val = x.bv_val;
2881 for( ; is->bv_len < x.bv_len; ) {
2882 if ( is->bv_val[is->bv_len] != '"' ) {
2886 if ( is->bv_val[is->bv_len+1] == '"' ) {
2893 x.bv_val += is->bv_len+1;
2894 x.bv_len -= is->bv_len+1;
2896 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2897 STRLENOF("serialNumber")) == 0 ))
2899 /* parse serialNumber */
2901 x.bv_val += STRLENOF("serialNumber");
2902 x.bv_len -= STRLENOF("serialNumber");
2904 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2905 x.bv_val++; x.bv_len--;
2907 /* eat leading spaces */
2908 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2912 sn->bv_val = x.bv_val;
2915 if( sn->bv_val[0] == '-' ) {
2920 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2921 sn->bv_val[1] == 'X' )) {
2923 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2924 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2926 } else if ( sn->bv_val[0] == '\'' ) {
2927 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2928 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2930 if ( sn->bv_val[sn->bv_len] == '\'' &&
2931 sn->bv_val[sn->bv_len+1] == 'H' )
2934 return LDAP_INVALID_SYNTAX;
2937 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2938 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2942 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2943 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2944 return LDAP_INVALID_SYNTAX;
2947 x.bv_val += sn->bv_len;
2948 x.bv_len -= sn->bv_len;
2950 } else return LDAP_INVALID_SYNTAX;
2952 /* eat trailing spaces */
2953 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2957 /* should have no characters left... */
2958 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2960 ber_dupbv_x( &ni, is, ctx );
2963 /* need to handle double dquotes here */
2969 serialNumberAndIssuerValidate(
2974 struct berval sn, i;
2976 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2979 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
2983 /* validate DN -- doesn't handle double dquote */
2984 rc = dnValidate( NULL, &i );
2986 rc = LDAP_INVALID_SYNTAX;
2988 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2989 slap_sl_free( i.bv_val, NULL );
2992 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2998 serialNumberAndIssuerPretty(
3005 struct berval sn, i, ni;
3007 assert( in != NULL );
3008 assert( out != NULL );
3010 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3013 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3017 rc = dnPretty( syntax, &i, &ni, ctx );
3019 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3020 slap_sl_free( i.bv_val, ctx );
3023 if( rc ) return LDAP_INVALID_SYNTAX;
3025 /* make room from sn + "$" */
3026 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3027 + sn.bv_len + ni.bv_len;
3028 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3030 if( out->bv_val == NULL ) {
3032 slap_sl_free( ni.bv_val, ctx );
3037 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3038 STRLENOF("{ serialNumber "));
3039 n = STRLENOF("{ serialNumber ");
3041 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3044 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3045 n += STRLENOF(", issuer rdnSequence:\"");
3047 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3050 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3051 n += STRLENOF("\" }");
3053 out->bv_val[n] = '\0';
3055 assert( n == out->bv_len );
3057 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3058 out->bv_val, 0, 0 );
3060 slap_sl_free( ni.bv_val, ctx );
3062 return LDAP_SUCCESS;
3066 * This routine is called by certificateExactNormalize when
3067 * certificateExactNormalize receives a search string instead of
3068 * a certificate. This routine checks if the search value is valid
3069 * and then returns the normalized value
3072 serialNumberAndIssuerNormalize(
3080 struct berval sn, sn2, i, ni;
3081 char sbuf[64], *stmp = sbuf;
3086 assert( in != NULL );
3087 assert( out != NULL );
3089 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3092 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3096 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3098 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3099 slap_sl_free( i.bv_val, ctx );
3102 if( rc ) return LDAP_INVALID_SYNTAX;
3104 /* Convert sn to canonical hex */
3105 if ( sn.bv_len > sizeof( sbuf )) {
3106 stmp = slap_sl_malloc( sn.bv_len, ctx );
3109 sn2.bv_len = sn.bv_len;
3110 if ( lutil_str2bin( &sn, &sn2 )) {
3111 rc = LDAP_INVALID_SYNTAX;
3115 /* make room for sn + "$" */
3116 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3117 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3118 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3120 if( out->bv_val == NULL ) {
3122 slap_sl_free( ni.bv_val, ctx );
3128 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3129 STRLENOF( "{ serialNumber " ));
3130 n = STRLENOF( "{ serialNumber " );
3132 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3135 unsigned char *v = sn2.bv_val;
3136 out->bv_val[n++] = '\'';
3137 for ( j = 0; j < sn2.bv_len; j++ ) {
3138 sprintf( &out->bv_val[n], "%02X", v[j] );
3141 out->bv_val[n++] = '\'';
3142 out->bv_val[n++] = 'H';
3145 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3146 n += STRLENOF( ", issuer rdnSequence:\"" );
3148 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3151 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3152 n += STRLENOF( "\" }" );
3154 out->bv_val[n] = '\0';
3156 assert( n == out->bv_len );
3158 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3159 out->bv_val, 0, 0 );
3163 slap_sl_free( stmp, ctx );
3164 slap_sl_free( ni.bv_val, ctx );
3170 certificateExactNormalize(
3175 struct berval *normalized,
3178 BerElementBuffer berbuf;
3179 BerElement *ber = (BerElement *)&berbuf;
3183 char serialbuf[64], *serial = serialbuf;
3184 ber_len_t seriallen;
3185 struct berval issuer_dn = BER_BVNULL, bvdn;
3187 int rc = LDAP_INVALID_SYNTAX;
3189 if( BER_BVISEMPTY( val ) ) goto done;
3191 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3192 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3195 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3197 ber_init2( ber, val, LBER_USE_DER );
3198 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3199 tag = ber_skip_tag( ber, &len ); /* Sequence */
3200 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3201 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3202 tag = ber_skip_tag( ber, &len );
3203 tag = ber_get_int( ber, &i ); /* version */
3206 /* NOTE: move the test here from certificateValidate,
3207 * so that we can validate certs with serial longer
3208 * than sizeof(ber_int_t) */
3209 tag = ber_peek_tag( ber, &len ); /* serial */
3211 /* Use hex format. '123456789abcdef'H
3217 tag = ber_skip_tag( ber, &len );
3218 ptr = (unsigned char *)ber->ber_ptr;
3219 ber_skip_data( ber, len );
3221 /* Check for minimal encodings */
3223 if ( ptr[0] & 0x80 ) {
3224 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3225 return LDAP_INVALID_SYNTAX;
3226 } else if ( ptr[0] == 0 ) {
3227 if (!( ptr[1] & 0x80 ))
3228 return LDAP_INVALID_SYNTAX;
3232 seriallen = len * 2 + 4; /* quotes, H, NUL */
3233 if ( seriallen > sizeof( serialbuf ))
3234 serial = slap_sl_malloc( seriallen, ctx );
3237 for ( i = 0; i<len; i++ ) {
3238 sprintf( sptr, "%02X", ptr[i] );
3245 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3246 ber_skip_data( ber, len );
3247 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3248 len = ber_ptrlen( ber );
3249 bvdn.bv_val = val->bv_val + len;
3250 bvdn.bv_len = val->bv_len - len;
3252 rc = dnX509normalize( &bvdn, &issuer_dn );
3253 if( rc != LDAP_SUCCESS ) goto done;
3255 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3256 + seriallen + issuer_dn.bv_len;
3257 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3259 p = (unsigned char *)normalized->bv_val;
3261 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3262 p += STRLENOF( "{ serialNumber " );
3264 AC_MEMCPY(p, serial, seriallen);
3267 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3268 p += STRLENOF( ", issuer rdnSequence:\"" );
3270 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3271 p += issuer_dn.bv_len;
3273 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3274 p += STRLENOF( "\" }" );
3278 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3279 normalized->bv_val, NULL, NULL );
3284 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3285 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3297 assert( in != NULL );
3298 assert( !BER_BVISNULL( in ) );
3300 for ( i = 0; i < in->bv_len; i++ ) {
3301 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3302 return LDAP_INVALID_SYNTAX;
3306 return LDAP_SUCCESS;
3309 /* Normalize a SID as used inside a CSN:
3310 * three-digit numeric string */
3317 struct berval *normalized,
3322 assert( val != NULL );
3323 assert( normalized != NULL );
3325 ber_dupbv_x( normalized, val, ctx );
3327 for ( i = 0; i < normalized->bv_len; i++ ) {
3328 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3329 ber_memfree_x( normalized->bv_val, ctx );
3330 BER_BVZERO( normalized );
3331 return LDAP_INVALID_SYNTAX;
3334 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3337 return LDAP_SUCCESS;
3345 assert( in != NULL );
3346 assert( !BER_BVISNULL( in ) );
3348 if ( in->bv_len != 3 ) {
3349 return LDAP_INVALID_SYNTAX;
3352 return hexValidate( NULL, in );
3355 /* Normalize a SID as used inside a CSN:
3356 * three-digit numeric string */
3363 struct berval *normalized,
3366 if ( val->bv_len != 3 ) {
3367 return LDAP_INVALID_SYNTAX;
3370 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3380 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3383 /* Normalize a SID as used inside a CSN, either as-is
3384 * (assertion value) or extracted from the CSN
3385 * (attribute value) */
3392 struct berval *normalized,
3400 if ( BER_BVISEMPTY( val ) ) {
3401 return LDAP_INVALID_SYNTAX;
3404 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3405 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3408 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3410 ptr = ber_bvchr( val, '#' );
3411 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3412 return LDAP_INVALID_SYNTAX;
3415 bv.bv_val = ptr + 1;
3416 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3418 ptr = ber_bvchr( &bv, '#' );
3419 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3420 return LDAP_INVALID_SYNTAX;
3423 bv.bv_val = ptr + 1;
3424 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3426 ptr = ber_bvchr( &bv, '#' );
3427 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3428 return LDAP_INVALID_SYNTAX;
3431 bv.bv_len = ptr - bv.bv_val;
3433 if ( bv.bv_len == 2 ) {
3434 /* OpenLDAP 2.3 SID */
3436 buf[ 1 ] = bv.bv_val[ 0 ];
3437 buf[ 2 ] = bv.bv_val[ 1 ];
3444 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3456 assert( in != NULL );
3457 assert( !BER_BVISNULL( in ) );
3459 if ( BER_BVISEMPTY( in ) ) {
3460 return LDAP_INVALID_SYNTAX;
3465 ptr = ber_bvchr( &bv, '#' );
3466 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3467 return LDAP_INVALID_SYNTAX;
3470 bv.bv_len = ptr - bv.bv_val;
3471 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3472 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3474 return LDAP_INVALID_SYNTAX;
3477 rc = generalizedTimeValidate( NULL, &bv );
3478 if ( rc != LDAP_SUCCESS ) {
3482 bv.bv_val = ptr + 1;
3483 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3485 ptr = ber_bvchr( &bv, '#' );
3486 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3487 return LDAP_INVALID_SYNTAX;
3490 bv.bv_len = ptr - bv.bv_val;
3491 if ( bv.bv_len != 6 ) {
3492 return LDAP_INVALID_SYNTAX;
3495 rc = hexValidate( NULL, &bv );
3496 if ( rc != LDAP_SUCCESS ) {
3500 bv.bv_val = ptr + 1;
3501 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3503 ptr = ber_bvchr( &bv, '#' );
3504 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3505 return LDAP_INVALID_SYNTAX;
3508 bv.bv_len = ptr - bv.bv_val;
3509 if ( bv.bv_len == 2 ) {
3510 /* tolerate old 2-digit replica-id */
3511 rc = hexValidate( NULL, &bv );
3514 rc = sidValidate( NULL, &bv );
3516 if ( rc != LDAP_SUCCESS ) {
3520 bv.bv_val = ptr + 1;
3521 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3523 if ( bv.bv_len != 6 ) {
3524 return LDAP_INVALID_SYNTAX;
3527 return hexValidate( NULL, &bv );
3530 /* Normalize a CSN in OpenLDAP 2.3 format */
3537 struct berval *normalized,
3540 struct berval gt, cnt, sid, mod;
3544 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3545 assert( !BER_BVISEMPTY( val ) );
3549 ptr = ber_bvchr( >, '#' );
3550 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3551 return LDAP_INVALID_SYNTAX;
3554 gt.bv_len = ptr - gt.bv_val;
3555 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3557 cnt.bv_val = ptr + 1;
3558 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3560 ptr = ber_bvchr( &cnt, '#' );
3561 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3562 return LDAP_INVALID_SYNTAX;
3565 cnt.bv_len = ptr - cnt.bv_val;
3566 assert( cnt.bv_len == STRLENOF( "000000" ) );
3568 sid.bv_val = ptr + 1;
3569 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3571 ptr = ber_bvchr( &sid, '#' );
3572 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3573 return LDAP_INVALID_SYNTAX;
3576 sid.bv_len = ptr - sid.bv_val;
3577 assert( sid.bv_len == STRLENOF( "00" ) );
3579 mod.bv_val = ptr + 1;
3580 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3581 assert( mod.bv_len == STRLENOF( "000000" ) );
3583 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3584 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3586 ptr = normalized->bv_val;
3587 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3588 ptr = lutil_strcopy( ptr, ".000000Z#" );
3589 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3592 for ( i = 0; i < sid.bv_len; i++ ) {
3593 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3596 for ( i = 0; i < mod.bv_len; i++ ) {
3597 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3601 assert( ptr - normalized->bv_val == normalized->bv_len );
3603 return LDAP_SUCCESS;
3606 /* Normalize a CSN */
3613 struct berval *normalized,
3616 struct berval cnt, sid, mod;
3620 assert( val != NULL );
3621 assert( normalized != NULL );
3623 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3625 if ( BER_BVISEMPTY( val ) ) {
3626 return LDAP_INVALID_SYNTAX;
3629 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3630 /* Openldap <= 2.3 */
3632 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3635 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3637 ptr = ber_bvchr( val, '#' );
3638 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3639 return LDAP_INVALID_SYNTAX;
3642 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3644 cnt.bv_val = ptr + 1;
3645 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3647 ptr = ber_bvchr( &cnt, '#' );
3648 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3649 return LDAP_INVALID_SYNTAX;
3652 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3654 sid.bv_val = ptr + 1;
3655 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3657 ptr = ber_bvchr( &sid, '#' );
3658 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3659 return LDAP_INVALID_SYNTAX;
3662 sid.bv_len = ptr - sid.bv_val;
3663 assert( sid.bv_len == STRLENOF( "000" ) );
3665 mod.bv_val = ptr + 1;
3666 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3668 assert( mod.bv_len == STRLENOF( "000000" ) );
3670 ber_dupbv_x( normalized, val, ctx );
3672 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3673 i < normalized->bv_len; i++ )
3675 /* assume it's already validated that's all hex digits */
3676 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3679 return LDAP_SUCCESS;
3689 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3692 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3693 /* slight optimization - does not need the start parameter */
3694 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3699 check_time_syntax (struct berval *val,
3702 struct berval *fraction)
3705 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3706 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3707 * GeneralizedTime supports leap seconds, UTCTime does not.
3709 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3710 static const int mdays[2][12] = {
3711 /* non-leap years */
3712 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3714 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3717 int part, c, c1, c2, tzoffset, leapyear = 0;
3720 e = p + val->bv_len;
3722 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3723 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3725 for (part = start; part < 7 && p < e; part++) {
3727 if (!ASCII_DIGIT(c1)) {
3732 return LDAP_INVALID_SYNTAX;
3735 if (!ASCII_DIGIT(c)) {
3736 return LDAP_INVALID_SYNTAX;
3738 c += c1 * 10 - '0' * 11;
3739 if ((part | 1) == 3) {
3742 return LDAP_INVALID_SYNTAX;
3745 if (c >= ceiling[part]) {
3746 if (! (c == 60 && part == 6 && start == 0))
3747 return LDAP_INVALID_SYNTAX;
3751 if (part < 5 + start) {
3752 return LDAP_INVALID_SYNTAX;
3754 for (; part < 9; part++) {
3758 /* leapyear check for the Gregorian calendar (year>1581) */
3759 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3763 if (parts[3] >= mdays[leapyear][parts[2]]) {
3764 return LDAP_INVALID_SYNTAX;
3768 fraction->bv_val = p;
3769 fraction->bv_len = 0;
3770 if (p < e && (*p == '.' || *p == ',')) {
3772 while (++p < e && ASCII_DIGIT(*p)) {
3775 if (p - fraction->bv_val == 1) {
3776 return LDAP_INVALID_SYNTAX;
3778 for (end_num = p; end_num[-1] == '0'; --end_num) {
3781 c = end_num - fraction->bv_val;
3782 if (c != 1) fraction->bv_len = c;
3788 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3794 return LDAP_INVALID_SYNTAX;
3800 for (part = 7; part < 9 && p < e; part++) {
3802 if (!ASCII_DIGIT(c1)) {
3807 return LDAP_INVALID_SYNTAX;
3810 if (!ASCII_DIGIT(c2)) {
3811 return LDAP_INVALID_SYNTAX;
3813 parts[part] = c1 * 10 + c2 - '0' * 11;
3814 if (parts[part] >= ceiling[part]) {
3815 return LDAP_INVALID_SYNTAX;
3818 if (part < 8 + start) {
3819 return LDAP_INVALID_SYNTAX;
3822 if (tzoffset == '-') {
3823 /* negative offset to UTC, ie west of Greenwich */
3824 parts[4] += parts[7];
3825 parts[5] += parts[8];
3826 /* offset is just hhmm, no seconds */
3827 for (part = 6; --part >= 0; ) {
3831 c = mdays[leapyear][parts[2]];
3833 if (parts[part] >= c) {
3835 return LDAP_INVALID_SYNTAX;
3840 } else if (part != 5) {
3845 /* positive offset to UTC, ie east of Greenwich */
3846 parts[4] -= parts[7];
3847 parts[5] -= parts[8];
3848 for (part = 6; --part >= 0; ) {
3849 if (parts[part] < 0) {
3851 return LDAP_INVALID_SYNTAX;
3856 /* make first arg to % non-negative */
3857 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3862 } else if (part != 5) {
3869 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3872 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3879 struct berval *normalized )
3883 rc = check_time_syntax(val, 1, parts, NULL);
3884 if (rc != LDAP_SUCCESS) {
3888 normalized->bv_val = ch_malloc( 14 );
3889 if ( normalized->bv_val == NULL ) {
3890 return LBER_ERROR_MEMORY;
3893 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3894 parts[1], parts[2] + 1, parts[3] + 1,
3895 parts[4], parts[5], parts[6] );
3896 normalized->bv_len = 13;
3898 return LDAP_SUCCESS;
3908 return check_time_syntax(in, 1, parts, NULL);
3911 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3914 generalizedTimeValidate(
3919 struct berval fraction;
3920 return check_time_syntax(in, 0, parts, &fraction);
3924 generalizedTimeNormalize(
3929 struct berval *normalized,
3934 struct berval fraction;
3936 rc = check_time_syntax(val, 0, parts, &fraction);
3937 if (rc != LDAP_SUCCESS) {
3941 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3942 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3943 if ( BER_BVISNULL( normalized ) ) {
3944 return LBER_ERROR_MEMORY;
3947 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3948 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3949 parts[4], parts[5], parts[6] );
3950 if ( !BER_BVISEMPTY( &fraction ) ) {
3951 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3952 fraction.bv_val, fraction.bv_len );
3953 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3955 strcpy( normalized->bv_val + len-1, "Z" );
3956 normalized->bv_len = len;
3958 return LDAP_SUCCESS;
3962 generalizedTimeOrderingMatch(
3967 struct berval *value,
3968 void *assertedValue )
3970 struct berval *asserted = (struct berval *) assertedValue;
3971 ber_len_t v_len = value->bv_len;
3972 ber_len_t av_len = asserted->bv_len;
3974 /* ignore trailing 'Z' when comparing */
3975 int match = memcmp( value->bv_val, asserted->bv_val,
3976 (v_len < av_len ? v_len : av_len) - 1 );
3977 if ( match == 0 ) match = v_len - av_len;
3980 return LDAP_SUCCESS;
3983 /* Index generation function */
3984 int generalizedTimeIndexer(
3989 struct berval *prefix,
3997 BerValue bvtmp; /* 40 bit index */
3999 struct lutil_timet tt;
4001 bvtmp.bv_len = sizeof(tmp);
4003 for( i=0; values[i].bv_val != NULL; i++ ) {
4004 /* just count them */
4007 /* we should have at least one value at this point */
4010 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4012 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4013 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4014 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4015 /* Use 40 bits of time for key */
4016 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4017 lutil_tm2time( &tm, &tt );
4018 tmp[0] = tt.tt_gsec & 0xff;
4019 tmp[4] = tt.tt_sec & 0xff;
4021 tmp[3] = tt.tt_sec & 0xff;
4023 tmp[2] = tt.tt_sec & 0xff;
4025 tmp[1] = tt.tt_sec & 0xff;
4027 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4031 keys[j].bv_val = NULL;
4036 return LDAP_SUCCESS;
4039 /* Index generation function */
4040 int generalizedTimeFilter(
4045 struct berval *prefix,
4046 void * assertedValue,
4052 BerValue bvtmp; /* 40 bit index */
4053 BerValue *value = (BerValue *) assertedValue;
4055 struct lutil_timet tt;
4057 bvtmp.bv_len = sizeof(tmp);
4059 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4060 /* Use 40 bits of time for key */
4061 if ( value->bv_val && value->bv_len >= 10 &&
4062 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4064 lutil_tm2time( &tm, &tt );
4065 tmp[0] = tt.tt_gsec & 0xff;
4066 tmp[4] = tt.tt_sec & 0xff;
4068 tmp[3] = tt.tt_sec & 0xff;
4070 tmp[2] = tt.tt_sec & 0xff;
4072 tmp[1] = tt.tt_sec & 0xff;
4074 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4075 ber_dupbv_x(keys, &bvtmp, ctx );
4076 keys[1].bv_val = NULL;
4084 return LDAP_SUCCESS;
4088 deliveryMethodValidate(
4090 struct berval *val )
4093 #define LENOF(s) (sizeof(s)-1)
4094 struct berval tmp = *val;
4096 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4097 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4098 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4101 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4103 switch( tmp.bv_val[0] ) {
4106 if(( tmp.bv_len >= LENOF("any") ) &&
4107 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4109 tmp.bv_len -= LENOF("any");
4110 tmp.bv_val += LENOF("any");
4113 return LDAP_INVALID_SYNTAX;
4117 if(( tmp.bv_len >= LENOF("mhs") ) &&
4118 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4120 tmp.bv_len -= LENOF("mhs");
4121 tmp.bv_val += LENOF("mhs");
4124 return LDAP_INVALID_SYNTAX;
4128 if(( tmp.bv_len >= LENOF("physical") ) &&
4129 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4131 tmp.bv_len -= LENOF("physical");
4132 tmp.bv_val += LENOF("physical");
4135 return LDAP_INVALID_SYNTAX;
4138 case 'T': /* telex or teletex or telephone */
4139 if(( tmp.bv_len >= LENOF("telex") ) &&
4140 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4142 tmp.bv_len -= LENOF("telex");
4143 tmp.bv_val += LENOF("telex");
4146 if(( tmp.bv_len >= LENOF("teletex") ) &&
4147 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4149 tmp.bv_len -= LENOF("teletex");
4150 tmp.bv_val += LENOF("teletex");
4153 if(( tmp.bv_len >= LENOF("telephone") ) &&
4154 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4156 tmp.bv_len -= LENOF("telephone");
4157 tmp.bv_val += LENOF("telephone");
4160 return LDAP_INVALID_SYNTAX;
4163 case 'G': /* g3fax or g4fax */
4164 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4165 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4166 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4168 tmp.bv_len -= LENOF("g3fax");
4169 tmp.bv_val += LENOF("g3fax");
4172 return LDAP_INVALID_SYNTAX;
4176 if(( tmp.bv_len >= LENOF("ia5") ) &&
4177 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4179 tmp.bv_len -= LENOF("ia5");
4180 tmp.bv_val += LENOF("ia5");
4183 return LDAP_INVALID_SYNTAX;
4187 if(( tmp.bv_len >= LENOF("videotex") ) &&
4188 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4190 tmp.bv_len -= LENOF("videotex");
4191 tmp.bv_val += LENOF("videotex");
4194 return LDAP_INVALID_SYNTAX;
4197 return LDAP_INVALID_SYNTAX;
4200 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4202 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4206 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4210 return LDAP_INVALID_SYNTAX;
4212 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4221 nisNetgroupTripleValidate(
4223 struct berval *val )
4228 if ( BER_BVISEMPTY( val ) ) {
4229 return LDAP_INVALID_SYNTAX;
4232 p = (char *)val->bv_val;
4233 e = p + val->bv_len;
4235 if ( *p != '(' /*')'*/ ) {
4236 return LDAP_INVALID_SYNTAX;
4239 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4243 return LDAP_INVALID_SYNTAX;
4246 } else if ( !AD_CHAR( *p ) ) {
4247 return LDAP_INVALID_SYNTAX;
4251 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4252 return LDAP_INVALID_SYNTAX;
4258 return LDAP_INVALID_SYNTAX;
4261 return LDAP_SUCCESS;
4265 bootParameterValidate(
4267 struct berval *val )
4271 if ( BER_BVISEMPTY( val ) ) {
4272 return LDAP_INVALID_SYNTAX;
4275 p = (char *)val->bv_val;
4276 e = p + val->bv_len;
4279 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4280 if ( !AD_CHAR( *p ) ) {
4281 return LDAP_INVALID_SYNTAX;
4286 return LDAP_INVALID_SYNTAX;
4290 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4291 if ( !AD_CHAR( *p ) ) {
4292 return LDAP_INVALID_SYNTAX;
4297 return LDAP_INVALID_SYNTAX;
4301 for ( p++; p < e; p++ ) {
4302 if ( !SLAP_PRINTABLE( *p ) ) {
4303 return LDAP_INVALID_SYNTAX;
4307 return LDAP_SUCCESS;
4311 firstComponentNormalize(
4316 struct berval *normalized,
4323 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4324 ber_dupbv_x( normalized, val, ctx );
4325 return LDAP_SUCCESS;
4328 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4330 if( val->bv_val[0] != '(' /*')'*/ &&
4331 val->bv_val[0] != '{' /*'}'*/ )
4333 return LDAP_INVALID_SYNTAX;
4336 /* trim leading white space */
4338 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4344 /* grab next word */
4345 comp.bv_val = &val->bv_val[len];
4346 len = val->bv_len - len;
4347 for( comp.bv_len = 0;
4348 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4354 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4355 rc = numericoidValidate( NULL, &comp );
4356 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4357 rc = integerValidate( NULL, &comp );
4359 rc = LDAP_INVALID_SYNTAX;
4363 if( rc == LDAP_SUCCESS ) {
4364 ber_dupbv_x( normalized, &comp, ctx );
4370 static char *country_gen_syn[] = {
4371 "1.3.6.1.4.1.1466.115.121.1.15",
4372 "1.3.6.1.4.1.1466.115.121.1.26",
4373 "1.3.6.1.4.1.1466.115.121.1.44",
4377 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4378 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4380 static slap_syntax_defs_rec syntax_defs[] = {
4381 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4382 X_BINARY X_NOT_H_R ")",
4383 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4384 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4385 0, NULL, NULL, NULL},
4386 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4387 0, NULL, NULL, NULL},
4388 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4390 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4391 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4393 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4394 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4395 0, NULL, bitStringValidate, NULL },
4396 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4397 0, NULL, booleanValidate, NULL},
4398 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4399 X_BINARY X_NOT_H_R ")",
4400 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4401 NULL, certificateValidate, NULL},
4402 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4403 X_BINARY X_NOT_H_R ")",
4404 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4405 NULL, certificateListValidate, NULL},
4406 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4407 X_BINARY X_NOT_H_R ")",
4408 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4409 NULL, sequenceValidate, NULL},
4410 #if 0 /* need to go __after__ printableString */
4411 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4412 0, "1.3.6.1.4.1.1466.115.121.1.44",
4413 countryStringValidate, NULL},
4415 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4416 0, NULL, dnValidate, dnPretty},
4417 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4418 0, NULL, rdnValidate, rdnPretty},
4419 #ifdef LDAP_COMP_MATCH
4420 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4421 0, NULL, allComponentsValidate, NULL},
4422 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4423 0, NULL, componentFilterValidate, NULL},
4425 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4426 0, NULL, NULL, NULL},
4427 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4428 0, NULL, deliveryMethodValidate, NULL},
4429 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4430 0, NULL, UTF8StringValidate, NULL},
4431 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4432 0, NULL, NULL, NULL},
4433 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4434 0, NULL, NULL, NULL},
4435 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4436 0, NULL, NULL, NULL},
4437 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4438 0, NULL, NULL, NULL},
4439 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4440 0, NULL, NULL, NULL},
4441 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4442 0, NULL, printablesStringValidate, NULL},
4443 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4444 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4445 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4446 0, NULL, generalizedTimeValidate, NULL},
4447 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4448 0, NULL, NULL, NULL},
4449 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4450 0, NULL, IA5StringValidate, NULL},
4451 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4452 0, NULL, integerValidate, NULL},
4453 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4454 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4455 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4456 0, NULL, NULL, NULL},
4457 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4458 0, NULL, NULL, NULL},
4459 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4460 0, NULL, NULL, NULL},
4461 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4462 0, NULL, NULL, NULL},
4463 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4464 0, NULL, NULL, NULL},
4465 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4466 0, NULL, nameUIDValidate, nameUIDPretty },
4467 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4468 0, NULL, NULL, NULL},
4469 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4470 0, NULL, numericStringValidate, NULL},
4471 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4472 0, NULL, NULL, NULL},
4473 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4474 0, NULL, numericoidValidate, NULL},
4475 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4476 0, NULL, IA5StringValidate, NULL},
4477 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4478 0, NULL, blobValidate, NULL},
4479 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4480 0, NULL, UTF8StringValidate, NULL},
4481 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4482 0, NULL, NULL, NULL},
4483 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4484 0, NULL, NULL, NULL},
4485 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4486 0, NULL, printableStringValidate, NULL},
4487 /* moved here because now depends on Directory String, IA5 String
4488 * and Printable String */
4489 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4490 0, country_gen_syn, countryStringValidate, NULL},
4491 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4492 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4493 0, NULL, subtreeSpecificationValidate, NULL},
4494 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4495 X_BINARY X_NOT_H_R ")",
4496 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4497 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4498 0, NULL, printableStringValidate, NULL},
4499 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4500 0, NULL, NULL, NULL},
4501 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4502 0, NULL, printablesStringValidate, NULL},
4503 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4504 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4505 0, NULL, utcTimeValidate, NULL},
4507 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4508 0, NULL, NULL, NULL},
4509 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4510 0, NULL, NULL, NULL},
4511 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4512 0, NULL, NULL, NULL},
4513 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4514 0, NULL, NULL, NULL},
4515 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4516 0, NULL, NULL, NULL},
4518 /* RFC 2307 NIS Syntaxes */
4519 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4520 0, NULL, nisNetgroupTripleValidate, NULL},
4521 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4522 0, NULL, bootParameterValidate, NULL},
4524 /* draft-zeilenga-ldap-x509 */
4525 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4526 SLAP_SYNTAX_HIDE, NULL,
4527 serialNumberAndIssuerValidate,
4528 serialNumberAndIssuerPretty},
4529 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4530 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4531 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4532 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4533 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4534 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4535 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4536 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4537 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4538 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4539 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4540 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4542 #ifdef SLAPD_AUTHPASSWD
4543 /* needs updating */
4544 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4545 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4548 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4549 0, NULL, UUIDValidate, UUIDPretty},
4551 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4552 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4554 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4555 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4557 /* OpenLDAP Void Syntax */
4558 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4559 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4561 /* FIXME: OID is unused, but not registered yet */
4562 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4563 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4565 {NULL, 0, NULL, NULL, NULL}
4568 char *csnSIDMatchSyntaxes[] = {
4569 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4572 char *certificateExactMatchSyntaxes[] = {
4573 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4576 #ifdef LDAP_COMP_MATCH
4577 char *componentFilterMatchSyntaxes[] = {
4578 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4582 char *directoryStringSyntaxes[] = {
4583 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4586 char *integerFirstComponentMatchSyntaxes[] = {
4587 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4588 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4591 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4592 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4593 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4594 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4595 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4596 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4597 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4598 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4599 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4604 * Other matching rules in X.520 that we do not use (yet):
4606 * 2.5.13.25 uTCTimeMatch
4607 * 2.5.13.26 uTCTimeOrderingMatch
4608 * 2.5.13.31* directoryStringFirstComponentMatch
4609 * 2.5.13.32* wordMatch
4610 * 2.5.13.33* keywordMatch
4611 * 2.5.13.36+ certificatePairExactMatch
4612 * 2.5.13.37+ certificatePairMatch
4613 * 2.5.13.38+ certificateListExactMatch
4614 * 2.5.13.39+ certificateListMatch
4615 * 2.5.13.40+ algorithmIdentifierMatch
4616 * 2.5.13.41* storedPrefixMatch
4617 * 2.5.13.42 attributeCertificateMatch
4618 * 2.5.13.43 readerAndKeyIDMatch
4619 * 2.5.13.44 attributeIntegrityMatch
4621 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4622 * (+) described in draft-zeilenga-ldap-x509
4624 static slap_mrule_defs_rec mrule_defs[] = {
4626 * EQUALITY matching rules must be listed after associated APPROX
4627 * matching rules. So, we list all APPROX matching rules first.
4629 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4631 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4632 NULL, NULL, directoryStringApproxMatch,
4633 directoryStringApproxIndexer, directoryStringApproxFilter,
4636 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4637 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4638 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4639 NULL, NULL, IA5StringApproxMatch,
4640 IA5StringApproxIndexer, IA5StringApproxFilter,
4644 * Other matching rules
4647 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4649 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4650 NULL, NULL, octetStringMatch,
4651 octetStringIndexer, octetStringFilter,
4654 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4656 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4657 NULL, dnNormalize, dnMatch,
4658 octetStringIndexer, octetStringFilter,
4661 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4663 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4664 NULL, dnNormalize, dnRelativeMatch,
4668 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4669 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4670 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4671 NULL, dnNormalize, dnRelativeMatch,
4675 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4676 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4677 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4678 NULL, dnNormalize, dnRelativeMatch,
4682 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4683 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4684 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4685 NULL, dnNormalize, dnRelativeMatch,
4689 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4690 "SYNTAX 1.2.36.79672281.1.5.0 )",
4691 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4692 NULL, rdnNormalize, rdnMatch,
4693 octetStringIndexer, octetStringFilter,
4696 #ifdef LDAP_COMP_MATCH
4697 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4698 "SYNTAX 1.2.36.79672281.1.5.2 )",
4699 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4700 NULL, NULL , componentFilterMatch,
4701 octetStringIndexer, octetStringFilter,
4704 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4705 "SYNTAX 1.2.36.79672281.1.5.3 )",
4706 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4707 NULL, NULL , allComponentsMatch,
4708 octetStringIndexer, octetStringFilter,
4711 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4712 "SYNTAX 1.2.36.79672281.1.5.3 )",
4713 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4714 NULL, NULL , directoryComponentsMatch,
4715 octetStringIndexer, octetStringFilter,
4719 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4720 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4721 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4722 NULL, UTF8StringNormalize, octetStringMatch,
4723 octetStringIndexer, octetStringFilter,
4724 directoryStringApproxMatchOID },
4726 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4728 SLAP_MR_ORDERING, directoryStringSyntaxes,
4729 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4731 "caseIgnoreMatch" },
4733 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4734 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4735 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4736 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4737 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4738 "caseIgnoreMatch" },
4740 {"( 2.5.13.5 NAME 'caseExactMatch' "
4741 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4742 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4743 NULL, UTF8StringNormalize, octetStringMatch,
4744 octetStringIndexer, octetStringFilter,
4745 directoryStringApproxMatchOID },
4747 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4748 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4749 SLAP_MR_ORDERING, directoryStringSyntaxes,
4750 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4754 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4755 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4756 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4757 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4758 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4761 {"( 2.5.13.8 NAME 'numericStringMatch' "
4762 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4763 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4764 NULL, numericStringNormalize, octetStringMatch,
4765 octetStringIndexer, octetStringFilter,
4768 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4769 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4770 SLAP_MR_ORDERING, NULL,
4771 NULL, numericStringNormalize, octetStringOrderingMatch,
4773 "numericStringMatch" },
4775 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4776 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4777 SLAP_MR_SUBSTR, NULL,
4778 NULL, numericStringNormalize, octetStringSubstringsMatch,
4779 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4780 "numericStringMatch" },
4782 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4783 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4784 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4785 NULL, NULL, NULL, NULL, NULL, NULL },
4787 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4788 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4789 SLAP_MR_SUBSTR, NULL,
4790 NULL, NULL, NULL, NULL, NULL,
4791 "caseIgnoreListMatch" },
4793 {"( 2.5.13.13 NAME 'booleanMatch' "
4794 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4795 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4796 NULL, NULL, booleanMatch,
4797 octetStringIndexer, octetStringFilter,
4800 {"( 2.5.13.14 NAME 'integerMatch' "
4801 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4802 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4803 NULL, NULL, integerMatch,
4804 integerIndexer, integerFilter,
4807 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4809 SLAP_MR_ORDERING, NULL,
4810 NULL, NULL, integerMatch,
4814 {"( 2.5.13.16 NAME 'bitStringMatch' "
4815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4816 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4817 NULL, NULL, octetStringMatch,
4818 octetStringIndexer, octetStringFilter,
4821 {"( 2.5.13.17 NAME 'octetStringMatch' "
4822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4823 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4824 NULL, NULL, octetStringMatch,
4825 octetStringIndexer, octetStringFilter,
4828 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4829 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4830 SLAP_MR_ORDERING, NULL,
4831 NULL, NULL, octetStringOrderingMatch,
4833 "octetStringMatch" },
4835 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4836 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4837 SLAP_MR_SUBSTR, NULL,
4838 NULL, NULL, octetStringSubstringsMatch,
4839 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4840 "octetStringMatch" },
4842 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4843 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4844 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4846 telephoneNumberNormalize, octetStringMatch,
4847 octetStringIndexer, octetStringFilter,
4850 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4851 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4852 SLAP_MR_SUBSTR, NULL,
4853 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4854 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4855 "telephoneNumberMatch" },
4857 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4858 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4859 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4860 NULL, NULL, NULL, NULL, NULL, NULL },
4862 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4864 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4865 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4866 uniqueMemberIndexer, uniqueMemberFilter,
4869 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4870 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4871 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4872 NULL, NULL, NULL, NULL, NULL, NULL },
4874 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4876 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4877 NULL, generalizedTimeNormalize, octetStringMatch,
4878 generalizedTimeIndexer, generalizedTimeFilter,
4881 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4882 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4883 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4884 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4886 "generalizedTimeMatch" },
4888 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4889 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4890 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4891 integerFirstComponentMatchSyntaxes,
4892 NULL, firstComponentNormalize, integerMatch,
4893 octetStringIndexer, octetStringFilter,
4896 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4897 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4898 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4899 objectIdentifierFirstComponentMatchSyntaxes,
4900 NULL, firstComponentNormalize, octetStringMatch,
4901 octetStringIndexer, octetStringFilter,
4904 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4905 "SYNTAX 1.3.6.1.1.15.1 )",
4906 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4907 NULL, certificateExactNormalize, octetStringMatch,
4908 octetStringIndexer, octetStringFilter,
4911 {"( 2.5.13.35 NAME 'certificateMatch' "
4912 "SYNTAX 1.3.6.1.1.15.2 )",
4913 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4914 NULL, NULL, NULL, NULL, NULL,
4917 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4919 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4920 NULL, IA5StringNormalize, octetStringMatch,
4921 octetStringIndexer, octetStringFilter,
4922 IA5StringApproxMatchOID },
4924 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4926 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4927 NULL, IA5StringNormalize, octetStringMatch,
4928 octetStringIndexer, octetStringFilter,
4929 IA5StringApproxMatchOID },
4931 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4932 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4933 SLAP_MR_SUBSTR, NULL,
4934 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4935 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4936 "caseIgnoreIA5Match" },
4938 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4939 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4940 SLAP_MR_SUBSTR, NULL,
4941 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4942 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4943 "caseExactIA5Match" },
4945 #ifdef SLAPD_AUTHPASSWD
4946 /* needs updating */
4947 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4948 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4949 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4950 NULL, NULL, authPasswordMatch,
4955 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4958 NULL, NULL, integerBitAndMatch,
4962 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4963 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4965 NULL, NULL, integerBitOrMatch,
4969 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4970 "SYNTAX 1.3.6.1.1.16.1 )",
4971 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4972 NULL, UUIDNormalize, octetStringMatch,
4973 octetStringIndexer, octetStringFilter,
4976 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4977 "SYNTAX 1.3.6.1.1.16.1 )",
4978 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4979 NULL, UUIDNormalize, octetStringOrderingMatch,
4980 octetStringIndexer, octetStringFilter,
4983 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4984 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4985 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4986 NULL, csnNormalize, csnMatch,
4987 csnIndexer, csnFilter,
4990 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4991 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4992 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4993 NULL, NULL, csnOrderingMatch,
4997 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
4998 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
4999 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5000 NULL, csnSidNormalize, octetStringMatch,
5001 octetStringIndexer, octetStringFilter,
5004 /* FIXME: OID is unused, but not registered yet */
5005 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5006 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5007 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5008 NULL, authzNormalize, authzMatch,
5012 {NULL, SLAP_MR_NONE, NULL,
5013 NULL, NULL, NULL, NULL, NULL,
5018 slap_schema_init( void )
5023 /* we should only be called once (from main) */
5024 assert( schema_init_done == 0 );
5026 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5027 res = register_syntax( &syntax_defs[i] );
5030 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5031 syntax_defs[i].sd_desc );
5036 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5037 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5038 mrule_defs[i].mrd_compat_syntaxes == NULL )
5041 "slap_schema_init: Ignoring unusable matching rule %s\n",
5042 mrule_defs[i].mrd_desc );
5046 res = register_matching_rule( &mrule_defs[i] );
5050 "slap_schema_init: Error registering matching rule %s\n",
5051 mrule_defs[i].mrd_desc );
5056 res = slap_schema_load();
5057 schema_init_done = 1;
5062 schema_destroy( void )
5071 if( schema_init_done ) {
5072 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5073 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );