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.
1451 Basically same as PrintableString. There are no examples in X.500,
1452 but same logic applies. So we require them to be non-empty as
1455 -------------------------------------------------------------------*/
1464 unsigned char *u = (unsigned char *)in->bv_val;
1466 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1467 /* directory strings cannot be empty */
1468 return LDAP_INVALID_SYNTAX;
1471 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1472 /* get the length indicated by the first byte */
1473 len = LDAP_UTF8_CHARLEN2( u, len );
1475 /* very basic checks */
1478 if( (u[5] & 0xC0) != 0x80 ) {
1479 return LDAP_INVALID_SYNTAX;
1482 if( (u[4] & 0xC0) != 0x80 ) {
1483 return LDAP_INVALID_SYNTAX;
1486 if( (u[3] & 0xC0) != 0x80 ) {
1487 return LDAP_INVALID_SYNTAX;
1490 if( (u[2] & 0xC0 )!= 0x80 ) {
1491 return LDAP_INVALID_SYNTAX;
1494 if( (u[1] & 0xC0) != 0x80 ) {
1495 return LDAP_INVALID_SYNTAX;
1498 /* CHARLEN already validated it */
1501 return LDAP_INVALID_SYNTAX;
1504 /* make sure len corresponds with the offset
1505 to the next character */
1506 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1510 return LDAP_INVALID_SYNTAX;
1513 return LDAP_SUCCESS;
1517 UTF8StringNormalize(
1522 struct berval *normalized,
1525 struct berval tmp, nvalue;
1529 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1531 if( BER_BVISNULL( val ) ) {
1532 /* assume we're dealing with a syntax (e.g., UTF8String)
1533 * which allows empty strings
1535 BER_BVZERO( normalized );
1536 return LDAP_SUCCESS;
1539 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1540 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1541 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1542 ? LDAP_UTF8_APPROX : 0;
1544 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1549 /* collapse spaces (in place) */
1551 nvalue.bv_val = tmp.bv_val;
1553 /* trim leading spaces? */
1554 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1555 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1557 for( i = 0; i < tmp.bv_len; i++) {
1558 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1559 if( wasspace++ == 0 ) {
1560 /* trim repeated spaces */
1561 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1565 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1569 if( !BER_BVISEMPTY( &nvalue ) ) {
1570 /* trim trailing space? */
1572 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1573 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1577 nvalue.bv_val[nvalue.bv_len] = '\0';
1580 /* string of all spaces is treated as one space */
1581 nvalue.bv_val[0] = ' ';
1582 nvalue.bv_val[1] = '\0';
1586 *normalized = nvalue;
1587 return LDAP_SUCCESS;
1591 directoryStringSubstringsMatch(
1596 struct berval *value,
1597 void *assertedValue )
1600 SubstringsAssertion *sub = assertedValue;
1601 struct berval left = *value;
1605 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1606 if ( sub->sa_initial.bv_len > left.bv_len ) {
1607 /* not enough left */
1612 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1613 sub->sa_initial.bv_len );
1619 left.bv_val += sub->sa_initial.bv_len;
1620 left.bv_len -= sub->sa_initial.bv_len;
1622 priorspace = ASCII_SPACE(
1623 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1626 if ( sub->sa_any ) {
1627 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1631 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1632 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1634 /* allow next space to match */
1641 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1645 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1646 /* not enough left */
1651 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1658 idx = p - left.bv_val;
1660 if ( idx >= left.bv_len ) {
1661 /* this shouldn't happen */
1668 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1669 /* not enough left */
1674 match = memcmp( left.bv_val,
1675 sub->sa_any[i].bv_val,
1676 sub->sa_any[i].bv_len );
1684 left.bv_val += sub->sa_any[i].bv_len;
1685 left.bv_len -= sub->sa_any[i].bv_len;
1687 priorspace = ASCII_SPACE(
1688 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1692 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1693 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1694 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1696 /* allow next space to match */
1701 if ( sub->sa_final.bv_len > left.bv_len ) {
1702 /* not enough left */
1707 match = memcmp( sub->sa_final.bv_val,
1708 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1709 sub->sa_final.bv_len );
1718 return LDAP_SUCCESS;
1721 #if defined(SLAPD_APPROX_INITIALS)
1722 # define SLAPD_APPROX_DELIMITER "._ "
1723 # define SLAPD_APPROX_WORDLEN 2
1725 # define SLAPD_APPROX_DELIMITER " "
1726 # define SLAPD_APPROX_WORDLEN 1
1735 struct berval *value,
1736 void *assertedValue )
1738 struct berval *nval, *assertv;
1739 char *val, **values, **words, *c;
1740 int i, count, len, nextchunk=0, nextavail=0;
1742 /* Yes, this is necessary */
1743 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1744 if( nval == NULL ) {
1746 return LDAP_SUCCESS;
1749 /* Yes, this is necessary */
1750 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1751 NULL, LDAP_UTF8_APPROX, NULL );
1752 if( assertv == NULL ) {
1755 return LDAP_SUCCESS;
1758 /* Isolate how many words there are */
1759 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1760 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1761 if ( c == NULL ) break;
1766 /* Get a phonetic copy of each word */
1767 words = (char **)ch_malloc( count * sizeof(char *) );
1768 values = (char **)ch_malloc( count * sizeof(char *) );
1769 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1771 values[i] = phonetic(c);
1774 /* Work through the asserted value's words, to see if at least some
1775 of the words are there, in the same order. */
1777 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1778 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1783 #if defined(SLAPD_APPROX_INITIALS)
1784 else if( len == 1 ) {
1785 /* Single letter words need to at least match one word's initial */
1786 for( i=nextavail; i<count; i++ )
1787 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1794 /* Isolate the next word in the asserted value and phonetic it */
1795 assertv->bv_val[nextchunk+len] = '\0';
1796 val = phonetic( assertv->bv_val + nextchunk );
1798 /* See if this phonetic chunk is in the remaining words of *value */
1799 for( i=nextavail; i<count; i++ ){
1800 if( !strcmp( val, values[i] ) ){
1808 /* This chunk in the asserted value was NOT within the *value. */
1814 /* Go on to the next word in the asserted value */
1818 /* If some of the words were seen, call it a match */
1819 if( nextavail > 0 ) {
1826 /* Cleanup allocs */
1827 ber_bvfree( assertv );
1828 for( i=0; i<count; i++ ) {
1829 ch_free( values[i] );
1835 return LDAP_SUCCESS;
1844 struct berval *prefix,
1850 int i,j, len, wordcount, keycount=0;
1851 struct berval *newkeys;
1852 BerVarray keys=NULL;
1854 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1855 struct berval val = BER_BVNULL;
1856 /* Yes, this is necessary */
1857 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1858 assert( !BER_BVISNULL( &val ) );
1860 /* Isolate how many words there are. There will be a key for each */
1861 for( wordcount = 0, c = val.bv_val; *c; c++) {
1862 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1863 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1865 if (*c == '\0') break;
1869 /* Allocate/increase storage to account for new keys */
1870 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1871 * sizeof(struct berval) );
1872 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1873 if( keys ) ch_free( keys );
1876 /* Get a phonetic copy of each word */
1877 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1879 if( len < SLAPD_APPROX_WORDLEN ) continue;
1880 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1885 ber_memfree( val.bv_val );
1887 BER_BVZERO( &keys[keycount] );
1890 return LDAP_SUCCESS;
1899 struct berval *prefix,
1900 void * assertedValue,
1909 /* Yes, this is necessary */
1910 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1911 NULL, LDAP_UTF8_APPROX, NULL );
1912 if( val == NULL || BER_BVISNULL( val ) ) {
1913 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1914 BER_BVZERO( &keys[0] );
1917 return LDAP_SUCCESS;
1920 /* Isolate how many words there are. There will be a key for each */
1921 for( count = 0,c = val->bv_val; *c; c++) {
1922 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1923 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1925 if (*c == '\0') break;
1929 /* Allocate storage for new keys */
1930 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1932 /* Get a phonetic copy of each word */
1933 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1935 if( len < SLAPD_APPROX_WORDLEN ) continue;
1936 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1942 BER_BVZERO( &keys[count] );
1945 return LDAP_SUCCESS;
1948 /* Remove all spaces and '-' characters */
1950 telephoneNumberNormalize(
1955 struct berval *normalized,
1960 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1962 /* validator should have refused an empty string */
1963 assert( !BER_BVISEMPTY( val ) );
1965 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1967 for( p = val->bv_val; *p; p++ ) {
1968 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1974 normalized->bv_len = q - normalized->bv_val;
1976 if( BER_BVISEMPTY( normalized ) ) {
1977 slap_sl_free( normalized->bv_val, ctx );
1978 BER_BVZERO( normalized );
1979 return LDAP_INVALID_SYNTAX;
1982 return LDAP_SUCCESS;
1990 struct berval val = *in;
1992 if( BER_BVISEMPTY( &val ) ) {
1993 /* disallow empty strings */
1994 return LDAP_INVALID_SYNTAX;
1997 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1998 if ( val.bv_len == 1 ) {
1999 return LDAP_SUCCESS;
2002 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2009 while ( OID_LEADCHAR( val.bv_val[0] )) {
2013 if ( val.bv_len == 0 ) {
2014 return LDAP_SUCCESS;
2018 if( !OID_SEPARATOR( val.bv_val[0] )) {
2026 return LDAP_INVALID_SYNTAX;
2035 struct berval val = *in;
2037 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2039 if ( val.bv_val[0] == '-' ) {
2043 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2044 return LDAP_INVALID_SYNTAX;
2047 if( val.bv_val[0] == '0' ) { /* "-0" */
2048 return LDAP_INVALID_SYNTAX;
2051 } else if ( val.bv_val[0] == '0' ) {
2052 if( val.bv_len > 1 ) { /* "0<more>" */
2053 return LDAP_INVALID_SYNTAX;
2056 return LDAP_SUCCESS;
2059 for( i=0; i < val.bv_len; i++ ) {
2060 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2061 return LDAP_INVALID_SYNTAX;
2065 return LDAP_SUCCESS;
2074 struct berval *value,
2075 void *assertedValue )
2077 struct berval *asserted = (struct berval *) assertedValue;
2078 int vsign = 1, asign = 1; /* default sign = '+' */
2083 if( v.bv_val[0] == '-' ) {
2089 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2092 if( a.bv_val[0] == '-' ) {
2098 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2100 match = vsign - asign;
2102 match = ( v.bv_len != a.bv_len
2103 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2104 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2105 if( vsign < 0 ) match = -match;
2109 return LDAP_SUCCESS;
2113 countryStringValidate(
2115 struct berval *val )
2117 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2119 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2120 return LDAP_INVALID_SYNTAX;
2122 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2123 return LDAP_INVALID_SYNTAX;
2126 return LDAP_SUCCESS;
2130 printableStringValidate(
2132 struct berval *val )
2136 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2138 for(i=0; i < val->bv_len; i++) {
2139 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2140 return LDAP_INVALID_SYNTAX;
2144 return LDAP_SUCCESS;
2148 printablesStringValidate(
2150 struct berval *val )
2154 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2156 for(i=0,len=0; i < val->bv_len; i++) {
2157 int c = val->bv_val[i];
2161 return LDAP_INVALID_SYNTAX;
2165 } else if ( SLAP_PRINTABLE(c) ) {
2168 return LDAP_INVALID_SYNTAX;
2173 return LDAP_INVALID_SYNTAX;
2176 return LDAP_SUCCESS;
2182 struct berval *val )
2186 for(i=0; i < val->bv_len; i++) {
2187 if( !LDAP_ASCII(val->bv_val[i]) ) {
2188 return LDAP_INVALID_SYNTAX;
2192 return LDAP_SUCCESS;
2201 struct berval *normalized,
2205 int casefold = !SLAP_MR_ASSOCIATED( mr,
2206 slap_schema.si_mr_caseExactIA5Match );
2208 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2212 /* Ignore initial whitespace */
2213 while ( ASCII_SPACE( *p ) ) p++;
2215 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2216 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2217 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2218 normalized->bv_val[normalized->bv_len] = '\0';
2220 p = q = normalized->bv_val;
2223 if ( ASCII_SPACE( *p ) ) {
2226 /* Ignore the extra whitespace */
2227 while ( ASCII_SPACE( *p ) ) {
2231 } else if ( casefold ) {
2232 /* Most IA5 rules require casefolding */
2233 *q++ = TOLOWER(*p); p++;
2240 assert( normalized->bv_val <= p );
2244 * If the string ended in space, backup the pointer one
2245 * position. One is enough because the above loop collapsed
2246 * all whitespace to a single space.
2248 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2250 /* null terminate */
2253 normalized->bv_len = q - normalized->bv_val;
2255 return LDAP_SUCCESS;
2264 if( in->bv_len != 36 ) {
2265 return LDAP_INVALID_SYNTAX;
2268 for( i=0; i<36; i++ ) {
2274 if( in->bv_val[i] != '-' ) {
2275 return LDAP_INVALID_SYNTAX;
2279 if( !ASCII_HEX( in->bv_val[i]) ) {
2280 return LDAP_INVALID_SYNTAX;
2285 return LDAP_SUCCESS;
2296 int rc=LDAP_INVALID_SYNTAX;
2298 assert( in != NULL );
2299 assert( out != NULL );
2301 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2304 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2306 for( i=0; i<36; i++ ) {
2312 if( in->bv_val[i] != '-' ) {
2315 out->bv_val[i] = '-';
2319 if( !ASCII_HEX( in->bv_val[i]) ) {
2322 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2327 out->bv_val[ out->bv_len ] = '\0';
2331 slap_sl_free( out->bv_val, ctx );
2344 struct berval *normalized,
2347 unsigned char octet = '\0';
2350 normalized->bv_len = 16;
2351 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2353 for( i=0, j=0; i<36; i++ ) {
2354 unsigned char nibble;
2355 if( val->bv_val[i] == '-' ) {
2358 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2359 nibble = val->bv_val[i] - '0';
2361 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2362 nibble = val->bv_val[i] - ('a'-10);
2364 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2365 nibble = val->bv_val[i] - ('A'-10);
2368 slap_sl_free( normalized->bv_val, ctx );
2369 return LDAP_INVALID_SYNTAX;
2374 normalized->bv_val[j>>1] = octet;
2376 octet = nibble << 4;
2381 normalized->bv_val[normalized->bv_len] = 0;
2382 return LDAP_SUCCESS;
2388 numericStringValidate(
2394 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2396 for(i=0; i < in->bv_len; i++) {
2397 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2398 return LDAP_INVALID_SYNTAX;
2402 return LDAP_SUCCESS;
2406 numericStringNormalize(
2411 struct berval *normalized,
2414 /* removal all spaces */
2417 assert( !BER_BVISEMPTY( val ) );
2419 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2422 q = normalized->bv_val;
2425 if ( ASCII_SPACE( *p ) ) {
2426 /* Ignore whitespace */
2433 /* we should have copied no more than is in val */
2434 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2436 /* null terminate */
2439 normalized->bv_len = q - normalized->bv_val;
2441 if( BER_BVISEMPTY( normalized ) ) {
2442 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2443 normalized->bv_val[0] = ' ';
2444 normalized->bv_val[1] = '\0';
2445 normalized->bv_len = 1;
2448 return LDAP_SUCCESS;
2452 * Integer conversion macros that will use the largest available
2455 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2456 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2457 # define SLAP_LONG long long
2459 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2460 # define SLAP_LONG long
2461 #endif /* HAVE_STRTOLL ... */
2469 struct berval *value,
2470 void *assertedValue )
2472 SLAP_LONG lValue, lAssertedValue;
2475 /* safe to assume integers are NUL terminated? */
2476 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2477 if( errno == ERANGE )
2479 return LDAP_CONSTRAINT_VIOLATION;
2482 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2484 if( errno == ERANGE )
2486 return LDAP_CONSTRAINT_VIOLATION;
2489 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2490 return LDAP_SUCCESS;
2499 struct berval *value,
2500 void *assertedValue )
2502 SLAP_LONG lValue, lAssertedValue;
2505 /* safe to assume integers are NUL terminated? */
2506 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2507 if( errno == ERANGE )
2509 return LDAP_CONSTRAINT_VIOLATION;
2512 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2514 if( errno == ERANGE )
2516 return LDAP_CONSTRAINT_VIOLATION;
2519 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2520 return LDAP_SUCCESS;
2524 serialNumberAndIssuerValidate(
2530 struct berval sn, i;
2532 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2535 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2537 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2538 /* Parse old format */
2539 i.bv_val = ber_bvchr( in, '$' );
2540 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2542 sn.bv_val = in->bv_val;
2543 sn.bv_len = i.bv_val - in->bv_val;
2546 i.bv_len = in->bv_len - (sn.bv_len + 1);
2548 /* eat leading zeros */
2549 for( n=0; n < (sn.bv_len-1); n++ ) {
2550 if( sn.bv_val[n] != '0' ) break;
2555 for( n=0; n < sn.bv_len; n++ ) {
2556 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2560 /* Parse GSER format */
2561 int havesn=0,haveissuer=0;
2562 struct berval x = *in;
2566 /* eat leading spaces */
2567 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2571 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2572 return LDAP_INVALID_SYNTAX;
2575 /* should be at issuer or serialNumber NamedValue */
2576 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2578 x.bv_val += STRLENOF("issuer");
2579 x.bv_len -= STRLENOF("issuer");
2581 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2582 x.bv_val++; x.bv_len--;
2584 /* eat leading spaces */
2585 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2589 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2590 x.bv_val++; x.bv_len--;
2592 i.bv_val = x.bv_val;
2595 for( ; i.bv_len < x.bv_len; ) {
2596 if ( i.bv_val[i.bv_len] != '"' ) {
2600 if ( i.bv_val[i.bv_len+1] == '"' ) {
2607 x.bv_val += i.bv_len+1;
2608 x.bv_len -= i.bv_len+1;
2610 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2611 return LDAP_INVALID_SYNTAX;
2616 } else if( strncasecmp( x.bv_val, "serialNumber",
2617 STRLENOF("serialNumber")) == 0 )
2619 /* parse serialNumber */
2621 x.bv_val += STRLENOF("serialNumber");
2622 x.bv_len -= STRLENOF("serialNumber");
2624 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2625 x.bv_val++; x.bv_len--;
2627 /* eat leading spaces */
2628 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2632 sn.bv_val = x.bv_val;
2635 if( sn.bv_val[0] == '-' ) {
2640 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2641 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2644 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2645 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2646 return LDAP_INVALID_SYNTAX;
2649 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2651 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2652 return LDAP_INVALID_SYNTAX;
2657 } else return LDAP_INVALID_SYNTAX;
2659 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2660 x.bv_val++; x.bv_len--;
2663 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2667 /* should be at remaining NamedValue */
2668 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2669 STRLENOF("issuer" )) == 0 ))
2672 x.bv_val += STRLENOF("issuer");
2673 x.bv_len -= STRLENOF("issuer");
2675 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2676 x.bv_val++; x.bv_len--;
2678 /* eat leading spaces */
2679 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2683 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2684 x.bv_val++; x.bv_len--;
2686 i.bv_val = x.bv_val;
2689 for( ; i.bv_len < x.bv_len; ) {
2690 if ( i.bv_val[i.bv_len] != '"' ) {
2694 if ( i.bv_val[i.bv_len+1] == '"' ) {
2701 x.bv_val += i.bv_len+1;
2702 x.bv_len -= i.bv_len+1;
2704 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2705 STRLENOF("serialNumber")) == 0 ))
2707 /* parse serialNumber */
2709 x.bv_val += STRLENOF("serialNumber");
2710 x.bv_len -= STRLENOF("serialNumber");
2712 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2713 x.bv_val++; x.bv_len--;
2715 /* eat leading spaces */
2716 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2720 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2721 x.bv_val++; x.bv_len--;
2723 sn.bv_val = x.bv_val;
2726 if( sn.bv_val[0] == '-' ) {
2731 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2732 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2735 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2736 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2737 return LDAP_INVALID_SYNTAX;
2740 x.bv_val += sn.bv_len;
2741 x.bv_len -= sn.bv_len;
2743 } else return LDAP_INVALID_SYNTAX;
2745 /* eat trailing spaces */
2746 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2750 /* should have no characters left... */
2751 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2754 /* validate DN -- doesn't handle double dquote */
2755 rc = dnValidate( NULL, &i );
2756 if( rc ) return LDAP_INVALID_SYNTAX;
2758 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2760 return LDAP_SUCCESS;
2764 serialNumberAndIssuerPretty(
2772 struct berval sn, i, ni;
2774 assert( in != NULL );
2775 assert( out != NULL );
2777 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2780 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2782 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2783 /* Parse old format */
2784 i.bv_val = ber_bvchr( in, '$' );
2785 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2787 sn.bv_val = in->bv_val;
2788 sn.bv_len = i.bv_val - in->bv_val;
2791 i.bv_len = in->bv_len - (sn.bv_len + 1);
2793 /* eat leading zeros */
2794 for( n=0; n < (sn.bv_len-1); n++ ) {
2795 if( sn.bv_val[n] != '0' ) break;
2800 for( n=0; n < sn.bv_len; n++ ) {
2801 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2805 /* Parse GSER format */
2806 int havesn=0,haveissuer=0;
2807 struct berval x = *in;
2811 /* eat leading spaces */
2812 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2816 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2817 return LDAP_INVALID_SYNTAX;
2820 /* should be at issuer or serialNumber NamedValue */
2821 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2823 x.bv_val += STRLENOF("issuer");
2824 x.bv_len -= STRLENOF("issuer");
2826 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2827 x.bv_val++; x.bv_len--;
2829 /* eat leading spaces */
2830 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2834 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2835 x.bv_val++; x.bv_len--;
2837 i.bv_val = x.bv_val;
2840 for( ; i.bv_len < x.bv_len; ) {
2841 if ( i.bv_val[i.bv_len] != '"' ) {
2845 if ( i.bv_val[i.bv_len+1] == '"' ) {
2852 x.bv_val += i.bv_len+1;
2853 x.bv_len -= i.bv_len+1;
2855 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2856 return LDAP_INVALID_SYNTAX;
2861 } else if( strncasecmp( x.bv_val, "serialNumber",
2862 STRLENOF("serialNumber")) == 0 )
2864 /* parse serialNumber */
2866 x.bv_val += STRLENOF("serialNumber");
2867 x.bv_len -= STRLENOF("serialNumber");
2869 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2870 x.bv_val++; x.bv_len--;
2872 /* eat leading spaces */
2873 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2877 sn.bv_val = x.bv_val;
2880 if( sn.bv_val[0] == '-' ) {
2885 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2886 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2889 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2890 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2891 return LDAP_INVALID_SYNTAX;
2894 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2896 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2897 return LDAP_INVALID_SYNTAX;
2902 } else return LDAP_INVALID_SYNTAX;
2904 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2905 x.bv_val++; x.bv_len--;
2908 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2912 /* should be at remaining NamedValue */
2913 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2914 STRLENOF("issuer" )) == 0 ))
2917 x.bv_val += STRLENOF("issuer");
2918 x.bv_len -= STRLENOF("issuer");
2920 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2921 x.bv_val++; x.bv_len--;
2923 /* eat leading spaces */
2924 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2928 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2929 x.bv_val++; x.bv_len--;
2931 i.bv_val = x.bv_val;
2934 for( ; i.bv_len < x.bv_len; ) {
2935 if ( i.bv_val[i.bv_len] != '"' ) {
2939 if ( i.bv_val[i.bv_len+1] == '"' ) {
2946 x.bv_val += i.bv_len+1;
2947 x.bv_len -= i.bv_len+1;
2949 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2950 STRLENOF("serialNumber")) == 0 ))
2952 /* parse serialNumber */
2954 x.bv_val += STRLENOF("serialNumber");
2955 x.bv_len -= STRLENOF("serialNumber");
2957 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2958 x.bv_val++; x.bv_len--;
2960 /* eat leading spaces */
2961 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2965 sn.bv_val = x.bv_val;
2968 if( sn.bv_val[0] == '-' ) {
2973 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2974 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2977 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2978 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2979 return LDAP_INVALID_SYNTAX;
2982 x.bv_val += sn.bv_len;
2983 x.bv_len -= sn.bv_len;
2985 } else return LDAP_INVALID_SYNTAX;
2987 /* eat trailing spaces */
2988 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2992 /* should have no characters left... */
2993 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2995 ber_dupbv_x( &ni, &i, ctx );
2998 /* need to handle double dquotes here */
3001 rc = dnPretty( syntax, &i, &ni, ctx );
3003 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3004 slap_sl_free( i.bv_val, ctx );
3007 if( rc ) return LDAP_INVALID_SYNTAX;
3009 /* make room from sn + "$" */
3010 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
3011 + sn.bv_len + ni.bv_len;
3012 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3014 if( out->bv_val == NULL ) {
3016 slap_sl_free( ni.bv_val, ctx );
3021 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3022 STRLENOF("{ serialNumber "));
3023 n = STRLENOF("{ serialNumber ");
3025 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3028 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
3029 n += STRLENOF(", issuer \"");
3031 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3034 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3035 n += STRLENOF("\" }");
3037 out->bv_val[n] = '\0';
3039 assert( n == out->bv_len );
3041 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3042 out->bv_val, 0, 0 );
3044 slap_sl_free( ni.bv_val, ctx );
3046 return LDAP_SUCCESS;
3050 * This routine is called by certificateExactNormalize when
3051 * certificateExactNormalize receives a search string instead of
3052 * a certificate. This routine checks if the search value is valid
3053 * and then returns the normalized value
3056 serialNumberAndIssuerNormalize(
3066 struct berval sn, i, ni;
3068 assert( in != NULL );
3069 assert( out != NULL );
3071 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3074 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3076 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3077 /* Parse old format */
3078 i.bv_val = ber_bvchr( in, '$' );
3079 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
3081 sn.bv_val = in->bv_val;
3082 sn.bv_len = i.bv_val - in->bv_val;
3085 i.bv_len = in->bv_len - (sn.bv_len + 1);
3087 /* eat leading zeros */
3088 for( n=0; n < (sn.bv_len-1); n++ ) {
3089 if( sn.bv_val[n] != '0' ) break;
3094 for( n=0; n < sn.bv_len; n++ ) {
3095 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3099 /* Parse GSER format */
3100 int havesn=0,haveissuer=0;
3101 struct berval x = *in;
3105 /* eat leading spaces */
3106 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3110 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3111 return LDAP_INVALID_SYNTAX;
3114 /* should be at issuer or serialNumber NamedValue */
3115 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3117 x.bv_val += STRLENOF("issuer");
3118 x.bv_len -= STRLENOF("issuer");
3120 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3121 x.bv_val++; x.bv_len--;
3123 /* eat leading spaces */
3124 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3128 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3129 x.bv_val++; x.bv_len--;
3131 i.bv_val = x.bv_val;
3134 for( ; i.bv_len < x.bv_len; ) {
3135 if ( i.bv_val[i.bv_len] != '"' ) {
3139 if ( i.bv_val[i.bv_len+1] == '"' ) {
3146 x.bv_val += i.bv_len+1;
3147 x.bv_len -= i.bv_len+1;
3149 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3150 return LDAP_INVALID_SYNTAX;
3155 } else if( strncasecmp( x.bv_val, "serialNumber",
3156 STRLENOF("serialNumber")) == 0 )
3158 /* parse serialNumber */
3160 x.bv_val += STRLENOF("serialNumber");
3161 x.bv_len -= STRLENOF("serialNumber");
3163 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3164 x.bv_val++; x.bv_len--;
3166 /* eat leading spaces */
3167 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3171 sn.bv_val = x.bv_val;
3174 if( sn.bv_val[0] == '-' ) {
3179 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3180 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3183 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3184 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3185 return LDAP_INVALID_SYNTAX;
3188 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3190 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3191 return LDAP_INVALID_SYNTAX;
3196 } else return LDAP_INVALID_SYNTAX;
3198 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3199 x.bv_val++; x.bv_len--;
3202 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3206 /* should be at remaining NamedValue */
3207 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3208 STRLENOF("issuer" )) == 0 ))
3211 x.bv_val += STRLENOF("issuer");
3212 x.bv_len -= STRLENOF("issuer");
3214 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3215 x.bv_val++; x.bv_len--;
3217 /* eat leading spaces */
3218 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3222 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3223 x.bv_val++; x.bv_len--;
3225 i.bv_val = x.bv_val;
3228 for( ; i.bv_len < x.bv_len; ) {
3229 if ( i.bv_val[i.bv_len] != '"' ) {
3233 if ( i.bv_val[i.bv_len+1] == '"' ) {
3240 x.bv_val += i.bv_len+1;
3241 x.bv_len -= i.bv_len+1;
3243 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3244 STRLENOF("serialNumber")) == 0 ))
3246 /* parse serialNumber */
3248 x.bv_val += STRLENOF("serialNumber");
3249 x.bv_len -= STRLENOF("serialNumber");
3251 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3252 x.bv_val++; x.bv_len--;
3254 /* eat leading spaces */
3255 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3259 sn.bv_val = x.bv_val;
3262 if( sn.bv_val[0] == '-' ) {
3267 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3268 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3271 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3272 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3273 return LDAP_INVALID_SYNTAX;
3276 x.bv_val += sn.bv_len;
3277 x.bv_len -= sn.bv_len;
3279 } else return LDAP_INVALID_SYNTAX;
3281 /* eat trailing spaces */
3282 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3286 /* should have no characters left... */
3287 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3289 ber_dupbv_x( &ni, &i, ctx );
3292 /* need to handle double dquotes here */
3295 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3297 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3298 slap_sl_free( i.bv_val, ctx );
3301 if( rc ) return LDAP_INVALID_SYNTAX;
3303 /* make room from sn + "$" */
3304 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3305 + sn.bv_len + ni.bv_len;
3306 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3308 if( out->bv_val == NULL ) {
3310 slap_sl_free( ni.bv_val, ctx );
3315 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3316 STRLENOF( "{ serialNumber " ));
3317 n = STRLENOF( "{ serialNumber " );
3319 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3322 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3323 n += STRLENOF( ", issuer \"" );
3325 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3328 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3329 n += STRLENOF( "\" }" );
3331 out->bv_val[n] = '\0';
3333 assert( n == out->bv_len );
3335 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3336 out->bv_val, 0, 0 );
3338 slap_sl_free( ni.bv_val, ctx );
3340 return LDAP_SUCCESS;
3344 certificateExactNormalize(
3349 struct berval *normalized,
3352 BerElementBuffer berbuf;
3353 BerElement *ber = (BerElement *)&berbuf;
3357 char serialbuf[64], *serial = serialbuf;
3358 ber_len_t seriallen;
3359 struct berval issuer_dn = BER_BVNULL, bvdn;
3361 int rc = LDAP_INVALID_SYNTAX;
3363 if( BER_BVISEMPTY( val ) ) goto done;
3365 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3366 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3369 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3371 ber_init2( ber, val, LBER_USE_DER );
3372 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3373 tag = ber_skip_tag( ber, &len ); /* Sequence */
3374 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3375 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3376 tag = ber_skip_tag( ber, &len );
3377 tag = ber_get_int( ber, &i ); /* version */
3380 /* NOTE: move the test here from certificateNormalize,
3381 * so that we can validate certs with serial longer
3382 * than sizeof(ber_int_t) */
3383 tag = ber_peek_tag( ber, &len ); /* serial */
3384 if ( len > sizeof(ber_int_t) ) {
3387 tag = ber_skip_tag( ber, &len );
3388 ptr = (unsigned char *)ber->ber_ptr;
3389 ber_skip_data( ber, len );
3391 while ( ptr[0] == '\0' && len > 0 ) {
3396 #if defined(USE_MP_BIGNUM)
3399 #elif defined(USE_MP_GMP)
3401 /* hint: use mpz_import(), mpz_get_str() */
3403 #elif defined(USE_MP_LONG_LONG)
3404 if ( len <= sizeof( unsigned long long ) ) {
3405 unsigned long long sn = 0;
3410 for ( i = 1; i < len; i++ ) {
3415 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%llu", sn );
3418 /* do not accept serialNumber that requires
3419 * more than long long */
3420 rc = LDAP_INVALID_SYNTAX;
3425 /* do not accept serialNumber that requires
3427 rc = LDAP_INVALID_SYNTAX;
3432 tag = ber_get_int( ber, &i ); /* serial */
3433 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
3435 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3436 ber_skip_data( ber, len );
3437 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3438 len = ber_ptrlen( ber );
3439 bvdn.bv_val = val->bv_val + len;
3440 bvdn.bv_len = val->bv_len - len;
3442 rc = dnX509normalize( &bvdn, &issuer_dn );
3443 if( rc != LDAP_SUCCESS ) goto done;
3445 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3446 + seriallen + issuer_dn.bv_len;
3447 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3449 p = (unsigned char *)normalized->bv_val;
3451 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3452 p += STRLENOF( "{ serialNumber " );
3454 AC_MEMCPY(p, serial, seriallen);
3457 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3458 p += STRLENOF( ", issuer \"" );
3460 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3461 p += issuer_dn.bv_len;
3463 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3464 p += STRLENOF( "\" }" );
3468 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3469 normalized->bv_val, NULL, NULL );
3474 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3475 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3487 assert( in != NULL );
3488 assert( !BER_BVISNULL( in ) );
3490 for ( i = 0; i < in->bv_len; i++ ) {
3491 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3492 return LDAP_INVALID_SYNTAX;
3496 return LDAP_SUCCESS;
3499 /* Normalize a SID as used inside a CSN:
3500 * three-digit numeric string */
3507 struct berval *normalized,
3512 ber_dupbv_x( normalized, val, ctx );
3514 for ( i = 0; i < normalized->bv_len; i++ ) {
3515 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3516 ber_memfree_x( normalized->bv_val, ctx );
3517 BER_BVZERO( normalized );
3518 return LDAP_INVALID_SYNTAX;
3521 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3524 return LDAP_SUCCESS;
3532 assert( in != NULL );
3533 assert( !BER_BVISNULL( in ) );
3535 if ( in->bv_len != 3 ) {
3536 return LDAP_INVALID_SYNTAX;
3539 return hexValidate( NULL, in );
3542 /* Normalize a SID as used inside a CSN:
3543 * three-digit numeric string */
3550 struct berval *normalized,
3553 if ( val->bv_len != 3 ) {
3554 return LDAP_INVALID_SYNTAX;
3557 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3567 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3570 /* Normalize a SID as used inside a CSN, either as-is
3571 * (assertion value) or extracted from the CSN
3572 * (attribute value) */
3579 struct berval *normalized,
3587 if ( BER_BVISEMPTY( val ) ) {
3588 return LDAP_INVALID_SYNTAX;
3591 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3592 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3595 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3597 ptr = ber_bvchr( val, '#' );
3598 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3599 return LDAP_INVALID_SYNTAX;
3602 bv.bv_val = ptr + 1;
3603 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3605 ptr = ber_bvchr( &bv, '#' );
3606 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3607 return LDAP_INVALID_SYNTAX;
3610 bv.bv_val = ptr + 1;
3611 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3613 ptr = ber_bvchr( &bv, '#' );
3614 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3615 return LDAP_INVALID_SYNTAX;
3618 bv.bv_len = ptr - bv.bv_val;
3620 if ( bv.bv_len == 2 ) {
3621 /* OpenLDAP 2.3 SID */
3623 buf[ 1 ] = bv.bv_val[ 0 ];
3624 buf[ 2 ] = bv.bv_val[ 1 ];
3631 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3643 assert( in != NULL );
3644 assert( !BER_BVISNULL( in ) );
3646 if ( BER_BVISEMPTY( in ) ) {
3647 return LDAP_INVALID_SYNTAX;
3652 ptr = ber_bvchr( &bv, '#' );
3653 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3654 return LDAP_INVALID_SYNTAX;
3657 bv.bv_len = ptr - bv.bv_val;
3658 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3659 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3661 return LDAP_INVALID_SYNTAX;
3664 rc = generalizedTimeValidate( NULL, &bv );
3665 if ( rc != LDAP_SUCCESS ) {
3669 bv.bv_val = ptr + 1;
3670 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3672 ptr = ber_bvchr( &bv, '#' );
3673 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3674 return LDAP_INVALID_SYNTAX;
3677 bv.bv_len = ptr - bv.bv_val;
3678 if ( bv.bv_len != 6 ) {
3679 return LDAP_INVALID_SYNTAX;
3682 rc = hexValidate( NULL, &bv );
3683 if ( rc != LDAP_SUCCESS ) {
3687 bv.bv_val = ptr + 1;
3688 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3690 ptr = ber_bvchr( &bv, '#' );
3691 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3692 return LDAP_INVALID_SYNTAX;
3695 bv.bv_len = ptr - bv.bv_val;
3696 if ( bv.bv_len == 2 ) {
3697 /* tolerate old 2-digit replica-id */
3698 rc = hexValidate( NULL, &bv );
3701 rc = sidValidate( NULL, &bv );
3703 if ( rc != LDAP_SUCCESS ) {
3707 bv.bv_val = ptr + 1;
3708 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3710 if ( bv.bv_len != 6 ) {
3711 return LDAP_INVALID_SYNTAX;
3714 return hexValidate( NULL, &bv );
3717 /* Normalize a CSN in OpenLDAP 2.3 format */
3724 struct berval *normalized,
3727 struct berval gt, cnt, sid, mod;
3731 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3732 assert( !BER_BVISEMPTY( val ) );
3736 ptr = ber_bvchr( >, '#' );
3737 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3738 return LDAP_INVALID_SYNTAX;
3741 gt.bv_len = ptr - gt.bv_val;
3742 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3744 cnt.bv_val = ptr + 1;
3745 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3747 ptr = ber_bvchr( &cnt, '#' );
3748 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3749 return LDAP_INVALID_SYNTAX;
3752 cnt.bv_len = ptr - cnt.bv_val;
3753 assert( cnt.bv_len == STRLENOF( "000000" ) );
3755 sid.bv_val = ptr + 1;
3756 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3758 ptr = ber_bvchr( &sid, '#' );
3759 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3760 return LDAP_INVALID_SYNTAX;
3763 sid.bv_len = ptr - sid.bv_val;
3764 assert( sid.bv_len == STRLENOF( "00" ) );
3766 mod.bv_val = ptr + 1;
3767 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3768 assert( mod.bv_len == STRLENOF( "000000" ) );
3770 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3771 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3773 ptr = normalized->bv_val;
3774 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3775 ptr = lutil_strcopy( ptr, ".000000Z#" );
3776 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3779 for ( i = 0; i < sid.bv_len; i++ ) {
3780 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3783 for ( i = 0; i < mod.bv_len; i++ ) {
3784 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3788 assert( ptr - normalized->bv_val == normalized->bv_len );
3790 return LDAP_SUCCESS;
3793 /* Normalize a CSN */
3800 struct berval *normalized,
3803 struct berval cnt, sid, mod;
3807 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3809 if ( BER_BVISEMPTY( val ) ) {
3810 return LDAP_INVALID_SYNTAX;
3813 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3814 /* Openldap <= 2.3 */
3816 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3819 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3821 ptr = ber_bvchr( val, '#' );
3822 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3823 return LDAP_INVALID_SYNTAX;
3826 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3828 cnt.bv_val = ptr + 1;
3829 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3831 ptr = ber_bvchr( &cnt, '#' );
3832 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3833 return LDAP_INVALID_SYNTAX;
3836 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3838 sid.bv_val = ptr + 1;
3839 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3841 ptr = ber_bvchr( &sid, '#' );
3842 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3843 return LDAP_INVALID_SYNTAX;
3846 sid.bv_len = ptr - sid.bv_val;
3847 assert( sid.bv_len == STRLENOF( "000" ) );
3849 mod.bv_val = ptr + 1;
3850 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3852 assert( mod.bv_len == STRLENOF( "000000" ) );
3854 ber_dupbv_x( normalized, val, ctx );
3856 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3857 i < normalized->bv_len; i++ )
3859 /* assume it's already validated that's all hex digits */
3860 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3863 return LDAP_SUCCESS;
3873 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3876 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3877 /* slight optimization - does not need the start parameter */
3878 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3883 check_time_syntax (struct berval *val,
3886 struct berval *fraction)
3889 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3890 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3891 * GeneralizedTime supports leap seconds, UTCTime does not.
3893 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3894 static const int mdays[2][12] = {
3895 /* non-leap years */
3896 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3898 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3901 int part, c, c1, c2, tzoffset, leapyear = 0;
3904 e = p + val->bv_len;
3906 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3907 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3909 for (part = start; part < 7 && p < e; part++) {
3911 if (!ASCII_DIGIT(c1)) {
3916 return LDAP_INVALID_SYNTAX;
3919 if (!ASCII_DIGIT(c)) {
3920 return LDAP_INVALID_SYNTAX;
3922 c += c1 * 10 - '0' * 11;
3923 if ((part | 1) == 3) {
3926 return LDAP_INVALID_SYNTAX;
3929 if (c >= ceiling[part]) {
3930 if (! (c == 60 && part == 6 && start == 0))
3931 return LDAP_INVALID_SYNTAX;
3935 if (part < 5 + start) {
3936 return LDAP_INVALID_SYNTAX;
3938 for (; part < 9; part++) {
3942 /* leapyear check for the Gregorian calendar (year>1581) */
3943 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3947 if (parts[3] >= mdays[leapyear][parts[2]]) {
3948 return LDAP_INVALID_SYNTAX;
3952 fraction->bv_val = p;
3953 fraction->bv_len = 0;
3954 if (p < e && (*p == '.' || *p == ',')) {
3956 while (++p < e && ASCII_DIGIT(*p)) {
3959 if (p - fraction->bv_val == 1) {
3960 return LDAP_INVALID_SYNTAX;
3962 for (end_num = p; end_num[-1] == '0'; --end_num) {
3965 c = end_num - fraction->bv_val;
3966 if (c != 1) fraction->bv_len = c;
3972 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3978 return LDAP_INVALID_SYNTAX;
3984 for (part = 7; part < 9 && p < e; part++) {
3986 if (!ASCII_DIGIT(c1)) {
3991 return LDAP_INVALID_SYNTAX;
3994 if (!ASCII_DIGIT(c2)) {
3995 return LDAP_INVALID_SYNTAX;
3997 parts[part] = c1 * 10 + c2 - '0' * 11;
3998 if (parts[part] >= ceiling[part]) {
3999 return LDAP_INVALID_SYNTAX;
4002 if (part < 8 + start) {
4003 return LDAP_INVALID_SYNTAX;
4006 if (tzoffset == '-') {
4007 /* negative offset to UTC, ie west of Greenwich */
4008 parts[4] += parts[7];
4009 parts[5] += parts[8];
4010 /* offset is just hhmm, no seconds */
4011 for (part = 6; --part >= 0; ) {
4015 c = mdays[leapyear][parts[2]];
4017 if (parts[part] >= c) {
4019 return LDAP_INVALID_SYNTAX;
4024 } else if (part != 5) {
4029 /* positive offset to UTC, ie east of Greenwich */
4030 parts[4] -= parts[7];
4031 parts[5] -= parts[8];
4032 for (part = 6; --part >= 0; ) {
4033 if (parts[part] < 0) {
4035 return LDAP_INVALID_SYNTAX;
4040 /* make first arg to % non-negative */
4041 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4046 } else if (part != 5) {
4053 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4056 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4063 struct berval *normalized )
4067 rc = check_time_syntax(val, 1, parts, NULL);
4068 if (rc != LDAP_SUCCESS) {
4072 normalized->bv_val = ch_malloc( 14 );
4073 if ( normalized->bv_val == NULL ) {
4074 return LBER_ERROR_MEMORY;
4077 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4078 parts[1], parts[2] + 1, parts[3] + 1,
4079 parts[4], parts[5], parts[6] );
4080 normalized->bv_len = 13;
4082 return LDAP_SUCCESS;
4092 return check_time_syntax(in, 1, parts, NULL);
4095 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4098 generalizedTimeValidate(
4103 struct berval fraction;
4104 return check_time_syntax(in, 0, parts, &fraction);
4108 generalizedTimeNormalize(
4113 struct berval *normalized,
4118 struct berval fraction;
4120 rc = check_time_syntax(val, 0, parts, &fraction);
4121 if (rc != LDAP_SUCCESS) {
4125 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4126 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4127 if ( BER_BVISNULL( normalized ) ) {
4128 return LBER_ERROR_MEMORY;
4131 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4132 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4133 parts[4], parts[5], parts[6] );
4134 if ( !BER_BVISEMPTY( &fraction ) ) {
4135 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4136 fraction.bv_val, fraction.bv_len );
4137 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4139 strcpy( normalized->bv_val + len-1, "Z" );
4140 normalized->bv_len = len;
4142 return LDAP_SUCCESS;
4146 generalizedTimeOrderingMatch(
4151 struct berval *value,
4152 void *assertedValue )
4154 struct berval *asserted = (struct berval *) assertedValue;
4155 ber_len_t v_len = value->bv_len;
4156 ber_len_t av_len = asserted->bv_len;
4158 /* ignore trailing 'Z' when comparing */
4159 int match = memcmp( value->bv_val, asserted->bv_val,
4160 (v_len < av_len ? v_len : av_len) - 1 );
4161 if ( match == 0 ) match = v_len - av_len;
4164 return LDAP_SUCCESS;
4167 /* Index generation function */
4168 int generalizedTimeIndexer(
4173 struct berval *prefix,
4181 BerValue bvtmp; /* 40 bit index */
4183 struct lutil_timet tt;
4185 bvtmp.bv_len = sizeof(tmp);
4187 for( i=0; values[i].bv_val != NULL; i++ ) {
4188 /* just count them */
4191 /* we should have at least one value at this point */
4194 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4196 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4197 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4198 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4199 /* Use 40 bits of time for key */
4200 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4201 lutil_tm2time( &tm, &tt );
4202 tmp[0] = tt.tt_gsec & 0xff;
4203 tmp[4] = tt.tt_sec & 0xff;
4205 tmp[3] = tt.tt_sec & 0xff;
4207 tmp[2] = tt.tt_sec & 0xff;
4209 tmp[1] = tt.tt_sec & 0xff;
4211 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4215 keys[j].bv_val = NULL;
4220 return LDAP_SUCCESS;
4223 /* Index generation function */
4224 int generalizedTimeFilter(
4229 struct berval *prefix,
4230 void * assertedValue,
4236 BerValue bvtmp; /* 40 bit index */
4237 BerValue *value = (BerValue *) assertedValue;
4239 struct lutil_timet tt;
4241 bvtmp.bv_len = sizeof(tmp);
4243 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4244 /* Use 40 bits of time for key */
4245 if ( value->bv_val && value->bv_len >= 10 &&
4246 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4248 lutil_tm2time( &tm, &tt );
4249 tmp[0] = tt.tt_gsec & 0xff;
4250 tmp[4] = tt.tt_sec & 0xff;
4252 tmp[3] = tt.tt_sec & 0xff;
4254 tmp[2] = tt.tt_sec & 0xff;
4256 tmp[1] = tt.tt_sec & 0xff;
4258 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4259 ber_dupbv_x(keys, &bvtmp, ctx );
4260 keys[1].bv_val = NULL;
4268 return LDAP_SUCCESS;
4272 deliveryMethodValidate(
4274 struct berval *val )
4277 #define LENOF(s) (sizeof(s)-1)
4278 struct berval tmp = *val;
4280 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4281 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4282 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4285 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4287 switch( tmp.bv_val[0] ) {
4290 if(( tmp.bv_len >= LENOF("any") ) &&
4291 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4293 tmp.bv_len -= LENOF("any");
4294 tmp.bv_val += LENOF("any");
4297 return LDAP_INVALID_SYNTAX;
4301 if(( tmp.bv_len >= LENOF("mhs") ) &&
4302 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4304 tmp.bv_len -= LENOF("mhs");
4305 tmp.bv_val += LENOF("mhs");
4308 return LDAP_INVALID_SYNTAX;
4312 if(( tmp.bv_len >= LENOF("physical") ) &&
4313 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4315 tmp.bv_len -= LENOF("physical");
4316 tmp.bv_val += LENOF("physical");
4319 return LDAP_INVALID_SYNTAX;
4322 case 'T': /* telex or teletex or telephone */
4323 if(( tmp.bv_len >= LENOF("telex") ) &&
4324 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4326 tmp.bv_len -= LENOF("telex");
4327 tmp.bv_val += LENOF("telex");
4330 if(( tmp.bv_len >= LENOF("teletex") ) &&
4331 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4333 tmp.bv_len -= LENOF("teletex");
4334 tmp.bv_val += LENOF("teletex");
4337 if(( tmp.bv_len >= LENOF("telephone") ) &&
4338 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4340 tmp.bv_len -= LENOF("telephone");
4341 tmp.bv_val += LENOF("telephone");
4344 return LDAP_INVALID_SYNTAX;
4347 case 'G': /* g3fax or g4fax */
4348 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4349 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4350 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4352 tmp.bv_len -= LENOF("g3fax");
4353 tmp.bv_val += LENOF("g3fax");
4356 return LDAP_INVALID_SYNTAX;
4360 if(( tmp.bv_len >= LENOF("ia5") ) &&
4361 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4363 tmp.bv_len -= LENOF("ia5");
4364 tmp.bv_val += LENOF("ia5");
4367 return LDAP_INVALID_SYNTAX;
4371 if(( tmp.bv_len >= LENOF("videotex") ) &&
4372 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4374 tmp.bv_len -= LENOF("videotex");
4375 tmp.bv_val += LENOF("videotex");
4378 return LDAP_INVALID_SYNTAX;
4381 return LDAP_INVALID_SYNTAX;
4384 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4386 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4390 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4394 return LDAP_INVALID_SYNTAX;
4396 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4405 nisNetgroupTripleValidate(
4407 struct berval *val )
4412 if ( BER_BVISEMPTY( val ) ) {
4413 return LDAP_INVALID_SYNTAX;
4416 p = (char *)val->bv_val;
4417 e = p + val->bv_len;
4419 if ( *p != '(' /*')'*/ ) {
4420 return LDAP_INVALID_SYNTAX;
4423 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4427 return LDAP_INVALID_SYNTAX;
4430 } else if ( !AD_CHAR( *p ) ) {
4431 return LDAP_INVALID_SYNTAX;
4435 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4436 return LDAP_INVALID_SYNTAX;
4442 return LDAP_INVALID_SYNTAX;
4445 return LDAP_SUCCESS;
4449 bootParameterValidate(
4451 struct berval *val )
4455 if ( BER_BVISEMPTY( val ) ) {
4456 return LDAP_INVALID_SYNTAX;
4459 p = (char *)val->bv_val;
4460 e = p + val->bv_len;
4463 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4464 if ( !AD_CHAR( *p ) ) {
4465 return LDAP_INVALID_SYNTAX;
4470 return LDAP_INVALID_SYNTAX;
4474 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4475 if ( !AD_CHAR( *p ) ) {
4476 return LDAP_INVALID_SYNTAX;
4481 return LDAP_INVALID_SYNTAX;
4485 for ( p++; p < e; p++ ) {
4486 if ( !SLAP_PRINTABLE( *p ) ) {
4487 return LDAP_INVALID_SYNTAX;
4491 return LDAP_SUCCESS;
4495 firstComponentNormalize(
4500 struct berval *normalized,
4507 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4508 ber_dupbv_x( normalized, val, ctx );
4509 return LDAP_SUCCESS;
4512 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4514 if( val->bv_val[0] != '(' /*')'*/ &&
4515 val->bv_val[0] != '{' /*'}'*/ )
4517 return LDAP_INVALID_SYNTAX;
4520 /* trim leading white space */
4522 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4528 /* grab next word */
4529 comp.bv_val = &val->bv_val[len];
4530 len = val->bv_len - len;
4531 for( comp.bv_len = 0;
4532 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4538 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4539 rc = numericoidValidate( NULL, &comp );
4540 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4541 rc = integerValidate( NULL, &comp );
4543 rc = LDAP_INVALID_SYNTAX;
4547 if( rc == LDAP_SUCCESS ) {
4548 ber_dupbv_x( normalized, &comp, ctx );
4554 static char *country_gen_syn[] = {
4555 "1.3.6.1.4.1.1466.115.121.1.15",
4556 "1.3.6.1.4.1.1466.115.121.1.26",
4557 "1.3.6.1.4.1.1466.115.121.1.44",
4561 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4562 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4564 static slap_syntax_defs_rec syntax_defs[] = {
4565 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4566 X_BINARY X_NOT_H_R ")",
4567 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4568 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4569 0, NULL, NULL, NULL},
4570 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4571 0, NULL, NULL, NULL},
4572 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4574 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4575 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4577 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4578 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4579 0, NULL, bitStringValidate, NULL },
4580 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4581 0, NULL, booleanValidate, NULL},
4582 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4583 X_BINARY X_NOT_H_R ")",
4584 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4585 NULL, certificateValidate, NULL},
4586 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4587 X_BINARY X_NOT_H_R ")",
4588 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4589 NULL, certificateListValidate, NULL},
4590 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4591 X_BINARY X_NOT_H_R ")",
4592 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4593 NULL, sequenceValidate, NULL},
4594 #if 0 /* need to go __after__ printableString */
4595 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4596 0, "1.3.6.1.4.1.1466.115.121.1.44",
4597 countryStringValidate, NULL},
4599 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4600 0, NULL, dnValidate, dnPretty},
4601 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4602 0, NULL, rdnValidate, rdnPretty},
4603 #ifdef LDAP_COMP_MATCH
4604 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4605 0, NULL, allComponentsValidate, NULL},
4606 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4607 0, NULL, componentFilterValidate, NULL},
4609 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4610 0, NULL, NULL, NULL},
4611 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4612 0, NULL, deliveryMethodValidate, NULL},
4613 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4614 0, NULL, UTF8StringValidate, NULL},
4615 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4616 0, NULL, NULL, NULL},
4617 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4618 0, NULL, NULL, NULL},
4619 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4620 0, NULL, NULL, NULL},
4621 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4622 0, NULL, NULL, NULL},
4623 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4624 0, NULL, NULL, NULL},
4625 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4626 0, NULL, printablesStringValidate, NULL},
4627 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4628 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4629 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4630 0, NULL, generalizedTimeValidate, NULL},
4631 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4632 0, NULL, NULL, NULL},
4633 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4634 0, NULL, IA5StringValidate, NULL},
4635 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4636 0, NULL, integerValidate, NULL},
4637 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4638 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4639 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4640 0, NULL, NULL, NULL},
4641 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4642 0, NULL, NULL, NULL},
4643 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4644 0, NULL, NULL, NULL},
4645 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4646 0, NULL, NULL, NULL},
4647 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4648 0, NULL, NULL, NULL},
4649 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4650 0, NULL, nameUIDValidate, nameUIDPretty },
4651 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4652 0, NULL, NULL, NULL},
4653 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4654 0, NULL, numericStringValidate, NULL},
4655 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4656 0, NULL, NULL, NULL},
4657 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4658 0, NULL, numericoidValidate, NULL},
4659 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4660 0, NULL, IA5StringValidate, NULL},
4661 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4662 0, NULL, blobValidate, NULL},
4663 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4664 0, NULL, UTF8StringValidate, NULL},
4665 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4666 0, NULL, NULL, NULL},
4667 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4668 0, NULL, NULL, NULL},
4669 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4670 0, NULL, printableStringValidate, NULL},
4671 /* moved here because now depends on Directory String, IA5 String
4672 * and Printable String */
4673 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4674 0, country_gen_syn, countryStringValidate, NULL},
4675 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4676 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4677 0, NULL, subtreeSpecificationValidate, NULL},
4678 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4679 X_BINARY X_NOT_H_R ")",
4680 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4681 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4682 0, NULL, printableStringValidate, NULL},
4683 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4684 0, NULL, NULL, NULL},
4685 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4686 0, NULL, printablesStringValidate, NULL},
4687 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4688 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4689 0, NULL, utcTimeValidate, NULL},
4691 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4692 0, NULL, NULL, NULL},
4693 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4694 0, NULL, NULL, NULL},
4695 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4696 0, NULL, NULL, NULL},
4697 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4698 0, NULL, NULL, NULL},
4699 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4700 0, NULL, NULL, NULL},
4702 /* RFC 2307 NIS Syntaxes */
4703 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4704 0, NULL, nisNetgroupTripleValidate, NULL},
4705 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4706 0, NULL, bootParameterValidate, NULL},
4708 /* draft-zeilenga-ldap-x509 */
4709 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4710 SLAP_SYNTAX_HIDE, NULL,
4711 serialNumberAndIssuerValidate,
4712 serialNumberAndIssuerPretty},
4713 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4714 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4715 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4716 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4717 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4718 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4719 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4720 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4721 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4722 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4723 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4724 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4726 #ifdef SLAPD_AUTHPASSWD
4727 /* needs updating */
4728 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4729 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4732 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4733 0, NULL, UUIDValidate, UUIDPretty},
4735 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4736 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4738 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4739 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4741 /* OpenLDAP Void Syntax */
4742 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4743 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4745 /* FIXME: OID is unused, but not registered yet */
4746 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4747 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4749 {NULL, 0, NULL, NULL, NULL}
4752 char *csnSIDMatchSyntaxes[] = {
4753 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4756 char *certificateExactMatchSyntaxes[] = {
4757 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4760 #ifdef LDAP_COMP_MATCH
4761 char *componentFilterMatchSyntaxes[] = {
4762 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4766 char *directoryStringSyntaxes[] = {
4767 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4770 char *integerFirstComponentMatchSyntaxes[] = {
4771 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4772 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4775 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4776 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4777 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4778 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4779 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4780 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4781 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4782 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4783 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4788 * Other matching rules in X.520 that we do not use (yet):
4790 * 2.5.13.25 uTCTimeMatch
4791 * 2.5.13.26 uTCTimeOrderingMatch
4792 * 2.5.13.31* directoryStringFirstComponentMatch
4793 * 2.5.13.32* wordMatch
4794 * 2.5.13.33* keywordMatch
4795 * 2.5.13.36+ certificatePairExactMatch
4796 * 2.5.13.37+ certificatePairMatch
4797 * 2.5.13.38+ certificateListExactMatch
4798 * 2.5.13.39+ certificateListMatch
4799 * 2.5.13.40+ algorithmIdentifierMatch
4800 * 2.5.13.41* storedPrefixMatch
4801 * 2.5.13.42 attributeCertificateMatch
4802 * 2.5.13.43 readerAndKeyIDMatch
4803 * 2.5.13.44 attributeIntegrityMatch
4805 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4806 * (+) described in draft-zeilenga-ldap-x509
4808 static slap_mrule_defs_rec mrule_defs[] = {
4810 * EQUALITY matching rules must be listed after associated APPROX
4811 * matching rules. So, we list all APPROX matching rules first.
4813 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4814 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4815 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4816 NULL, NULL, directoryStringApproxMatch,
4817 directoryStringApproxIndexer, directoryStringApproxFilter,
4820 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4821 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4822 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4823 NULL, NULL, IA5StringApproxMatch,
4824 IA5StringApproxIndexer, IA5StringApproxFilter,
4828 * Other matching rules
4831 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4832 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4833 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4834 NULL, NULL, octetStringMatch,
4835 octetStringIndexer, octetStringFilter,
4838 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4839 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4840 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4841 NULL, dnNormalize, dnMatch,
4842 octetStringIndexer, octetStringFilter,
4845 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4846 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4847 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4848 NULL, dnNormalize, dnRelativeMatch,
4852 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4853 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4854 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4855 NULL, dnNormalize, dnRelativeMatch,
4859 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4860 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4861 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4862 NULL, dnNormalize, dnRelativeMatch,
4866 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4867 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4868 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4869 NULL, dnNormalize, dnRelativeMatch,
4873 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4874 "SYNTAX 1.2.36.79672281.1.5.0 )",
4875 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4876 NULL, rdnNormalize, rdnMatch,
4877 octetStringIndexer, octetStringFilter,
4880 #ifdef LDAP_COMP_MATCH
4881 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4882 "SYNTAX 1.2.36.79672281.1.5.2 )",
4883 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4884 NULL, NULL , componentFilterMatch,
4885 octetStringIndexer, octetStringFilter,
4888 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4889 "SYNTAX 1.2.36.79672281.1.5.3 )",
4890 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4891 NULL, NULL , allComponentsMatch,
4892 octetStringIndexer, octetStringFilter,
4895 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4896 "SYNTAX 1.2.36.79672281.1.5.3 )",
4897 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4898 NULL, NULL , directoryComponentsMatch,
4899 octetStringIndexer, octetStringFilter,
4903 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4904 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4905 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4906 NULL, UTF8StringNormalize, octetStringMatch,
4907 octetStringIndexer, octetStringFilter,
4908 directoryStringApproxMatchOID },
4910 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4911 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4912 SLAP_MR_ORDERING, directoryStringSyntaxes,
4913 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4915 "caseIgnoreMatch" },
4917 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4919 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4920 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4921 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4922 "caseIgnoreMatch" },
4924 {"( 2.5.13.5 NAME 'caseExactMatch' "
4925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4926 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4927 NULL, UTF8StringNormalize, octetStringMatch,
4928 octetStringIndexer, octetStringFilter,
4929 directoryStringApproxMatchOID },
4931 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4932 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4933 SLAP_MR_ORDERING, directoryStringSyntaxes,
4934 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4938 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4939 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4940 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4941 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4942 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4945 {"( 2.5.13.8 NAME 'numericStringMatch' "
4946 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4947 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4948 NULL, numericStringNormalize, octetStringMatch,
4949 octetStringIndexer, octetStringFilter,
4952 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4953 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4954 SLAP_MR_ORDERING, NULL,
4955 NULL, numericStringNormalize, octetStringOrderingMatch,
4957 "numericStringMatch" },
4959 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4960 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4961 SLAP_MR_SUBSTR, NULL,
4962 NULL, numericStringNormalize, octetStringSubstringsMatch,
4963 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4964 "numericStringMatch" },
4966 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4968 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4969 NULL, NULL, NULL, NULL, NULL, NULL },
4971 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4973 SLAP_MR_SUBSTR, NULL,
4974 NULL, NULL, NULL, NULL, NULL,
4975 "caseIgnoreListMatch" },
4977 {"( 2.5.13.13 NAME 'booleanMatch' "
4978 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4979 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4980 NULL, NULL, booleanMatch,
4981 octetStringIndexer, octetStringFilter,
4984 {"( 2.5.13.14 NAME 'integerMatch' "
4985 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4986 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4987 NULL, NULL, integerMatch,
4988 octetStringIndexer, octetStringFilter,
4991 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4992 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4993 SLAP_MR_ORDERING, NULL,
4994 NULL, NULL, integerMatch,
4998 {"( 2.5.13.16 NAME 'bitStringMatch' "
4999 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5000 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5001 NULL, NULL, octetStringMatch,
5002 octetStringIndexer, octetStringFilter,
5005 {"( 2.5.13.17 NAME 'octetStringMatch' "
5006 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5007 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5008 NULL, NULL, octetStringMatch,
5009 octetStringIndexer, octetStringFilter,
5012 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5013 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5014 SLAP_MR_ORDERING, NULL,
5015 NULL, NULL, octetStringOrderingMatch,
5017 "octetStringMatch" },
5019 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5020 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5021 SLAP_MR_SUBSTR, NULL,
5022 NULL, NULL, octetStringSubstringsMatch,
5023 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5024 "octetStringMatch" },
5026 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5027 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5028 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5030 telephoneNumberNormalize, octetStringMatch,
5031 octetStringIndexer, octetStringFilter,
5034 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5035 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5036 SLAP_MR_SUBSTR, NULL,
5037 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5038 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5039 "telephoneNumberMatch" },
5041 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5042 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5043 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5044 NULL, NULL, NULL, NULL, NULL, NULL },
5046 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5047 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5048 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5049 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5050 uniqueMemberIndexer, uniqueMemberFilter,
5053 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5054 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5055 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5056 NULL, NULL, NULL, NULL, NULL, NULL },
5058 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5059 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5060 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5061 NULL, generalizedTimeNormalize, octetStringMatch,
5062 generalizedTimeIndexer, generalizedTimeFilter,
5065 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5066 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5067 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5068 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5070 "generalizedTimeMatch" },
5072 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5073 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5074 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5075 integerFirstComponentMatchSyntaxes,
5076 NULL, firstComponentNormalize, integerMatch,
5077 octetStringIndexer, octetStringFilter,
5080 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5081 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5082 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5083 objectIdentifierFirstComponentMatchSyntaxes,
5084 NULL, firstComponentNormalize, octetStringMatch,
5085 octetStringIndexer, octetStringFilter,
5088 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5089 "SYNTAX 1.3.6.1.1.15.1 )",
5090 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5091 NULL, certificateExactNormalize, octetStringMatch,
5092 octetStringIndexer, octetStringFilter,
5095 {"( 2.5.13.35 NAME 'certificateMatch' "
5096 "SYNTAX 1.3.6.1.1.15.2 )",
5097 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5098 NULL, NULL, NULL, NULL, NULL,
5101 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5102 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5103 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5104 NULL, IA5StringNormalize, octetStringMatch,
5105 octetStringIndexer, octetStringFilter,
5106 IA5StringApproxMatchOID },
5108 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5109 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5110 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5111 NULL, IA5StringNormalize, octetStringMatch,
5112 octetStringIndexer, octetStringFilter,
5113 IA5StringApproxMatchOID },
5115 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5116 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5117 SLAP_MR_SUBSTR, NULL,
5118 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5119 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5120 "caseIgnoreIA5Match" },
5122 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5123 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5124 SLAP_MR_SUBSTR, NULL,
5125 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5126 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5127 "caseExactIA5Match" },
5129 #ifdef SLAPD_AUTHPASSWD
5130 /* needs updating */
5131 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5132 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5133 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5134 NULL, NULL, authPasswordMatch,
5139 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5140 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5142 NULL, NULL, integerBitAndMatch,
5146 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5147 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5149 NULL, NULL, integerBitOrMatch,
5153 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5154 "SYNTAX 1.3.6.1.1.16.1 )",
5155 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5156 NULL, UUIDNormalize, octetStringMatch,
5157 octetStringIndexer, octetStringFilter,
5160 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5161 "SYNTAX 1.3.6.1.1.16.1 )",
5162 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5163 NULL, UUIDNormalize, octetStringOrderingMatch,
5164 octetStringIndexer, octetStringFilter,
5167 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5168 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5169 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5170 NULL, csnNormalize, csnMatch,
5171 csnIndexer, csnFilter,
5174 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5175 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5176 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5177 NULL, NULL, csnOrderingMatch,
5181 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5182 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5183 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5184 NULL, csnSidNormalize, octetStringMatch,
5185 octetStringIndexer, octetStringFilter,
5188 /* FIXME: OID is unused, but not registered yet */
5189 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5190 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5191 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5192 NULL, authzNormalize, authzMatch,
5196 {NULL, SLAP_MR_NONE, NULL,
5197 NULL, NULL, NULL, NULL, NULL,
5202 slap_schema_init( void )
5207 /* we should only be called once (from main) */
5208 assert( schema_init_done == 0 );
5210 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5211 res = register_syntax( &syntax_defs[i] );
5214 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5215 syntax_defs[i].sd_desc );
5220 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5221 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5222 mrule_defs[i].mrd_compat_syntaxes == NULL )
5225 "slap_schema_init: Ignoring unusable matching rule %s\n",
5226 mrule_defs[i].mrd_desc );
5230 res = register_matching_rule( &mrule_defs[i] );
5234 "slap_schema_init: Error registering matching rule %s\n",
5235 mrule_defs[i].mrd_desc );
5240 res = slap_schema_load();
5241 schema_init_done = 1;
5246 schema_destroy( void )
5255 if( schema_init_done ) {
5256 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5257 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );