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