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 );
3572 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3575 /* Normalize a SID as used inside a CSN, either as-is
3576 * (assertion value) or extracted from the CSN
3577 * (attribute value) */
3584 struct berval *normalized,
3592 if ( BER_BVISEMPTY( val ) ) {
3593 return LDAP_INVALID_SYNTAX;
3596 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3597 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3600 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3602 ptr = ber_bvchr( val, '#' );
3603 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3604 return LDAP_INVALID_SYNTAX;
3607 bv.bv_val = ptr + 1;
3608 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3610 ptr = ber_bvchr( &bv, '#' );
3611 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3612 return LDAP_INVALID_SYNTAX;
3615 bv.bv_val = ptr + 1;
3616 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3618 ptr = ber_bvchr( &bv, '#' );
3619 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3620 return LDAP_INVALID_SYNTAX;
3623 bv.bv_len = ptr - bv.bv_val;
3625 if ( bv.bv_len == 2 ) {
3626 /* OpenLDAP 2.3 SID */
3628 buf[ 1 ] = bv.bv_val[ 0 ];
3629 buf[ 2 ] = bv.bv_val[ 1 ];
3636 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3648 assert( in != NULL );
3649 assert( !BER_BVISNULL( in ) );
3651 if ( BER_BVISEMPTY( in ) ) {
3652 return LDAP_INVALID_SYNTAX;
3657 ptr = ber_bvchr( &bv, '#' );
3658 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3659 return LDAP_INVALID_SYNTAX;
3662 bv.bv_len = ptr - bv.bv_val;
3663 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3664 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3666 return LDAP_INVALID_SYNTAX;
3669 rc = generalizedTimeValidate( NULL, &bv );
3670 if ( rc != LDAP_SUCCESS ) {
3674 bv.bv_val = ptr + 1;
3675 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3677 ptr = ber_bvchr( &bv, '#' );
3678 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3679 return LDAP_INVALID_SYNTAX;
3682 bv.bv_len = ptr - bv.bv_val;
3683 if ( bv.bv_len != 6 ) {
3684 return LDAP_INVALID_SYNTAX;
3687 rc = hexValidate( NULL, &bv );
3688 if ( rc != LDAP_SUCCESS ) {
3692 bv.bv_val = ptr + 1;
3693 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3695 ptr = ber_bvchr( &bv, '#' );
3696 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3697 return LDAP_INVALID_SYNTAX;
3700 bv.bv_len = ptr - bv.bv_val;
3701 if ( bv.bv_len == 2 ) {
3702 /* tolerate old 2-digit replica-id */
3703 rc = hexValidate( NULL, &bv );
3706 rc = sidValidate( NULL, &bv );
3708 if ( rc != LDAP_SUCCESS ) {
3712 bv.bv_val = ptr + 1;
3713 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3715 if ( bv.bv_len != 6 ) {
3716 return LDAP_INVALID_SYNTAX;
3719 return hexValidate( NULL, &bv );
3722 /* Normalize a CSN in OpenLDAP 2.3 format */
3729 struct berval *normalized,
3732 struct berval gt, cnt, sid, mod;
3736 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3737 assert( !BER_BVISEMPTY( val ) );
3741 ptr = ber_bvchr( >, '#' );
3742 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3743 return LDAP_INVALID_SYNTAX;
3746 gt.bv_len = ptr - gt.bv_val;
3747 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3749 cnt.bv_val = ptr + 1;
3750 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3752 ptr = ber_bvchr( &cnt, '#' );
3753 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3754 return LDAP_INVALID_SYNTAX;
3757 cnt.bv_len = ptr - cnt.bv_val;
3758 assert( cnt.bv_len == STRLENOF( "000000" ) );
3760 sid.bv_val = ptr + 1;
3761 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3763 ptr = ber_bvchr( &sid, '#' );
3764 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3765 return LDAP_INVALID_SYNTAX;
3768 sid.bv_len = ptr - sid.bv_val;
3769 assert( sid.bv_len == STRLENOF( "00" ) );
3771 mod.bv_val = ptr + 1;
3772 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3773 assert( mod.bv_len == STRLENOF( "000000" ) );
3775 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3776 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3778 ptr = normalized->bv_val;
3779 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3780 ptr = lutil_strcopy( ptr, ".000000Z#" );
3781 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3784 for ( i = 0; i < sid.bv_len; i++ ) {
3785 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3788 for ( i = 0; i < mod.bv_len; i++ ) {
3789 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3793 assert( ptr - normalized->bv_val == normalized->bv_len );
3795 return LDAP_SUCCESS;
3798 /* Normalize a CSN */
3805 struct berval *normalized,
3808 struct berval cnt, sid, mod;
3812 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3814 if ( BER_BVISEMPTY( val ) ) {
3815 return LDAP_INVALID_SYNTAX;
3818 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3819 /* Openldap <= 2.3 */
3821 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3824 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3826 ptr = ber_bvchr( val, '#' );
3827 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3828 return LDAP_INVALID_SYNTAX;
3831 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3833 cnt.bv_val = ptr + 1;
3834 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3836 ptr = ber_bvchr( &cnt, '#' );
3837 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3838 return LDAP_INVALID_SYNTAX;
3841 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3843 sid.bv_val = ptr + 1;
3844 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3846 ptr = ber_bvchr( &sid, '#' );
3847 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3848 return LDAP_INVALID_SYNTAX;
3851 sid.bv_len = ptr - sid.bv_val;
3852 assert( sid.bv_len == STRLENOF( "000" ) );
3854 mod.bv_val = ptr + 1;
3855 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3857 assert( mod.bv_len == STRLENOF( "000000" ) );
3859 ber_dupbv_x( normalized, val, ctx );
3861 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3862 i < normalized->bv_len; i++ )
3864 /* assume it's already validated that's all hex digits */
3865 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3868 return LDAP_SUCCESS;
3878 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3881 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3882 /* slight optimization - does not need the start parameter */
3883 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3888 check_time_syntax (struct berval *val,
3891 struct berval *fraction)
3894 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3895 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3896 * GeneralizedTime supports leap seconds, UTCTime does not.
3898 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3899 static const int mdays[2][12] = {
3900 /* non-leap years */
3901 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3903 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3906 int part, c, c1, c2, tzoffset, leapyear = 0;
3909 e = p + val->bv_len;
3911 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3912 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3914 for (part = start; part < 7 && p < e; part++) {
3916 if (!ASCII_DIGIT(c1)) {
3921 return LDAP_INVALID_SYNTAX;
3924 if (!ASCII_DIGIT(c)) {
3925 return LDAP_INVALID_SYNTAX;
3927 c += c1 * 10 - '0' * 11;
3928 if ((part | 1) == 3) {
3931 return LDAP_INVALID_SYNTAX;
3934 if (c >= ceiling[part]) {
3935 if (! (c == 60 && part == 6 && start == 0))
3936 return LDAP_INVALID_SYNTAX;
3940 if (part < 5 + start) {
3941 return LDAP_INVALID_SYNTAX;
3943 for (; part < 9; part++) {
3947 /* leapyear check for the Gregorian calendar (year>1581) */
3948 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3952 if (parts[3] >= mdays[leapyear][parts[2]]) {
3953 return LDAP_INVALID_SYNTAX;
3957 fraction->bv_val = p;
3958 fraction->bv_len = 0;
3959 if (p < e && (*p == '.' || *p == ',')) {
3961 while (++p < e && ASCII_DIGIT(*p)) {
3964 if (p - fraction->bv_val == 1) {
3965 return LDAP_INVALID_SYNTAX;
3967 for (end_num = p; end_num[-1] == '0'; --end_num) {
3970 c = end_num - fraction->bv_val;
3971 if (c != 1) fraction->bv_len = c;
3977 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3983 return LDAP_INVALID_SYNTAX;
3989 for (part = 7; part < 9 && p < e; part++) {
3991 if (!ASCII_DIGIT(c1)) {
3996 return LDAP_INVALID_SYNTAX;
3999 if (!ASCII_DIGIT(c2)) {
4000 return LDAP_INVALID_SYNTAX;
4002 parts[part] = c1 * 10 + c2 - '0' * 11;
4003 if (parts[part] >= ceiling[part]) {
4004 return LDAP_INVALID_SYNTAX;
4007 if (part < 8 + start) {
4008 return LDAP_INVALID_SYNTAX;
4011 if (tzoffset == '-') {
4012 /* negative offset to UTC, ie west of Greenwich */
4013 parts[4] += parts[7];
4014 parts[5] += parts[8];
4015 /* offset is just hhmm, no seconds */
4016 for (part = 6; --part >= 0; ) {
4020 c = mdays[leapyear][parts[2]];
4022 if (parts[part] >= c) {
4024 return LDAP_INVALID_SYNTAX;
4029 } else if (part != 5) {
4034 /* positive offset to UTC, ie east of Greenwich */
4035 parts[4] -= parts[7];
4036 parts[5] -= parts[8];
4037 for (part = 6; --part >= 0; ) {
4038 if (parts[part] < 0) {
4040 return LDAP_INVALID_SYNTAX;
4045 /* make first arg to % non-negative */
4046 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4051 } else if (part != 5) {
4058 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4061 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4068 struct berval *normalized )
4072 rc = check_time_syntax(val, 1, parts, NULL);
4073 if (rc != LDAP_SUCCESS) {
4077 normalized->bv_val = ch_malloc( 14 );
4078 if ( normalized->bv_val == NULL ) {
4079 return LBER_ERROR_MEMORY;
4082 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4083 parts[1], parts[2] + 1, parts[3] + 1,
4084 parts[4], parts[5], parts[6] );
4085 normalized->bv_len = 13;
4087 return LDAP_SUCCESS;
4097 return check_time_syntax(in, 1, parts, NULL);
4100 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4103 generalizedTimeValidate(
4108 struct berval fraction;
4109 return check_time_syntax(in, 0, parts, &fraction);
4113 generalizedTimeNormalize(
4118 struct berval *normalized,
4123 struct berval fraction;
4125 rc = check_time_syntax(val, 0, parts, &fraction);
4126 if (rc != LDAP_SUCCESS) {
4130 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4131 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4132 if ( BER_BVISNULL( normalized ) ) {
4133 return LBER_ERROR_MEMORY;
4136 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4137 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4138 parts[4], parts[5], parts[6] );
4139 if ( !BER_BVISEMPTY( &fraction ) ) {
4140 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4141 fraction.bv_val, fraction.bv_len );
4142 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4144 strcpy( normalized->bv_val + len-1, "Z" );
4145 normalized->bv_len = len;
4147 return LDAP_SUCCESS;
4151 generalizedTimeOrderingMatch(
4156 struct berval *value,
4157 void *assertedValue )
4159 struct berval *asserted = (struct berval *) assertedValue;
4160 ber_len_t v_len = value->bv_len;
4161 ber_len_t av_len = asserted->bv_len;
4163 /* ignore trailing 'Z' when comparing */
4164 int match = memcmp( value->bv_val, asserted->bv_val,
4165 (v_len < av_len ? v_len : av_len) - 1 );
4166 if ( match == 0 ) match = v_len - av_len;
4169 return LDAP_SUCCESS;
4172 /* Index generation function */
4173 int generalizedTimeIndexer(
4178 struct berval *prefix,
4186 BerValue bvtmp; /* 40 bit index */
4188 struct lutil_timet tt;
4190 bvtmp.bv_len = sizeof(tmp);
4192 for( i=0; values[i].bv_val != NULL; i++ ) {
4193 /* just count them */
4196 /* we should have at least one value at this point */
4199 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4201 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4202 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4203 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4204 /* Use 40 bits of time for key */
4205 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4206 lutil_tm2time( &tm, &tt );
4207 tmp[0] = tt.tt_gsec & 0xff;
4208 tmp[4] = tt.tt_sec & 0xff;
4210 tmp[3] = tt.tt_sec & 0xff;
4212 tmp[2] = tt.tt_sec & 0xff;
4214 tmp[1] = tt.tt_sec & 0xff;
4216 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4220 keys[j].bv_val = NULL;
4225 return LDAP_SUCCESS;
4228 /* Index generation function */
4229 int generalizedTimeFilter(
4234 struct berval *prefix,
4235 void * assertedValue,
4241 BerValue bvtmp; /* 40 bit index */
4242 BerValue *value = (BerValue *) assertedValue;
4244 struct lutil_timet tt;
4246 bvtmp.bv_len = sizeof(tmp);
4248 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4249 /* Use 40 bits of time for key */
4250 if ( value->bv_val && value->bv_len >= 10 &&
4251 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4253 lutil_tm2time( &tm, &tt );
4254 tmp[0] = tt.tt_gsec & 0xff;
4255 tmp[4] = tt.tt_sec & 0xff;
4257 tmp[3] = tt.tt_sec & 0xff;
4259 tmp[2] = tt.tt_sec & 0xff;
4261 tmp[1] = tt.tt_sec & 0xff;
4263 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4264 ber_dupbv_x(keys, &bvtmp, ctx );
4265 keys[1].bv_val = NULL;
4273 return LDAP_SUCCESS;
4277 deliveryMethodValidate(
4279 struct berval *val )
4282 #define LENOF(s) (sizeof(s)-1)
4283 struct berval tmp = *val;
4285 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4286 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4287 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4290 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4292 switch( tmp.bv_val[0] ) {
4295 if(( tmp.bv_len >= LENOF("any") ) &&
4296 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4298 tmp.bv_len -= LENOF("any");
4299 tmp.bv_val += LENOF("any");
4302 return LDAP_INVALID_SYNTAX;
4306 if(( tmp.bv_len >= LENOF("mhs") ) &&
4307 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4309 tmp.bv_len -= LENOF("mhs");
4310 tmp.bv_val += LENOF("mhs");
4313 return LDAP_INVALID_SYNTAX;
4317 if(( tmp.bv_len >= LENOF("physical") ) &&
4318 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4320 tmp.bv_len -= LENOF("physical");
4321 tmp.bv_val += LENOF("physical");
4324 return LDAP_INVALID_SYNTAX;
4327 case 'T': /* telex or teletex or telephone */
4328 if(( tmp.bv_len >= LENOF("telex") ) &&
4329 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4331 tmp.bv_len -= LENOF("telex");
4332 tmp.bv_val += LENOF("telex");
4335 if(( tmp.bv_len >= LENOF("teletex") ) &&
4336 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4338 tmp.bv_len -= LENOF("teletex");
4339 tmp.bv_val += LENOF("teletex");
4342 if(( tmp.bv_len >= LENOF("telephone") ) &&
4343 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4345 tmp.bv_len -= LENOF("telephone");
4346 tmp.bv_val += LENOF("telephone");
4349 return LDAP_INVALID_SYNTAX;
4352 case 'G': /* g3fax or g4fax */
4353 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4354 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4355 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4357 tmp.bv_len -= LENOF("g3fax");
4358 tmp.bv_val += LENOF("g3fax");
4361 return LDAP_INVALID_SYNTAX;
4365 if(( tmp.bv_len >= LENOF("ia5") ) &&
4366 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4368 tmp.bv_len -= LENOF("ia5");
4369 tmp.bv_val += LENOF("ia5");
4372 return LDAP_INVALID_SYNTAX;
4376 if(( tmp.bv_len >= LENOF("videotex") ) &&
4377 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4379 tmp.bv_len -= LENOF("videotex");
4380 tmp.bv_val += LENOF("videotex");
4383 return LDAP_INVALID_SYNTAX;
4386 return LDAP_INVALID_SYNTAX;
4389 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4391 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4395 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4399 return LDAP_INVALID_SYNTAX;
4401 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4410 nisNetgroupTripleValidate(
4412 struct berval *val )
4417 if ( BER_BVISEMPTY( val ) ) {
4418 return LDAP_INVALID_SYNTAX;
4421 p = (char *)val->bv_val;
4422 e = p + val->bv_len;
4424 if ( *p != '(' /*')'*/ ) {
4425 return LDAP_INVALID_SYNTAX;
4428 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4432 return LDAP_INVALID_SYNTAX;
4435 } else if ( !AD_CHAR( *p ) ) {
4436 return LDAP_INVALID_SYNTAX;
4440 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4441 return LDAP_INVALID_SYNTAX;
4447 return LDAP_INVALID_SYNTAX;
4450 return LDAP_SUCCESS;
4454 bootParameterValidate(
4456 struct berval *val )
4460 if ( BER_BVISEMPTY( val ) ) {
4461 return LDAP_INVALID_SYNTAX;
4464 p = (char *)val->bv_val;
4465 e = p + val->bv_len;
4468 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4469 if ( !AD_CHAR( *p ) ) {
4470 return LDAP_INVALID_SYNTAX;
4475 return LDAP_INVALID_SYNTAX;
4479 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4480 if ( !AD_CHAR( *p ) ) {
4481 return LDAP_INVALID_SYNTAX;
4486 return LDAP_INVALID_SYNTAX;
4490 for ( p++; p < e; p++ ) {
4491 if ( !SLAP_PRINTABLE( *p ) ) {
4492 return LDAP_INVALID_SYNTAX;
4496 return LDAP_SUCCESS;
4500 firstComponentNormalize(
4505 struct berval *normalized,
4512 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4513 ber_dupbv_x( normalized, val, ctx );
4514 return LDAP_SUCCESS;
4517 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4519 if( val->bv_val[0] != '(' /*')'*/ &&
4520 val->bv_val[0] != '{' /*'}'*/ )
4522 return LDAP_INVALID_SYNTAX;
4525 /* trim leading white space */
4527 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4533 /* grab next word */
4534 comp.bv_val = &val->bv_val[len];
4535 len = val->bv_len - len;
4536 for( comp.bv_len = 0;
4537 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4543 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4544 rc = numericoidValidate( NULL, &comp );
4545 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4546 rc = integerValidate( NULL, &comp );
4548 rc = LDAP_INVALID_SYNTAX;
4552 if( rc == LDAP_SUCCESS ) {
4553 ber_dupbv_x( normalized, &comp, ctx );
4559 static char *country_gen_syn[] = {
4560 "1.3.6.1.4.1.1466.115.121.1.15",
4561 "1.3.6.1.4.1.1466.115.121.1.26",
4562 "1.3.6.1.4.1.1466.115.121.1.44",
4566 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4567 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4569 static slap_syntax_defs_rec syntax_defs[] = {
4570 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4571 X_BINARY X_NOT_H_R ")",
4572 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4573 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4574 0, NULL, NULL, NULL},
4575 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4576 0, NULL, NULL, NULL},
4577 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4579 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4580 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4582 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4583 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4584 0, NULL, bitStringValidate, NULL },
4585 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4586 0, NULL, booleanValidate, NULL},
4587 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4588 X_BINARY X_NOT_H_R ")",
4589 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4590 NULL, certificateValidate, NULL},
4591 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4592 X_BINARY X_NOT_H_R ")",
4593 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4594 NULL, certificateListValidate, NULL},
4595 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4596 X_BINARY X_NOT_H_R ")",
4597 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4598 NULL, sequenceValidate, NULL},
4599 #if 0 /* need to go __after__ printableString */
4600 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4601 0, "1.3.6.1.4.1.1466.115.121.1.44",
4602 countryStringValidate, NULL},
4604 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4605 0, NULL, dnValidate, dnPretty},
4606 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4607 0, NULL, rdnValidate, rdnPretty},
4608 #ifdef LDAP_COMP_MATCH
4609 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4610 0, NULL, allComponentsValidate, NULL},
4611 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4612 0, NULL, componentFilterValidate, NULL},
4614 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4615 0, NULL, NULL, NULL},
4616 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4617 0, NULL, deliveryMethodValidate, NULL},
4618 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4619 0, NULL, UTF8StringValidate, NULL},
4620 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4621 0, NULL, NULL, NULL},
4622 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4623 0, NULL, NULL, NULL},
4624 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4625 0, NULL, NULL, NULL},
4626 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4627 0, NULL, NULL, NULL},
4628 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4629 0, NULL, NULL, NULL},
4630 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4631 0, NULL, printablesStringValidate, NULL},
4632 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4633 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4634 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4635 0, NULL, generalizedTimeValidate, NULL},
4636 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4637 0, NULL, NULL, NULL},
4638 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4639 0, NULL, IA5StringValidate, NULL},
4640 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4641 0, NULL, integerValidate, NULL},
4642 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4643 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4644 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4645 0, NULL, NULL, NULL},
4646 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4647 0, NULL, NULL, NULL},
4648 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4649 0, NULL, NULL, NULL},
4650 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4651 0, NULL, NULL, NULL},
4652 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4653 0, NULL, NULL, NULL},
4654 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4655 0, NULL, nameUIDValidate, nameUIDPretty },
4656 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4657 0, NULL, NULL, NULL},
4658 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4659 0, NULL, numericStringValidate, NULL},
4660 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4661 0, NULL, NULL, NULL},
4662 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4663 0, NULL, numericoidValidate, NULL},
4664 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4665 0, NULL, IA5StringValidate, NULL},
4666 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4667 0, NULL, blobValidate, NULL},
4668 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4669 0, NULL, UTF8StringValidate, NULL},
4670 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4671 0, NULL, NULL, NULL},
4672 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4673 0, NULL, NULL, NULL},
4674 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4675 0, NULL, printableStringValidate, NULL},
4676 /* moved here because now depends on Directory String, IA5 String
4677 * and Printable String */
4678 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4679 0, country_gen_syn, countryStringValidate, NULL},
4680 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4681 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4682 0, NULL, subtreeSpecificationValidate, NULL},
4683 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4684 X_BINARY X_NOT_H_R ")",
4685 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4686 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4687 0, NULL, printableStringValidate, NULL},
4688 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4689 0, NULL, NULL, NULL},
4690 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4691 0, NULL, printablesStringValidate, NULL},
4692 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4693 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4694 0, NULL, utcTimeValidate, NULL},
4696 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4697 0, NULL, NULL, NULL},
4698 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4699 0, NULL, NULL, NULL},
4700 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4701 0, NULL, NULL, NULL},
4702 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4703 0, NULL, NULL, NULL},
4704 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4705 0, NULL, NULL, NULL},
4707 /* RFC 2307 NIS Syntaxes */
4708 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4709 0, NULL, nisNetgroupTripleValidate, NULL},
4710 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4711 0, NULL, bootParameterValidate, NULL},
4713 /* draft-zeilenga-ldap-x509 */
4714 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4715 SLAP_SYNTAX_HIDE, NULL,
4716 serialNumberAndIssuerValidate,
4717 serialNumberAndIssuerPretty},
4718 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4719 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4720 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4721 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4722 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4723 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4724 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4725 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4726 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4727 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4728 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4729 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4731 #ifdef SLAPD_AUTHPASSWD
4732 /* needs updating */
4733 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4734 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4737 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4738 0, NULL, UUIDValidate, UUIDPretty},
4740 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4741 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4743 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4744 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4746 /* OpenLDAP Void Syntax */
4747 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4748 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4750 /* FIXME: OID is unused, but not registered yet */
4751 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4752 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4754 {NULL, 0, NULL, NULL, NULL}
4757 char *csnSIDMatchSyntaxes[] = {
4758 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4761 char *certificateExactMatchSyntaxes[] = {
4762 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4765 #ifdef LDAP_COMP_MATCH
4766 char *componentFilterMatchSyntaxes[] = {
4767 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4771 char *directoryStringSyntaxes[] = {
4772 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4775 char *integerFirstComponentMatchSyntaxes[] = {
4776 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4777 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4780 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4781 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4782 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4783 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4784 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4785 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4786 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4787 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4788 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4793 * Other matching rules in X.520 that we do not use (yet):
4795 * 2.5.13.25 uTCTimeMatch
4796 * 2.5.13.26 uTCTimeOrderingMatch
4797 * 2.5.13.31* directoryStringFirstComponentMatch
4798 * 2.5.13.32* wordMatch
4799 * 2.5.13.33* keywordMatch
4800 * 2.5.13.36+ certificatePairExactMatch
4801 * 2.5.13.37+ certificatePairMatch
4802 * 2.5.13.38+ certificateListExactMatch
4803 * 2.5.13.39+ certificateListMatch
4804 * 2.5.13.40+ algorithmIdentifierMatch
4805 * 2.5.13.41* storedPrefixMatch
4806 * 2.5.13.42 attributeCertificateMatch
4807 * 2.5.13.43 readerAndKeyIDMatch
4808 * 2.5.13.44 attributeIntegrityMatch
4810 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4811 * (+) described in draft-zeilenga-ldap-x509
4813 static slap_mrule_defs_rec mrule_defs[] = {
4815 * EQUALITY matching rules must be listed after associated APPROX
4816 * matching rules. So, we list all APPROX matching rules first.
4818 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4819 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4820 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4821 NULL, NULL, directoryStringApproxMatch,
4822 directoryStringApproxIndexer, directoryStringApproxFilter,
4825 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4826 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4827 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4828 NULL, NULL, IA5StringApproxMatch,
4829 IA5StringApproxIndexer, IA5StringApproxFilter,
4833 * Other matching rules
4836 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4837 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4838 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4839 NULL, NULL, octetStringMatch,
4840 octetStringIndexer, octetStringFilter,
4843 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4844 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4845 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4846 NULL, dnNormalize, dnMatch,
4847 octetStringIndexer, octetStringFilter,
4850 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4851 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4852 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4853 NULL, dnNormalize, dnRelativeMatch,
4857 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4858 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4859 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4860 NULL, dnNormalize, dnRelativeMatch,
4864 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4865 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4866 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4867 NULL, dnNormalize, dnRelativeMatch,
4871 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4872 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4873 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4874 NULL, dnNormalize, dnRelativeMatch,
4878 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4879 "SYNTAX 1.2.36.79672281.1.5.0 )",
4880 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4881 NULL, rdnNormalize, rdnMatch,
4882 octetStringIndexer, octetStringFilter,
4885 #ifdef LDAP_COMP_MATCH
4886 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4887 "SYNTAX 1.2.36.79672281.1.5.2 )",
4888 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4889 NULL, NULL , componentFilterMatch,
4890 octetStringIndexer, octetStringFilter,
4893 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4894 "SYNTAX 1.2.36.79672281.1.5.3 )",
4895 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4896 NULL, NULL , allComponentsMatch,
4897 octetStringIndexer, octetStringFilter,
4900 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4901 "SYNTAX 1.2.36.79672281.1.5.3 )",
4902 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4903 NULL, NULL , directoryComponentsMatch,
4904 octetStringIndexer, octetStringFilter,
4908 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4909 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4910 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4911 NULL, UTF8StringNormalize, octetStringMatch,
4912 octetStringIndexer, octetStringFilter,
4913 directoryStringApproxMatchOID },
4915 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4916 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4917 SLAP_MR_ORDERING, directoryStringSyntaxes,
4918 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4920 "caseIgnoreMatch" },
4922 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4923 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4924 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4925 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4926 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4927 "caseIgnoreMatch" },
4929 {"( 2.5.13.5 NAME 'caseExactMatch' "
4930 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4931 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4932 NULL, UTF8StringNormalize, octetStringMatch,
4933 octetStringIndexer, octetStringFilter,
4934 directoryStringApproxMatchOID },
4936 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4937 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4938 SLAP_MR_ORDERING, directoryStringSyntaxes,
4939 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4943 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4944 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4945 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4946 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4947 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4950 {"( 2.5.13.8 NAME 'numericStringMatch' "
4951 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4952 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4953 NULL, numericStringNormalize, octetStringMatch,
4954 octetStringIndexer, octetStringFilter,
4957 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4958 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4959 SLAP_MR_ORDERING, NULL,
4960 NULL, numericStringNormalize, octetStringOrderingMatch,
4962 "numericStringMatch" },
4964 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4965 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4966 SLAP_MR_SUBSTR, NULL,
4967 NULL, numericStringNormalize, octetStringSubstringsMatch,
4968 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4969 "numericStringMatch" },
4971 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4973 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4974 NULL, NULL, NULL, NULL, NULL, NULL },
4976 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4977 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4978 SLAP_MR_SUBSTR, NULL,
4979 NULL, NULL, NULL, NULL, NULL,
4980 "caseIgnoreListMatch" },
4982 {"( 2.5.13.13 NAME 'booleanMatch' "
4983 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4984 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4985 NULL, NULL, booleanMatch,
4986 octetStringIndexer, octetStringFilter,
4989 {"( 2.5.13.14 NAME 'integerMatch' "
4990 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4991 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4992 NULL, NULL, integerMatch,
4993 octetStringIndexer, octetStringFilter,
4996 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4997 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4998 SLAP_MR_ORDERING, NULL,
4999 NULL, NULL, integerMatch,
5003 {"( 2.5.13.16 NAME 'bitStringMatch' "
5004 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5005 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5006 NULL, NULL, octetStringMatch,
5007 octetStringIndexer, octetStringFilter,
5010 {"( 2.5.13.17 NAME 'octetStringMatch' "
5011 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5012 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5013 NULL, NULL, octetStringMatch,
5014 octetStringIndexer, octetStringFilter,
5017 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5018 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5019 SLAP_MR_ORDERING, NULL,
5020 NULL, NULL, octetStringOrderingMatch,
5022 "octetStringMatch" },
5024 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5025 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5026 SLAP_MR_SUBSTR, NULL,
5027 NULL, NULL, octetStringSubstringsMatch,
5028 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5029 "octetStringMatch" },
5031 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5032 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5033 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5035 telephoneNumberNormalize, octetStringMatch,
5036 octetStringIndexer, octetStringFilter,
5039 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5040 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5041 SLAP_MR_SUBSTR, NULL,
5042 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5043 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5044 "telephoneNumberMatch" },
5046 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5047 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5048 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5049 NULL, NULL, NULL, NULL, NULL, NULL },
5051 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5052 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5053 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5054 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5055 uniqueMemberIndexer, uniqueMemberFilter,
5058 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5059 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5060 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5061 NULL, NULL, NULL, NULL, NULL, NULL },
5063 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5064 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5065 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5066 NULL, generalizedTimeNormalize, octetStringMatch,
5067 generalizedTimeIndexer, generalizedTimeFilter,
5070 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5071 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5072 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5073 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5075 "generalizedTimeMatch" },
5077 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5078 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5079 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5080 integerFirstComponentMatchSyntaxes,
5081 NULL, firstComponentNormalize, integerMatch,
5082 octetStringIndexer, octetStringFilter,
5085 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5086 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5087 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5088 objectIdentifierFirstComponentMatchSyntaxes,
5089 NULL, firstComponentNormalize, octetStringMatch,
5090 octetStringIndexer, octetStringFilter,
5093 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5094 "SYNTAX 1.3.6.1.1.15.1 )",
5095 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5096 NULL, certificateExactNormalize, octetStringMatch,
5097 octetStringIndexer, octetStringFilter,
5100 {"( 2.5.13.35 NAME 'certificateMatch' "
5101 "SYNTAX 1.3.6.1.1.15.2 )",
5102 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5103 NULL, NULL, NULL, NULL, NULL,
5106 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5108 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5109 NULL, IA5StringNormalize, octetStringMatch,
5110 octetStringIndexer, octetStringFilter,
5111 IA5StringApproxMatchOID },
5113 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5115 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5116 NULL, IA5StringNormalize, octetStringMatch,
5117 octetStringIndexer, octetStringFilter,
5118 IA5StringApproxMatchOID },
5120 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5121 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5122 SLAP_MR_SUBSTR, NULL,
5123 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5124 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5125 "caseIgnoreIA5Match" },
5127 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5128 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5129 SLAP_MR_SUBSTR, NULL,
5130 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5131 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5132 "caseExactIA5Match" },
5134 #ifdef SLAPD_AUTHPASSWD
5135 /* needs updating */
5136 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5137 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5138 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5139 NULL, NULL, authPasswordMatch,
5144 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5145 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5147 NULL, NULL, integerBitAndMatch,
5151 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5152 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5154 NULL, NULL, integerBitOrMatch,
5158 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5159 "SYNTAX 1.3.6.1.1.16.1 )",
5160 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5161 NULL, UUIDNormalize, octetStringMatch,
5162 octetStringIndexer, octetStringFilter,
5165 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5166 "SYNTAX 1.3.6.1.1.16.1 )",
5167 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5168 NULL, UUIDNormalize, octetStringOrderingMatch,
5169 octetStringIndexer, octetStringFilter,
5172 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5173 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5174 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5175 NULL, csnNormalize, csnMatch,
5176 csnIndexer, csnFilter,
5179 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5180 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5181 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5182 NULL, NULL, csnOrderingMatch,
5186 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5187 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5188 SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5189 NULL, csnSidNormalize, octetStringMatch,
5190 octetStringIndexer, octetStringFilter,
5193 /* FIXME: OID is unused, but not registered yet */
5194 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5195 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5196 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5197 NULL, authzNormalize, authzMatch,
5201 {NULL, SLAP_MR_NONE, NULL,
5202 NULL, NULL, NULL, NULL, NULL,
5207 slap_schema_init( void )
5212 /* we should only be called once (from main) */
5213 assert( schema_init_done == 0 );
5215 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5216 res = register_syntax( &syntax_defs[i] );
5219 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5220 syntax_defs[i].sd_desc );
5225 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5226 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5227 mrule_defs[i].mrd_compat_syntaxes == NULL )
5230 "slap_schema_init: Ignoring unusable matching rule %s\n",
5231 mrule_defs[i].mrd_desc );
5235 res = register_matching_rule( &mrule_defs[i] );
5239 "slap_schema_init: Error registering matching rule %s\n",
5240 mrule_defs[i].mrd_desc );
5245 res = slap_schema_load();
5246 schema_init_done = 1;
5251 schema_destroy( void )
5260 if( schema_init_done ) {
5261 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5262 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );