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 /* FIXME: temporary */
59 #define authzMatch octetStringMatch
61 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
62 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
63 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
64 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
66 ldap_pvt_thread_mutex_t ad_undef_mutex;
67 ldap_pvt_thread_mutex_t oc_undef_mutex;
70 generalizedTimeValidate(
79 /* no value allowed */
80 return LDAP_INVALID_SYNTAX;
88 /* any value allowed */
92 #define berValidate blobValidate
99 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
100 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
105 /* X.509 related stuff */
113 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
116 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
117 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
118 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
119 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
123 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
126 /* X.509 certificate validation */
127 static int certificateValidate( Syntax *syntax, struct berval *in )
129 BerElementBuffer berbuf;
130 BerElement *ber = (BerElement *)&berbuf;
133 ber_int_t version = SLAP_X509_V1;
135 ber_init2( ber, in, LBER_USE_DER );
136 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
137 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
138 tag = ber_skip_tag( ber, &len ); /* Sequence */
139 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
140 tag = ber_peek_tag( ber, &len );
141 /* Optional version */
142 if ( tag == SLAP_X509_OPT_C_VERSION ) {
143 tag = ber_skip_tag( ber, &len );
144 tag = ber_get_int( ber, &version );
145 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
147 /* NOTE: don't try to parse Serial, because it might be longer
148 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
149 tag = ber_skip_tag( ber, &len ); /* Serial */
150 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
151 ber_skip_data( ber, len );
152 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
153 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
154 ber_skip_data( ber, len );
155 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
157 ber_skip_data( ber, len );
158 tag = ber_skip_tag( ber, &len ); /* Validity */
159 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
160 ber_skip_data( ber, len );
161 tag = ber_skip_tag( ber, &len ); /* Subject DN */
162 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
163 ber_skip_data( ber, len );
164 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
165 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
166 ber_skip_data( ber, len );
167 tag = ber_skip_tag( ber, &len );
168 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
169 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
170 ber_skip_data( ber, len );
171 tag = ber_skip_tag( ber, &len );
173 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
174 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
175 ber_skip_data( ber, len );
176 tag = ber_skip_tag( ber, &len );
178 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
179 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
180 tag = ber_skip_tag( ber, &len );
181 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
182 ber_skip_data( ber, len );
183 tag = ber_skip_tag( ber, &len );
185 /* signatureAlgorithm */
186 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
187 ber_skip_data( ber, len );
188 tag = ber_skip_tag( ber, &len );
190 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
191 ber_skip_data( ber, len );
192 tag = ber_skip_tag( ber, &len );
193 /* Must be at end now */
194 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
198 /* X.509 certificate list validation */
200 static int certificateListValidate( Syntax *syntax, struct berval *in )
202 BerElementBuffer berbuf;
203 BerElement *ber = (BerElement *)&berbuf;
206 ber_int_t version = SLAP_X509_V1;
208 ber_init2( ber, in, LBER_USE_DER );
209 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
210 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
211 tag = ber_skip_tag( ber, &len ); /* Sequence */
212 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
213 tag = ber_peek_tag( ber, &len );
214 /* Optional version */
215 if ( tag == LBER_INTEGER ) {
216 tag = ber_get_int( ber, &version );
217 assert( tag == LBER_INTEGER );
218 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
220 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
221 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
222 ber_skip_data( ber, len );
223 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
224 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
225 ber_skip_data( ber, len );
226 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
227 /* NOTE: in the certificates I'm playing with, the time is UTC.
228 * maybe the tag is different from 0x17U for generalizedTime? */
229 if ( tag != 0x17U ) return LDAP_INVALID_SYNTAX;
230 ber_skip_data( ber, len );
231 /* Optional nextUpdate */
232 tag = ber_skip_tag( ber, &len );
233 if ( tag == 0x17U ) {
234 ber_skip_data( ber, len );
235 tag = ber_skip_tag( ber, &len );
237 /* Optional revokedCertificates */
238 if ( tag == LBER_SEQUENCE ) {
239 /* Should NOT be empty */
240 ber_skip_data( ber, len );
241 tag = ber_skip_tag( ber, &len );
243 /* Optional Extensions */
244 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
245 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
246 tag = ber_skip_tag( ber, &len );
247 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
248 ber_skip_data( ber, len );
249 tag = ber_skip_tag( ber, &len );
251 /* signatureAlgorithm */
252 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
253 ber_skip_data( ber, len );
254 tag = ber_skip_tag( ber, &len );
256 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
257 ber_skip_data( ber, len );
258 tag = ber_skip_tag( ber, &len );
259 /* Must be at end now */
260 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
263 #else /* ! LDAP_DEVEL */
264 #define certificateListValidate sequenceValidate
265 #endif /* ! LDAP_DEVEL */
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.
1456 Basically same as PrintableString. There are no examples in X.500,
1457 but same logic applies. So we require them to be non-empty as
1460 -------------------------------------------------------------------*/
1469 unsigned char *u = (unsigned char *)in->bv_val;
1471 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1472 /* directory strings cannot be empty */
1473 return LDAP_INVALID_SYNTAX;
1476 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1477 /* get the length indicated by the first byte */
1478 len = LDAP_UTF8_CHARLEN2( u, len );
1480 /* very basic checks */
1483 if( (u[5] & 0xC0) != 0x80 ) {
1484 return LDAP_INVALID_SYNTAX;
1487 if( (u[4] & 0xC0) != 0x80 ) {
1488 return LDAP_INVALID_SYNTAX;
1491 if( (u[3] & 0xC0) != 0x80 ) {
1492 return LDAP_INVALID_SYNTAX;
1495 if( (u[2] & 0xC0 )!= 0x80 ) {
1496 return LDAP_INVALID_SYNTAX;
1499 if( (u[1] & 0xC0) != 0x80 ) {
1500 return LDAP_INVALID_SYNTAX;
1503 /* CHARLEN already validated it */
1506 return LDAP_INVALID_SYNTAX;
1509 /* make sure len corresponds with the offset
1510 to the next character */
1511 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1515 return LDAP_INVALID_SYNTAX;
1518 return LDAP_SUCCESS;
1522 UTF8StringNormalize(
1527 struct berval *normalized,
1530 struct berval tmp, nvalue;
1534 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1536 if( BER_BVISNULL( val ) ) {
1537 /* assume we're dealing with a syntax (e.g., UTF8String)
1538 * which allows empty strings
1540 BER_BVZERO( normalized );
1541 return LDAP_SUCCESS;
1544 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1545 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1546 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1547 ? LDAP_UTF8_APPROX : 0;
1549 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1554 /* collapse spaces (in place) */
1556 nvalue.bv_val = tmp.bv_val;
1558 /* trim leading spaces? */
1559 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1560 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1562 for( i = 0; i < tmp.bv_len; i++) {
1563 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1564 if( wasspace++ == 0 ) {
1565 /* trim repeated spaces */
1566 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1570 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1574 if( !BER_BVISEMPTY( &nvalue ) ) {
1575 /* trim trailing space? */
1577 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1578 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1582 nvalue.bv_val[nvalue.bv_len] = '\0';
1585 /* string of all spaces is treated as one space */
1586 nvalue.bv_val[0] = ' ';
1587 nvalue.bv_val[1] = '\0';
1591 *normalized = nvalue;
1592 return LDAP_SUCCESS;
1596 directoryStringSubstringsMatch(
1601 struct berval *value,
1602 void *assertedValue )
1605 SubstringsAssertion *sub = assertedValue;
1606 struct berval left = *value;
1610 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1611 if ( sub->sa_initial.bv_len > left.bv_len ) {
1612 /* not enough left */
1617 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1618 sub->sa_initial.bv_len );
1624 left.bv_val += sub->sa_initial.bv_len;
1625 left.bv_len -= sub->sa_initial.bv_len;
1627 priorspace = ASCII_SPACE(
1628 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1631 if ( sub->sa_any ) {
1632 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1636 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1637 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1639 /* allow next space to match */
1646 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1650 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1651 /* not enough left */
1656 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1663 idx = p - left.bv_val;
1665 if ( idx >= left.bv_len ) {
1666 /* this shouldn't happen */
1673 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1674 /* not enough left */
1679 match = memcmp( left.bv_val,
1680 sub->sa_any[i].bv_val,
1681 sub->sa_any[i].bv_len );
1689 left.bv_val += sub->sa_any[i].bv_len;
1690 left.bv_len -= sub->sa_any[i].bv_len;
1692 priorspace = ASCII_SPACE(
1693 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1697 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1698 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1699 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1701 /* allow next space to match */
1706 if ( sub->sa_final.bv_len > left.bv_len ) {
1707 /* not enough left */
1712 match = memcmp( sub->sa_final.bv_val,
1713 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1714 sub->sa_final.bv_len );
1723 return LDAP_SUCCESS;
1726 #if defined(SLAPD_APPROX_INITIALS)
1727 # define SLAPD_APPROX_DELIMITER "._ "
1728 # define SLAPD_APPROX_WORDLEN 2
1730 # define SLAPD_APPROX_DELIMITER " "
1731 # define SLAPD_APPROX_WORDLEN 1
1740 struct berval *value,
1741 void *assertedValue )
1743 struct berval *nval, *assertv;
1744 char *val, **values, **words, *c;
1745 int i, count, len, nextchunk=0, nextavail=0;
1747 /* Yes, this is necessary */
1748 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1749 if( nval == NULL ) {
1751 return LDAP_SUCCESS;
1754 /* Yes, this is necessary */
1755 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1756 NULL, LDAP_UTF8_APPROX, NULL );
1757 if( assertv == NULL ) {
1760 return LDAP_SUCCESS;
1763 /* Isolate how many words there are */
1764 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1765 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1766 if ( c == NULL ) break;
1771 /* Get a phonetic copy of each word */
1772 words = (char **)ch_malloc( count * sizeof(char *) );
1773 values = (char **)ch_malloc( count * sizeof(char *) );
1774 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1776 values[i] = phonetic(c);
1779 /* Work through the asserted value's words, to see if at least some
1780 of the words are there, in the same order. */
1782 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1783 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1788 #if defined(SLAPD_APPROX_INITIALS)
1789 else if( len == 1 ) {
1790 /* Single letter words need to at least match one word's initial */
1791 for( i=nextavail; i<count; i++ )
1792 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1799 /* Isolate the next word in the asserted value and phonetic it */
1800 assertv->bv_val[nextchunk+len] = '\0';
1801 val = phonetic( assertv->bv_val + nextchunk );
1803 /* See if this phonetic chunk is in the remaining words of *value */
1804 for( i=nextavail; i<count; i++ ){
1805 if( !strcmp( val, values[i] ) ){
1813 /* This chunk in the asserted value was NOT within the *value. */
1819 /* Go on to the next word in the asserted value */
1823 /* If some of the words were seen, call it a match */
1824 if( nextavail > 0 ) {
1831 /* Cleanup allocs */
1832 ber_bvfree( assertv );
1833 for( i=0; i<count; i++ ) {
1834 ch_free( values[i] );
1840 return LDAP_SUCCESS;
1849 struct berval *prefix,
1855 int i,j, len, wordcount, keycount=0;
1856 struct berval *newkeys;
1857 BerVarray keys=NULL;
1859 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1860 struct berval val = BER_BVNULL;
1861 /* Yes, this is necessary */
1862 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1863 assert( !BER_BVISNULL( &val ) );
1865 /* Isolate how many words there are. There will be a key for each */
1866 for( wordcount = 0, c = val.bv_val; *c; c++) {
1867 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1868 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1870 if (*c == '\0') break;
1874 /* Allocate/increase storage to account for new keys */
1875 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1876 * sizeof(struct berval) );
1877 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1878 if( keys ) ch_free( keys );
1881 /* Get a phonetic copy of each word */
1882 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1884 if( len < SLAPD_APPROX_WORDLEN ) continue;
1885 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1890 ber_memfree( val.bv_val );
1892 BER_BVZERO( &keys[keycount] );
1895 return LDAP_SUCCESS;
1904 struct berval *prefix,
1905 void * assertedValue,
1914 /* Yes, this is necessary */
1915 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1916 NULL, LDAP_UTF8_APPROX, NULL );
1917 if( val == NULL || BER_BVISNULL( val ) ) {
1918 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1919 BER_BVZERO( &keys[0] );
1922 return LDAP_SUCCESS;
1925 /* Isolate how many words there are. There will be a key for each */
1926 for( count = 0,c = val->bv_val; *c; c++) {
1927 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1928 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1930 if (*c == '\0') break;
1934 /* Allocate storage for new keys */
1935 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1937 /* Get a phonetic copy of each word */
1938 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1940 if( len < SLAPD_APPROX_WORDLEN ) continue;
1941 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1947 BER_BVZERO( &keys[count] );
1950 return LDAP_SUCCESS;
1953 /* Remove all spaces and '-' characters */
1955 telephoneNumberNormalize(
1960 struct berval *normalized,
1965 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1967 /* validator should have refused an empty string */
1968 assert( !BER_BVISEMPTY( val ) );
1970 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1972 for( p = val->bv_val; *p; p++ ) {
1973 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1979 normalized->bv_len = q - normalized->bv_val;
1981 if( BER_BVISEMPTY( normalized ) ) {
1982 slap_sl_free( normalized->bv_val, ctx );
1983 BER_BVZERO( normalized );
1984 return LDAP_INVALID_SYNTAX;
1987 return LDAP_SUCCESS;
1995 struct berval val = *in;
1997 if( BER_BVISEMPTY( &val ) ) {
1998 /* disallow empty strings */
1999 return LDAP_INVALID_SYNTAX;
2002 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2003 if ( val.bv_len == 1 ) {
2004 return LDAP_SUCCESS;
2007 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2014 while ( OID_LEADCHAR( val.bv_val[0] )) {
2018 if ( val.bv_len == 0 ) {
2019 return LDAP_SUCCESS;
2023 if( !OID_SEPARATOR( val.bv_val[0] )) {
2031 return LDAP_INVALID_SYNTAX;
2040 struct berval val = *in;
2042 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2044 if ( val.bv_val[0] == '-' ) {
2048 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2049 return LDAP_INVALID_SYNTAX;
2052 if( val.bv_val[0] == '0' ) { /* "-0" */
2053 return LDAP_INVALID_SYNTAX;
2056 } else if ( val.bv_val[0] == '0' ) {
2057 if( val.bv_len > 1 ) { /* "0<more>" */
2058 return LDAP_INVALID_SYNTAX;
2061 return LDAP_SUCCESS;
2064 for( i=0; i < val.bv_len; i++ ) {
2065 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2066 return LDAP_INVALID_SYNTAX;
2070 return LDAP_SUCCESS;
2079 struct berval *value,
2080 void *assertedValue )
2082 struct berval *asserted = (struct berval *) assertedValue;
2083 int vsign = 1, asign = 1; /* default sign = '+' */
2088 if( v.bv_val[0] == '-' ) {
2094 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2097 if( a.bv_val[0] == '-' ) {
2103 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2105 match = vsign - asign;
2107 match = ( v.bv_len != a.bv_len
2108 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2109 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2110 if( vsign < 0 ) match = -match;
2114 return LDAP_SUCCESS;
2118 countryStringValidate(
2120 struct berval *val )
2122 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2124 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2125 return LDAP_INVALID_SYNTAX;
2127 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2128 return LDAP_INVALID_SYNTAX;
2131 return LDAP_SUCCESS;
2135 printableStringValidate(
2137 struct berval *val )
2141 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2143 for(i=0; i < val->bv_len; i++) {
2144 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2145 return LDAP_INVALID_SYNTAX;
2149 return LDAP_SUCCESS;
2153 printablesStringValidate(
2155 struct berval *val )
2159 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2161 for(i=0,len=0; i < val->bv_len; i++) {
2162 int c = val->bv_val[i];
2166 return LDAP_INVALID_SYNTAX;
2170 } else if ( SLAP_PRINTABLE(c) ) {
2173 return LDAP_INVALID_SYNTAX;
2178 return LDAP_INVALID_SYNTAX;
2181 return LDAP_SUCCESS;
2187 struct berval *val )
2191 for(i=0; i < val->bv_len; i++) {
2192 if( !LDAP_ASCII(val->bv_val[i]) ) {
2193 return LDAP_INVALID_SYNTAX;
2197 return LDAP_SUCCESS;
2206 struct berval *normalized,
2210 int casefold = !SLAP_MR_ASSOCIATED( mr,
2211 slap_schema.si_mr_caseExactIA5Match );
2213 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2217 /* Ignore initial whitespace */
2218 while ( ASCII_SPACE( *p ) ) p++;
2220 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2221 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2222 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2223 normalized->bv_val[normalized->bv_len] = '\0';
2225 p = q = normalized->bv_val;
2228 if ( ASCII_SPACE( *p ) ) {
2231 /* Ignore the extra whitespace */
2232 while ( ASCII_SPACE( *p ) ) {
2236 } else if ( casefold ) {
2237 /* Most IA5 rules require casefolding */
2238 *q++ = TOLOWER(*p); p++;
2245 assert( normalized->bv_val <= p );
2249 * If the string ended in space, backup the pointer one
2250 * position. One is enough because the above loop collapsed
2251 * all whitespace to a single space.
2253 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2255 /* null terminate */
2258 normalized->bv_len = q - normalized->bv_val;
2260 return LDAP_SUCCESS;
2269 if( in->bv_len != 36 ) {
2270 return LDAP_INVALID_SYNTAX;
2273 for( i=0; i<36; i++ ) {
2279 if( in->bv_val[i] != '-' ) {
2280 return LDAP_INVALID_SYNTAX;
2284 if( !ASCII_HEX( in->bv_val[i]) ) {
2285 return LDAP_INVALID_SYNTAX;
2290 return LDAP_SUCCESS;
2301 int rc=LDAP_INVALID_SYNTAX;
2303 assert( in != NULL );
2304 assert( out != NULL );
2306 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2309 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2311 for( i=0; i<36; i++ ) {
2317 if( in->bv_val[i] != '-' ) {
2320 out->bv_val[i] = '-';
2324 if( !ASCII_HEX( in->bv_val[i]) ) {
2327 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2332 out->bv_val[ out->bv_len ] = '\0';
2336 slap_sl_free( out->bv_val, ctx );
2349 struct berval *normalized,
2352 unsigned char octet = '\0';
2355 normalized->bv_len = 16;
2356 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2358 for( i=0, j=0; i<36; i++ ) {
2359 unsigned char nibble;
2360 if( val->bv_val[i] == '-' ) {
2363 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2364 nibble = val->bv_val[i] - '0';
2366 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2367 nibble = val->bv_val[i] - ('a'-10);
2369 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2370 nibble = val->bv_val[i] - ('A'-10);
2373 slap_sl_free( normalized->bv_val, ctx );
2374 return LDAP_INVALID_SYNTAX;
2379 normalized->bv_val[j>>1] = octet;
2381 octet = nibble << 4;
2386 normalized->bv_val[normalized->bv_len] = 0;
2387 return LDAP_SUCCESS;
2393 numericStringValidate(
2399 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2401 for(i=0; i < in->bv_len; i++) {
2402 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2403 return LDAP_INVALID_SYNTAX;
2407 return LDAP_SUCCESS;
2411 numericStringNormalize(
2416 struct berval *normalized,
2419 /* removal all spaces */
2422 assert( !BER_BVISEMPTY( val ) );
2424 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2427 q = normalized->bv_val;
2430 if ( ASCII_SPACE( *p ) ) {
2431 /* Ignore whitespace */
2438 /* we should have copied no more than is in val */
2439 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2441 /* null terminate */
2444 normalized->bv_len = q - normalized->bv_val;
2446 if( BER_BVISEMPTY( normalized ) ) {
2447 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2448 normalized->bv_val[0] = ' ';
2449 normalized->bv_val[1] = '\0';
2450 normalized->bv_len = 1;
2453 return LDAP_SUCCESS;
2457 * Integer conversion macros that will use the largest available
2460 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2461 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2462 # define SLAP_LONG long long
2464 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2465 # define SLAP_LONG long
2466 #endif /* HAVE_STRTOLL ... */
2474 struct berval *value,
2475 void *assertedValue )
2477 SLAP_LONG lValue, lAssertedValue;
2480 /* safe to assume integers are NUL terminated? */
2481 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2482 if( errno == ERANGE )
2484 return LDAP_CONSTRAINT_VIOLATION;
2487 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2489 if( errno == ERANGE )
2491 return LDAP_CONSTRAINT_VIOLATION;
2494 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2495 return LDAP_SUCCESS;
2504 struct berval *value,
2505 void *assertedValue )
2507 SLAP_LONG lValue, lAssertedValue;
2510 /* safe to assume integers are NUL terminated? */
2511 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2512 if( errno == ERANGE )
2514 return LDAP_CONSTRAINT_VIOLATION;
2517 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2519 if( errno == ERANGE )
2521 return LDAP_CONSTRAINT_VIOLATION;
2524 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2525 return LDAP_SUCCESS;
2529 serialNumberAndIssuerValidate(
2535 struct berval sn, i;
2537 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2540 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2542 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2543 /* Parse old format */
2544 i.bv_val = ber_bvchr( in, '$' );
2545 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2547 sn.bv_val = in->bv_val;
2548 sn.bv_len = i.bv_val - in->bv_val;
2551 i.bv_len = in->bv_len - (sn.bv_len + 1);
2553 /* eat leading zeros */
2554 for( n=0; n < (sn.bv_len-1); n++ ) {
2555 if( sn.bv_val[n] != '0' ) break;
2560 for( n=0; n < sn.bv_len; n++ ) {
2561 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2565 /* Parse GSER format */
2566 int havesn=0,haveissuer=0;
2567 struct berval x = *in;
2571 /* eat leading spaces */
2572 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2576 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2577 return LDAP_INVALID_SYNTAX;
2580 /* should be at issuer or serialNumber NamedValue */
2581 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2583 x.bv_val += STRLENOF("issuer");
2584 x.bv_len -= STRLENOF("issuer");
2586 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2587 x.bv_val++; x.bv_len--;
2589 /* eat leading spaces */
2590 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2594 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2595 x.bv_val++; x.bv_len--;
2597 i.bv_val = x.bv_val;
2600 for( ; i.bv_len < x.bv_len; ) {
2601 if ( i.bv_val[i.bv_len] != '"' ) {
2605 if ( i.bv_val[i.bv_len+1] == '"' ) {
2612 x.bv_val += i.bv_len+1;
2613 x.bv_len -= i.bv_len+1;
2615 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2616 return LDAP_INVALID_SYNTAX;
2621 } else if( strncasecmp( x.bv_val, "serialNumber",
2622 STRLENOF("serialNumber")) == 0 )
2624 /* parse serialNumber */
2626 x.bv_val += STRLENOF("serialNumber");
2627 x.bv_len -= STRLENOF("serialNumber");
2629 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2630 x.bv_val++; x.bv_len--;
2632 /* eat leading spaces */
2633 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2637 sn.bv_val = x.bv_val;
2640 if( sn.bv_val[0] == '-' ) {
2645 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2646 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2649 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2650 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2651 return LDAP_INVALID_SYNTAX;
2654 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2656 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2657 return LDAP_INVALID_SYNTAX;
2662 } else return LDAP_INVALID_SYNTAX;
2664 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2665 x.bv_val++; x.bv_len--;
2668 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2672 /* should be at remaining NamedValue */
2673 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2674 STRLENOF("issuer" )) == 0 ))
2677 x.bv_val += STRLENOF("issuer");
2678 x.bv_len -= STRLENOF("issuer");
2680 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2681 x.bv_val++; x.bv_len--;
2683 /* eat leading spaces */
2684 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2688 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2689 x.bv_val++; x.bv_len--;
2691 i.bv_val = x.bv_val;
2694 for( ; i.bv_len < x.bv_len; ) {
2695 if ( i.bv_val[i.bv_len] != '"' ) {
2699 if ( i.bv_val[i.bv_len+1] == '"' ) {
2706 x.bv_val += i.bv_len+1;
2707 x.bv_len -= i.bv_len+1;
2709 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2710 STRLENOF("serialNumber")) == 0 ))
2712 /* parse serialNumber */
2714 x.bv_val += STRLENOF("serialNumber");
2715 x.bv_len -= STRLENOF("serialNumber");
2717 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2718 x.bv_val++; x.bv_len--;
2720 /* eat leading spaces */
2721 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2725 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2726 x.bv_val++; x.bv_len--;
2728 sn.bv_val = x.bv_val;
2731 if( sn.bv_val[0] == '-' ) {
2736 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2737 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2740 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2741 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2742 return LDAP_INVALID_SYNTAX;
2745 x.bv_val += sn.bv_len;
2746 x.bv_len -= sn.bv_len;
2748 } else return LDAP_INVALID_SYNTAX;
2750 /* eat trailing spaces */
2751 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2755 /* should have no characters left... */
2756 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2759 /* validate DN -- doesn't handle double dquote */
2760 rc = dnValidate( NULL, &i );
2761 if( rc ) return LDAP_INVALID_SYNTAX;
2763 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2765 return LDAP_SUCCESS;
2769 serialNumberAndIssuerPretty(
2777 struct berval sn, i, ni;
2779 assert( in != NULL );
2780 assert( out != NULL );
2782 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2785 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2787 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2788 /* Parse old format */
2789 i.bv_val = ber_bvchr( in, '$' );
2790 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2792 sn.bv_val = in->bv_val;
2793 sn.bv_len = i.bv_val - in->bv_val;
2796 i.bv_len = in->bv_len - (sn.bv_len + 1);
2798 /* eat leading zeros */
2799 for( n=0; n < (sn.bv_len-1); n++ ) {
2800 if( sn.bv_val[n] != '0' ) break;
2805 for( n=0; n < sn.bv_len; n++ ) {
2806 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2810 /* Parse GSER format */
2811 int havesn=0,haveissuer=0;
2812 struct berval x = *in;
2816 /* eat leading spaces */
2817 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2821 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2822 return LDAP_INVALID_SYNTAX;
2825 /* should be at issuer or serialNumber NamedValue */
2826 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2828 x.bv_val += STRLENOF("issuer");
2829 x.bv_len -= STRLENOF("issuer");
2831 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2832 x.bv_val++; x.bv_len--;
2834 /* eat leading spaces */
2835 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2839 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2840 x.bv_val++; x.bv_len--;
2842 i.bv_val = x.bv_val;
2845 for( ; i.bv_len < x.bv_len; ) {
2846 if ( i.bv_val[i.bv_len] != '"' ) {
2850 if ( i.bv_val[i.bv_len+1] == '"' ) {
2857 x.bv_val += i.bv_len+1;
2858 x.bv_len -= i.bv_len+1;
2860 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2861 return LDAP_INVALID_SYNTAX;
2866 } else if( strncasecmp( x.bv_val, "serialNumber",
2867 STRLENOF("serialNumber")) == 0 )
2869 /* parse serialNumber */
2871 x.bv_val += STRLENOF("serialNumber");
2872 x.bv_len -= STRLENOF("serialNumber");
2874 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2875 x.bv_val++; x.bv_len--;
2877 /* eat leading spaces */
2878 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2882 sn.bv_val = x.bv_val;
2885 if( sn.bv_val[0] == '-' ) {
2890 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2891 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2894 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2895 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2896 return LDAP_INVALID_SYNTAX;
2899 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2901 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2902 return LDAP_INVALID_SYNTAX;
2907 } else return LDAP_INVALID_SYNTAX;
2909 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2910 x.bv_val++; x.bv_len--;
2913 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2917 /* should be at remaining NamedValue */
2918 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2919 STRLENOF("issuer" )) == 0 ))
2922 x.bv_val += STRLENOF("issuer");
2923 x.bv_len -= STRLENOF("issuer");
2925 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2926 x.bv_val++; x.bv_len--;
2928 /* eat leading spaces */
2929 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2933 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2934 x.bv_val++; x.bv_len--;
2936 i.bv_val = x.bv_val;
2939 for( ; i.bv_len < x.bv_len; ) {
2940 if ( i.bv_val[i.bv_len] != '"' ) {
2944 if ( i.bv_val[i.bv_len+1] == '"' ) {
2951 x.bv_val += i.bv_len+1;
2952 x.bv_len -= i.bv_len+1;
2954 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2955 STRLENOF("serialNumber")) == 0 ))
2957 /* parse serialNumber */
2959 x.bv_val += STRLENOF("serialNumber");
2960 x.bv_len -= STRLENOF("serialNumber");
2962 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2963 x.bv_val++; x.bv_len--;
2965 /* eat leading spaces */
2966 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2970 sn.bv_val = x.bv_val;
2973 if( sn.bv_val[0] == '-' ) {
2978 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2979 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2982 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2983 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2984 return LDAP_INVALID_SYNTAX;
2987 x.bv_val += sn.bv_len;
2988 x.bv_len -= sn.bv_len;
2990 } else return LDAP_INVALID_SYNTAX;
2992 /* eat trailing spaces */
2993 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2997 /* should have no characters left... */
2998 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3000 ber_dupbv_x( &ni, &i, ctx );
3003 /* need to handle double dquotes here */
3006 rc = dnPretty( syntax, &i, &ni, ctx );
3008 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3009 slap_sl_free( i.bv_val, ctx );
3012 if( rc ) return LDAP_INVALID_SYNTAX;
3014 /* make room from sn + "$" */
3015 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
3016 + sn.bv_len + ni.bv_len;
3017 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3019 if( out->bv_val == NULL ) {
3021 slap_sl_free( ni.bv_val, ctx );
3026 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3027 STRLENOF("{ serialNumber "));
3028 n = STRLENOF("{ serialNumber ");
3030 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3033 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
3034 n += STRLENOF(", issuer \"");
3036 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3039 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3040 n += STRLENOF("\" }");
3042 out->bv_val[n] = '\0';
3044 assert( n == out->bv_len );
3046 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3047 out->bv_val, 0, 0 );
3049 slap_sl_free( ni.bv_val, ctx );
3051 return LDAP_SUCCESS;
3055 * This routine is called by certificateExactNormalize when
3056 * certificateExactNormalize receives a search string instead of
3057 * a certificate. This routine checks if the search value is valid
3058 * and then returns the normalized value
3061 serialNumberAndIssuerNormalize(
3071 struct berval sn, i, ni;
3073 assert( in != NULL );
3074 assert( out != NULL );
3076 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3079 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3081 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3082 /* Parse old format */
3083 i.bv_val = ber_bvchr( in, '$' );
3084 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
3086 sn.bv_val = in->bv_val;
3087 sn.bv_len = i.bv_val - in->bv_val;
3090 i.bv_len = in->bv_len - (sn.bv_len + 1);
3092 /* eat leading zeros */
3093 for( n=0; n < (sn.bv_len-1); n++ ) {
3094 if( sn.bv_val[n] != '0' ) break;
3099 for( n=0; n < sn.bv_len; n++ ) {
3100 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3104 /* Parse GSER format */
3105 int havesn=0,haveissuer=0;
3106 struct berval x = *in;
3110 /* eat leading spaces */
3111 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3115 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3116 return LDAP_INVALID_SYNTAX;
3119 /* should be at issuer or serialNumber NamedValue */
3120 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3122 x.bv_val += STRLENOF("issuer");
3123 x.bv_len -= STRLENOF("issuer");
3125 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3126 x.bv_val++; x.bv_len--;
3128 /* eat leading spaces */
3129 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3133 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3134 x.bv_val++; x.bv_len--;
3136 i.bv_val = x.bv_val;
3139 for( ; i.bv_len < x.bv_len; ) {
3140 if ( i.bv_val[i.bv_len] != '"' ) {
3144 if ( i.bv_val[i.bv_len+1] == '"' ) {
3151 x.bv_val += i.bv_len+1;
3152 x.bv_len -= i.bv_len+1;
3154 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3155 return LDAP_INVALID_SYNTAX;
3160 } else if( strncasecmp( x.bv_val, "serialNumber",
3161 STRLENOF("serialNumber")) == 0 )
3163 /* parse serialNumber */
3165 x.bv_val += STRLENOF("serialNumber");
3166 x.bv_len -= STRLENOF("serialNumber");
3168 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3169 x.bv_val++; x.bv_len--;
3171 /* eat leading spaces */
3172 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3176 sn.bv_val = x.bv_val;
3179 if( sn.bv_val[0] == '-' ) {
3184 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3185 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3188 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3189 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3190 return LDAP_INVALID_SYNTAX;
3193 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3195 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3196 return LDAP_INVALID_SYNTAX;
3201 } else return LDAP_INVALID_SYNTAX;
3203 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3204 x.bv_val++; x.bv_len--;
3207 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3211 /* should be at remaining NamedValue */
3212 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3213 STRLENOF("issuer" )) == 0 ))
3216 x.bv_val += STRLENOF("issuer");
3217 x.bv_len -= STRLENOF("issuer");
3219 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3220 x.bv_val++; x.bv_len--;
3222 /* eat leading spaces */
3223 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3227 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3228 x.bv_val++; x.bv_len--;
3230 i.bv_val = x.bv_val;
3233 for( ; i.bv_len < x.bv_len; ) {
3234 if ( i.bv_val[i.bv_len] != '"' ) {
3238 if ( i.bv_val[i.bv_len+1] == '"' ) {
3245 x.bv_val += i.bv_len+1;
3246 x.bv_len -= i.bv_len+1;
3248 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3249 STRLENOF("serialNumber")) == 0 ))
3251 /* parse serialNumber */
3253 x.bv_val += STRLENOF("serialNumber");
3254 x.bv_len -= STRLENOF("serialNumber");
3256 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3257 x.bv_val++; x.bv_len--;
3259 /* eat leading spaces */
3260 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3264 sn.bv_val = x.bv_val;
3267 if( sn.bv_val[0] == '-' ) {
3272 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3273 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3276 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3277 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3278 return LDAP_INVALID_SYNTAX;
3281 x.bv_val += sn.bv_len;
3282 x.bv_len -= sn.bv_len;
3284 } else return LDAP_INVALID_SYNTAX;
3286 /* eat trailing spaces */
3287 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3291 /* should have no characters left... */
3292 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3294 ber_dupbv_x( &ni, &i, ctx );
3297 /* need to handle double dquotes here */
3300 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3302 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3303 slap_sl_free( i.bv_val, ctx );
3306 if( rc ) return LDAP_INVALID_SYNTAX;
3308 /* make room from sn + "$" */
3309 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3310 + sn.bv_len + ni.bv_len;
3311 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3313 if( out->bv_val == NULL ) {
3315 slap_sl_free( ni.bv_val, ctx );
3320 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3321 STRLENOF( "{ serialNumber " ));
3322 n = STRLENOF( "{ serialNumber " );
3324 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3327 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3328 n += STRLENOF( ", issuer \"" );
3330 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3333 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3334 n += STRLENOF( "\" }" );
3336 out->bv_val[n] = '\0';
3338 assert( n == out->bv_len );
3340 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3341 out->bv_val, 0, 0 );
3343 slap_sl_free( ni.bv_val, ctx );
3345 return LDAP_SUCCESS;
3349 certificateExactNormalize(
3354 struct berval *normalized,
3357 BerElementBuffer berbuf;
3358 BerElement *ber = (BerElement *)&berbuf;
3362 char serialbuf[64], *serial = serialbuf;
3363 ber_len_t seriallen;
3364 struct berval issuer_dn = BER_BVNULL, bvdn;
3366 int rc = LDAP_INVALID_SYNTAX;
3368 if( BER_BVISEMPTY( val ) ) goto done;
3370 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3371 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3374 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3376 ber_init2( ber, val, LBER_USE_DER );
3377 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3378 tag = ber_skip_tag( ber, &len ); /* Sequence */
3379 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3380 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3381 tag = ber_skip_tag( ber, &len );
3382 tag = ber_get_int( ber, &i ); /* version */
3385 /* NOTE: move the test here from certificateNormalize,
3386 * so that we can validate certs with serial longer
3387 * than sizeof(ber_int_t) */
3388 tag = ber_peek_tag( ber, &len ); /* serial */
3389 if ( len > sizeof(ber_int_t) ) {
3392 tag = ber_skip_tag( ber, &len );
3393 ptr = (unsigned char *)ber->ber_ptr;
3394 ber_skip_data( ber, len );
3396 while ( ptr[0] == '\0' && len > 0 ) {
3401 #if defined(USE_MP_BIGNUM)
3404 #elif defined(USE_MP_GMP)
3406 /* hint: use mpz_import(), mpz_get_str() */
3408 #elif defined(USE_MP_LONG_LONG)
3409 if ( len <= sizeof( unsigned long long ) ) {
3410 unsigned long long sn = 0;
3415 for ( i = 1; i < len; i++ ) {
3420 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%llu", sn );
3423 /* do not accept serialNumber that requires
3424 * more than long long */
3425 rc = LDAP_INVALID_SYNTAX;
3430 /* do not accept serialNumber that requires
3432 rc = LDAP_INVALID_SYNTAX;
3437 tag = ber_get_int( ber, &i ); /* serial */
3438 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
3440 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3441 ber_skip_data( ber, len );
3442 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3443 len = ber_ptrlen( ber );
3444 bvdn.bv_val = val->bv_val + len;
3445 bvdn.bv_len = val->bv_len - len;
3447 rc = dnX509normalize( &bvdn, &issuer_dn );
3448 if( rc != LDAP_SUCCESS ) goto done;
3450 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3451 + seriallen + issuer_dn.bv_len;
3452 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3454 p = (unsigned char *)normalized->bv_val;
3456 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3457 p += STRLENOF( "{ serialNumber " );
3459 AC_MEMCPY(p, serial, seriallen);
3462 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3463 p += STRLENOF( ", issuer \"" );
3465 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3466 p += issuer_dn.bv_len;
3468 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3469 p += STRLENOF( "\" }" );
3473 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3474 normalized->bv_val, NULL, NULL );
3479 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3480 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3492 assert( in != NULL );
3493 assert( !BER_BVISNULL( in ) );
3495 for ( i = 0; i < in->bv_len; i++ ) {
3496 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3497 return LDAP_INVALID_SYNTAX;
3501 return LDAP_SUCCESS;
3504 /* Normalize a SID as used inside a CSN:
3505 * three-digit numeric string */
3512 struct berval *normalized,
3517 ber_dupbv_x( normalized, val, ctx );
3519 for ( i = 0; i < normalized->bv_len; i++ ) {
3520 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3521 ber_memfree_x( normalized->bv_val, ctx );
3522 BER_BVZERO( normalized );
3523 return LDAP_INVALID_SYNTAX;
3526 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3529 return LDAP_SUCCESS;
3537 assert( in != NULL );
3538 assert( !BER_BVISNULL( in ) );
3540 if ( in->bv_len != 3 ) {
3541 return LDAP_INVALID_SYNTAX;
3544 return hexValidate( NULL, in );
3547 /* Normalize a SID as used inside a CSN:
3548 * three-digit numeric string */
3555 struct berval *normalized,
3558 if ( val->bv_len != 3 ) {
3559 return LDAP_INVALID_SYNTAX;
3562 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3565 /* Normalize a SID as used inside a CSN, either as-is
3566 * (assertion value) or extracted from the CSN
3567 * (attribute value) */
3574 struct berval *normalized,
3580 if ( BER_BVISEMPTY( val ) ) {
3581 return LDAP_INVALID_SYNTAX;
3584 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3585 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3588 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3590 ptr = ber_bvchr( val, '#' );
3591 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3592 return LDAP_INVALID_SYNTAX;
3595 bv.bv_val = ptr + 1;
3596 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3598 ptr = ber_bvchr( &bv, '#' );
3599 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3600 return LDAP_INVALID_SYNTAX;
3603 bv.bv_val = ptr + 1;
3604 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3606 ptr = ber_bvchr( &bv, '#' );
3607 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3608 return LDAP_INVALID_SYNTAX;
3611 bv.bv_len = ptr - bv.bv_val;
3613 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3625 assert( in != NULL );
3626 assert( !BER_BVISNULL( in ) );
3628 if ( BER_BVISEMPTY( in ) ) {
3629 return LDAP_INVALID_SYNTAX;
3634 ptr = ber_bvchr( &bv, '#' );
3635 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3636 return LDAP_INVALID_SYNTAX;
3639 bv.bv_len = ptr - bv.bv_val;
3640 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3641 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3643 return LDAP_INVALID_SYNTAX;
3646 rc = generalizedTimeValidate( NULL, &bv );
3647 if ( rc != LDAP_SUCCESS ) {
3651 bv.bv_val = ptr + 1;
3652 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3654 ptr = ber_bvchr( &bv, '#' );
3655 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3656 return LDAP_INVALID_SYNTAX;
3659 bv.bv_len = ptr - bv.bv_val;
3660 if ( bv.bv_len != 6 ) {
3661 return LDAP_INVALID_SYNTAX;
3664 rc = hexValidate( NULL, &bv );
3665 if ( rc != LDAP_SUCCESS ) {
3669 bv.bv_val = ptr + 1;
3670 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3672 ptr = ber_bvchr( &bv, '#' );
3673 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3674 return LDAP_INVALID_SYNTAX;
3677 bv.bv_len = ptr - bv.bv_val;
3678 if ( bv.bv_len == 2 ) {
3679 /* tolerate old 2-digit replica-id */
3680 rc = hexValidate( NULL, &bv );
3683 rc = sidValidate( NULL, &bv );
3685 if ( rc != LDAP_SUCCESS ) {
3689 bv.bv_val = ptr + 1;
3690 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3692 if ( bv.bv_len != 6 ) {
3693 return LDAP_INVALID_SYNTAX;
3696 return hexValidate( NULL, &bv );
3699 /* Normalize a CSN in OpenLDAP 2.3 format */
3706 struct berval *normalized,
3709 struct berval gt, cnt, sid, mod;
3713 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3714 assert( !BER_BVISEMPTY( val ) );
3718 ptr = ber_bvchr( >, '#' );
3719 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3720 return LDAP_INVALID_SYNTAX;
3723 gt.bv_len = ptr - gt.bv_val;
3724 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3726 cnt.bv_val = ptr + 1;
3727 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3729 ptr = ber_bvchr( &cnt, '#' );
3730 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3731 return LDAP_INVALID_SYNTAX;
3734 cnt.bv_len = ptr - cnt.bv_val;
3735 assert( cnt.bv_len == STRLENOF( "000000" ) );
3737 sid.bv_val = ptr + 1;
3738 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3740 ptr = ber_bvchr( &sid, '#' );
3741 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3742 return LDAP_INVALID_SYNTAX;
3745 sid.bv_len = ptr - sid.bv_val;
3746 assert( sid.bv_len == STRLENOF( "00" ) );
3748 mod.bv_val = ptr + 1;
3749 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3750 assert( mod.bv_len == STRLENOF( "000000" ) );
3752 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3753 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3755 ptr = normalized->bv_val;
3756 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3757 ptr = lutil_strcopy( ptr, ".000000Z#" );
3758 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3761 for ( i = 0; i < sid.bv_len; i++ ) {
3762 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3765 for ( i = 0; i < mod.bv_len; i++ ) {
3766 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3770 assert( ptr - normalized->bv_val == normalized->bv_len );
3772 return LDAP_SUCCESS;
3775 /* Normalize a CSN */
3782 struct berval *normalized,
3785 struct berval cnt, sid, mod;
3789 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3791 if ( BER_BVISEMPTY( val ) ) {
3792 return LDAP_INVALID_SYNTAX;
3795 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3796 /* Openldap <= 2.3 */
3798 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3801 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3803 ptr = ber_bvchr( val, '#' );
3804 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3805 return LDAP_INVALID_SYNTAX;
3808 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3810 cnt.bv_val = ptr + 1;
3811 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3813 ptr = ber_bvchr( &cnt, '#' );
3814 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3815 return LDAP_INVALID_SYNTAX;
3818 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3820 sid.bv_val = ptr + 1;
3821 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3823 ptr = ber_bvchr( &sid, '#' );
3824 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3825 return LDAP_INVALID_SYNTAX;
3828 sid.bv_len = ptr - sid.bv_val;
3829 assert( sid.bv_len == STRLENOF( "000" ) );
3831 mod.bv_val = ptr + 1;
3832 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3834 assert( mod.bv_len == STRLENOF( "000000" ) );
3836 ber_dupbv_x( normalized, val, ctx );
3838 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3839 i < normalized->bv_len; i++ )
3841 /* assume it's already validated that's all hex digits */
3842 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3845 return LDAP_SUCCESS;
3848 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3849 /* slight optimization - does not need the start parameter */
3850 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3855 check_time_syntax (struct berval *val,
3858 struct berval *fraction)
3861 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3862 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3863 * GeneralizedTime supports leap seconds, UTCTime does not.
3865 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3866 static const int mdays[2][12] = {
3867 /* non-leap years */
3868 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3870 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3873 int part, c, c1, c2, tzoffset, leapyear = 0;
3876 e = p + val->bv_len;
3878 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3879 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3881 for (part = start; part < 7 && p < e; part++) {
3883 if (!ASCII_DIGIT(c1)) {
3888 return LDAP_INVALID_SYNTAX;
3891 if (!ASCII_DIGIT(c)) {
3892 return LDAP_INVALID_SYNTAX;
3894 c += c1 * 10 - '0' * 11;
3895 if ((part | 1) == 3) {
3898 return LDAP_INVALID_SYNTAX;
3901 if (c >= ceiling[part]) {
3902 if (! (c == 60 && part == 6 && start == 0))
3903 return LDAP_INVALID_SYNTAX;
3907 if (part < 5 + start) {
3908 return LDAP_INVALID_SYNTAX;
3910 for (; part < 9; part++) {
3914 /* leapyear check for the Gregorian calendar (year>1581) */
3915 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3919 if (parts[3] >= mdays[leapyear][parts[2]]) {
3920 return LDAP_INVALID_SYNTAX;
3924 fraction->bv_val = p;
3925 fraction->bv_len = 0;
3926 if (p < e && (*p == '.' || *p == ',')) {
3928 while (++p < e && ASCII_DIGIT(*p)) {
3931 if (p - fraction->bv_val == 1) {
3932 return LDAP_INVALID_SYNTAX;
3934 for (end_num = p; end_num[-1] == '0'; --end_num) {
3937 c = end_num - fraction->bv_val;
3938 if (c != 1) fraction->bv_len = c;
3944 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3950 return LDAP_INVALID_SYNTAX;
3956 for (part = 7; part < 9 && p < e; part++) {
3958 if (!ASCII_DIGIT(c1)) {
3963 return LDAP_INVALID_SYNTAX;
3966 if (!ASCII_DIGIT(c2)) {
3967 return LDAP_INVALID_SYNTAX;
3969 parts[part] = c1 * 10 + c2 - '0' * 11;
3970 if (parts[part] >= ceiling[part]) {
3971 return LDAP_INVALID_SYNTAX;
3974 if (part < 8 + start) {
3975 return LDAP_INVALID_SYNTAX;
3978 if (tzoffset == '-') {
3979 /* negative offset to UTC, ie west of Greenwich */
3980 parts[4] += parts[7];
3981 parts[5] += parts[8];
3982 /* offset is just hhmm, no seconds */
3983 for (part = 6; --part >= 0; ) {
3987 c = mdays[leapyear][parts[2]];
3989 if (parts[part] >= c) {
3991 return LDAP_INVALID_SYNTAX;
3996 } else if (part != 5) {
4001 /* positive offset to UTC, ie east of Greenwich */
4002 parts[4] -= parts[7];
4003 parts[5] -= parts[8];
4004 for (part = 6; --part >= 0; ) {
4005 if (parts[part] < 0) {
4007 return LDAP_INVALID_SYNTAX;
4012 /* make first arg to % non-negative */
4013 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4018 } else if (part != 5) {
4025 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4028 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4035 struct berval *normalized )
4039 rc = check_time_syntax(val, 1, parts, NULL);
4040 if (rc != LDAP_SUCCESS) {
4044 normalized->bv_val = ch_malloc( 14 );
4045 if ( normalized->bv_val == NULL ) {
4046 return LBER_ERROR_MEMORY;
4049 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4050 parts[1], parts[2] + 1, parts[3] + 1,
4051 parts[4], parts[5], parts[6] );
4052 normalized->bv_len = 13;
4054 return LDAP_SUCCESS;
4064 return check_time_syntax(in, 1, parts, NULL);
4067 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4070 generalizedTimeValidate(
4075 struct berval fraction;
4076 return check_time_syntax(in, 0, parts, &fraction);
4080 generalizedTimeNormalize(
4085 struct berval *normalized,
4090 struct berval fraction;
4092 rc = check_time_syntax(val, 0, parts, &fraction);
4093 if (rc != LDAP_SUCCESS) {
4097 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4098 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4099 if ( BER_BVISNULL( normalized ) ) {
4100 return LBER_ERROR_MEMORY;
4103 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4104 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4105 parts[4], parts[5], parts[6] );
4106 if ( !BER_BVISEMPTY( &fraction ) ) {
4107 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4108 fraction.bv_val, fraction.bv_len );
4109 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4111 strcpy( normalized->bv_val + len-1, "Z" );
4112 normalized->bv_len = len;
4114 return LDAP_SUCCESS;
4118 generalizedTimeOrderingMatch(
4123 struct berval *value,
4124 void *assertedValue )
4126 struct berval *asserted = (struct berval *) assertedValue;
4127 ber_len_t v_len = value->bv_len;
4128 ber_len_t av_len = asserted->bv_len;
4130 /* ignore trailing 'Z' when comparing */
4131 int match = memcmp( value->bv_val, asserted->bv_val,
4132 (v_len < av_len ? v_len : av_len) - 1 );
4133 if ( match == 0 ) match = v_len - av_len;
4136 return LDAP_SUCCESS;
4139 /* Index generation function */
4140 int generalizedTimeIndexer(
4145 struct berval *prefix,
4153 BerValue bvtmp; /* 40 bit index */
4155 struct lutil_timet tt;
4157 bvtmp.bv_len = sizeof(tmp);
4159 for( i=0; values[i].bv_val != NULL; i++ ) {
4160 /* just count them */
4163 /* we should have at least one value at this point */
4166 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4168 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4169 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4170 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4171 /* Use 40 bits of time for key */
4172 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4173 lutil_tm2time( &tm, &tt );
4174 tmp[0] = tt.tt_gsec & 0xff;
4175 tmp[4] = tt.tt_sec & 0xff;
4177 tmp[3] = tt.tt_sec & 0xff;
4179 tmp[2] = tt.tt_sec & 0xff;
4181 tmp[1] = tt.tt_sec & 0xff;
4183 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4187 keys[j].bv_val = NULL;
4192 return LDAP_SUCCESS;
4195 /* Index generation function */
4196 int generalizedTimeFilter(
4201 struct berval *prefix,
4202 void * assertedValue,
4208 BerValue bvtmp; /* 40 bit index */
4209 BerValue *value = (BerValue *) assertedValue;
4211 struct lutil_timet tt;
4213 bvtmp.bv_len = sizeof(tmp);
4215 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4216 /* Use 40 bits of time for key */
4217 if ( value->bv_val && value->bv_len >= 10 &&
4218 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4220 lutil_tm2time( &tm, &tt );
4221 tmp[0] = tt.tt_gsec & 0xff;
4222 tmp[4] = tt.tt_sec & 0xff;
4224 tmp[3] = tt.tt_sec & 0xff;
4226 tmp[2] = tt.tt_sec & 0xff;
4228 tmp[1] = tt.tt_sec & 0xff;
4230 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4231 ber_dupbv_x(keys, &bvtmp, ctx );
4232 keys[1].bv_val = NULL;
4240 return LDAP_SUCCESS;
4244 deliveryMethodValidate(
4246 struct berval *val )
4249 #define LENOF(s) (sizeof(s)-1)
4250 struct berval tmp = *val;
4252 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4253 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4254 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4257 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4259 switch( tmp.bv_val[0] ) {
4262 if(( tmp.bv_len >= LENOF("any") ) &&
4263 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4265 tmp.bv_len -= LENOF("any");
4266 tmp.bv_val += LENOF("any");
4269 return LDAP_INVALID_SYNTAX;
4273 if(( tmp.bv_len >= LENOF("mhs") ) &&
4274 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4276 tmp.bv_len -= LENOF("mhs");
4277 tmp.bv_val += LENOF("mhs");
4280 return LDAP_INVALID_SYNTAX;
4284 if(( tmp.bv_len >= LENOF("physical") ) &&
4285 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4287 tmp.bv_len -= LENOF("physical");
4288 tmp.bv_val += LENOF("physical");
4291 return LDAP_INVALID_SYNTAX;
4294 case 'T': /* telex or teletex or telephone */
4295 if(( tmp.bv_len >= LENOF("telex") ) &&
4296 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4298 tmp.bv_len -= LENOF("telex");
4299 tmp.bv_val += LENOF("telex");
4302 if(( tmp.bv_len >= LENOF("teletex") ) &&
4303 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4305 tmp.bv_len -= LENOF("teletex");
4306 tmp.bv_val += LENOF("teletex");
4309 if(( tmp.bv_len >= LENOF("telephone") ) &&
4310 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4312 tmp.bv_len -= LENOF("telephone");
4313 tmp.bv_val += LENOF("telephone");
4316 return LDAP_INVALID_SYNTAX;
4319 case 'G': /* g3fax or g4fax */
4320 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4321 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4322 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4324 tmp.bv_len -= LENOF("g3fax");
4325 tmp.bv_val += LENOF("g3fax");
4328 return LDAP_INVALID_SYNTAX;
4332 if(( tmp.bv_len >= LENOF("ia5") ) &&
4333 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4335 tmp.bv_len -= LENOF("ia5");
4336 tmp.bv_val += LENOF("ia5");
4339 return LDAP_INVALID_SYNTAX;
4343 if(( tmp.bv_len >= LENOF("videotex") ) &&
4344 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4346 tmp.bv_len -= LENOF("videotex");
4347 tmp.bv_val += LENOF("videotex");
4350 return LDAP_INVALID_SYNTAX;
4353 return LDAP_INVALID_SYNTAX;
4356 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4358 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4362 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4366 return LDAP_INVALID_SYNTAX;
4368 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4377 nisNetgroupTripleValidate(
4379 struct berval *val )
4384 if ( BER_BVISEMPTY( val ) ) {
4385 return LDAP_INVALID_SYNTAX;
4388 p = (char *)val->bv_val;
4389 e = p + val->bv_len;
4391 if ( *p != '(' /*')'*/ ) {
4392 return LDAP_INVALID_SYNTAX;
4395 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4399 return LDAP_INVALID_SYNTAX;
4402 } else if ( !AD_CHAR( *p ) ) {
4403 return LDAP_INVALID_SYNTAX;
4407 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4408 return LDAP_INVALID_SYNTAX;
4414 return LDAP_INVALID_SYNTAX;
4417 return LDAP_SUCCESS;
4421 bootParameterValidate(
4423 struct berval *val )
4427 if ( BER_BVISEMPTY( val ) ) {
4428 return LDAP_INVALID_SYNTAX;
4431 p = (char *)val->bv_val;
4432 e = p + val->bv_len;
4435 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4436 if ( !AD_CHAR( *p ) ) {
4437 return LDAP_INVALID_SYNTAX;
4442 return LDAP_INVALID_SYNTAX;
4446 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4447 if ( !AD_CHAR( *p ) ) {
4448 return LDAP_INVALID_SYNTAX;
4453 return LDAP_INVALID_SYNTAX;
4457 for ( p++; p < e; p++ ) {
4458 if ( !SLAP_PRINTABLE( *p ) ) {
4459 return LDAP_INVALID_SYNTAX;
4463 return LDAP_SUCCESS;
4467 firstComponentNormalize(
4472 struct berval *normalized,
4479 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4480 ber_dupbv_x( normalized, val, ctx );
4481 return LDAP_SUCCESS;
4484 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4486 if( val->bv_val[0] != '(' /*')'*/ &&
4487 val->bv_val[0] != '{' /*'}'*/ )
4489 return LDAP_INVALID_SYNTAX;
4492 /* trim leading white space */
4494 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4500 /* grab next word */
4501 comp.bv_val = &val->bv_val[len];
4502 len = val->bv_len - len;
4503 for( comp.bv_len = 0;
4504 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4510 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4511 rc = numericoidValidate( NULL, &comp );
4512 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4513 rc = integerValidate( NULL, &comp );
4515 rc = LDAP_INVALID_SYNTAX;
4519 if( rc == LDAP_SUCCESS ) {
4520 ber_dupbv_x( normalized, &comp, ctx );
4526 static char *country_gen_syn[] = {
4527 "1.3.6.1.4.1.1466.115.121.1.15",
4528 "1.3.6.1.4.1.1466.115.121.1.26",
4529 "1.3.6.1.4.1.1466.115.121.1.44",
4533 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4534 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4536 static slap_syntax_defs_rec syntax_defs[] = {
4537 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4538 X_BINARY X_NOT_H_R ")",
4539 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4540 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4541 0, NULL, NULL, NULL},
4542 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4543 0, NULL, NULL, NULL},
4544 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4546 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4547 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4549 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4550 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4551 0, NULL, bitStringValidate, NULL },
4552 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4553 0, NULL, booleanValidate, NULL},
4554 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4555 X_BINARY X_NOT_H_R ")",
4556 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4557 NULL, certificateValidate, NULL},
4558 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4559 X_BINARY X_NOT_H_R ")",
4560 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4561 NULL, certificateListValidate, NULL},
4562 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4563 X_BINARY X_NOT_H_R ")",
4564 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4565 NULL, sequenceValidate, NULL},
4566 #if 0 /* need to go __after__ printableString */
4567 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4568 0, "1.3.6.1.4.1.1466.115.121.1.44",
4569 countryStringValidate, NULL},
4571 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4572 0, NULL, dnValidate, dnPretty},
4573 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4574 0, NULL, rdnValidate, rdnPretty},
4575 #ifdef LDAP_COMP_MATCH
4576 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4577 0, NULL, allComponentsValidate, NULL},
4578 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4579 0, NULL, componentFilterValidate, NULL},
4581 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4582 0, NULL, NULL, NULL},
4583 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4584 0, NULL, deliveryMethodValidate, NULL},
4585 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4586 0, NULL, UTF8StringValidate, NULL},
4587 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4588 0, NULL, NULL, NULL},
4589 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4590 0, NULL, NULL, NULL},
4591 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4592 0, NULL, NULL, NULL},
4593 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4594 0, NULL, NULL, NULL},
4595 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4596 0, NULL, NULL, NULL},
4597 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4598 0, NULL, printablesStringValidate, NULL},
4599 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4600 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4601 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4602 0, NULL, generalizedTimeValidate, NULL},
4603 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4604 0, NULL, NULL, NULL},
4605 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4606 0, NULL, IA5StringValidate, NULL},
4607 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4608 0, NULL, integerValidate, NULL},
4609 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4610 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4611 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4612 0, NULL, NULL, NULL},
4613 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4614 0, NULL, NULL, NULL},
4615 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4616 0, NULL, NULL, NULL},
4617 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4618 0, NULL, NULL, NULL},
4619 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4620 0, NULL, NULL, NULL},
4621 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4622 0, NULL, nameUIDValidate, nameUIDPretty },
4623 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4624 0, NULL, NULL, NULL},
4625 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4626 0, NULL, numericStringValidate, NULL},
4627 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4628 0, NULL, NULL, NULL},
4629 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4630 0, NULL, numericoidValidate, NULL},
4631 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4632 0, NULL, IA5StringValidate, NULL},
4633 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4634 0, NULL, blobValidate, NULL},
4635 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4636 0, NULL, UTF8StringValidate, NULL},
4637 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4638 0, NULL, NULL, NULL},
4639 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4640 0, NULL, NULL, NULL},
4641 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4642 0, NULL, printableStringValidate, NULL},
4643 /* moved here because now depends on Directory String, IA5 String
4644 * and Printable String */
4645 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4646 0, country_gen_syn, countryStringValidate, NULL},
4647 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4648 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4649 0, NULL, subtreeSpecificationValidate, NULL},
4650 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4651 X_BINARY X_NOT_H_R ")",
4652 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4653 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4654 0, NULL, printableStringValidate, NULL},
4655 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4656 0, NULL, NULL, NULL},
4657 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4658 0, NULL, printablesStringValidate, NULL},
4659 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4660 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4661 0, NULL, utcTimeValidate, NULL},
4663 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4664 0, NULL, NULL, NULL},
4665 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4666 0, NULL, NULL, NULL},
4667 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4668 0, NULL, NULL, NULL},
4669 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4670 0, NULL, NULL, NULL},
4671 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4672 0, NULL, NULL, NULL},
4674 /* RFC 2307 NIS Syntaxes */
4675 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4676 0, NULL, nisNetgroupTripleValidate, NULL},
4677 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4678 0, NULL, bootParameterValidate, NULL},
4680 /* draft-zeilenga-ldap-x509 */
4681 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4682 SLAP_SYNTAX_HIDE, NULL,
4683 serialNumberAndIssuerValidate,
4684 serialNumberAndIssuerPretty},
4685 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4686 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4687 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4688 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4689 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4690 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4691 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4692 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4693 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4694 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4695 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4696 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4698 #ifdef SLAPD_AUTHPASSWD
4699 /* needs updating */
4700 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4701 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4704 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4705 0, NULL, UUIDValidate, UUIDPretty},
4707 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4708 SLAP_SYNTAX_HIDE, NULL, csnValidate, NULL},
4710 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4711 SLAP_SYNTAX_HIDE, NULL, sidValidate, NULL},
4713 /* OpenLDAP Void Syntax */
4714 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4715 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4717 /* FIXME: OID is unused, but not registered yet */
4718 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4719 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4721 {NULL, 0, NULL, NULL, NULL}
4724 char *csnSIDMatchSyntaxes[] = {
4725 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4728 char *certificateExactMatchSyntaxes[] = {
4729 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4732 #ifdef LDAP_COMP_MATCH
4733 char *componentFilterMatchSyntaxes[] = {
4734 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4738 char *directoryStringSyntaxes[] = {
4739 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4742 char *integerFirstComponentMatchSyntaxes[] = {
4743 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4744 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4747 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4748 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4749 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4750 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4751 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4752 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4753 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4754 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4755 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4760 * Other matching rules in X.520 that we do not use (yet):
4762 * 2.5.13.25 uTCTimeMatch
4763 * 2.5.13.26 uTCTimeOrderingMatch
4764 * 2.5.13.31* directoryStringFirstComponentMatch
4765 * 2.5.13.32* wordMatch
4766 * 2.5.13.33* keywordMatch
4767 * 2.5.13.36+ certificatePairExactMatch
4768 * 2.5.13.37+ certificatePairMatch
4769 * 2.5.13.38+ certificateListExactMatch
4770 * 2.5.13.39+ certificateListMatch
4771 * 2.5.13.40+ algorithmIdentifierMatch
4772 * 2.5.13.41* storedPrefixMatch
4773 * 2.5.13.42 attributeCertificateMatch
4774 * 2.5.13.43 readerAndKeyIDMatch
4775 * 2.5.13.44 attributeIntegrityMatch
4777 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4778 * (+) described in draft-zeilenga-ldap-x509
4780 static slap_mrule_defs_rec mrule_defs[] = {
4782 * EQUALITY matching rules must be listed after associated APPROX
4783 * matching rules. So, we list all APPROX matching rules first.
4785 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4786 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4787 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4788 NULL, NULL, directoryStringApproxMatch,
4789 directoryStringApproxIndexer, directoryStringApproxFilter,
4792 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4793 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4794 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4795 NULL, NULL, IA5StringApproxMatch,
4796 IA5StringApproxIndexer, IA5StringApproxFilter,
4800 * Other matching rules
4803 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4804 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4805 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4806 NULL, NULL, octetStringMatch,
4807 octetStringIndexer, octetStringFilter,
4810 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4811 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4812 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4813 NULL, dnNormalize, dnMatch,
4814 octetStringIndexer, octetStringFilter,
4817 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4818 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4819 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4820 NULL, dnNormalize, dnRelativeMatch,
4824 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4825 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4826 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4827 NULL, dnNormalize, dnRelativeMatch,
4831 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4832 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4833 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4834 NULL, dnNormalize, dnRelativeMatch,
4838 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4839 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4840 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4841 NULL, dnNormalize, dnRelativeMatch,
4845 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4846 "SYNTAX 1.2.36.79672281.1.5.0 )",
4847 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4848 NULL, rdnNormalize, rdnMatch,
4849 octetStringIndexer, octetStringFilter,
4852 #ifdef LDAP_COMP_MATCH
4853 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4854 "SYNTAX 1.2.36.79672281.1.5.2 )",
4855 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4856 NULL, NULL , componentFilterMatch,
4857 octetStringIndexer, octetStringFilter,
4860 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4861 "SYNTAX 1.2.36.79672281.1.5.3 )",
4862 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4863 NULL, NULL , allComponentsMatch,
4864 octetStringIndexer, octetStringFilter,
4867 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4868 "SYNTAX 1.2.36.79672281.1.5.3 )",
4869 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4870 NULL, NULL , directoryComponentsMatch,
4871 octetStringIndexer, octetStringFilter,
4875 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4876 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4877 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4878 NULL, UTF8StringNormalize, octetStringMatch,
4879 octetStringIndexer, octetStringFilter,
4880 directoryStringApproxMatchOID },
4882 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4883 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4884 SLAP_MR_ORDERING, directoryStringSyntaxes,
4885 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4887 "caseIgnoreMatch" },
4889 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4890 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4891 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4892 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4893 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4894 "caseIgnoreMatch" },
4896 {"( 2.5.13.5 NAME 'caseExactMatch' "
4897 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4898 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4899 NULL, UTF8StringNormalize, octetStringMatch,
4900 octetStringIndexer, octetStringFilter,
4901 directoryStringApproxMatchOID },
4903 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4904 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4905 SLAP_MR_ORDERING, directoryStringSyntaxes,
4906 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4910 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4911 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4912 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4913 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4914 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4917 {"( 2.5.13.8 NAME 'numericStringMatch' "
4918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4919 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4920 NULL, numericStringNormalize, octetStringMatch,
4921 octetStringIndexer, octetStringFilter,
4924 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4926 SLAP_MR_ORDERING, NULL,
4927 NULL, numericStringNormalize, octetStringOrderingMatch,
4929 "numericStringMatch" },
4931 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4932 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4933 SLAP_MR_SUBSTR, NULL,
4934 NULL, numericStringNormalize, octetStringSubstringsMatch,
4935 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4936 "numericStringMatch" },
4938 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4939 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4940 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4941 NULL, NULL, NULL, NULL, NULL, NULL },
4943 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4944 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4945 SLAP_MR_SUBSTR, NULL,
4946 NULL, NULL, NULL, NULL, NULL,
4947 "caseIgnoreListMatch" },
4949 {"( 2.5.13.13 NAME 'booleanMatch' "
4950 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4951 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4952 NULL, NULL, booleanMatch,
4953 octetStringIndexer, octetStringFilter,
4956 {"( 2.5.13.14 NAME 'integerMatch' "
4957 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4958 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4959 NULL, NULL, integerMatch,
4960 octetStringIndexer, octetStringFilter,
4963 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4964 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4965 SLAP_MR_ORDERING, NULL,
4966 NULL, NULL, integerMatch,
4970 {"( 2.5.13.16 NAME 'bitStringMatch' "
4971 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4972 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4973 NULL, NULL, octetStringMatch,
4974 octetStringIndexer, octetStringFilter,
4977 {"( 2.5.13.17 NAME 'octetStringMatch' "
4978 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4979 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4980 NULL, NULL, octetStringMatch,
4981 octetStringIndexer, octetStringFilter,
4984 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4985 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4986 SLAP_MR_ORDERING, NULL,
4987 NULL, NULL, octetStringOrderingMatch,
4989 "octetStringMatch" },
4991 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4992 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4993 SLAP_MR_SUBSTR, NULL,
4994 NULL, NULL, octetStringSubstringsMatch,
4995 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4996 "octetStringMatch" },
4998 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4999 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5000 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5002 telephoneNumberNormalize, octetStringMatch,
5003 octetStringIndexer, octetStringFilter,
5006 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5008 SLAP_MR_SUBSTR, NULL,
5009 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5010 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5011 "telephoneNumberMatch" },
5013 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5015 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5016 NULL, NULL, NULL, NULL, NULL, NULL },
5018 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5019 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5020 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5021 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5022 uniqueMemberIndexer, uniqueMemberFilter,
5025 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5026 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5027 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5028 NULL, NULL, NULL, NULL, NULL, NULL },
5030 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5031 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5032 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5033 NULL, generalizedTimeNormalize, octetStringMatch,
5034 generalizedTimeIndexer, generalizedTimeFilter,
5037 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5038 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5039 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5040 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5042 "generalizedTimeMatch" },
5044 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5045 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5046 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5047 integerFirstComponentMatchSyntaxes,
5048 NULL, firstComponentNormalize, integerMatch,
5049 octetStringIndexer, octetStringFilter,
5052 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5054 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5055 objectIdentifierFirstComponentMatchSyntaxes,
5056 NULL, firstComponentNormalize, octetStringMatch,
5057 octetStringIndexer, octetStringFilter,
5060 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5061 "SYNTAX 1.3.6.1.1.15.1 )",
5062 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5063 NULL, certificateExactNormalize, octetStringMatch,
5064 octetStringIndexer, octetStringFilter,
5067 {"( 2.5.13.35 NAME 'certificateMatch' "
5068 "SYNTAX 1.3.6.1.1.15.2 )",
5069 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5070 NULL, NULL, NULL, NULL, NULL,
5073 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5074 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5075 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5076 NULL, IA5StringNormalize, octetStringMatch,
5077 octetStringIndexer, octetStringFilter,
5078 IA5StringApproxMatchOID },
5080 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5081 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5082 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5083 NULL, IA5StringNormalize, octetStringMatch,
5084 octetStringIndexer, octetStringFilter,
5085 IA5StringApproxMatchOID },
5087 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5088 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5089 SLAP_MR_SUBSTR, NULL,
5090 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5091 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5092 "caseIgnoreIA5Match" },
5094 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5095 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5096 SLAP_MR_SUBSTR, NULL,
5097 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5098 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5099 "caseExactIA5Match" },
5101 #ifdef SLAPD_AUTHPASSWD
5102 /* needs updating */
5103 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5104 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5105 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5106 NULL, NULL, authPasswordMatch,
5111 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5112 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5114 NULL, NULL, integerBitAndMatch,
5118 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5119 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5121 NULL, NULL, integerBitOrMatch,
5125 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5126 "SYNTAX 1.3.6.1.1.16.1 )",
5127 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5128 NULL, UUIDNormalize, octetStringMatch,
5129 octetStringIndexer, octetStringFilter,
5132 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5133 "SYNTAX 1.3.6.1.1.16.1 )",
5134 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5135 NULL, UUIDNormalize, octetStringOrderingMatch,
5136 octetStringIndexer, octetStringFilter,
5139 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5140 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5141 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5142 NULL, csnNormalize, csnMatch,
5143 csnIndexer, csnFilter,
5146 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5147 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5148 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5149 NULL, NULL, csnOrderingMatch,
5153 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5154 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5155 SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5156 NULL, csnSidNormalize, octetStringMatch,
5157 octetStringIndexer, octetStringFilter,
5160 /* FIXME: OID is unused, but not registered yet */
5161 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5162 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5163 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5164 NULL, authzNormalize, authzMatch,
5168 {NULL, SLAP_MR_NONE, NULL,
5169 NULL, NULL, NULL, NULL, NULL,
5174 slap_schema_init( void )
5179 /* we should only be called once (from main) */
5180 assert( schema_init_done == 0 );
5182 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5183 res = register_syntax( &syntax_defs[i] );
5186 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5187 syntax_defs[i].sd_desc );
5192 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5193 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5194 mrule_defs[i].mrd_compat_syntaxes == NULL )
5197 "slap_schema_init: Ignoring unusable matching rule %s\n",
5198 mrule_defs[i].mrd_desc );
5202 res = register_matching_rule( &mrule_defs[i] );
5206 "slap_schema_init: Error registering matching rule %s\n",
5207 mrule_defs[i].mrd_desc );
5212 res = slap_schema_load();
5213 schema_init_done = 1;
5218 schema_destroy( void )
5227 if( schema_init_done ) {
5228 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5229 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );