1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 ldap_pvt_thread_mutex_t ad_undef_mutex;
66 ldap_pvt_thread_mutex_t oc_undef_mutex;
69 generalizedTimeValidate(
78 /* no value allowed */
79 return LDAP_INVALID_SYNTAX;
87 /* any value allowed */
91 #define berValidate blobValidate
98 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
99 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
104 /* X.509 related stuff */
112 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
115 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
116 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
117 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
118 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
122 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
125 /* X.509 certificate validation */
126 static int certificateValidate( Syntax *syntax, struct berval *in )
128 BerElementBuffer berbuf;
129 BerElement *ber = (BerElement *)&berbuf;
132 ber_int_t version = SLAP_X509_V1;
134 ber_init2( ber, in, LBER_USE_DER );
135 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
136 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
137 tag = ber_skip_tag( ber, &len ); /* Sequence */
138 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
139 tag = ber_peek_tag( ber, &len );
140 /* Optional version */
141 if ( tag == SLAP_X509_OPT_C_VERSION ) {
142 tag = ber_skip_tag( ber, &len );
143 tag = ber_get_int( ber, &version );
144 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
146 /* NOTE: don't try to parse Serial, because it might be longer
147 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
148 tag = ber_skip_tag( ber, &len ); /* Serial */
149 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
150 ber_skip_data( ber, len );
151 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
152 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
153 ber_skip_data( ber, len );
154 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
155 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
156 ber_skip_data( ber, len );
157 tag = ber_skip_tag( ber, &len ); /* Validity */
158 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
159 ber_skip_data( ber, len );
160 tag = ber_skip_tag( ber, &len ); /* Subject DN */
161 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
162 ber_skip_data( ber, len );
163 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
164 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
165 ber_skip_data( ber, len );
166 tag = ber_skip_tag( ber, &len );
167 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
168 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
169 ber_skip_data( ber, len );
170 tag = ber_skip_tag( ber, &len );
172 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
173 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
174 ber_skip_data( ber, len );
175 tag = ber_skip_tag( ber, &len );
177 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
178 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
179 tag = ber_skip_tag( ber, &len );
180 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
181 ber_skip_data( ber, len );
182 tag = ber_skip_tag( ber, &len );
184 /* signatureAlgorithm */
185 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
186 ber_skip_data( ber, len );
187 tag = ber_skip_tag( ber, &len );
189 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
190 ber_skip_data( ber, len );
191 tag = ber_skip_tag( ber, &len );
192 /* Must be at end now */
193 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
197 /* X.509 certificate list validation */
198 static int certificateListValidate( Syntax *syntax, struct berval *in )
200 BerElementBuffer berbuf;
201 BerElement *ber = (BerElement *)&berbuf;
204 ber_int_t version = SLAP_X509_V1;
206 ber_init2( ber, in, LBER_USE_DER );
207 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
208 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
209 tag = ber_skip_tag( ber, &len ); /* Sequence */
210 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
211 tag = ber_peek_tag( ber, &len );
212 /* Optional version */
213 if ( tag == LBER_INTEGER ) {
214 tag = ber_get_int( ber, &version );
215 assert( tag == LBER_INTEGER );
216 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
218 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
219 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
220 ber_skip_data( ber, len );
221 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
222 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
223 ber_skip_data( ber, len );
224 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
225 /* NOTE: in the certificates I'm playing with, the time is UTC.
226 * maybe the tag is different from 0x17U for generalizedTime? */
227 if ( tag != 0x17U ) return LDAP_INVALID_SYNTAX;
228 ber_skip_data( ber, len );
229 /* Optional nextUpdate */
230 tag = ber_skip_tag( ber, &len );
231 if ( tag == 0x17U ) {
232 ber_skip_data( ber, len );
233 tag = ber_skip_tag( ber, &len );
235 /* Optional revokedCertificates */
236 if ( tag == LBER_SEQUENCE ) {
237 /* Should NOT be empty */
238 ber_skip_data( ber, len );
239 tag = ber_skip_tag( ber, &len );
241 /* Optional Extensions */
242 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
243 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
244 tag = ber_skip_tag( ber, &len );
245 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
246 ber_skip_data( ber, len );
247 tag = ber_skip_tag( ber, &len );
249 /* signatureAlgorithm */
250 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
251 ber_skip_data( ber, len );
252 tag = ber_skip_tag( ber, &len );
254 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
255 ber_skip_data( ber, len );
256 tag = ber_skip_tag( ber, &len );
257 /* Must be at end now */
258 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
268 struct berval *value,
269 void *assertedValue )
271 struct berval *asserted = (struct berval *) assertedValue;
272 int match = value->bv_len - asserted->bv_len;
275 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
283 octetStringOrderingMatch(
288 struct berval *value,
289 void *assertedValue )
291 struct berval *asserted = (struct berval *) assertedValue;
292 ber_len_t v_len = value->bv_len;
293 ber_len_t av_len = asserted->bv_len;
295 int match = memcmp( value->bv_val, asserted->bv_val,
296 (v_len < av_len ? v_len : av_len) );
298 if( match == 0 ) match = v_len - av_len;
306 HASH_CONTEXT *HASHcontext,
307 struct berval *prefix,
312 HASH_Init(HASHcontext);
313 if(prefix && prefix->bv_len > 0) {
314 HASH_Update(HASHcontext,
315 (unsigned char *)prefix->bv_val, prefix->bv_len);
317 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
318 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
319 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
325 HASH_CONTEXT *HASHcontext,
326 unsigned char *HASHdigest,
327 unsigned char *value,
330 HASH_CONTEXT ctx = *HASHcontext;
331 HASH_Update( &ctx, value, len );
332 HASH_Final( HASHdigest, &ctx );
335 /* Index generation function */
336 int octetStringIndexer(
341 struct berval *prefix,
349 HASH_CONTEXT HASHcontext;
350 unsigned char HASHdigest[HASH_BYTES];
351 struct berval digest;
352 digest.bv_val = (char *)HASHdigest;
353 digest.bv_len = sizeof(HASHdigest);
355 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
356 /* just count them */
359 /* we should have at least one value at this point */
362 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
364 slen = syntax->ssyn_oidlen;
365 mlen = mr->smr_oidlen;
367 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
368 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
369 hashIter( &HASHcontext, HASHdigest,
370 (unsigned char *)values[i].bv_val, values[i].bv_len );
371 ber_dupbv_x( &keys[i], &digest, ctx );
374 BER_BVZERO( &keys[i] );
381 /* Index generation function */
382 int octetStringFilter(
387 struct berval *prefix,
388 void * assertedValue,
394 HASH_CONTEXT HASHcontext;
395 unsigned char HASHdigest[HASH_BYTES];
396 struct berval *value = (struct berval *) assertedValue;
397 struct berval digest;
398 digest.bv_val = (char *)HASHdigest;
399 digest.bv_len = sizeof(HASHdigest);
401 slen = syntax->ssyn_oidlen;
402 mlen = mr->smr_oidlen;
404 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
406 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
407 hashIter( &HASHcontext, HASHdigest,
408 (unsigned char *)value->bv_val, value->bv_len );
410 ber_dupbv_x( keys, &digest, ctx );
411 BER_BVZERO( &keys[1] );
419 octetStringSubstringsMatch(
424 struct berval *value,
425 void *assertedValue )
428 SubstringsAssertion *sub = assertedValue;
429 struct berval left = *value;
433 /* Add up asserted input length */
434 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
435 inlen += sub->sa_initial.bv_len;
438 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
439 inlen += sub->sa_any[i].bv_len;
442 if ( !BER_BVISNULL( &sub->sa_final ) ) {
443 inlen += sub->sa_final.bv_len;
446 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
447 if ( inlen > left.bv_len ) {
452 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
453 sub->sa_initial.bv_len );
459 left.bv_val += sub->sa_initial.bv_len;
460 left.bv_len -= sub->sa_initial.bv_len;
461 inlen -= sub->sa_initial.bv_len;
464 if ( !BER_BVISNULL( &sub->sa_final ) ) {
465 if ( inlen > left.bv_len ) {
470 match = memcmp( sub->sa_final.bv_val,
471 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
472 sub->sa_final.bv_len );
478 left.bv_len -= sub->sa_final.bv_len;
479 inlen -= sub->sa_final.bv_len;
483 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
488 if ( inlen > left.bv_len ) {
489 /* not enough length */
494 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
498 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
505 idx = p - left.bv_val;
507 if ( idx >= left.bv_len ) {
508 /* this shouldn't happen */
515 if ( sub->sa_any[i].bv_len > left.bv_len ) {
516 /* not enough left */
521 match = memcmp( left.bv_val,
522 sub->sa_any[i].bv_val,
523 sub->sa_any[i].bv_len );
531 left.bv_val += sub->sa_any[i].bv_len;
532 left.bv_len -= sub->sa_any[i].bv_len;
533 inlen -= sub->sa_any[i].bv_len;
542 /* Substrings Index generation function */
544 octetStringSubstringsIndexer(
549 struct berval *prefix,
558 HASH_CONTEXT HCany, HCini, HCfin;
559 unsigned char HASHdigest[HASH_BYTES];
560 struct berval digest;
561 digest.bv_val = (char *)HASHdigest;
562 digest.bv_len = sizeof(HASHdigest);
566 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
567 /* count number of indices to generate */
568 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
569 if( values[i].bv_len >= index_substr_if_maxlen ) {
570 nkeys += index_substr_if_maxlen -
571 (index_substr_if_minlen - 1);
572 } else if( values[i].bv_len >= index_substr_if_minlen ) {
573 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
577 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
578 if( values[i].bv_len >= index_substr_any_len ) {
579 nkeys += values[i].bv_len - (index_substr_any_len - 1);
583 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
584 if( values[i].bv_len >= index_substr_if_maxlen ) {
585 nkeys += index_substr_if_maxlen -
586 (index_substr_if_minlen - 1);
587 } else if( values[i].bv_len >= index_substr_if_minlen ) {
588 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
594 /* no keys to generate */
599 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
601 slen = syntax->ssyn_oidlen;
602 mlen = mr->smr_oidlen;
604 if ( flags & SLAP_INDEX_SUBSTR_ANY )
605 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
606 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
607 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
608 if( flags & SLAP_INDEX_SUBSTR_FINAL )
609 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
612 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
615 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
616 ( values[i].bv_len >= index_substr_any_len ) )
618 max = values[i].bv_len - (index_substr_any_len - 1);
620 for( j=0; j<max; j++ ) {
621 hashIter( &HCany, HASHdigest,
622 (unsigned char *)&values[i].bv_val[j],
623 index_substr_any_len );
624 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
628 /* skip if too short */
629 if( values[i].bv_len < index_substr_if_minlen ) continue;
631 max = index_substr_if_maxlen < values[i].bv_len
632 ? index_substr_if_maxlen : values[i].bv_len;
634 for( j=index_substr_if_minlen; j<=max; j++ ) {
636 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
637 hashIter( &HCini, HASHdigest,
638 (unsigned char *)values[i].bv_val, j );
639 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
642 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
643 hashIter( &HCfin, HASHdigest,
644 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
645 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
652 BER_BVZERO( &keys[nkeys] );
663 octetStringSubstringsFilter (
668 struct berval *prefix,
669 void * assertedValue,
673 SubstringsAssertion *sa;
676 size_t slen, mlen, klen;
678 HASH_CONTEXT HASHcontext;
679 unsigned char HASHdigest[HASH_BYTES];
680 struct berval *value;
681 struct berval digest;
683 sa = (SubstringsAssertion *) assertedValue;
685 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
686 !BER_BVISNULL( &sa->sa_initial ) &&
687 sa->sa_initial.bv_len >= index_substr_if_minlen )
690 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
691 ( flags & SLAP_INDEX_SUBSTR_ANY ))
693 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
697 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
699 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
700 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
701 /* don't bother accounting with stepping */
702 nkeys += sa->sa_any[i].bv_len -
703 ( index_substr_any_len - 1 );
708 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
709 !BER_BVISNULL( &sa->sa_final ) &&
710 sa->sa_final.bv_len >= index_substr_if_minlen )
713 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
714 ( flags & SLAP_INDEX_SUBSTR_ANY ))
716 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
725 digest.bv_val = (char *)HASHdigest;
726 digest.bv_len = sizeof(HASHdigest);
728 slen = syntax->ssyn_oidlen;
729 mlen = mr->smr_oidlen;
731 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
734 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
735 !BER_BVISNULL( &sa->sa_initial ) &&
736 sa->sa_initial.bv_len >= index_substr_if_minlen )
738 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
739 value = &sa->sa_initial;
741 klen = index_substr_if_maxlen < value->bv_len
742 ? index_substr_if_maxlen : value->bv_len;
744 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
745 hashIter( &HASHcontext, HASHdigest,
746 (unsigned char *)value->bv_val, klen );
747 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
749 /* If initial is too long and we have subany indexed, use it
750 * to match the excess...
752 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
755 pre = SLAP_INDEX_SUBSTR_PREFIX;
756 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
757 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
759 hashIter( &HASHcontext, HASHdigest,
760 (unsigned char *)&value->bv_val[j], index_substr_any_len );
761 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
766 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
768 pre = SLAP_INDEX_SUBSTR_PREFIX;
769 klen = index_substr_any_len;
771 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
772 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
776 value = &sa->sa_any[i];
778 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
780 j <= value->bv_len - index_substr_any_len;
781 j += index_substr_any_step )
783 hashIter( &HASHcontext, HASHdigest,
784 (unsigned char *)&value->bv_val[j], klen );
785 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
790 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
791 !BER_BVISNULL( &sa->sa_final ) &&
792 sa->sa_final.bv_len >= index_substr_if_minlen )
794 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
795 value = &sa->sa_final;
797 klen = index_substr_if_maxlen < value->bv_len
798 ? index_substr_if_maxlen : value->bv_len;
800 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
801 hashIter( &HASHcontext, HASHdigest,
802 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
803 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
805 /* If final is too long and we have subany indexed, use it
806 * to match the excess...
808 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
811 pre = SLAP_INDEX_SUBSTR_PREFIX;
812 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
813 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
815 hashIter( &HASHcontext, HASHdigest,
816 (unsigned char *)&value->bv_val[j], index_substr_any_len );
817 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
823 BER_BVZERO( &keys[nkeys] );
840 /* very unforgiving validation, requires no normalization
841 * before simplistic matching
843 if( in->bv_len < 3 ) {
844 return LDAP_INVALID_SYNTAX;
847 /* RFC 4517 Section 3.3.2 Bit String:
848 * BitString = SQUOTE *binary-digit SQUOTE "B"
849 * binary-digit = "0" / "1"
851 * where SQUOTE [RFC4512] is
852 * SQUOTE = %x27 ; single quote ("'")
854 * Example: '0101111101'B
857 if( in->bv_val[0] != '\'' ||
858 in->bv_val[in->bv_len - 2] != '\'' ||
859 in->bv_val[in->bv_len - 1] != 'B' )
861 return LDAP_INVALID_SYNTAX;
864 for( i = in->bv_len - 3; i > 0; i-- ) {
865 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
866 return LDAP_INVALID_SYNTAX;
874 * Syntaxes from RFC 4517
879 A value of the Bit String syntax is a sequence of binary digits. The
880 LDAP-specific encoding of a value of this syntax is defined by the
883 BitString = SQUOTE *binary-digit SQUOTE "B"
885 binary-digit = "0" / "1"
887 The <SQUOTE> rule is defined in [MODELS].
892 The LDAP definition for the Bit String syntax is:
894 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
896 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
900 3.3.21. Name and Optional UID
902 A value of the Name and Optional UID syntax is the distinguished name
903 [MODELS] of an entity optionally accompanied by a unique identifier
904 that serves to differentiate the entity from others with an identical
907 The LDAP-specific encoding of a value of this syntax is defined by
910 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
912 The <BitString> rule is defined in Section 3.3.2. The
913 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
916 Note that although the '#' character may occur in the string
917 representation of a distinguished name, no additional escaping of
918 this character is performed when a <distinguishedName> is encoded in
919 a <NameAndOptionalUID>.
922 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
924 The LDAP definition for the Name and Optional UID syntax is:
926 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
928 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
935 1.4. Common ABNF Productions
938 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
940 SQUOTE = %x27 ; single quote ("'")
944 * Note: normalization strips any leading "0"s, unless the
945 * bit string is exactly "'0'B", so the normalized example,
946 * in slapd, would result in
948 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
950 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
951 * be escaped except when at the beginning of a value, the
952 * definition of Name and Optional UID appears to be flawed,
953 * because there is no clear means to determine whether the
954 * UID part is present or not.
958 * cn=Someone,dc=example,dc=com#'1'B
960 * could be either a NameAndOptionalUID with trailing UID, i.e.
962 * DN = "cn=Someone,dc=example,dc=com"
965 * or a NameAndOptionalUID with no trailing UID, and the AVA
966 * in the last RDN made of
969 * attributeValue = com#'1'B
971 * in fact "com#'1'B" is a valid IA5 string.
973 * As a consequence, current slapd code assumes that the
974 * presence of portions of a BitString at the end of the string
975 * representation of a NameAndOptionalUID means a BitString
976 * is expected, and cause an error otherwise. This is quite
977 * arbitrary, and might change in the future.
987 struct berval dn, uid;
989 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
991 ber_dupbv( &dn, in );
992 if( !dn.bv_val ) return LDAP_OTHER;
994 /* if there's a "#", try bitStringValidate()... */
995 uid.bv_val = strrchr( dn.bv_val, '#' );
996 if ( !BER_BVISNULL( &uid ) ) {
998 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1000 rc = bitStringValidate( NULL, &uid );
1001 if ( rc == LDAP_SUCCESS ) {
1002 /* in case of success, trim the UID,
1003 * otherwise treat it as part of the DN */
1004 dn.bv_len -= uid.bv_len + 1;
1005 uid.bv_val[-1] = '\0';
1009 rc = dnValidate( NULL, &dn );
1011 ber_memfree( dn.bv_val );
1022 assert( val != NULL );
1023 assert( out != NULL );
1026 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1028 if( BER_BVISEMPTY( val ) ) {
1029 ber_dupbv_x( out, val, ctx );
1031 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1032 return LDAP_INVALID_SYNTAX;
1036 struct berval dnval = *val;
1037 struct berval uidval = BER_BVNULL;
1039 uidval.bv_val = strrchr( val->bv_val, '#' );
1040 if ( !BER_BVISNULL( &uidval ) ) {
1042 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1044 rc = bitStringValidate( NULL, &uidval );
1046 if ( rc == LDAP_SUCCESS ) {
1047 ber_dupbv_x( &dnval, val, ctx );
1048 dnval.bv_len -= uidval.bv_len + 1;
1049 dnval.bv_val[dnval.bv_len] = '\0';
1052 BER_BVZERO( &uidval );
1056 rc = dnPretty( syntax, &dnval, out, ctx );
1057 if ( dnval.bv_val != val->bv_val ) {
1058 slap_sl_free( dnval.bv_val, ctx );
1060 if( rc != LDAP_SUCCESS ) {
1064 if( !BER_BVISNULL( &uidval ) ) {
1068 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1069 + STRLENOF( "#" ) + uidval.bv_len + 1,
1072 ber_memfree_x( out->bv_val, ctx );
1076 out->bv_val[out->bv_len++] = '#';
1077 out->bv_val[out->bv_len++] = '\'';
1079 got1 = uidval.bv_len < sizeof("'0'B");
1080 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1081 c = uidval.bv_val[i];
1084 if( got1 ) out->bv_val[out->bv_len++] = c;
1088 out->bv_val[out->bv_len++] = c;
1093 out->bv_val[out->bv_len++] = '\'';
1094 out->bv_val[out->bv_len++] = 'B';
1095 out->bv_val[out->bv_len] = '\0';
1099 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1101 return LDAP_SUCCESS;
1105 uniqueMemberNormalize(
1110 struct berval *normalized,
1116 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1118 ber_dupbv_x( &out, val, ctx );
1119 if ( BER_BVISEMPTY( &out ) ) {
1123 struct berval uid = BER_BVNULL;
1125 uid.bv_val = strrchr( out.bv_val, '#' );
1126 if ( !BER_BVISNULL( &uid ) ) {
1128 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1130 rc = bitStringValidate( NULL, &uid );
1131 if ( rc == LDAP_SUCCESS ) {
1132 uid.bv_val[-1] = '\0';
1133 out.bv_len -= uid.bv_len + 1;
1139 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1141 if( rc != LDAP_SUCCESS ) {
1142 slap_sl_free( out.bv_val, ctx );
1143 return LDAP_INVALID_SYNTAX;
1146 if( !BER_BVISNULL( &uid ) ) {
1149 tmp = ch_realloc( normalized->bv_val,
1150 normalized->bv_len + uid.bv_len
1151 + STRLENOF("#") + 1 );
1152 if ( tmp == NULL ) {
1153 ber_memfree_x( normalized->bv_val, ctx );
1157 normalized->bv_val = tmp;
1159 /* insert the separator */
1160 normalized->bv_val[normalized->bv_len++] = '#';
1162 /* append the UID */
1163 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1164 uid.bv_val, uid.bv_len );
1165 normalized->bv_len += uid.bv_len;
1168 normalized->bv_val[normalized->bv_len] = '\0';
1171 slap_sl_free( out.bv_val, ctx );
1174 return LDAP_SUCCESS;
1183 struct berval *value,
1184 void *assertedValue )
1187 struct berval *asserted = (struct berval *) assertedValue;
1188 struct berval assertedDN = *asserted;
1189 struct berval assertedUID = BER_BVNULL;
1190 struct berval valueDN = *value;
1191 struct berval valueUID = BER_BVNULL;
1192 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1194 if ( !BER_BVISEMPTY( asserted ) ) {
1195 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1196 if ( !BER_BVISNULL( &assertedUID ) ) {
1197 assertedUID.bv_val++;
1198 assertedUID.bv_len = assertedDN.bv_len
1199 - ( assertedUID.bv_val - assertedDN.bv_val );
1201 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1202 assertedDN.bv_len -= assertedUID.bv_len + 1;
1205 BER_BVZERO( &assertedUID );
1210 if ( !BER_BVISEMPTY( value ) ) {
1212 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1213 if ( !BER_BVISNULL( &valueUID ) ) {
1215 valueUID.bv_len = valueDN.bv_len
1216 - ( valueUID.bv_val - valueDN.bv_val );
1218 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1219 valueDN.bv_len -= valueUID.bv_len + 1;
1222 BER_BVZERO( &valueUID );
1227 if( valueUID.bv_len && assertedUID.bv_len ) {
1228 match = valueUID.bv_len - assertedUID.bv_len;
1231 return LDAP_SUCCESS;
1234 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1237 return LDAP_SUCCESS;
1240 } else if ( !approx && valueUID.bv_len ) {
1243 return LDAP_SUCCESS;
1245 } else if ( !approx && assertedUID.bv_len ) {
1248 return LDAP_SUCCESS;
1251 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1255 uniqueMemberIndexer(
1260 struct berval *prefix,
1268 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1269 /* just count them */
1273 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1275 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1276 struct berval assertedDN = values[i];
1277 struct berval assertedUID = BER_BVNULL;
1279 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1280 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1281 if ( !BER_BVISNULL( &assertedUID ) ) {
1282 assertedUID.bv_val++;
1283 assertedUID.bv_len = assertedDN.bv_len
1284 - ( assertedUID.bv_val - assertedDN.bv_val );
1286 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1287 assertedDN.bv_len -= assertedUID.bv_len + 1;
1290 BER_BVZERO( &assertedUID );
1295 dnvalues[i] = assertedDN;
1297 BER_BVZERO( &dnvalues[i] );
1299 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1300 dnvalues, keysp, ctx );
1302 slap_sl_free( dnvalues, ctx );
1312 struct berval *prefix,
1313 void * assertedValue,
1317 struct berval *asserted = (struct berval *) assertedValue;
1318 struct berval assertedDN = *asserted;
1319 struct berval assertedUID = BER_BVNULL;
1321 if ( !BER_BVISEMPTY( asserted ) ) {
1322 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1323 if ( !BER_BVISNULL( &assertedUID ) ) {
1324 assertedUID.bv_val++;
1325 assertedUID.bv_len = assertedDN.bv_len
1326 - ( assertedUID.bv_val - assertedDN.bv_val );
1328 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1329 assertedDN.bv_len -= assertedUID.bv_len + 1;
1332 BER_BVZERO( &assertedUID );
1337 return octetStringFilter( use, flags, syntax, mr, prefix,
1338 &assertedDN, keysp, ctx );
1343 * Handling boolean syntax and matching is quite rigid.
1344 * A more flexible approach would be to allow a variety
1345 * of strings to be normalized and prettied into TRUE
1353 /* very unforgiving validation, requires no normalization
1354 * before simplistic matching
1357 if( in->bv_len == 4 ) {
1358 if( bvmatch( in, &slap_true_bv ) ) {
1359 return LDAP_SUCCESS;
1361 } else if( in->bv_len == 5 ) {
1362 if( bvmatch( in, &slap_false_bv ) ) {
1363 return LDAP_SUCCESS;
1367 return LDAP_INVALID_SYNTAX;
1376 struct berval *value,
1377 void *assertedValue )
1379 /* simplistic matching allowed by rigid validation */
1380 struct berval *asserted = (struct berval *) assertedValue;
1381 *matchp = value->bv_len != asserted->bv_len;
1382 return LDAP_SUCCESS;
1385 /*-------------------------------------------------------------------
1386 LDAP/X.500 string syntax / matching rules have a few oddities. This
1387 comment attempts to detail how slapd(8) treats them.
1390 StringSyntax X.500 LDAP Matching/Comments
1391 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1392 PrintableString subset subset i/e + ignore insignificant spaces
1393 PrintableString subset subset i/e + ignore insignificant spaces
1394 NumericString subset subset ignore all spaces
1395 IA5String ASCII ASCII i/e + ignore insignificant spaces
1396 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1398 TelephoneNumber subset subset i + ignore all spaces and "-"
1400 See RFC 4518 for details.
1404 In X.500(93), a directory string can be either a PrintableString,
1405 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1406 In later versions, more CHOICEs were added. In all cases the string
1409 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1410 A directory string cannot be zero length.
1412 For matching, there are both case ignore and exact rules. Both
1413 also require that "insignificant" spaces be ignored.
1414 spaces before the first non-space are ignored;
1415 spaces after the last non-space are ignored;
1416 spaces after a space are ignored.
1417 Note: by these rules (and as clarified in X.520), a string of only
1418 spaces is to be treated as if held one space, not empty (which
1419 would be a syntax error).
1422 In ASN.1, numeric string is just a string of digits and spaces
1423 and could be empty. However, in X.500, all attribute values of
1424 numeric string carry a non-empty constraint. For example:
1426 internationalISDNNumber ATTRIBUTE ::= {
1427 WITH SYNTAX InternationalISDNNumber
1428 EQUALITY MATCHING RULE numericStringMatch
1429 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1430 ID id-at-internationalISDNNumber }
1431 InternationalISDNNumber ::=
1432 NumericString (SIZE(1..ub-international-isdn-number))
1434 Unforunately, some assertion values are don't carry the same
1435 constraint (but its unclear how such an assertion could ever
1436 be true). In LDAP, there is one syntax (numericString) not two
1437 (numericString with constraint, numericString without constraint).
1438 This should be treated as numericString with non-empty constraint.
1439 Note that while someone may have no ISDN number, there are no ISDN
1440 numbers which are zero length.
1442 In matching, spaces are ignored.
1445 In ASN.1, Printable string is just a string of printable characters
1446 and can be empty. In X.500, semantics much like NumericString (see
1447 serialNumber for a like example) excepting uses insignificant space
1448 handling instead of ignore all spaces. They must be non-empty.
1451 Basically same as PrintableString. There are no examples in X.500,
1452 but same logic applies. Empty strings are allowed.
1454 -------------------------------------------------------------------*/
1463 unsigned char *u = (unsigned char *)in->bv_val;
1465 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1466 /* directory strings cannot be empty */
1467 return LDAP_INVALID_SYNTAX;
1470 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1471 /* get the length indicated by the first byte */
1472 len = LDAP_UTF8_CHARLEN2( u, len );
1474 /* very basic checks */
1477 if( (u[5] & 0xC0) != 0x80 ) {
1478 return LDAP_INVALID_SYNTAX;
1481 if( (u[4] & 0xC0) != 0x80 ) {
1482 return LDAP_INVALID_SYNTAX;
1485 if( (u[3] & 0xC0) != 0x80 ) {
1486 return LDAP_INVALID_SYNTAX;
1489 if( (u[2] & 0xC0 )!= 0x80 ) {
1490 return LDAP_INVALID_SYNTAX;
1493 if( (u[1] & 0xC0) != 0x80 ) {
1494 return LDAP_INVALID_SYNTAX;
1497 /* CHARLEN already validated it */
1500 return LDAP_INVALID_SYNTAX;
1503 /* make sure len corresponds with the offset
1504 to the next character */
1505 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1509 return LDAP_INVALID_SYNTAX;
1512 return LDAP_SUCCESS;
1516 UTF8StringNormalize(
1521 struct berval *normalized,
1524 struct berval tmp, nvalue;
1528 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1530 if( BER_BVISNULL( val ) ) {
1531 /* assume we're dealing with a syntax (e.g., UTF8String)
1532 * which allows empty strings
1534 BER_BVZERO( normalized );
1535 return LDAP_SUCCESS;
1538 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1539 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1540 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1541 ? LDAP_UTF8_APPROX : 0;
1543 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1548 /* collapse spaces (in place) */
1550 nvalue.bv_val = tmp.bv_val;
1552 /* trim leading spaces? */
1553 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1554 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1556 for( i = 0; i < tmp.bv_len; i++) {
1557 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1558 if( wasspace++ == 0 ) {
1559 /* trim repeated spaces */
1560 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1564 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1568 if( !BER_BVISEMPTY( &nvalue ) ) {
1569 /* trim trailing space? */
1571 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1572 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1576 nvalue.bv_val[nvalue.bv_len] = '\0';
1579 /* string of all spaces is treated as one space */
1580 nvalue.bv_val[0] = ' ';
1581 nvalue.bv_val[1] = '\0';
1585 *normalized = nvalue;
1586 return LDAP_SUCCESS;
1590 directoryStringSubstringsMatch(
1595 struct berval *value,
1596 void *assertedValue )
1599 SubstringsAssertion *sub = assertedValue;
1600 struct berval left = *value;
1604 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1605 if ( sub->sa_initial.bv_len > left.bv_len ) {
1606 /* not enough left */
1611 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1612 sub->sa_initial.bv_len );
1618 left.bv_val += sub->sa_initial.bv_len;
1619 left.bv_len -= sub->sa_initial.bv_len;
1621 priorspace = ASCII_SPACE(
1622 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1625 if ( sub->sa_any ) {
1626 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1630 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1631 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1633 /* allow next space to match */
1640 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1644 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1645 /* not enough left */
1650 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1657 idx = p - left.bv_val;
1659 if ( idx >= left.bv_len ) {
1660 /* this shouldn't happen */
1667 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1668 /* not enough left */
1673 match = memcmp( left.bv_val,
1674 sub->sa_any[i].bv_val,
1675 sub->sa_any[i].bv_len );
1683 left.bv_val += sub->sa_any[i].bv_len;
1684 left.bv_len -= sub->sa_any[i].bv_len;
1686 priorspace = ASCII_SPACE(
1687 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1691 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1692 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1693 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1695 /* allow next space to match */
1700 if ( sub->sa_final.bv_len > left.bv_len ) {
1701 /* not enough left */
1706 match = memcmp( sub->sa_final.bv_val,
1707 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1708 sub->sa_final.bv_len );
1717 return LDAP_SUCCESS;
1720 #if defined(SLAPD_APPROX_INITIALS)
1721 # define SLAPD_APPROX_DELIMITER "._ "
1722 # define SLAPD_APPROX_WORDLEN 2
1724 # define SLAPD_APPROX_DELIMITER " "
1725 # define SLAPD_APPROX_WORDLEN 1
1734 struct berval *value,
1735 void *assertedValue )
1737 struct berval *nval, *assertv;
1738 char *val, **values, **words, *c;
1739 int i, count, len, nextchunk=0, nextavail=0;
1741 /* Yes, this is necessary */
1742 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1743 if( nval == NULL ) {
1745 return LDAP_SUCCESS;
1748 /* Yes, this is necessary */
1749 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1750 NULL, LDAP_UTF8_APPROX, NULL );
1751 if( assertv == NULL ) {
1754 return LDAP_SUCCESS;
1757 /* Isolate how many words there are */
1758 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1759 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1760 if ( c == NULL ) break;
1765 /* Get a phonetic copy of each word */
1766 words = (char **)ch_malloc( count * sizeof(char *) );
1767 values = (char **)ch_malloc( count * sizeof(char *) );
1768 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1770 values[i] = phonetic(c);
1773 /* Work through the asserted value's words, to see if at least some
1774 of the words are there, in the same order. */
1776 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1777 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1782 #if defined(SLAPD_APPROX_INITIALS)
1783 else if( len == 1 ) {
1784 /* Single letter words need to at least match one word's initial */
1785 for( i=nextavail; i<count; i++ )
1786 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1793 /* Isolate the next word in the asserted value and phonetic it */
1794 assertv->bv_val[nextchunk+len] = '\0';
1795 val = phonetic( assertv->bv_val + nextchunk );
1797 /* See if this phonetic chunk is in the remaining words of *value */
1798 for( i=nextavail; i<count; i++ ){
1799 if( !strcmp( val, values[i] ) ){
1807 /* This chunk in the asserted value was NOT within the *value. */
1813 /* Go on to the next word in the asserted value */
1817 /* If some of the words were seen, call it a match */
1818 if( nextavail > 0 ) {
1825 /* Cleanup allocs */
1826 ber_bvfree( assertv );
1827 for( i=0; i<count; i++ ) {
1828 ch_free( values[i] );
1834 return LDAP_SUCCESS;
1843 struct berval *prefix,
1849 int i,j, len, wordcount, keycount=0;
1850 struct berval *newkeys;
1851 BerVarray keys=NULL;
1853 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1854 struct berval val = BER_BVNULL;
1855 /* Yes, this is necessary */
1856 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1857 assert( !BER_BVISNULL( &val ) );
1859 /* Isolate how many words there are. There will be a key for each */
1860 for( wordcount = 0, c = val.bv_val; *c; c++) {
1861 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1862 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1864 if (*c == '\0') break;
1868 /* Allocate/increase storage to account for new keys */
1869 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1870 * sizeof(struct berval) );
1871 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1872 if( keys ) ch_free( keys );
1875 /* Get a phonetic copy of each word */
1876 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1878 if( len < SLAPD_APPROX_WORDLEN ) continue;
1879 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1884 ber_memfree( val.bv_val );
1886 BER_BVZERO( &keys[keycount] );
1889 return LDAP_SUCCESS;
1898 struct berval *prefix,
1899 void * assertedValue,
1908 /* Yes, this is necessary */
1909 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1910 NULL, LDAP_UTF8_APPROX, NULL );
1911 if( val == NULL || BER_BVISNULL( val ) ) {
1912 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1913 BER_BVZERO( &keys[0] );
1916 return LDAP_SUCCESS;
1919 /* Isolate how many words there are. There will be a key for each */
1920 for( count = 0,c = val->bv_val; *c; c++) {
1921 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1922 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1924 if (*c == '\0') break;
1928 /* Allocate storage for new keys */
1929 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1931 /* Get a phonetic copy of each word */
1932 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1934 if( len < SLAPD_APPROX_WORDLEN ) continue;
1935 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1941 BER_BVZERO( &keys[count] );
1944 return LDAP_SUCCESS;
1947 /* Remove all spaces and '-' characters */
1949 telephoneNumberNormalize(
1954 struct berval *normalized,
1959 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1961 /* validator should have refused an empty string */
1962 assert( !BER_BVISEMPTY( val ) );
1964 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1966 for( p = val->bv_val; *p; p++ ) {
1967 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1973 normalized->bv_len = q - normalized->bv_val;
1975 if( BER_BVISEMPTY( normalized ) ) {
1976 slap_sl_free( normalized->bv_val, ctx );
1977 BER_BVZERO( normalized );
1978 return LDAP_INVALID_SYNTAX;
1981 return LDAP_SUCCESS;
1989 struct berval val = *in;
1991 if( BER_BVISEMPTY( &val ) ) {
1992 /* disallow empty strings */
1993 return LDAP_INVALID_SYNTAX;
1996 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1997 if ( val.bv_len == 1 ) {
1998 return LDAP_SUCCESS;
2001 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2008 while ( OID_LEADCHAR( val.bv_val[0] )) {
2012 if ( val.bv_len == 0 ) {
2013 return LDAP_SUCCESS;
2017 if( !OID_SEPARATOR( val.bv_val[0] )) {
2025 return LDAP_INVALID_SYNTAX;
2034 struct berval val = *in;
2036 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2038 if ( val.bv_val[0] == '-' ) {
2042 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2043 return LDAP_INVALID_SYNTAX;
2046 if( val.bv_val[0] == '0' ) { /* "-0" */
2047 return LDAP_INVALID_SYNTAX;
2050 } else if ( val.bv_val[0] == '0' ) {
2051 if( val.bv_len > 1 ) { /* "0<more>" */
2052 return LDAP_INVALID_SYNTAX;
2055 return LDAP_SUCCESS;
2058 for( i=0; i < val.bv_len; i++ ) {
2059 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2060 return LDAP_INVALID_SYNTAX;
2064 return LDAP_SUCCESS;
2073 struct berval *value,
2074 void *assertedValue )
2076 struct berval *asserted = (struct berval *) assertedValue;
2077 int vsign = 1, asign = 1; /* default sign = '+' */
2082 if( v.bv_val[0] == '-' ) {
2088 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2091 if( a.bv_val[0] == '-' ) {
2097 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2099 match = vsign - asign;
2101 match = ( v.bv_len != a.bv_len
2102 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2103 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2104 if( vsign < 0 ) match = -match;
2108 return LDAP_SUCCESS;
2112 countryStringValidate(
2114 struct berval *val )
2116 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2118 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2119 return LDAP_INVALID_SYNTAX;
2121 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2122 return LDAP_INVALID_SYNTAX;
2125 return LDAP_SUCCESS;
2129 printableStringValidate(
2131 struct berval *val )
2135 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2137 for(i=0; i < val->bv_len; i++) {
2138 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2139 return LDAP_INVALID_SYNTAX;
2143 return LDAP_SUCCESS;
2147 printablesStringValidate(
2149 struct berval *val )
2153 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2155 for(i=0,len=0; i < val->bv_len; i++) {
2156 int c = val->bv_val[i];
2160 return LDAP_INVALID_SYNTAX;
2164 } else if ( SLAP_PRINTABLE(c) ) {
2167 return LDAP_INVALID_SYNTAX;
2172 return LDAP_INVALID_SYNTAX;
2175 return LDAP_SUCCESS;
2181 struct berval *val )
2185 for(i=0; i < val->bv_len; i++) {
2186 if( !LDAP_ASCII(val->bv_val[i]) ) {
2187 return LDAP_INVALID_SYNTAX;
2191 return LDAP_SUCCESS;
2200 struct berval *normalized,
2204 int casefold = !SLAP_MR_ASSOCIATED( mr,
2205 slap_schema.si_mr_caseExactIA5Match );
2207 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2211 /* Ignore initial whitespace */
2212 while ( ASCII_SPACE( *p ) ) p++;
2214 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2215 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2216 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2217 normalized->bv_val[normalized->bv_len] = '\0';
2219 p = q = normalized->bv_val;
2222 if ( ASCII_SPACE( *p ) ) {
2225 /* Ignore the extra whitespace */
2226 while ( ASCII_SPACE( *p ) ) {
2230 } else if ( casefold ) {
2231 /* Most IA5 rules require casefolding */
2232 *q++ = TOLOWER(*p); p++;
2239 assert( normalized->bv_val <= p );
2243 * If the string ended in space, backup the pointer one
2244 * position. One is enough because the above loop collapsed
2245 * all whitespace to a single space.
2247 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2249 /* null terminate */
2252 normalized->bv_len = q - normalized->bv_val;
2254 return LDAP_SUCCESS;
2263 if( in->bv_len != 36 ) {
2264 return LDAP_INVALID_SYNTAX;
2267 for( i=0; i<36; i++ ) {
2273 if( in->bv_val[i] != '-' ) {
2274 return LDAP_INVALID_SYNTAX;
2278 if( !ASCII_HEX( in->bv_val[i]) ) {
2279 return LDAP_INVALID_SYNTAX;
2284 return LDAP_SUCCESS;
2295 int rc=LDAP_INVALID_SYNTAX;
2297 assert( in != NULL );
2298 assert( out != NULL );
2300 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2303 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2305 for( i=0; i<36; i++ ) {
2311 if( in->bv_val[i] != '-' ) {
2314 out->bv_val[i] = '-';
2318 if( !ASCII_HEX( in->bv_val[i]) ) {
2321 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2326 out->bv_val[ out->bv_len ] = '\0';
2330 slap_sl_free( out->bv_val, ctx );
2343 struct berval *normalized,
2346 unsigned char octet = '\0';
2349 normalized->bv_len = 16;
2350 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2352 for( i=0, j=0; i<36; i++ ) {
2353 unsigned char nibble;
2354 if( val->bv_val[i] == '-' ) {
2357 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2358 nibble = val->bv_val[i] - '0';
2360 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2361 nibble = val->bv_val[i] - ('a'-10);
2363 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2364 nibble = val->bv_val[i] - ('A'-10);
2367 slap_sl_free( normalized->bv_val, ctx );
2368 return LDAP_INVALID_SYNTAX;
2373 normalized->bv_val[j>>1] = octet;
2375 octet = nibble << 4;
2380 normalized->bv_val[normalized->bv_len] = 0;
2381 return LDAP_SUCCESS;
2387 numericStringValidate(
2393 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2395 for(i=0; i < in->bv_len; i++) {
2396 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2397 return LDAP_INVALID_SYNTAX;
2401 return LDAP_SUCCESS;
2405 numericStringNormalize(
2410 struct berval *normalized,
2413 /* removal all spaces */
2416 assert( !BER_BVISEMPTY( val ) );
2418 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2421 q = normalized->bv_val;
2424 if ( ASCII_SPACE( *p ) ) {
2425 /* Ignore whitespace */
2432 /* we should have copied no more than is in val */
2433 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2435 /* null terminate */
2438 normalized->bv_len = q - normalized->bv_val;
2440 if( BER_BVISEMPTY( normalized ) ) {
2441 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2442 normalized->bv_val[0] = ' ';
2443 normalized->bv_val[1] = '\0';
2444 normalized->bv_len = 1;
2447 return LDAP_SUCCESS;
2451 * Integer conversion macros that will use the largest available
2454 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2455 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2456 # define SLAP_LONG long long
2458 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2459 # define SLAP_LONG long
2460 #endif /* HAVE_STRTOLL ... */
2468 struct berval *value,
2469 void *assertedValue )
2471 SLAP_LONG lValue, lAssertedValue;
2474 /* safe to assume integers are NUL terminated? */
2475 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2476 if( errno == ERANGE )
2478 return LDAP_CONSTRAINT_VIOLATION;
2481 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2483 if( errno == ERANGE )
2485 return LDAP_CONSTRAINT_VIOLATION;
2488 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2489 return LDAP_SUCCESS;
2498 struct berval *value,
2499 void *assertedValue )
2501 SLAP_LONG lValue, lAssertedValue;
2504 /* safe to assume integers are NUL terminated? */
2505 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2506 if( errno == ERANGE )
2508 return LDAP_CONSTRAINT_VIOLATION;
2511 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2513 if( errno == ERANGE )
2515 return LDAP_CONSTRAINT_VIOLATION;
2518 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2519 return LDAP_SUCCESS;
2523 serialNumberAndIssuerValidate(
2529 struct berval sn, i;
2531 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2534 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2536 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2537 /* Parse old format */
2538 i.bv_val = ber_bvchr( in, '$' );
2539 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2541 sn.bv_val = in->bv_val;
2542 sn.bv_len = i.bv_val - in->bv_val;
2545 i.bv_len = in->bv_len - (sn.bv_len + 1);
2547 /* eat leading zeros */
2548 for( n=0; n < (sn.bv_len-1); n++ ) {
2549 if( sn.bv_val[n] != '0' ) break;
2554 for( n=0; n < sn.bv_len; n++ ) {
2555 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2559 /* Parse GSER format */
2560 int havesn=0,haveissuer=0;
2561 struct berval x = *in;
2565 /* eat leading spaces */
2566 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2570 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2571 return LDAP_INVALID_SYNTAX;
2574 /* should be at issuer or serialNumber NamedValue */
2575 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2577 x.bv_val += STRLENOF("issuer");
2578 x.bv_len -= STRLENOF("issuer");
2580 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2581 x.bv_val++; x.bv_len--;
2583 /* eat leading spaces */
2584 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2588 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2589 x.bv_val++; x.bv_len--;
2591 i.bv_val = x.bv_val;
2594 for( ; i.bv_len < x.bv_len; ) {
2595 if ( i.bv_val[i.bv_len] != '"' ) {
2599 if ( i.bv_val[i.bv_len+1] == '"' ) {
2606 x.bv_val += i.bv_len+1;
2607 x.bv_len -= i.bv_len+1;
2609 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2610 return LDAP_INVALID_SYNTAX;
2615 } else if( strncasecmp( x.bv_val, "serialNumber",
2616 STRLENOF("serialNumber")) == 0 )
2618 /* parse serialNumber */
2620 x.bv_val += STRLENOF("serialNumber");
2621 x.bv_len -= STRLENOF("serialNumber");
2623 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2624 x.bv_val++; x.bv_len--;
2626 /* eat leading spaces */
2627 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2631 sn.bv_val = x.bv_val;
2634 if( sn.bv_val[0] == '-' ) {
2639 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2640 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2643 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2644 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2645 return LDAP_INVALID_SYNTAX;
2648 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2650 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2651 return LDAP_INVALID_SYNTAX;
2656 } else return LDAP_INVALID_SYNTAX;
2658 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2659 x.bv_val++; x.bv_len--;
2662 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2666 /* should be at remaining NamedValue */
2667 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2668 STRLENOF("issuer" )) == 0 ))
2671 x.bv_val += STRLENOF("issuer");
2672 x.bv_len -= STRLENOF("issuer");
2674 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2675 x.bv_val++; x.bv_len--;
2677 /* eat leading spaces */
2678 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2682 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2683 x.bv_val++; x.bv_len--;
2685 i.bv_val = x.bv_val;
2688 for( ; i.bv_len < x.bv_len; ) {
2689 if ( i.bv_val[i.bv_len] != '"' ) {
2693 if ( i.bv_val[i.bv_len+1] == '"' ) {
2700 x.bv_val += i.bv_len+1;
2701 x.bv_len -= i.bv_len+1;
2703 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2704 STRLENOF("serialNumber")) == 0 ))
2706 /* parse serialNumber */
2708 x.bv_val += STRLENOF("serialNumber");
2709 x.bv_len -= STRLENOF("serialNumber");
2711 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2712 x.bv_val++; x.bv_len--;
2714 /* eat leading spaces */
2715 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2719 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2720 x.bv_val++; x.bv_len--;
2722 sn.bv_val = x.bv_val;
2725 if( sn.bv_val[0] == '-' ) {
2730 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2731 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2734 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2735 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2736 return LDAP_INVALID_SYNTAX;
2739 x.bv_val += sn.bv_len;
2740 x.bv_len -= sn.bv_len;
2742 } else return LDAP_INVALID_SYNTAX;
2744 /* eat trailing spaces */
2745 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2749 /* should have no characters left... */
2750 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2753 /* validate DN -- doesn't handle double dquote */
2754 rc = dnValidate( NULL, &i );
2755 if( rc ) return LDAP_INVALID_SYNTAX;
2757 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2759 return LDAP_SUCCESS;
2763 serialNumberAndIssuerPretty(
2771 struct berval sn, i, ni;
2773 assert( in != NULL );
2774 assert( out != NULL );
2776 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2779 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2781 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2782 /* Parse old format */
2783 i.bv_val = ber_bvchr( in, '$' );
2784 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2786 sn.bv_val = in->bv_val;
2787 sn.bv_len = i.bv_val - in->bv_val;
2790 i.bv_len = in->bv_len - (sn.bv_len + 1);
2792 /* eat leading zeros */
2793 for( n=0; n < (sn.bv_len-1); n++ ) {
2794 if( sn.bv_val[n] != '0' ) break;
2799 for( n=0; n < sn.bv_len; n++ ) {
2800 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2804 /* Parse GSER format */
2805 int havesn=0,haveissuer=0;
2806 struct berval x = *in;
2810 /* eat leading spaces */
2811 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2815 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2816 return LDAP_INVALID_SYNTAX;
2819 /* should be at issuer or serialNumber NamedValue */
2820 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2822 x.bv_val += STRLENOF("issuer");
2823 x.bv_len -= STRLENOF("issuer");
2825 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2826 x.bv_val++; x.bv_len--;
2828 /* eat leading spaces */
2829 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2833 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2834 x.bv_val++; x.bv_len--;
2836 i.bv_val = x.bv_val;
2839 for( ; i.bv_len < x.bv_len; ) {
2840 if ( i.bv_val[i.bv_len] != '"' ) {
2844 if ( i.bv_val[i.bv_len+1] == '"' ) {
2851 x.bv_val += i.bv_len+1;
2852 x.bv_len -= i.bv_len+1;
2854 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2855 return LDAP_INVALID_SYNTAX;
2860 } else if( strncasecmp( x.bv_val, "serialNumber",
2861 STRLENOF("serialNumber")) == 0 )
2863 /* parse serialNumber */
2865 x.bv_val += STRLENOF("serialNumber");
2866 x.bv_len -= STRLENOF("serialNumber");
2868 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2869 x.bv_val++; x.bv_len--;
2871 /* eat leading spaces */
2872 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2876 sn.bv_val = x.bv_val;
2879 if( sn.bv_val[0] == '-' ) {
2884 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2885 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2888 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2889 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2890 return LDAP_INVALID_SYNTAX;
2893 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2895 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2896 return LDAP_INVALID_SYNTAX;
2901 } else return LDAP_INVALID_SYNTAX;
2903 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2904 x.bv_val++; x.bv_len--;
2907 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2911 /* should be at remaining NamedValue */
2912 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2913 STRLENOF("issuer" )) == 0 ))
2916 x.bv_val += STRLENOF("issuer");
2917 x.bv_len -= STRLENOF("issuer");
2919 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2920 x.bv_val++; x.bv_len--;
2922 /* eat leading spaces */
2923 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2927 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2928 x.bv_val++; x.bv_len--;
2930 i.bv_val = x.bv_val;
2933 for( ; i.bv_len < x.bv_len; ) {
2934 if ( i.bv_val[i.bv_len] != '"' ) {
2938 if ( i.bv_val[i.bv_len+1] == '"' ) {
2945 x.bv_val += i.bv_len+1;
2946 x.bv_len -= i.bv_len+1;
2948 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2949 STRLENOF("serialNumber")) == 0 ))
2951 /* parse serialNumber */
2953 x.bv_val += STRLENOF("serialNumber");
2954 x.bv_len -= STRLENOF("serialNumber");
2956 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2957 x.bv_val++; x.bv_len--;
2959 /* eat leading spaces */
2960 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2964 sn.bv_val = x.bv_val;
2967 if( sn.bv_val[0] == '-' ) {
2972 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2973 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2976 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2977 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2978 return LDAP_INVALID_SYNTAX;
2981 x.bv_val += sn.bv_len;
2982 x.bv_len -= sn.bv_len;
2984 } else return LDAP_INVALID_SYNTAX;
2986 /* eat trailing spaces */
2987 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2991 /* should have no characters left... */
2992 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2994 ber_dupbv_x( &ni, &i, ctx );
2997 /* need to handle double dquotes here */
3000 rc = dnPretty( syntax, &i, &ni, ctx );
3002 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3003 slap_sl_free( i.bv_val, ctx );
3006 if( rc ) return LDAP_INVALID_SYNTAX;
3008 /* make room from sn + "$" */
3009 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
3010 + sn.bv_len + ni.bv_len;
3011 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3013 if( out->bv_val == NULL ) {
3015 slap_sl_free( ni.bv_val, ctx );
3020 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3021 STRLENOF("{ serialNumber "));
3022 n = STRLENOF("{ serialNumber ");
3024 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3027 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
3028 n += STRLENOF(", issuer \"");
3030 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3033 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3034 n += STRLENOF("\" }");
3036 out->bv_val[n] = '\0';
3038 assert( n == out->bv_len );
3040 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3041 out->bv_val, 0, 0 );
3043 slap_sl_free( ni.bv_val, ctx );
3045 return LDAP_SUCCESS;
3049 * This routine is called by certificateExactNormalize when
3050 * certificateExactNormalize receives a search string instead of
3051 * a certificate. This routine checks if the search value is valid
3052 * and then returns the normalized value
3055 serialNumberAndIssuerNormalize(
3065 struct berval sn, i, ni;
3067 assert( in != NULL );
3068 assert( out != NULL );
3070 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3073 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3075 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3076 /* Parse old format */
3077 i.bv_val = ber_bvchr( in, '$' );
3078 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
3080 sn.bv_val = in->bv_val;
3081 sn.bv_len = i.bv_val - in->bv_val;
3084 i.bv_len = in->bv_len - (sn.bv_len + 1);
3086 /* eat leading zeros */
3087 for( n=0; n < (sn.bv_len-1); n++ ) {
3088 if( sn.bv_val[n] != '0' ) break;
3093 for( n=0; n < sn.bv_len; n++ ) {
3094 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3098 /* Parse GSER format */
3099 int havesn=0,haveissuer=0;
3100 struct berval x = *in;
3104 /* eat leading spaces */
3105 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3109 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3110 return LDAP_INVALID_SYNTAX;
3113 /* should be at issuer or serialNumber NamedValue */
3114 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3116 x.bv_val += STRLENOF("issuer");
3117 x.bv_len -= STRLENOF("issuer");
3119 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3120 x.bv_val++; x.bv_len--;
3122 /* eat leading spaces */
3123 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3127 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3128 x.bv_val++; x.bv_len--;
3130 i.bv_val = x.bv_val;
3133 for( ; i.bv_len < x.bv_len; ) {
3134 if ( i.bv_val[i.bv_len] != '"' ) {
3138 if ( i.bv_val[i.bv_len+1] == '"' ) {
3145 x.bv_val += i.bv_len+1;
3146 x.bv_len -= i.bv_len+1;
3148 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3149 return LDAP_INVALID_SYNTAX;
3154 } else if( strncasecmp( x.bv_val, "serialNumber",
3155 STRLENOF("serialNumber")) == 0 )
3157 /* parse serialNumber */
3159 x.bv_val += STRLENOF("serialNumber");
3160 x.bv_len -= STRLENOF("serialNumber");
3162 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3163 x.bv_val++; x.bv_len--;
3165 /* eat leading spaces */
3166 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3170 sn.bv_val = x.bv_val;
3173 if( sn.bv_val[0] == '-' ) {
3178 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3179 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3182 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3183 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3184 return LDAP_INVALID_SYNTAX;
3187 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3189 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3190 return LDAP_INVALID_SYNTAX;
3195 } else return LDAP_INVALID_SYNTAX;
3197 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3198 x.bv_val++; x.bv_len--;
3201 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3205 /* should be at remaining NamedValue */
3206 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3207 STRLENOF("issuer" )) == 0 ))
3210 x.bv_val += STRLENOF("issuer");
3211 x.bv_len -= STRLENOF("issuer");
3213 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3214 x.bv_val++; x.bv_len--;
3216 /* eat leading spaces */
3217 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3221 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3222 x.bv_val++; x.bv_len--;
3224 i.bv_val = x.bv_val;
3227 for( ; i.bv_len < x.bv_len; ) {
3228 if ( i.bv_val[i.bv_len] != '"' ) {
3232 if ( i.bv_val[i.bv_len+1] == '"' ) {
3239 x.bv_val += i.bv_len+1;
3240 x.bv_len -= i.bv_len+1;
3242 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3243 STRLENOF("serialNumber")) == 0 ))
3245 /* parse serialNumber */
3247 x.bv_val += STRLENOF("serialNumber");
3248 x.bv_len -= STRLENOF("serialNumber");
3250 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3251 x.bv_val++; x.bv_len--;
3253 /* eat leading spaces */
3254 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3258 sn.bv_val = x.bv_val;
3261 if( sn.bv_val[0] == '-' ) {
3266 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3267 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3270 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3271 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3272 return LDAP_INVALID_SYNTAX;
3275 x.bv_val += sn.bv_len;
3276 x.bv_len -= sn.bv_len;
3278 } else return LDAP_INVALID_SYNTAX;
3280 /* eat trailing spaces */
3281 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3285 /* should have no characters left... */
3286 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3288 ber_dupbv_x( &ni, &i, ctx );
3291 /* need to handle double dquotes here */
3294 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3296 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3297 slap_sl_free( i.bv_val, ctx );
3300 if( rc ) return LDAP_INVALID_SYNTAX;
3302 /* make room from sn + "$" */
3303 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3304 + sn.bv_len + ni.bv_len;
3305 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3307 if( out->bv_val == NULL ) {
3309 slap_sl_free( ni.bv_val, ctx );
3314 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3315 STRLENOF( "{ serialNumber " ));
3316 n = STRLENOF( "{ serialNumber " );
3318 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3321 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3322 n += STRLENOF( ", issuer \"" );
3324 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3327 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3328 n += STRLENOF( "\" }" );
3330 out->bv_val[n] = '\0';
3332 assert( n == out->bv_len );
3334 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3335 out->bv_val, 0, 0 );
3337 slap_sl_free( ni.bv_val, ctx );
3339 return LDAP_SUCCESS;
3343 certificateExactNormalize(
3348 struct berval *normalized,
3351 BerElementBuffer berbuf;
3352 BerElement *ber = (BerElement *)&berbuf;
3356 char serialbuf[64], *serial = serialbuf;
3357 ber_len_t seriallen;
3358 struct berval issuer_dn = BER_BVNULL, bvdn;
3360 int rc = LDAP_INVALID_SYNTAX;
3362 if( BER_BVISEMPTY( val ) ) goto done;
3364 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3365 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3368 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3370 ber_init2( ber, val, LBER_USE_DER );
3371 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3372 tag = ber_skip_tag( ber, &len ); /* Sequence */
3373 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3374 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3375 tag = ber_skip_tag( ber, &len );
3376 tag = ber_get_int( ber, &i ); /* version */
3379 /* NOTE: move the test here from certificateNormalize,
3380 * so that we can validate certs with serial longer
3381 * than sizeof(ber_int_t) */
3382 tag = ber_peek_tag( ber, &len ); /* serial */
3383 if ( len > sizeof(ber_int_t) ) {
3386 tag = ber_skip_tag( ber, &len );
3387 ptr = (unsigned char *)ber->ber_ptr;
3388 ber_skip_data( ber, len );
3390 while ( ptr[0] == '\0' && len > 0 ) {
3395 #if defined(USE_MP_BIGNUM)
3398 #elif defined(USE_MP_GMP)
3400 /* hint: use mpz_import(), mpz_get_str() */
3402 #elif defined(USE_MP_LONG_LONG)
3403 if ( len <= sizeof( unsigned long long ) ) {
3404 unsigned long long sn = 0;
3409 for ( i = 1; i < len; i++ ) {
3414 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%llu", sn );
3417 /* do not accept serialNumber that requires
3418 * more than long long */
3419 rc = LDAP_INVALID_SYNTAX;
3424 /* do not accept serialNumber that requires
3426 rc = LDAP_INVALID_SYNTAX;
3431 tag = ber_get_int( ber, &i ); /* serial */
3432 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
3434 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3435 ber_skip_data( ber, len );
3436 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3437 len = ber_ptrlen( ber );
3438 bvdn.bv_val = val->bv_val + len;
3439 bvdn.bv_len = val->bv_len - len;
3441 rc = dnX509normalize( &bvdn, &issuer_dn );
3442 if( rc != LDAP_SUCCESS ) goto done;
3444 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3445 + seriallen + issuer_dn.bv_len;
3446 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3448 p = (unsigned char *)normalized->bv_val;
3450 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3451 p += STRLENOF( "{ serialNumber " );
3453 AC_MEMCPY(p, serial, seriallen);
3456 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3457 p += STRLENOF( ", issuer \"" );
3459 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3460 p += issuer_dn.bv_len;
3462 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3463 p += STRLENOF( "\" }" );
3467 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3468 normalized->bv_val, NULL, NULL );
3473 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3474 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3486 assert( in != NULL );
3487 assert( !BER_BVISNULL( in ) );
3489 for ( i = 0; i < in->bv_len; i++ ) {
3490 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3491 return LDAP_INVALID_SYNTAX;
3495 return LDAP_SUCCESS;
3498 /* Normalize a SID as used inside a CSN:
3499 * three-digit numeric string */
3506 struct berval *normalized,
3511 ber_dupbv_x( normalized, val, ctx );
3513 for ( i = 0; i < normalized->bv_len; i++ ) {
3514 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3515 ber_memfree_x( normalized->bv_val, ctx );
3516 BER_BVZERO( normalized );
3517 return LDAP_INVALID_SYNTAX;
3520 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3523 return LDAP_SUCCESS;
3531 assert( in != NULL );
3532 assert( !BER_BVISNULL( in ) );
3534 if ( in->bv_len != 3 ) {
3535 return LDAP_INVALID_SYNTAX;
3538 return hexValidate( NULL, in );
3541 /* Normalize a SID as used inside a CSN:
3542 * three-digit numeric string */
3549 struct berval *normalized,
3552 if ( val->bv_len != 3 ) {
3553 return LDAP_INVALID_SYNTAX;
3556 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3566 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3569 /* Normalize a SID as used inside a CSN, either as-is
3570 * (assertion value) or extracted from the CSN
3571 * (attribute value) */
3578 struct berval *normalized,
3586 if ( BER_BVISEMPTY( val ) ) {
3587 return LDAP_INVALID_SYNTAX;
3590 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3591 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3594 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3596 ptr = ber_bvchr( val, '#' );
3597 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3598 return LDAP_INVALID_SYNTAX;
3601 bv.bv_val = ptr + 1;
3602 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3604 ptr = ber_bvchr( &bv, '#' );
3605 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3606 return LDAP_INVALID_SYNTAX;
3609 bv.bv_val = ptr + 1;
3610 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3612 ptr = ber_bvchr( &bv, '#' );
3613 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3614 return LDAP_INVALID_SYNTAX;
3617 bv.bv_len = ptr - bv.bv_val;
3619 if ( bv.bv_len == 2 ) {
3620 /* OpenLDAP 2.3 SID */
3622 buf[ 1 ] = bv.bv_val[ 0 ];
3623 buf[ 2 ] = bv.bv_val[ 1 ];
3630 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3642 assert( in != NULL );
3643 assert( !BER_BVISNULL( in ) );
3645 if ( BER_BVISEMPTY( in ) ) {
3646 return LDAP_INVALID_SYNTAX;
3651 ptr = ber_bvchr( &bv, '#' );
3652 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3653 return LDAP_INVALID_SYNTAX;
3656 bv.bv_len = ptr - bv.bv_val;
3657 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3658 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3660 return LDAP_INVALID_SYNTAX;
3663 rc = generalizedTimeValidate( NULL, &bv );
3664 if ( rc != LDAP_SUCCESS ) {
3668 bv.bv_val = ptr + 1;
3669 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3671 ptr = ber_bvchr( &bv, '#' );
3672 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3673 return LDAP_INVALID_SYNTAX;
3676 bv.bv_len = ptr - bv.bv_val;
3677 if ( bv.bv_len != 6 ) {
3678 return LDAP_INVALID_SYNTAX;
3681 rc = hexValidate( NULL, &bv );
3682 if ( rc != LDAP_SUCCESS ) {
3686 bv.bv_val = ptr + 1;
3687 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3689 ptr = ber_bvchr( &bv, '#' );
3690 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3691 return LDAP_INVALID_SYNTAX;
3694 bv.bv_len = ptr - bv.bv_val;
3695 if ( bv.bv_len == 2 ) {
3696 /* tolerate old 2-digit replica-id */
3697 rc = hexValidate( NULL, &bv );
3700 rc = sidValidate( NULL, &bv );
3702 if ( rc != LDAP_SUCCESS ) {
3706 bv.bv_val = ptr + 1;
3707 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3709 if ( bv.bv_len != 6 ) {
3710 return LDAP_INVALID_SYNTAX;
3713 return hexValidate( NULL, &bv );
3716 /* Normalize a CSN in OpenLDAP 2.3 format */
3723 struct berval *normalized,
3726 struct berval gt, cnt, sid, mod;
3730 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3731 assert( !BER_BVISEMPTY( val ) );
3735 ptr = ber_bvchr( >, '#' );
3736 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3737 return LDAP_INVALID_SYNTAX;
3740 gt.bv_len = ptr - gt.bv_val;
3741 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3743 cnt.bv_val = ptr + 1;
3744 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3746 ptr = ber_bvchr( &cnt, '#' );
3747 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3748 return LDAP_INVALID_SYNTAX;
3751 cnt.bv_len = ptr - cnt.bv_val;
3752 assert( cnt.bv_len == STRLENOF( "000000" ) );
3754 sid.bv_val = ptr + 1;
3755 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3757 ptr = ber_bvchr( &sid, '#' );
3758 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3759 return LDAP_INVALID_SYNTAX;
3762 sid.bv_len = ptr - sid.bv_val;
3763 assert( sid.bv_len == STRLENOF( "00" ) );
3765 mod.bv_val = ptr + 1;
3766 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3767 assert( mod.bv_len == STRLENOF( "000000" ) );
3769 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3770 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3772 ptr = normalized->bv_val;
3773 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3774 ptr = lutil_strcopy( ptr, ".000000Z#" );
3775 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3778 for ( i = 0; i < sid.bv_len; i++ ) {
3779 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3782 for ( i = 0; i < mod.bv_len; i++ ) {
3783 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3787 assert( ptr - normalized->bv_val == normalized->bv_len );
3789 return LDAP_SUCCESS;
3792 /* Normalize a CSN */
3799 struct berval *normalized,
3802 struct berval cnt, sid, mod;
3806 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3808 if ( BER_BVISEMPTY( val ) ) {
3809 return LDAP_INVALID_SYNTAX;
3812 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3813 /* Openldap <= 2.3 */
3815 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3818 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3820 ptr = ber_bvchr( val, '#' );
3821 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3822 return LDAP_INVALID_SYNTAX;
3825 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3827 cnt.bv_val = ptr + 1;
3828 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3830 ptr = ber_bvchr( &cnt, '#' );
3831 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3832 return LDAP_INVALID_SYNTAX;
3835 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3837 sid.bv_val = ptr + 1;
3838 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3840 ptr = ber_bvchr( &sid, '#' );
3841 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3842 return LDAP_INVALID_SYNTAX;
3845 sid.bv_len = ptr - sid.bv_val;
3846 assert( sid.bv_len == STRLENOF( "000" ) );
3848 mod.bv_val = ptr + 1;
3849 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3851 assert( mod.bv_len == STRLENOF( "000000" ) );
3853 ber_dupbv_x( normalized, val, ctx );
3855 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3856 i < normalized->bv_len; i++ )
3858 /* assume it's already validated that's all hex digits */
3859 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3862 return LDAP_SUCCESS;
3872 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3875 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3876 /* slight optimization - does not need the start parameter */
3877 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3882 check_time_syntax (struct berval *val,
3885 struct berval *fraction)
3888 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3889 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3890 * GeneralizedTime supports leap seconds, UTCTime does not.
3892 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3893 static const int mdays[2][12] = {
3894 /* non-leap years */
3895 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3897 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3900 int part, c, c1, c2, tzoffset, leapyear = 0;
3903 e = p + val->bv_len;
3905 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3906 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3908 for (part = start; part < 7 && p < e; part++) {
3910 if (!ASCII_DIGIT(c1)) {
3915 return LDAP_INVALID_SYNTAX;
3918 if (!ASCII_DIGIT(c)) {
3919 return LDAP_INVALID_SYNTAX;
3921 c += c1 * 10 - '0' * 11;
3922 if ((part | 1) == 3) {
3925 return LDAP_INVALID_SYNTAX;
3928 if (c >= ceiling[part]) {
3929 if (! (c == 60 && part == 6 && start == 0))
3930 return LDAP_INVALID_SYNTAX;
3934 if (part < 5 + start) {
3935 return LDAP_INVALID_SYNTAX;
3937 for (; part < 9; part++) {
3941 /* leapyear check for the Gregorian calendar (year>1581) */
3942 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3946 if (parts[3] >= mdays[leapyear][parts[2]]) {
3947 return LDAP_INVALID_SYNTAX;
3951 fraction->bv_val = p;
3952 fraction->bv_len = 0;
3953 if (p < e && (*p == '.' || *p == ',')) {
3955 while (++p < e && ASCII_DIGIT(*p)) {
3958 if (p - fraction->bv_val == 1) {
3959 return LDAP_INVALID_SYNTAX;
3961 for (end_num = p; end_num[-1] == '0'; --end_num) {
3964 c = end_num - fraction->bv_val;
3965 if (c != 1) fraction->bv_len = c;
3971 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3977 return LDAP_INVALID_SYNTAX;
3983 for (part = 7; part < 9 && p < e; part++) {
3985 if (!ASCII_DIGIT(c1)) {
3990 return LDAP_INVALID_SYNTAX;
3993 if (!ASCII_DIGIT(c2)) {
3994 return LDAP_INVALID_SYNTAX;
3996 parts[part] = c1 * 10 + c2 - '0' * 11;
3997 if (parts[part] >= ceiling[part]) {
3998 return LDAP_INVALID_SYNTAX;
4001 if (part < 8 + start) {
4002 return LDAP_INVALID_SYNTAX;
4005 if (tzoffset == '-') {
4006 /* negative offset to UTC, ie west of Greenwich */
4007 parts[4] += parts[7];
4008 parts[5] += parts[8];
4009 /* offset is just hhmm, no seconds */
4010 for (part = 6; --part >= 0; ) {
4014 c = mdays[leapyear][parts[2]];
4016 if (parts[part] >= c) {
4018 return LDAP_INVALID_SYNTAX;
4023 } else if (part != 5) {
4028 /* positive offset to UTC, ie east of Greenwich */
4029 parts[4] -= parts[7];
4030 parts[5] -= parts[8];
4031 for (part = 6; --part >= 0; ) {
4032 if (parts[part] < 0) {
4034 return LDAP_INVALID_SYNTAX;
4039 /* make first arg to % non-negative */
4040 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4045 } else if (part != 5) {
4052 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4055 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4062 struct berval *normalized )
4066 rc = check_time_syntax(val, 1, parts, NULL);
4067 if (rc != LDAP_SUCCESS) {
4071 normalized->bv_val = ch_malloc( 14 );
4072 if ( normalized->bv_val == NULL ) {
4073 return LBER_ERROR_MEMORY;
4076 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4077 parts[1], parts[2] + 1, parts[3] + 1,
4078 parts[4], parts[5], parts[6] );
4079 normalized->bv_len = 13;
4081 return LDAP_SUCCESS;
4091 return check_time_syntax(in, 1, parts, NULL);
4094 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4097 generalizedTimeValidate(
4102 struct berval fraction;
4103 return check_time_syntax(in, 0, parts, &fraction);
4107 generalizedTimeNormalize(
4112 struct berval *normalized,
4117 struct berval fraction;
4119 rc = check_time_syntax(val, 0, parts, &fraction);
4120 if (rc != LDAP_SUCCESS) {
4124 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4125 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4126 if ( BER_BVISNULL( normalized ) ) {
4127 return LBER_ERROR_MEMORY;
4130 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4131 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4132 parts[4], parts[5], parts[6] );
4133 if ( !BER_BVISEMPTY( &fraction ) ) {
4134 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4135 fraction.bv_val, fraction.bv_len );
4136 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4138 strcpy( normalized->bv_val + len-1, "Z" );
4139 normalized->bv_len = len;
4141 return LDAP_SUCCESS;
4145 generalizedTimeOrderingMatch(
4150 struct berval *value,
4151 void *assertedValue )
4153 struct berval *asserted = (struct berval *) assertedValue;
4154 ber_len_t v_len = value->bv_len;
4155 ber_len_t av_len = asserted->bv_len;
4157 /* ignore trailing 'Z' when comparing */
4158 int match = memcmp( value->bv_val, asserted->bv_val,
4159 (v_len < av_len ? v_len : av_len) - 1 );
4160 if ( match == 0 ) match = v_len - av_len;
4163 return LDAP_SUCCESS;
4166 /* Index generation function */
4167 int generalizedTimeIndexer(
4172 struct berval *prefix,
4180 BerValue bvtmp; /* 40 bit index */
4182 struct lutil_timet tt;
4184 bvtmp.bv_len = sizeof(tmp);
4186 for( i=0; values[i].bv_val != NULL; i++ ) {
4187 /* just count them */
4190 /* we should have at least one value at this point */
4193 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4195 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4196 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4197 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4198 /* Use 40 bits of time for key */
4199 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4200 lutil_tm2time( &tm, &tt );
4201 tmp[0] = tt.tt_gsec & 0xff;
4202 tmp[4] = tt.tt_sec & 0xff;
4204 tmp[3] = tt.tt_sec & 0xff;
4206 tmp[2] = tt.tt_sec & 0xff;
4208 tmp[1] = tt.tt_sec & 0xff;
4210 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4214 keys[j].bv_val = NULL;
4219 return LDAP_SUCCESS;
4222 /* Index generation function */
4223 int generalizedTimeFilter(
4228 struct berval *prefix,
4229 void * assertedValue,
4235 BerValue bvtmp; /* 40 bit index */
4236 BerValue *value = (BerValue *) assertedValue;
4238 struct lutil_timet tt;
4240 bvtmp.bv_len = sizeof(tmp);
4242 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4243 /* Use 40 bits of time for key */
4244 if ( value->bv_val && value->bv_len >= 10 &&
4245 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4247 lutil_tm2time( &tm, &tt );
4248 tmp[0] = tt.tt_gsec & 0xff;
4249 tmp[4] = tt.tt_sec & 0xff;
4251 tmp[3] = tt.tt_sec & 0xff;
4253 tmp[2] = tt.tt_sec & 0xff;
4255 tmp[1] = tt.tt_sec & 0xff;
4257 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4258 ber_dupbv_x(keys, &bvtmp, ctx );
4259 keys[1].bv_val = NULL;
4267 return LDAP_SUCCESS;
4271 deliveryMethodValidate(
4273 struct berval *val )
4276 #define LENOF(s) (sizeof(s)-1)
4277 struct berval tmp = *val;
4279 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4280 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4281 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4284 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4286 switch( tmp.bv_val[0] ) {
4289 if(( tmp.bv_len >= LENOF("any") ) &&
4290 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4292 tmp.bv_len -= LENOF("any");
4293 tmp.bv_val += LENOF("any");
4296 return LDAP_INVALID_SYNTAX;
4300 if(( tmp.bv_len >= LENOF("mhs") ) &&
4301 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4303 tmp.bv_len -= LENOF("mhs");
4304 tmp.bv_val += LENOF("mhs");
4307 return LDAP_INVALID_SYNTAX;
4311 if(( tmp.bv_len >= LENOF("physical") ) &&
4312 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4314 tmp.bv_len -= LENOF("physical");
4315 tmp.bv_val += LENOF("physical");
4318 return LDAP_INVALID_SYNTAX;
4321 case 'T': /* telex or teletex or telephone */
4322 if(( tmp.bv_len >= LENOF("telex") ) &&
4323 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4325 tmp.bv_len -= LENOF("telex");
4326 tmp.bv_val += LENOF("telex");
4329 if(( tmp.bv_len >= LENOF("teletex") ) &&
4330 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4332 tmp.bv_len -= LENOF("teletex");
4333 tmp.bv_val += LENOF("teletex");
4336 if(( tmp.bv_len >= LENOF("telephone") ) &&
4337 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4339 tmp.bv_len -= LENOF("telephone");
4340 tmp.bv_val += LENOF("telephone");
4343 return LDAP_INVALID_SYNTAX;
4346 case 'G': /* g3fax or g4fax */
4347 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4348 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4349 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4351 tmp.bv_len -= LENOF("g3fax");
4352 tmp.bv_val += LENOF("g3fax");
4355 return LDAP_INVALID_SYNTAX;
4359 if(( tmp.bv_len >= LENOF("ia5") ) &&
4360 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4362 tmp.bv_len -= LENOF("ia5");
4363 tmp.bv_val += LENOF("ia5");
4366 return LDAP_INVALID_SYNTAX;
4370 if(( tmp.bv_len >= LENOF("videotex") ) &&
4371 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4373 tmp.bv_len -= LENOF("videotex");
4374 tmp.bv_val += LENOF("videotex");
4377 return LDAP_INVALID_SYNTAX;
4380 return LDAP_INVALID_SYNTAX;
4383 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4385 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4389 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4393 return LDAP_INVALID_SYNTAX;
4395 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4404 nisNetgroupTripleValidate(
4406 struct berval *val )
4411 if ( BER_BVISEMPTY( val ) ) {
4412 return LDAP_INVALID_SYNTAX;
4415 p = (char *)val->bv_val;
4416 e = p + val->bv_len;
4418 if ( *p != '(' /*')'*/ ) {
4419 return LDAP_INVALID_SYNTAX;
4422 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4426 return LDAP_INVALID_SYNTAX;
4429 } else if ( !AD_CHAR( *p ) ) {
4430 return LDAP_INVALID_SYNTAX;
4434 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4435 return LDAP_INVALID_SYNTAX;
4441 return LDAP_INVALID_SYNTAX;
4444 return LDAP_SUCCESS;
4448 bootParameterValidate(
4450 struct berval *val )
4454 if ( BER_BVISEMPTY( val ) ) {
4455 return LDAP_INVALID_SYNTAX;
4458 p = (char *)val->bv_val;
4459 e = p + val->bv_len;
4462 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4463 if ( !AD_CHAR( *p ) ) {
4464 return LDAP_INVALID_SYNTAX;
4469 return LDAP_INVALID_SYNTAX;
4473 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4474 if ( !AD_CHAR( *p ) ) {
4475 return LDAP_INVALID_SYNTAX;
4480 return LDAP_INVALID_SYNTAX;
4484 for ( p++; p < e; p++ ) {
4485 if ( !SLAP_PRINTABLE( *p ) ) {
4486 return LDAP_INVALID_SYNTAX;
4490 return LDAP_SUCCESS;
4494 firstComponentNormalize(
4499 struct berval *normalized,
4506 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4507 ber_dupbv_x( normalized, val, ctx );
4508 return LDAP_SUCCESS;
4511 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4513 if( val->bv_val[0] != '(' /*')'*/ &&
4514 val->bv_val[0] != '{' /*'}'*/ )
4516 return LDAP_INVALID_SYNTAX;
4519 /* trim leading white space */
4521 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4527 /* grab next word */
4528 comp.bv_val = &val->bv_val[len];
4529 len = val->bv_len - len;
4530 for( comp.bv_len = 0;
4531 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4537 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4538 rc = numericoidValidate( NULL, &comp );
4539 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4540 rc = integerValidate( NULL, &comp );
4542 rc = LDAP_INVALID_SYNTAX;
4546 if( rc == LDAP_SUCCESS ) {
4547 ber_dupbv_x( normalized, &comp, ctx );
4553 static char *country_gen_syn[] = {
4554 "1.3.6.1.4.1.1466.115.121.1.15",
4555 "1.3.6.1.4.1.1466.115.121.1.26",
4556 "1.3.6.1.4.1.1466.115.121.1.44",
4560 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4561 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4563 static slap_syntax_defs_rec syntax_defs[] = {
4564 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4565 X_BINARY X_NOT_H_R ")",
4566 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4567 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4568 0, NULL, NULL, NULL},
4569 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4570 0, NULL, NULL, NULL},
4571 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4573 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4574 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4576 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4577 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4578 0, NULL, bitStringValidate, NULL },
4579 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4580 0, NULL, booleanValidate, NULL},
4581 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4582 X_BINARY X_NOT_H_R ")",
4583 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4584 NULL, certificateValidate, NULL},
4585 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4586 X_BINARY X_NOT_H_R ")",
4587 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4588 NULL, certificateListValidate, NULL},
4589 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4590 X_BINARY X_NOT_H_R ")",
4591 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4592 NULL, sequenceValidate, NULL},
4593 #if 0 /* need to go __after__ printableString */
4594 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4595 0, "1.3.6.1.4.1.1466.115.121.1.44",
4596 countryStringValidate, NULL},
4598 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4599 0, NULL, dnValidate, dnPretty},
4600 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4601 0, NULL, rdnValidate, rdnPretty},
4602 #ifdef LDAP_COMP_MATCH
4603 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4604 0, NULL, allComponentsValidate, NULL},
4605 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4606 0, NULL, componentFilterValidate, NULL},
4608 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4609 0, NULL, NULL, NULL},
4610 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4611 0, NULL, deliveryMethodValidate, NULL},
4612 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4613 0, NULL, UTF8StringValidate, NULL},
4614 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4615 0, NULL, NULL, NULL},
4616 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4617 0, NULL, NULL, NULL},
4618 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4619 0, NULL, NULL, NULL},
4620 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4621 0, NULL, NULL, NULL},
4622 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4623 0, NULL, NULL, NULL},
4624 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4625 0, NULL, printablesStringValidate, NULL},
4626 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4627 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4628 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4629 0, NULL, generalizedTimeValidate, NULL},
4630 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4631 0, NULL, NULL, NULL},
4632 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4633 0, NULL, IA5StringValidate, NULL},
4634 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4635 0, NULL, integerValidate, NULL},
4636 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4637 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4638 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4639 0, NULL, NULL, NULL},
4640 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4641 0, NULL, NULL, NULL},
4642 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4643 0, NULL, NULL, NULL},
4644 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4645 0, NULL, NULL, NULL},
4646 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4647 0, NULL, NULL, NULL},
4648 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4649 0, NULL, nameUIDValidate, nameUIDPretty },
4650 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4651 0, NULL, NULL, NULL},
4652 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4653 0, NULL, numericStringValidate, NULL},
4654 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4655 0, NULL, NULL, NULL},
4656 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4657 0, NULL, numericoidValidate, NULL},
4658 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4659 0, NULL, IA5StringValidate, NULL},
4660 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4661 0, NULL, blobValidate, NULL},
4662 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4663 0, NULL, UTF8StringValidate, NULL},
4664 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4665 0, NULL, NULL, NULL},
4666 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4667 0, NULL, NULL, NULL},
4668 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4669 0, NULL, printableStringValidate, NULL},
4670 /* moved here because now depends on Directory String, IA5 String
4671 * and Printable String */
4672 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4673 0, country_gen_syn, countryStringValidate, NULL},
4674 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4675 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4676 0, NULL, subtreeSpecificationValidate, NULL},
4677 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4678 X_BINARY X_NOT_H_R ")",
4679 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4680 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4681 0, NULL, printableStringValidate, NULL},
4682 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4683 0, NULL, NULL, NULL},
4684 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4685 0, NULL, printablesStringValidate, NULL},
4686 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4687 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4688 0, NULL, utcTimeValidate, NULL},
4690 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4691 0, NULL, NULL, NULL},
4692 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4693 0, NULL, NULL, NULL},
4694 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4695 0, NULL, NULL, NULL},
4696 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4697 0, NULL, NULL, NULL},
4698 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4699 0, NULL, NULL, NULL},
4701 /* RFC 2307 NIS Syntaxes */
4702 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4703 0, NULL, nisNetgroupTripleValidate, NULL},
4704 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4705 0, NULL, bootParameterValidate, NULL},
4707 /* draft-zeilenga-ldap-x509 */
4708 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4709 SLAP_SYNTAX_HIDE, NULL,
4710 serialNumberAndIssuerValidate,
4711 serialNumberAndIssuerPretty},
4712 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4713 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4714 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4715 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4716 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4717 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4718 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4719 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4720 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4721 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4722 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4723 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4725 #ifdef SLAPD_AUTHPASSWD
4726 /* needs updating */
4727 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4728 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4731 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4732 0, NULL, UUIDValidate, UUIDPretty},
4734 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4735 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4737 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4738 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4740 /* OpenLDAP Void Syntax */
4741 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4742 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4744 /* FIXME: OID is unused, but not registered yet */
4745 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4746 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4748 {NULL, 0, NULL, NULL, NULL}
4751 char *csnSIDMatchSyntaxes[] = {
4752 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4755 char *certificateExactMatchSyntaxes[] = {
4756 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4759 #ifdef LDAP_COMP_MATCH
4760 char *componentFilterMatchSyntaxes[] = {
4761 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4765 char *directoryStringSyntaxes[] = {
4766 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4769 char *integerFirstComponentMatchSyntaxes[] = {
4770 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4771 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4774 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4775 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4776 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4777 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4778 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4779 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4780 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4781 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4782 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4787 * Other matching rules in X.520 that we do not use (yet):
4789 * 2.5.13.25 uTCTimeMatch
4790 * 2.5.13.26 uTCTimeOrderingMatch
4791 * 2.5.13.31* directoryStringFirstComponentMatch
4792 * 2.5.13.32* wordMatch
4793 * 2.5.13.33* keywordMatch
4794 * 2.5.13.36+ certificatePairExactMatch
4795 * 2.5.13.37+ certificatePairMatch
4796 * 2.5.13.38+ certificateListExactMatch
4797 * 2.5.13.39+ certificateListMatch
4798 * 2.5.13.40+ algorithmIdentifierMatch
4799 * 2.5.13.41* storedPrefixMatch
4800 * 2.5.13.42 attributeCertificateMatch
4801 * 2.5.13.43 readerAndKeyIDMatch
4802 * 2.5.13.44 attributeIntegrityMatch
4804 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4805 * (+) described in draft-zeilenga-ldap-x509
4807 static slap_mrule_defs_rec mrule_defs[] = {
4809 * EQUALITY matching rules must be listed after associated APPROX
4810 * matching rules. So, we list all APPROX matching rules first.
4812 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4813 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4814 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4815 NULL, NULL, directoryStringApproxMatch,
4816 directoryStringApproxIndexer, directoryStringApproxFilter,
4819 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4820 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4821 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4822 NULL, NULL, IA5StringApproxMatch,
4823 IA5StringApproxIndexer, IA5StringApproxFilter,
4827 * Other matching rules
4830 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4831 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4832 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4833 NULL, NULL, octetStringMatch,
4834 octetStringIndexer, octetStringFilter,
4837 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4838 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4839 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4840 NULL, dnNormalize, dnMatch,
4841 octetStringIndexer, octetStringFilter,
4844 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4845 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4846 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4847 NULL, dnNormalize, dnRelativeMatch,
4851 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4852 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4853 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4854 NULL, dnNormalize, dnRelativeMatch,
4858 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4859 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4860 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4861 NULL, dnNormalize, dnRelativeMatch,
4865 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4866 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4867 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4868 NULL, dnNormalize, dnRelativeMatch,
4872 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4873 "SYNTAX 1.2.36.79672281.1.5.0 )",
4874 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4875 NULL, rdnNormalize, rdnMatch,
4876 octetStringIndexer, octetStringFilter,
4879 #ifdef LDAP_COMP_MATCH
4880 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4881 "SYNTAX 1.2.36.79672281.1.5.2 )",
4882 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4883 NULL, NULL , componentFilterMatch,
4884 octetStringIndexer, octetStringFilter,
4887 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4888 "SYNTAX 1.2.36.79672281.1.5.3 )",
4889 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4890 NULL, NULL , allComponentsMatch,
4891 octetStringIndexer, octetStringFilter,
4894 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4895 "SYNTAX 1.2.36.79672281.1.5.3 )",
4896 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4897 NULL, NULL , directoryComponentsMatch,
4898 octetStringIndexer, octetStringFilter,
4902 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4903 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4904 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4905 NULL, UTF8StringNormalize, octetStringMatch,
4906 octetStringIndexer, octetStringFilter,
4907 directoryStringApproxMatchOID },
4909 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4910 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4911 SLAP_MR_ORDERING, directoryStringSyntaxes,
4912 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4914 "caseIgnoreMatch" },
4916 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4917 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4918 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4919 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4920 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4921 "caseIgnoreMatch" },
4923 {"( 2.5.13.5 NAME 'caseExactMatch' "
4924 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4925 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4926 NULL, UTF8StringNormalize, octetStringMatch,
4927 octetStringIndexer, octetStringFilter,
4928 directoryStringApproxMatchOID },
4930 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4931 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4932 SLAP_MR_ORDERING, directoryStringSyntaxes,
4933 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4937 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4938 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4939 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4940 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4941 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4944 {"( 2.5.13.8 NAME 'numericStringMatch' "
4945 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4946 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4947 NULL, numericStringNormalize, octetStringMatch,
4948 octetStringIndexer, octetStringFilter,
4951 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4952 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4953 SLAP_MR_ORDERING, NULL,
4954 NULL, numericStringNormalize, octetStringOrderingMatch,
4956 "numericStringMatch" },
4958 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4959 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4960 SLAP_MR_SUBSTR, NULL,
4961 NULL, numericStringNormalize, octetStringSubstringsMatch,
4962 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4963 "numericStringMatch" },
4965 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4966 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4967 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4968 NULL, NULL, NULL, NULL, NULL, NULL },
4970 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4971 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4972 SLAP_MR_SUBSTR, NULL,
4973 NULL, NULL, NULL, NULL, NULL,
4974 "caseIgnoreListMatch" },
4976 {"( 2.5.13.13 NAME 'booleanMatch' "
4977 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4978 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4979 NULL, NULL, booleanMatch,
4980 octetStringIndexer, octetStringFilter,
4983 {"( 2.5.13.14 NAME 'integerMatch' "
4984 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4985 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4986 NULL, NULL, integerMatch,
4987 octetStringIndexer, octetStringFilter,
4990 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4991 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4992 SLAP_MR_ORDERING, NULL,
4993 NULL, NULL, integerMatch,
4997 {"( 2.5.13.16 NAME 'bitStringMatch' "
4998 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4999 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5000 NULL, NULL, octetStringMatch,
5001 octetStringIndexer, octetStringFilter,
5004 {"( 2.5.13.17 NAME 'octetStringMatch' "
5005 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5006 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5007 NULL, NULL, octetStringMatch,
5008 octetStringIndexer, octetStringFilter,
5011 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5012 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5013 SLAP_MR_ORDERING, NULL,
5014 NULL, NULL, octetStringOrderingMatch,
5016 "octetStringMatch" },
5018 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5019 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5020 SLAP_MR_SUBSTR, NULL,
5021 NULL, NULL, octetStringSubstringsMatch,
5022 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5023 "octetStringMatch" },
5025 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5026 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5027 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5029 telephoneNumberNormalize, octetStringMatch,
5030 octetStringIndexer, octetStringFilter,
5033 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5034 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5035 SLAP_MR_SUBSTR, NULL,
5036 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5037 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5038 "telephoneNumberMatch" },
5040 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5041 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5042 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5043 NULL, NULL, NULL, NULL, NULL, NULL },
5045 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5046 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5047 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5048 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5049 uniqueMemberIndexer, uniqueMemberFilter,
5052 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5054 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5055 NULL, NULL, NULL, NULL, NULL, NULL },
5057 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5058 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5059 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5060 NULL, generalizedTimeNormalize, octetStringMatch,
5061 generalizedTimeIndexer, generalizedTimeFilter,
5064 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5065 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5066 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5067 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5069 "generalizedTimeMatch" },
5071 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5072 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5073 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5074 integerFirstComponentMatchSyntaxes,
5075 NULL, firstComponentNormalize, integerMatch,
5076 octetStringIndexer, octetStringFilter,
5079 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5080 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5081 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5082 objectIdentifierFirstComponentMatchSyntaxes,
5083 NULL, firstComponentNormalize, octetStringMatch,
5084 octetStringIndexer, octetStringFilter,
5087 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5088 "SYNTAX 1.3.6.1.1.15.1 )",
5089 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5090 NULL, certificateExactNormalize, octetStringMatch,
5091 octetStringIndexer, octetStringFilter,
5094 {"( 2.5.13.35 NAME 'certificateMatch' "
5095 "SYNTAX 1.3.6.1.1.15.2 )",
5096 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5097 NULL, NULL, NULL, NULL, NULL,
5100 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5101 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5102 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5103 NULL, IA5StringNormalize, octetStringMatch,
5104 octetStringIndexer, octetStringFilter,
5105 IA5StringApproxMatchOID },
5107 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5108 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5109 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5110 NULL, IA5StringNormalize, octetStringMatch,
5111 octetStringIndexer, octetStringFilter,
5112 IA5StringApproxMatchOID },
5114 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5115 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5116 SLAP_MR_SUBSTR, NULL,
5117 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5118 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5119 "caseIgnoreIA5Match" },
5121 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5122 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5123 SLAP_MR_SUBSTR, NULL,
5124 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5125 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5126 "caseExactIA5Match" },
5128 #ifdef SLAPD_AUTHPASSWD
5129 /* needs updating */
5130 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5131 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5132 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5133 NULL, NULL, authPasswordMatch,
5138 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5139 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5141 NULL, NULL, integerBitAndMatch,
5145 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5146 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5148 NULL, NULL, integerBitOrMatch,
5152 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5153 "SYNTAX 1.3.6.1.1.16.1 )",
5154 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5155 NULL, UUIDNormalize, octetStringMatch,
5156 octetStringIndexer, octetStringFilter,
5159 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5160 "SYNTAX 1.3.6.1.1.16.1 )",
5161 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5162 NULL, UUIDNormalize, octetStringOrderingMatch,
5163 octetStringIndexer, octetStringFilter,
5166 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5167 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5168 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5169 NULL, csnNormalize, csnMatch,
5170 csnIndexer, csnFilter,
5173 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5174 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5175 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5176 NULL, NULL, csnOrderingMatch,
5180 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5181 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5182 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5183 NULL, csnSidNormalize, octetStringMatch,
5184 octetStringIndexer, octetStringFilter,
5187 /* FIXME: OID is unused, but not registered yet */
5188 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5189 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5190 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5191 NULL, authzNormalize, authzMatch,
5195 {NULL, SLAP_MR_NONE, NULL,
5196 NULL, NULL, NULL, NULL, NULL,
5201 slap_schema_init( void )
5206 /* we should only be called once (from main) */
5207 assert( schema_init_done == 0 );
5209 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5210 res = register_syntax( &syntax_defs[i] );
5213 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5214 syntax_defs[i].sd_desc );
5219 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5220 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5221 mrule_defs[i].mrd_compat_syntaxes == NULL )
5224 "slap_schema_init: Ignoring unusable matching rule %s\n",
5225 mrule_defs[i].mrd_desc );
5229 res = register_matching_rule( &mrule_defs[i] );
5233 "slap_schema_init: Error registering matching rule %s\n",
5234 mrule_defs[i].mrd_desc );
5239 res = slap_schema_load();
5240 schema_init_done = 1;
5245 schema_destroy( void )
5254 if( schema_init_done ) {
5255 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5256 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );