1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 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 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
66 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
67 SLAP_INDEX_INTLEN_DEFAULT );
69 ldap_pvt_thread_mutex_t ad_undef_mutex;
70 ldap_pvt_thread_mutex_t oc_undef_mutex;
73 generalizedTimeValidate(
77 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
82 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
89 /* no value allowed */
90 return LDAP_INVALID_SYNTAX;
98 /* any value allowed */
102 #define berValidate blobValidate
109 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
110 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
115 /* X.509 related stuff */
124 SLAP_TAG_UTCTIME = 0x17U,
125 SLAP_TAG_GENERALIZEDTIME = 0x18U
129 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
132 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
133 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
134 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
135 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
139 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
142 /* X.509 certificate validation */
144 certificateValidate( Syntax *syntax, struct berval *in )
146 BerElementBuffer berbuf;
147 BerElement *ber = (BerElement *)&berbuf;
150 ber_int_t version = SLAP_X509_V1;
152 ber_init2( ber, in, LBER_USE_DER );
153 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
154 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
155 tag = ber_skip_tag( ber, &len ); /* Sequence */
156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
157 tag = ber_peek_tag( ber, &len );
158 /* Optional version */
159 if ( tag == SLAP_X509_OPT_C_VERSION ) {
160 tag = ber_skip_tag( ber, &len );
161 tag = ber_get_int( ber, &version );
162 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
164 /* NOTE: don't try to parse Serial, because it might be longer
165 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
166 tag = ber_skip_tag( ber, &len ); /* Serial */
167 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
168 ber_skip_data( ber, len );
169 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
170 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
171 ber_skip_data( ber, len );
172 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
173 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
174 ber_skip_data( ber, len );
175 tag = ber_skip_tag( ber, &len ); /* Validity */
176 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
177 ber_skip_data( ber, len );
178 tag = ber_skip_tag( ber, &len ); /* Subject DN */
179 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
180 ber_skip_data( ber, len );
181 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
182 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
183 ber_skip_data( ber, len );
184 tag = ber_skip_tag( ber, &len );
185 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
186 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
187 ber_skip_data( ber, len );
188 tag = ber_skip_tag( ber, &len );
190 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
191 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
192 ber_skip_data( ber, len );
193 tag = ber_skip_tag( ber, &len );
195 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
196 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
197 tag = ber_skip_tag( ber, &len );
198 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
199 ber_skip_data( ber, len );
200 tag = ber_skip_tag( ber, &len );
202 /* signatureAlgorithm */
203 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
204 ber_skip_data( ber, len );
205 tag = ber_skip_tag( ber, &len );
207 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
208 ber_skip_data( ber, len );
209 tag = ber_skip_tag( ber, &len );
210 /* Must be at end now */
211 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
215 /* X.509 certificate list validation */
217 certificateListValidate( Syntax *syntax, struct berval *in )
219 BerElementBuffer berbuf;
220 BerElement *ber = (BerElement *)&berbuf;
223 ber_int_t version = SLAP_X509_V1;
225 ber_init2( ber, in, LBER_USE_DER );
226 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
227 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
228 tag = ber_skip_tag( ber, &len ); /* Sequence */
229 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
230 tag = ber_peek_tag( ber, &len );
231 /* Optional version */
232 if ( tag == LBER_INTEGER ) {
233 tag = ber_get_int( ber, &version );
234 assert( tag == LBER_INTEGER );
235 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
237 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
238 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
239 ber_skip_data( ber, len );
240 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
241 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
242 ber_skip_data( ber, len );
243 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
244 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
245 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
246 ber_skip_data( ber, len );
247 /* Optional nextUpdate */
248 tag = ber_skip_tag( ber, &len );
249 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
250 ber_skip_data( ber, len );
251 tag = ber_skip_tag( ber, &len );
253 /* revokedCertificates - Sequence of Sequence, Optional */
254 if ( tag == LBER_SEQUENCE ) {
256 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
257 /* Should NOT be empty */
258 ber_skip_data( ber, len );
259 tag = ber_skip_tag( ber, &len );
262 /* Optional Extensions */
263 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
264 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
265 tag = ber_skip_tag( ber, &len );
266 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
267 ber_skip_data( ber, len );
268 tag = ber_skip_tag( ber, &len );
270 /* signatureAlgorithm */
271 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
272 ber_skip_data( ber, len );
273 tag = ber_skip_tag( ber, &len );
275 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
276 ber_skip_data( ber, len );
277 tag = ber_skip_tag( ber, &len );
278 /* Must be at end now */
279 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
289 struct berval *value,
290 void *assertedValue )
292 struct berval *asserted = (struct berval *) assertedValue;
293 int match = value->bv_len - asserted->bv_len;
296 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
304 octetStringOrderingMatch(
309 struct berval *value,
310 void *assertedValue )
312 struct berval *asserted = (struct berval *) assertedValue;
313 ber_len_t v_len = value->bv_len;
314 ber_len_t av_len = asserted->bv_len;
316 int match = memcmp( value->bv_val, asserted->bv_val,
317 (v_len < av_len ? v_len : av_len) );
319 if( match == 0 ) match = v_len - av_len;
327 HASH_CONTEXT *HASHcontext,
328 struct berval *prefix,
333 HASH_Init(HASHcontext);
334 if(prefix && prefix->bv_len > 0) {
335 HASH_Update(HASHcontext,
336 (unsigned char *)prefix->bv_val, prefix->bv_len);
338 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
339 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
340 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
346 HASH_CONTEXT *HASHcontext,
347 unsigned char *HASHdigest,
348 unsigned char *value,
351 HASH_CONTEXT ctx = *HASHcontext;
352 HASH_Update( &ctx, value, len );
353 HASH_Final( HASHdigest, &ctx );
356 /* Index generation function */
357 int octetStringIndexer(
362 struct berval *prefix,
370 HASH_CONTEXT HASHcontext;
371 unsigned char HASHdigest[HASH_BYTES];
372 struct berval digest;
373 digest.bv_val = (char *)HASHdigest;
374 digest.bv_len = sizeof(HASHdigest);
376 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
377 /* just count them */
380 /* we should have at least one value at this point */
383 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
385 slen = syntax->ssyn_oidlen;
386 mlen = mr->smr_oidlen;
388 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
389 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
390 hashIter( &HASHcontext, HASHdigest,
391 (unsigned char *)values[i].bv_val, values[i].bv_len );
392 ber_dupbv_x( &keys[i], &digest, ctx );
395 BER_BVZERO( &keys[i] );
402 /* Index generation function */
403 int octetStringFilter(
408 struct berval *prefix,
409 void * assertedValue,
415 HASH_CONTEXT HASHcontext;
416 unsigned char HASHdigest[HASH_BYTES];
417 struct berval *value = (struct berval *) assertedValue;
418 struct berval digest;
419 digest.bv_val = (char *)HASHdigest;
420 digest.bv_len = sizeof(HASHdigest);
422 slen = syntax->ssyn_oidlen;
423 mlen = mr->smr_oidlen;
425 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
427 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
428 hashIter( &HASHcontext, HASHdigest,
429 (unsigned char *)value->bv_val, value->bv_len );
431 ber_dupbv_x( keys, &digest, ctx );
432 BER_BVZERO( &keys[1] );
440 octetStringSubstringsMatch(
445 struct berval *value,
446 void *assertedValue )
449 SubstringsAssertion *sub = assertedValue;
450 struct berval left = *value;
454 /* Add up asserted input length */
455 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
456 inlen += sub->sa_initial.bv_len;
459 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
460 inlen += sub->sa_any[i].bv_len;
463 if ( !BER_BVISNULL( &sub->sa_final ) ) {
464 inlen += sub->sa_final.bv_len;
467 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
468 if ( inlen > left.bv_len ) {
473 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
474 sub->sa_initial.bv_len );
480 left.bv_val += sub->sa_initial.bv_len;
481 left.bv_len -= sub->sa_initial.bv_len;
482 inlen -= sub->sa_initial.bv_len;
485 if ( !BER_BVISNULL( &sub->sa_final ) ) {
486 if ( inlen > left.bv_len ) {
491 match = memcmp( sub->sa_final.bv_val,
492 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
493 sub->sa_final.bv_len );
499 left.bv_len -= sub->sa_final.bv_len;
500 inlen -= sub->sa_final.bv_len;
504 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
509 if ( inlen > left.bv_len ) {
510 /* not enough length */
515 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
519 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
526 idx = p - left.bv_val;
528 if ( idx >= left.bv_len ) {
529 /* this shouldn't happen */
536 if ( sub->sa_any[i].bv_len > left.bv_len ) {
537 /* not enough left */
542 match = memcmp( left.bv_val,
543 sub->sa_any[i].bv_val,
544 sub->sa_any[i].bv_len );
552 left.bv_val += sub->sa_any[i].bv_len;
553 left.bv_len -= sub->sa_any[i].bv_len;
554 inlen -= sub->sa_any[i].bv_len;
563 /* Substrings Index generation function */
565 octetStringSubstringsIndexer(
570 struct berval *prefix,
579 HASH_CONTEXT HCany, HCini, HCfin;
580 unsigned char HASHdigest[HASH_BYTES];
581 struct berval digest;
582 digest.bv_val = (char *)HASHdigest;
583 digest.bv_len = sizeof(HASHdigest);
587 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
588 /* count number of indices to generate */
589 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
590 if( values[i].bv_len >= index_substr_if_maxlen ) {
591 nkeys += index_substr_if_maxlen -
592 (index_substr_if_minlen - 1);
593 } else if( values[i].bv_len >= index_substr_if_minlen ) {
594 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
598 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
599 if( values[i].bv_len >= index_substr_any_len ) {
600 nkeys += values[i].bv_len - (index_substr_any_len - 1);
604 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
605 if( values[i].bv_len >= index_substr_if_maxlen ) {
606 nkeys += index_substr_if_maxlen -
607 (index_substr_if_minlen - 1);
608 } else if( values[i].bv_len >= index_substr_if_minlen ) {
609 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
615 /* no keys to generate */
620 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
622 slen = syntax->ssyn_oidlen;
623 mlen = mr->smr_oidlen;
625 if ( flags & SLAP_INDEX_SUBSTR_ANY )
626 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
627 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
628 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
629 if( flags & SLAP_INDEX_SUBSTR_FINAL )
630 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
633 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
636 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
637 ( values[i].bv_len >= index_substr_any_len ) )
639 max = values[i].bv_len - (index_substr_any_len - 1);
641 for( j=0; j<max; j++ ) {
642 hashIter( &HCany, HASHdigest,
643 (unsigned char *)&values[i].bv_val[j],
644 index_substr_any_len );
645 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
649 /* skip if too short */
650 if( values[i].bv_len < index_substr_if_minlen ) continue;
652 max = index_substr_if_maxlen < values[i].bv_len
653 ? index_substr_if_maxlen : values[i].bv_len;
655 for( j=index_substr_if_minlen; j<=max; j++ ) {
657 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
658 hashIter( &HCini, HASHdigest,
659 (unsigned char *)values[i].bv_val, j );
660 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
663 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
664 hashIter( &HCfin, HASHdigest,
665 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
666 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
673 BER_BVZERO( &keys[nkeys] );
684 octetStringSubstringsFilter (
689 struct berval *prefix,
690 void * assertedValue,
694 SubstringsAssertion *sa;
697 size_t slen, mlen, klen;
699 HASH_CONTEXT HASHcontext;
700 unsigned char HASHdigest[HASH_BYTES];
701 struct berval *value;
702 struct berval digest;
704 sa = (SubstringsAssertion *) assertedValue;
706 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
707 !BER_BVISNULL( &sa->sa_initial ) &&
708 sa->sa_initial.bv_len >= index_substr_if_minlen )
711 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
712 ( flags & SLAP_INDEX_SUBSTR_ANY ))
714 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
718 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
720 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
721 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
722 /* don't bother accounting with stepping */
723 nkeys += sa->sa_any[i].bv_len -
724 ( index_substr_any_len - 1 );
729 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
730 !BER_BVISNULL( &sa->sa_final ) &&
731 sa->sa_final.bv_len >= index_substr_if_minlen )
734 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
735 ( flags & SLAP_INDEX_SUBSTR_ANY ))
737 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
746 digest.bv_val = (char *)HASHdigest;
747 digest.bv_len = sizeof(HASHdigest);
749 slen = syntax->ssyn_oidlen;
750 mlen = mr->smr_oidlen;
752 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
755 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
756 !BER_BVISNULL( &sa->sa_initial ) &&
757 sa->sa_initial.bv_len >= index_substr_if_minlen )
759 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
760 value = &sa->sa_initial;
762 klen = index_substr_if_maxlen < value->bv_len
763 ? index_substr_if_maxlen : value->bv_len;
765 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
766 hashIter( &HASHcontext, HASHdigest,
767 (unsigned char *)value->bv_val, klen );
768 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
770 /* If initial is too long and we have subany indexed, use it
771 * to match the excess...
773 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
776 pre = SLAP_INDEX_SUBSTR_PREFIX;
777 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
778 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
780 hashIter( &HASHcontext, HASHdigest,
781 (unsigned char *)&value->bv_val[j], index_substr_any_len );
782 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
787 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
789 pre = SLAP_INDEX_SUBSTR_PREFIX;
790 klen = index_substr_any_len;
792 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
793 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
797 value = &sa->sa_any[i];
799 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
801 j <= value->bv_len - index_substr_any_len;
802 j += index_substr_any_step )
804 hashIter( &HASHcontext, HASHdigest,
805 (unsigned char *)&value->bv_val[j], klen );
806 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
811 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
812 !BER_BVISNULL( &sa->sa_final ) &&
813 sa->sa_final.bv_len >= index_substr_if_minlen )
815 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
816 value = &sa->sa_final;
818 klen = index_substr_if_maxlen < value->bv_len
819 ? index_substr_if_maxlen : value->bv_len;
821 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
822 hashIter( &HASHcontext, HASHdigest,
823 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
824 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
826 /* If final is too long and we have subany indexed, use it
827 * to match the excess...
829 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
832 pre = SLAP_INDEX_SUBSTR_PREFIX;
833 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
834 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
836 hashIter( &HASHcontext, HASHdigest,
837 (unsigned char *)&value->bv_val[j], index_substr_any_len );
838 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
844 BER_BVZERO( &keys[nkeys] );
861 /* very unforgiving validation, requires no normalization
862 * before simplistic matching
864 if( in->bv_len < 3 ) {
865 return LDAP_INVALID_SYNTAX;
868 /* RFC 4517 Section 3.3.2 Bit String:
869 * BitString = SQUOTE *binary-digit SQUOTE "B"
870 * binary-digit = "0" / "1"
872 * where SQUOTE [RFC4512] is
873 * SQUOTE = %x27 ; single quote ("'")
875 * Example: '0101111101'B
878 if( in->bv_val[0] != '\'' ||
879 in->bv_val[in->bv_len - 2] != '\'' ||
880 in->bv_val[in->bv_len - 1] != 'B' )
882 return LDAP_INVALID_SYNTAX;
885 for( i = in->bv_len - 3; i > 0; i-- ) {
886 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
887 return LDAP_INVALID_SYNTAX;
895 * Syntaxes from RFC 4517
900 A value of the Bit String syntax is a sequence of binary digits. The
901 LDAP-specific encoding of a value of this syntax is defined by the
904 BitString = SQUOTE *binary-digit SQUOTE "B"
906 binary-digit = "0" / "1"
908 The <SQUOTE> rule is defined in [MODELS].
913 The LDAP definition for the Bit String syntax is:
915 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
917 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
921 3.3.21. Name and Optional UID
923 A value of the Name and Optional UID syntax is the distinguished name
924 [MODELS] of an entity optionally accompanied by a unique identifier
925 that serves to differentiate the entity from others with an identical
928 The LDAP-specific encoding of a value of this syntax is defined by
931 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
933 The <BitString> rule is defined in Section 3.3.2. The
934 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
937 Note that although the '#' character may occur in the string
938 representation of a distinguished name, no additional escaping of
939 this character is performed when a <distinguishedName> is encoded in
940 a <NameAndOptionalUID>.
943 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
945 The LDAP definition for the Name and Optional UID syntax is:
947 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
949 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
956 1.4. Common ABNF Productions
959 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
961 SQUOTE = %x27 ; single quote ("'")
965 * Note: normalization strips any leading "0"s, unless the
966 * bit string is exactly "'0'B", so the normalized example,
967 * in slapd, would result in
969 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
971 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
972 * be escaped except when at the beginning of a value, the
973 * definition of Name and Optional UID appears to be flawed,
974 * because there is no clear means to determine whether the
975 * UID part is present or not.
979 * cn=Someone,dc=example,dc=com#'1'B
981 * could be either a NameAndOptionalUID with trailing UID, i.e.
983 * DN = "cn=Someone,dc=example,dc=com"
986 * or a NameAndOptionalUID with no trailing UID, and the AVA
987 * in the last RDN made of
990 * attributeValue = com#'1'B
992 * in fact "com#'1'B" is a valid IA5 string.
994 * As a consequence, current slapd code assumes that the
995 * presence of portions of a BitString at the end of the string
996 * representation of a NameAndOptionalUID means a BitString
997 * is expected, and cause an error otherwise. This is quite
998 * arbitrary, and might change in the future.
1008 struct berval dn, uid;
1010 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1012 ber_dupbv( &dn, in );
1013 if( !dn.bv_val ) return LDAP_OTHER;
1015 /* if there's a "#", try bitStringValidate()... */
1016 uid.bv_val = strrchr( dn.bv_val, '#' );
1017 if ( !BER_BVISNULL( &uid ) ) {
1019 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1021 rc = bitStringValidate( NULL, &uid );
1022 if ( rc == LDAP_SUCCESS ) {
1023 /* in case of success, trim the UID,
1024 * otherwise treat it as part of the DN */
1025 dn.bv_len -= uid.bv_len + 1;
1026 uid.bv_val[-1] = '\0';
1030 rc = dnValidate( NULL, &dn );
1032 ber_memfree( dn.bv_val );
1043 assert( val != NULL );
1044 assert( out != NULL );
1047 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1049 if( BER_BVISEMPTY( val ) ) {
1050 ber_dupbv_x( out, val, ctx );
1052 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1053 return LDAP_INVALID_SYNTAX;
1057 struct berval dnval = *val;
1058 struct berval uidval = BER_BVNULL;
1060 uidval.bv_val = strrchr( val->bv_val, '#' );
1061 if ( !BER_BVISNULL( &uidval ) ) {
1063 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1065 rc = bitStringValidate( NULL, &uidval );
1067 if ( rc == LDAP_SUCCESS ) {
1068 ber_dupbv_x( &dnval, val, ctx );
1069 dnval.bv_len -= uidval.bv_len + 1;
1070 dnval.bv_val[dnval.bv_len] = '\0';
1073 BER_BVZERO( &uidval );
1077 rc = dnPretty( syntax, &dnval, out, ctx );
1078 if ( dnval.bv_val != val->bv_val ) {
1079 slap_sl_free( dnval.bv_val, ctx );
1081 if( rc != LDAP_SUCCESS ) {
1085 if( !BER_BVISNULL( &uidval ) ) {
1089 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1090 + STRLENOF( "#" ) + uidval.bv_len + 1,
1093 ber_memfree_x( out->bv_val, ctx );
1097 out->bv_val[out->bv_len++] = '#';
1098 out->bv_val[out->bv_len++] = '\'';
1100 got1 = uidval.bv_len < sizeof("'0'B");
1101 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1102 c = uidval.bv_val[i];
1105 if( got1 ) out->bv_val[out->bv_len++] = c;
1109 out->bv_val[out->bv_len++] = c;
1114 out->bv_val[out->bv_len++] = '\'';
1115 out->bv_val[out->bv_len++] = 'B';
1116 out->bv_val[out->bv_len] = '\0';
1120 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1122 return LDAP_SUCCESS;
1126 uniqueMemberNormalize(
1131 struct berval *normalized,
1137 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1139 ber_dupbv_x( &out, val, ctx );
1140 if ( BER_BVISEMPTY( &out ) ) {
1144 struct berval uid = BER_BVNULL;
1146 uid.bv_val = strrchr( out.bv_val, '#' );
1147 if ( !BER_BVISNULL( &uid ) ) {
1149 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1151 rc = bitStringValidate( NULL, &uid );
1152 if ( rc == LDAP_SUCCESS ) {
1153 uid.bv_val[-1] = '\0';
1154 out.bv_len -= uid.bv_len + 1;
1160 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1162 if( rc != LDAP_SUCCESS ) {
1163 slap_sl_free( out.bv_val, ctx );
1164 return LDAP_INVALID_SYNTAX;
1167 if( !BER_BVISNULL( &uid ) ) {
1170 tmp = ch_realloc( normalized->bv_val,
1171 normalized->bv_len + uid.bv_len
1172 + STRLENOF("#") + 1 );
1173 if ( tmp == NULL ) {
1174 ber_memfree_x( normalized->bv_val, ctx );
1178 normalized->bv_val = tmp;
1180 /* insert the separator */
1181 normalized->bv_val[normalized->bv_len++] = '#';
1183 /* append the UID */
1184 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1185 uid.bv_val, uid.bv_len );
1186 normalized->bv_len += uid.bv_len;
1189 normalized->bv_val[normalized->bv_len] = '\0';
1192 slap_sl_free( out.bv_val, ctx );
1195 return LDAP_SUCCESS;
1204 struct berval *value,
1205 void *assertedValue )
1208 struct berval *asserted = (struct berval *) assertedValue;
1209 struct berval assertedDN = *asserted;
1210 struct berval assertedUID = BER_BVNULL;
1211 struct berval valueDN = *value;
1212 struct berval valueUID = BER_BVNULL;
1213 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1215 if ( !BER_BVISEMPTY( asserted ) ) {
1216 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1217 if ( !BER_BVISNULL( &assertedUID ) ) {
1218 assertedUID.bv_val++;
1219 assertedUID.bv_len = assertedDN.bv_len
1220 - ( assertedUID.bv_val - assertedDN.bv_val );
1222 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1223 assertedDN.bv_len -= assertedUID.bv_len + 1;
1226 BER_BVZERO( &assertedUID );
1231 if ( !BER_BVISEMPTY( value ) ) {
1233 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1234 if ( !BER_BVISNULL( &valueUID ) ) {
1236 valueUID.bv_len = valueDN.bv_len
1237 - ( valueUID.bv_val - valueDN.bv_val );
1239 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1240 valueDN.bv_len -= valueUID.bv_len + 1;
1243 BER_BVZERO( &valueUID );
1248 if( valueUID.bv_len && assertedUID.bv_len ) {
1249 match = valueUID.bv_len - assertedUID.bv_len;
1252 return LDAP_SUCCESS;
1255 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1258 return LDAP_SUCCESS;
1261 } else if ( !approx && valueUID.bv_len ) {
1264 return LDAP_SUCCESS;
1266 } else if ( !approx && assertedUID.bv_len ) {
1269 return LDAP_SUCCESS;
1272 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1276 uniqueMemberIndexer(
1281 struct berval *prefix,
1289 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1290 /* just count them */
1294 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1296 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1297 struct berval assertedDN = values[i];
1298 struct berval assertedUID = BER_BVNULL;
1300 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1301 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1302 if ( !BER_BVISNULL( &assertedUID ) ) {
1303 assertedUID.bv_val++;
1304 assertedUID.bv_len = assertedDN.bv_len
1305 - ( assertedUID.bv_val - assertedDN.bv_val );
1307 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1308 assertedDN.bv_len -= assertedUID.bv_len + 1;
1311 BER_BVZERO( &assertedUID );
1316 dnvalues[i] = assertedDN;
1318 BER_BVZERO( &dnvalues[i] );
1320 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1321 dnvalues, keysp, ctx );
1323 slap_sl_free( dnvalues, ctx );
1333 struct berval *prefix,
1334 void * assertedValue,
1338 struct berval *asserted = (struct berval *) assertedValue;
1339 struct berval assertedDN = *asserted;
1340 struct berval assertedUID = BER_BVNULL;
1342 if ( !BER_BVISEMPTY( asserted ) ) {
1343 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1344 if ( !BER_BVISNULL( &assertedUID ) ) {
1345 assertedUID.bv_val++;
1346 assertedUID.bv_len = assertedDN.bv_len
1347 - ( assertedUID.bv_val - assertedDN.bv_val );
1349 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1350 assertedDN.bv_len -= assertedUID.bv_len + 1;
1353 BER_BVZERO( &assertedUID );
1358 return octetStringFilter( use, flags, syntax, mr, prefix,
1359 &assertedDN, keysp, ctx );
1364 * Handling boolean syntax and matching is quite rigid.
1365 * A more flexible approach would be to allow a variety
1366 * of strings to be normalized and prettied into TRUE
1374 /* very unforgiving validation, requires no normalization
1375 * before simplistic matching
1378 if( in->bv_len == 4 ) {
1379 if( bvmatch( in, &slap_true_bv ) ) {
1380 return LDAP_SUCCESS;
1382 } else if( in->bv_len == 5 ) {
1383 if( bvmatch( in, &slap_false_bv ) ) {
1384 return LDAP_SUCCESS;
1388 return LDAP_INVALID_SYNTAX;
1397 struct berval *value,
1398 void *assertedValue )
1400 /* simplistic matching allowed by rigid validation */
1401 struct berval *asserted = (struct berval *) assertedValue;
1402 *matchp = value->bv_len != asserted->bv_len;
1403 return LDAP_SUCCESS;
1406 /*-------------------------------------------------------------------
1407 LDAP/X.500 string syntax / matching rules have a few oddities. This
1408 comment attempts to detail how slapd(8) treats them.
1411 StringSyntax X.500 LDAP Matching/Comments
1412 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1413 PrintableString subset subset i/e + ignore insignificant spaces
1414 PrintableString subset subset i/e + ignore insignificant spaces
1415 NumericString subset subset ignore all spaces
1416 IA5String ASCII ASCII i/e + ignore insignificant spaces
1417 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1419 TelephoneNumber subset subset i + ignore all spaces and "-"
1421 See RFC 4518 for details.
1425 In X.500(93), a directory string can be either a PrintableString,
1426 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1427 In later versions, more CHOICEs were added. In all cases the string
1430 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1431 A directory string cannot be zero length.
1433 For matching, there are both case ignore and exact rules. Both
1434 also require that "insignificant" spaces be ignored.
1435 spaces before the first non-space are ignored;
1436 spaces after the last non-space are ignored;
1437 spaces after a space are ignored.
1438 Note: by these rules (and as clarified in X.520), a string of only
1439 spaces is to be treated as if held one space, not empty (which
1440 would be a syntax error).
1443 In ASN.1, numeric string is just a string of digits and spaces
1444 and could be empty. However, in X.500, all attribute values of
1445 numeric string carry a non-empty constraint. For example:
1447 internationalISDNNumber ATTRIBUTE ::= {
1448 WITH SYNTAX InternationalISDNNumber
1449 EQUALITY MATCHING RULE numericStringMatch
1450 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1451 ID id-at-internationalISDNNumber }
1452 InternationalISDNNumber ::=
1453 NumericString (SIZE(1..ub-international-isdn-number))
1455 Unforunately, some assertion values are don't carry the same
1456 constraint (but its unclear how such an assertion could ever
1457 be true). In LDAP, there is one syntax (numericString) not two
1458 (numericString with constraint, numericString without constraint).
1459 This should be treated as numericString with non-empty constraint.
1460 Note that while someone may have no ISDN number, there are no ISDN
1461 numbers which are zero length.
1463 In matching, spaces are ignored.
1466 In ASN.1, Printable string is just a string of printable characters
1467 and can be empty. In X.500, semantics much like NumericString (see
1468 serialNumber for a like example) excepting uses insignificant space
1469 handling instead of ignore all spaces. They must be non-empty.
1472 Basically same as PrintableString. There are no examples in X.500,
1473 but same logic applies. Empty strings are allowed.
1475 -------------------------------------------------------------------*/
1484 unsigned char *u = (unsigned char *)in->bv_val;
1486 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1487 /* directory strings cannot be empty */
1488 return LDAP_INVALID_SYNTAX;
1491 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1492 /* get the length indicated by the first byte */
1493 len = LDAP_UTF8_CHARLEN2( u, len );
1495 /* very basic checks */
1498 if( (u[5] & 0xC0) != 0x80 ) {
1499 return LDAP_INVALID_SYNTAX;
1502 if( (u[4] & 0xC0) != 0x80 ) {
1503 return LDAP_INVALID_SYNTAX;
1506 if( (u[3] & 0xC0) != 0x80 ) {
1507 return LDAP_INVALID_SYNTAX;
1510 if( (u[2] & 0xC0 )!= 0x80 ) {
1511 return LDAP_INVALID_SYNTAX;
1514 if( (u[1] & 0xC0) != 0x80 ) {
1515 return LDAP_INVALID_SYNTAX;
1518 /* CHARLEN already validated it */
1521 return LDAP_INVALID_SYNTAX;
1524 /* make sure len corresponds with the offset
1525 to the next character */
1526 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1530 return LDAP_INVALID_SYNTAX;
1533 return LDAP_SUCCESS;
1537 UTF8StringNormalize(
1542 struct berval *normalized,
1545 struct berval tmp, nvalue;
1549 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1551 if( BER_BVISNULL( val ) ) {
1552 /* assume we're dealing with a syntax (e.g., UTF8String)
1553 * which allows empty strings
1555 BER_BVZERO( normalized );
1556 return LDAP_SUCCESS;
1559 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1560 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1561 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1562 ? LDAP_UTF8_APPROX : 0;
1564 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1569 /* collapse spaces (in place) */
1571 nvalue.bv_val = tmp.bv_val;
1573 /* trim leading spaces? */
1574 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1575 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1577 for( i = 0; i < tmp.bv_len; i++) {
1578 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1579 if( wasspace++ == 0 ) {
1580 /* trim repeated spaces */
1581 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1585 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1589 if( !BER_BVISEMPTY( &nvalue ) ) {
1590 /* trim trailing space? */
1592 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1593 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1597 nvalue.bv_val[nvalue.bv_len] = '\0';
1600 /* string of all spaces is treated as one space */
1601 nvalue.bv_val[0] = ' ';
1602 nvalue.bv_val[1] = '\0';
1606 *normalized = nvalue;
1607 return LDAP_SUCCESS;
1611 directoryStringSubstringsMatch(
1616 struct berval *value,
1617 void *assertedValue )
1620 SubstringsAssertion *sub = assertedValue;
1621 struct berval left = *value;
1625 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1626 if ( sub->sa_initial.bv_len > left.bv_len ) {
1627 /* not enough left */
1632 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1633 sub->sa_initial.bv_len );
1639 left.bv_val += sub->sa_initial.bv_len;
1640 left.bv_len -= sub->sa_initial.bv_len;
1642 priorspace = ASCII_SPACE(
1643 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1646 if ( sub->sa_any ) {
1647 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1651 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1652 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1654 /* allow next space to match */
1661 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1665 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1666 /* not enough left */
1671 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1678 idx = p - left.bv_val;
1680 if ( idx >= left.bv_len ) {
1681 /* this shouldn't happen */
1688 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1689 /* not enough left */
1694 match = memcmp( left.bv_val,
1695 sub->sa_any[i].bv_val,
1696 sub->sa_any[i].bv_len );
1704 left.bv_val += sub->sa_any[i].bv_len;
1705 left.bv_len -= sub->sa_any[i].bv_len;
1707 priorspace = ASCII_SPACE(
1708 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1712 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1713 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1714 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1716 /* allow next space to match */
1721 if ( sub->sa_final.bv_len > left.bv_len ) {
1722 /* not enough left */
1727 match = memcmp( sub->sa_final.bv_val,
1728 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1729 sub->sa_final.bv_len );
1738 return LDAP_SUCCESS;
1741 #if defined(SLAPD_APPROX_INITIALS)
1742 # define SLAPD_APPROX_DELIMITER "._ "
1743 # define SLAPD_APPROX_WORDLEN 2
1745 # define SLAPD_APPROX_DELIMITER " "
1746 # define SLAPD_APPROX_WORDLEN 1
1755 struct berval *value,
1756 void *assertedValue )
1758 struct berval *nval, *assertv;
1759 char *val, **values, **words, *c;
1760 int i, count, len, nextchunk=0, nextavail=0;
1762 /* Yes, this is necessary */
1763 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1764 if( nval == NULL ) {
1766 return LDAP_SUCCESS;
1769 /* Yes, this is necessary */
1770 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1771 NULL, LDAP_UTF8_APPROX, NULL );
1772 if( assertv == NULL ) {
1775 return LDAP_SUCCESS;
1778 /* Isolate how many words there are */
1779 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1780 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1781 if ( c == NULL ) break;
1786 /* Get a phonetic copy of each word */
1787 words = (char **)ch_malloc( count * sizeof(char *) );
1788 values = (char **)ch_malloc( count * sizeof(char *) );
1789 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1791 values[i] = phonetic(c);
1794 /* Work through the asserted value's words, to see if at least some
1795 * of the words are there, in the same order. */
1797 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1798 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1803 #if defined(SLAPD_APPROX_INITIALS)
1804 else if( len == 1 ) {
1805 /* Single letter words need to at least match one word's initial */
1806 for( i=nextavail; i<count; i++ )
1807 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1814 /* Isolate the next word in the asserted value and phonetic it */
1815 assertv->bv_val[nextchunk+len] = '\0';
1816 val = phonetic( assertv->bv_val + nextchunk );
1818 /* See if this phonetic chunk is in the remaining words of *value */
1819 for( i=nextavail; i<count; i++ ){
1820 if( !strcmp( val, values[i] ) ){
1828 /* This chunk in the asserted value was NOT within the *value. */
1834 /* Go on to the next word in the asserted value */
1838 /* If some of the words were seen, call it a match */
1839 if( nextavail > 0 ) {
1846 /* Cleanup allocs */
1847 ber_bvfree( assertv );
1848 for( i=0; i<count; i++ ) {
1849 ch_free( values[i] );
1855 return LDAP_SUCCESS;
1864 struct berval *prefix,
1870 int i,j, len, wordcount, keycount=0;
1871 struct berval *newkeys;
1872 BerVarray keys=NULL;
1874 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1875 struct berval val = BER_BVNULL;
1876 /* Yes, this is necessary */
1877 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1878 assert( !BER_BVISNULL( &val ) );
1880 /* Isolate how many words there are. There will be a key for each */
1881 for( wordcount = 0, c = val.bv_val; *c; c++) {
1882 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1883 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1885 if (*c == '\0') break;
1889 /* Allocate/increase storage to account for new keys */
1890 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1891 * sizeof(struct berval) );
1892 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1893 if( keys ) ch_free( keys );
1896 /* Get a phonetic copy of each word */
1897 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1899 if( len < SLAPD_APPROX_WORDLEN ) continue;
1900 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1905 ber_memfree( val.bv_val );
1907 BER_BVZERO( &keys[keycount] );
1910 return LDAP_SUCCESS;
1919 struct berval *prefix,
1920 void * assertedValue,
1929 /* Yes, this is necessary */
1930 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1931 NULL, LDAP_UTF8_APPROX, NULL );
1932 if( val == NULL || BER_BVISNULL( val ) ) {
1933 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1934 BER_BVZERO( &keys[0] );
1937 return LDAP_SUCCESS;
1940 /* Isolate how many words there are. There will be a key for each */
1941 for( count = 0,c = val->bv_val; *c; c++) {
1942 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1943 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1945 if (*c == '\0') break;
1949 /* Allocate storage for new keys */
1950 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1952 /* Get a phonetic copy of each word */
1953 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1955 if( len < SLAPD_APPROX_WORDLEN ) continue;
1956 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1962 BER_BVZERO( &keys[count] );
1965 return LDAP_SUCCESS;
1968 /* Remove all spaces and '-' characters */
1970 telephoneNumberNormalize(
1975 struct berval *normalized,
1980 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1982 /* validator should have refused an empty string */
1983 assert( !BER_BVISEMPTY( val ) );
1985 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1987 for( p = val->bv_val; *p; p++ ) {
1988 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1994 normalized->bv_len = q - normalized->bv_val;
1996 if( BER_BVISEMPTY( normalized ) ) {
1997 slap_sl_free( normalized->bv_val, ctx );
1998 BER_BVZERO( normalized );
1999 return LDAP_INVALID_SYNTAX;
2002 return LDAP_SUCCESS;
2006 postalAddressValidate(
2010 struct berval bv = *in;
2013 for ( c = 0; c < in->bv_len; c++ ) {
2014 if ( in->bv_val[c] == '\\' ) {
2016 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2017 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2019 return LDAP_INVALID_SYNTAX;
2024 if ( in->bv_val[c] == '$' ) {
2025 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2026 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2027 return LDAP_INVALID_SYNTAX;
2029 bv.bv_val = &in->bv_val[c] + 1;
2033 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2034 return UTF8StringValidate( NULL, &bv );
2038 postalAddressNormalize(
2043 struct berval *normalized,
2046 BerVarray lines = NULL, nlines = NULL;
2048 int rc = LDAP_SUCCESS;
2049 MatchingRule *xmr = NULL;
2052 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2053 xmr = slap_schema.si_mr_caseIgnoreMatch;
2056 xmr = slap_schema.si_mr_caseExactMatch;
2059 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2060 if ( val->bv_val[c] == '$' ) {
2065 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2066 nlines = &lines[l + 2];
2068 lines[0].bv_val = val->bv_val;
2069 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2070 if ( val->bv_val[c] == '$' ) {
2071 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2073 lines[l].bv_val = &val->bv_val[c + 1];
2076 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2078 normalized->bv_len = l;
2080 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2081 /* NOTE: we directly normalize each line,
2082 * without unescaping the values, since the special
2083 * values '\24' ('$') and '\5C' ('\') are not affected
2084 * by normalization */
2085 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2086 if ( rc != LDAP_SUCCESS ) {
2087 rc = LDAP_INVALID_SYNTAX;
2091 normalized->bv_len += nlines[l].bv_len;
2094 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2096 p = normalized->bv_val;
2097 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2098 p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2104 assert( p - normalized->bv_val == normalized->bv_len );
2107 if ( nlines != NULL ) {
2108 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2109 slap_sl_free( nlines[l].bv_val, ctx );
2112 slap_sl_free( lines, ctx );
2123 struct berval val = *in;
2125 if( BER_BVISEMPTY( &val ) ) {
2126 /* disallow empty strings */
2127 return LDAP_INVALID_SYNTAX;
2130 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2131 if ( val.bv_len == 1 ) {
2132 return LDAP_SUCCESS;
2135 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2142 while ( OID_LEADCHAR( val.bv_val[0] )) {
2146 if ( val.bv_len == 0 ) {
2147 return LDAP_SUCCESS;
2151 if( !OID_SEPARATOR( val.bv_val[0] )) {
2159 return LDAP_INVALID_SYNTAX;
2168 struct berval val = *in;
2170 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2172 if ( val.bv_val[0] == '-' ) {
2176 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2177 return LDAP_INVALID_SYNTAX;
2180 if( val.bv_val[0] == '0' ) { /* "-0" */
2181 return LDAP_INVALID_SYNTAX;
2184 } else if ( val.bv_val[0] == '0' ) {
2185 if( val.bv_len > 1 ) { /* "0<more>" */
2186 return LDAP_INVALID_SYNTAX;
2189 return LDAP_SUCCESS;
2192 for( i=0; i < val.bv_len; i++ ) {
2193 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2194 return LDAP_INVALID_SYNTAX;
2198 return LDAP_SUCCESS;
2207 struct berval *value,
2208 void *assertedValue )
2210 struct berval *asserted = (struct berval *) assertedValue;
2211 int vsign = 1, asign = 1; /* default sign = '+' */
2216 if( v.bv_val[0] == '-' ) {
2222 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2225 if( a.bv_val[0] == '-' ) {
2231 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2233 match = vsign - asign;
2235 match = ( v.bv_len != a.bv_len
2236 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2237 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2238 if( vsign < 0 ) match = -match;
2242 return LDAP_SUCCESS;
2245 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2246 #define INDEX_INTLEN_CHOP 7
2247 #define INDEX_INTLEN_CHOPBYTES 3
2257 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2258 * two's complement value (sign-extended or chopped as needed),
2259 * however the top <number of exponent-bytes + 1> bits of first byte
2260 * above is the inverse sign. The next bit is the sign as delimiter.
2262 ber_slen_t k = index_intlen_strlen;
2264 unsigned signmask = ~0x7fU;
2265 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2266 struct berval val = *in, itmp = *tmp;
2268 if ( val.bv_val[0] != '-' ) {
2273 /* Chop least significant digits, increase length instead */
2274 if ( val.bv_len > (ber_len_t) k ) {
2275 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2276 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2277 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2280 if ( lutil_str2bin( &val, &itmp, ctx )) {
2281 return LDAP_INVALID_SYNTAX;
2284 /* Omit leading sign byte */
2285 if ( itmp.bv_val[0] == neg ) {
2290 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2292 assert( chop == 0 );
2293 memset( key->bv_val, neg, k ); /* sign-extend */
2294 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2295 lenp = lenbuf + sizeof(lenbuf);
2296 chop = - (ber_len_t) k;
2298 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2300 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2301 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2302 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2303 k = (lenbuf + sizeof(lenbuf)) - lenp;
2304 if ( k > (ber_slen_t) index_intlen )
2306 memcpy( key->bv_val, lenp, k );
2307 itmp.bv_len = index_intlen - k;
2309 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2310 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2314 /* Index generation function */
2321 struct berval *prefix,
2331 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2333 /* count the values and find max needed length */
2335 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2336 if ( vlen < values[i].bv_len )
2337 vlen = values[i].bv_len;
2339 if ( vlen > maxstrlen )
2342 /* we should have at least one value at this point */
2345 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2346 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2347 keys[i].bv_len = index_intlen;
2348 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2351 keys[i].bv_val = NULL;
2353 if ( vlen > sizeof(ibuf) ) {
2354 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2358 itmp.bv_len = sizeof(ibuf);
2360 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2361 if ( itmp.bv_val != ibuf ) {
2362 itmp.bv_len = values[i].bv_len;
2363 if ( itmp.bv_len <= sizeof(ibuf) )
2364 itmp.bv_len = sizeof(ibuf);
2365 else if ( itmp.bv_len > maxstrlen )
2366 itmp.bv_len = maxstrlen;
2368 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2374 if ( itmp.bv_val != ibuf ) {
2375 slap_sl_free( itmp.bv_val, ctx );
2380 /* Index generation function */
2387 struct berval *prefix,
2388 void * assertedValue,
2395 struct berval *value;
2398 value = (struct berval *) assertedValue;
2400 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2402 keys[0].bv_len = index_intlen;
2403 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2405 keys[1].bv_val = NULL;
2407 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2408 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2409 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2410 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2413 iv.bv_len = sizeof(ibuf);
2416 rc = integerVal2Key( value, keys, &iv, ctx );
2420 if ( iv.bv_val != ibuf ) {
2421 slap_sl_free( iv.bv_val, ctx );
2427 countryStringValidate(
2429 struct berval *val )
2431 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2433 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2434 return LDAP_INVALID_SYNTAX;
2436 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2437 return LDAP_INVALID_SYNTAX;
2440 return LDAP_SUCCESS;
2444 printableStringValidate(
2446 struct berval *val )
2450 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2452 for(i=0; i < val->bv_len; i++) {
2453 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2454 return LDAP_INVALID_SYNTAX;
2458 return LDAP_SUCCESS;
2462 printablesStringValidate(
2464 struct berval *val )
2468 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2470 for(i=0,len=0; i < val->bv_len; i++) {
2471 int c = val->bv_val[i];
2475 return LDAP_INVALID_SYNTAX;
2479 } else if ( SLAP_PRINTABLE(c) ) {
2482 return LDAP_INVALID_SYNTAX;
2487 return LDAP_INVALID_SYNTAX;
2490 return LDAP_SUCCESS;
2496 struct berval *val )
2500 for(i=0; i < val->bv_len; i++) {
2501 if( !LDAP_ASCII(val->bv_val[i]) ) {
2502 return LDAP_INVALID_SYNTAX;
2506 return LDAP_SUCCESS;
2515 struct berval *normalized,
2519 int casefold = !SLAP_MR_ASSOCIATED( mr,
2520 slap_schema.si_mr_caseExactIA5Match );
2522 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2526 /* Ignore initial whitespace */
2527 while ( ASCII_SPACE( *p ) ) p++;
2529 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2530 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2531 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2532 normalized->bv_val[normalized->bv_len] = '\0';
2534 p = q = normalized->bv_val;
2537 if ( ASCII_SPACE( *p ) ) {
2540 /* Ignore the extra whitespace */
2541 while ( ASCII_SPACE( *p ) ) {
2545 } else if ( casefold ) {
2546 /* Most IA5 rules require casefolding */
2547 *q++ = TOLOWER(*p); p++;
2554 assert( normalized->bv_val <= p );
2558 * If the string ended in space, backup the pointer one
2559 * position. One is enough because the above loop collapsed
2560 * all whitespace to a single space.
2562 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2564 /* null terminate */
2567 normalized->bv_len = q - normalized->bv_val;
2569 return LDAP_SUCCESS;
2578 if( in->bv_len != 36 ) {
2579 return LDAP_INVALID_SYNTAX;
2582 for( i=0; i<36; i++ ) {
2588 if( in->bv_val[i] != '-' ) {
2589 return LDAP_INVALID_SYNTAX;
2593 if( !ASCII_HEX( in->bv_val[i]) ) {
2594 return LDAP_INVALID_SYNTAX;
2599 return LDAP_SUCCESS;
2610 int rc=LDAP_INVALID_SYNTAX;
2612 assert( in != NULL );
2613 assert( out != NULL );
2615 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2618 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2620 for( i=0; i<36; i++ ) {
2626 if( in->bv_val[i] != '-' ) {
2629 out->bv_val[i] = '-';
2633 if( !ASCII_HEX( in->bv_val[i]) ) {
2636 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2641 out->bv_val[ out->bv_len ] = '\0';
2645 slap_sl_free( out->bv_val, ctx );
2658 struct berval *normalized,
2661 unsigned char octet = '\0';
2665 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2666 /* NOTE: must be a normalized UUID */
2667 assert( val->bv_len == 16 );
2669 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2670 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2671 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2672 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2674 return LDAP_SUCCESS;
2677 normalized->bv_len = 16;
2678 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2680 for( i=0, j=0; i<36; i++ ) {
2681 unsigned char nibble;
2682 if( val->bv_val[i] == '-' ) {
2685 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2686 nibble = val->bv_val[i] - '0';
2688 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2689 nibble = val->bv_val[i] - ('a'-10);
2691 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2692 nibble = val->bv_val[i] - ('A'-10);
2695 slap_sl_free( normalized->bv_val, ctx );
2696 return LDAP_INVALID_SYNTAX;
2701 normalized->bv_val[j>>1] = octet;
2703 octet = nibble << 4;
2708 normalized->bv_val[normalized->bv_len] = 0;
2709 return LDAP_SUCCESS;
2715 numericStringValidate(
2721 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2723 for(i=0; i < in->bv_len; i++) {
2724 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2725 return LDAP_INVALID_SYNTAX;
2729 return LDAP_SUCCESS;
2733 numericStringNormalize(
2738 struct berval *normalized,
2741 /* removal all spaces */
2744 assert( !BER_BVISEMPTY( val ) );
2746 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2749 q = normalized->bv_val;
2752 if ( ASCII_SPACE( *p ) ) {
2753 /* Ignore whitespace */
2760 /* we should have copied no more than is in val */
2761 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2763 /* null terminate */
2766 normalized->bv_len = q - normalized->bv_val;
2768 if( BER_BVISEMPTY( normalized ) ) {
2769 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2770 normalized->bv_val[0] = ' ';
2771 normalized->bv_val[1] = '\0';
2772 normalized->bv_len = 1;
2775 return LDAP_SUCCESS;
2779 * Integer conversion macros that will use the largest available
2782 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2783 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2784 # define SLAP_LONG long long
2786 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2787 # define SLAP_LONG long
2788 #endif /* HAVE_STRTOLL ... */
2796 struct berval *value,
2797 void *assertedValue )
2799 SLAP_LONG lValue, lAssertedValue;
2802 /* safe to assume integers are NUL terminated? */
2803 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2804 if( errno == ERANGE )
2806 return LDAP_CONSTRAINT_VIOLATION;
2809 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2811 if( errno == ERANGE )
2813 return LDAP_CONSTRAINT_VIOLATION;
2816 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2817 return LDAP_SUCCESS;
2826 struct berval *value,
2827 void *assertedValue )
2829 SLAP_LONG lValue, lAssertedValue;
2832 /* safe to assume integers are NUL terminated? */
2833 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2834 if( errno == ERANGE )
2836 return LDAP_CONSTRAINT_VIOLATION;
2839 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2841 if( errno == ERANGE )
2843 return LDAP_CONSTRAINT_VIOLATION;
2846 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2847 return LDAP_SUCCESS;
2851 checkNum( struct berval *in, struct berval *out )
2853 /* parse serialNumber */
2858 out->bv_val = in->bv_val;
2861 if ( out->bv_val[0] == '-' ) {
2866 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
2867 first = out->bv_val[2];
2870 out->bv_len += STRLENOF("0x");
2871 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2872 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2875 } else if ( out->bv_val[0] == '\'' ) {
2876 first = out->bv_val[1];
2879 out->bv_len += STRLENOF("'");
2881 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2882 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2884 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
2887 out->bv_len += STRLENOF("'H");
2890 first = out->bv_val[0];
2891 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2892 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
2896 if ( !( out->bv_len > neg ) ) {
2900 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
2908 serialNumberAndIssuerCheck(
2916 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2918 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2919 /* Parse old format */
2920 is->bv_val = ber_bvchr( in, '$' );
2921 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2923 sn->bv_val = in->bv_val;
2924 sn->bv_len = is->bv_val - in->bv_val;
2927 is->bv_len = in->bv_len - (sn->bv_len + 1);
2929 /* eat leading zeros */
2930 for( n=0; n < (sn->bv_len-1); n++ ) {
2931 if( sn->bv_val[n] != '0' ) break;
2936 for( n=0; n < sn->bv_len; n++ ) {
2937 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2941 /* Parse GSER format */
2946 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
2950 struct berval x = *in;
2956 /* eat leading spaces */
2957 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
2961 /* should be at issuer or serialNumber NamedValue */
2962 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
2963 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
2966 x.bv_val += STRLENOF("issuer");
2967 x.bv_len -= STRLENOF("issuer");
2969 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2973 /* eat leading spaces */
2974 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
2978 /* For backward compatibility, this part is optional */
2979 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
2980 x.bv_val += STRLENOF("rdnSequence:");
2981 x.bv_len -= STRLENOF("rdnSequence:");
2984 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2988 is->bv_val = x.bv_val;
2991 for ( ; is->bv_len < x.bv_len; ) {
2992 if ( is->bv_val[is->bv_len] != '"' ) {
2996 if ( is->bv_val[is->bv_len+1] == '"' ) {
3003 x.bv_val += is->bv_len + 1;
3004 x.bv_len -= is->bv_len + 1;
3006 have |= HAVE_ISSUER;
3008 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3010 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3012 /* parse serialNumber */
3013 x.bv_val += STRLENOF("serialNumber");
3014 x.bv_len -= STRLENOF("serialNumber");
3016 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3020 /* eat leading spaces */
3021 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3025 if ( checkNum( &x, sn ) ) {
3026 return LDAP_INVALID_SYNTAX;
3029 x.bv_val += sn->bv_len;
3030 x.bv_len -= sn->bv_len;
3035 return LDAP_INVALID_SYNTAX;
3038 /* eat leading spaces */
3039 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3043 if ( have == HAVE_ALL ) {
3047 if ( x.bv_val[0] != ',' ) {
3048 return LDAP_INVALID_SYNTAX;
3055 /* should have no characters left... */
3056 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3058 if ( numdquotes == 0 ) {
3059 ber_dupbv_x( &ni, is, ctx );
3064 ni.bv_len = is->bv_len - numdquotes;
3065 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3066 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3067 if ( is->bv_val[src] == '"' ) {
3070 ni.bv_val[dst] = is->bv_val[src];
3072 ni.bv_val[dst] = '\0';
3082 serialNumberAndIssuerValidate(
3087 struct berval sn, i;
3089 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3092 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3097 /* validate DN -- doesn't handle double dquote */
3098 rc = dnValidate( NULL, &i );
3100 rc = LDAP_INVALID_SYNTAX;
3103 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3104 slap_sl_free( i.bv_val, NULL );
3107 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3108 in->bv_val, rc, 0 );
3115 serialNumberAndIssuerPretty(
3122 struct berval sn, i, ni = BER_BVNULL;
3125 assert( in != NULL );
3126 assert( out != NULL );
3130 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3133 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3138 rc = dnPretty( syntax, &i, &ni, ctx );
3140 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3141 slap_sl_free( i.bv_val, ctx );
3145 rc = LDAP_INVALID_SYNTAX;
3149 /* make room from sn + "$" */
3150 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3151 + sn.bv_len + ni.bv_len;
3152 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3154 if ( out->bv_val == NULL ) {
3161 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3162 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3163 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3164 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3165 p = lutil_strcopy( p, /*{*/ "\" }" );
3167 assert( p - out->bv_val == out->bv_len );
3170 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3171 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3173 slap_sl_free( ni.bv_val, ctx );
3175 return LDAP_SUCCESS;
3185 /* Use hex format. '123456789abcdef'H */
3186 unsigned char *ptr, zero = '\0';
3190 ber_len_t len, nlen;
3192 assert( in != NULL );
3193 assert( !BER_BVISNULL( in ) );
3194 assert( out != NULL );
3195 assert( !BER_BVISNULL( out ) );
3197 ptr = (unsigned char *)in->bv_val;
3200 /* Check for minimal encodings */
3202 if ( ptr[0] & 0x80 ) {
3203 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3207 } else if ( ptr[0] == 0 ) {
3208 if ( !( ptr[1] & 0x80 ) ) {
3215 } else if ( len == 0 ) {
3216 /* FIXME: this should not be possible,
3217 * since a value of zero would have length 1 */
3222 first = !( ptr[0] & 0xf0U );
3223 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3224 if ( nlen >= out->bv_len ) {
3225 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3231 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3235 for ( ; i < len; i++ ) {
3236 sprintf( sptr, "%02X", ptr[i] );
3243 assert( sptr - out->bv_val == nlen );
3250 #define SLAP_SN_BUFLEN (64)
3253 * This routine is called by certificateExactNormalize when
3254 * certificateExactNormalize receives a search string instead of
3255 * a certificate. This routine checks if the search value is valid
3256 * and then returns the normalized value
3259 serialNumberAndIssuerNormalize(
3267 struct berval sn, sn2, sn3, i, ni;
3268 char sbuf2[SLAP_SN_BUFLEN];
3269 char sbuf3[SLAP_SN_BUFLEN];
3273 assert( in != NULL );
3274 assert( out != NULL );
3276 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3279 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3284 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3286 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3287 slap_sl_free( i.bv_val, ctx );
3291 return LDAP_INVALID_SYNTAX;
3294 /* Convert sn to canonical hex */
3296 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3297 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3299 sn2.bv_len = sn.bv_len;
3300 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3301 rc = LDAP_INVALID_SYNTAX;
3306 sn3.bv_len = sizeof(sbuf3);
3307 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3308 rc = LDAP_INVALID_SYNTAX;
3312 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3313 + sn3.bv_len + ni.bv_len;
3314 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3316 if ( out->bv_val == NULL ) {
3324 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3325 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3326 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3327 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3328 p = lutil_strcopy( p, /*{*/ "\" }" );
3330 assert( p - out->bv_val == out->bv_len );
3333 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3334 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3336 if ( sn2.bv_val != sbuf2 ) {
3337 slap_sl_free( sn2.bv_val, ctx );
3340 if ( sn3.bv_val != sbuf3 ) {
3341 slap_sl_free( sn3.bv_val, ctx );
3344 slap_sl_free( ni.bv_val, ctx );
3350 certificateExactNormalize(
3355 struct berval *normalized,
3358 BerElementBuffer berbuf;
3359 BerElement *ber = (BerElement *)&berbuf;
3363 char serialbuf2[SLAP_SN_BUFLEN];
3364 struct berval sn, sn2 = BER_BVNULL;
3365 struct berval issuer_dn = BER_BVNULL, bvdn;
3367 int rc = LDAP_INVALID_SYNTAX;
3369 assert( val != NULL );
3371 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3372 val->bv_val, val->bv_len, 0 );
3374 if ( BER_BVISEMPTY( val ) ) goto done;
3376 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3377 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3380 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3382 ber_init2( ber, val, LBER_USE_DER );
3383 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3384 tag = ber_skip_tag( ber, &len ); /* Sequence */
3385 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3386 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3387 tag = ber_skip_tag( ber, &len );
3388 tag = ber_get_int( ber, &i ); /* version */
3391 /* NOTE: move the test here from certificateValidate,
3392 * so that we can validate certs with serial longer
3393 * than sizeof(ber_int_t) */
3394 tag = ber_skip_tag( ber, &len ); /* serial */
3396 sn.bv_val = (char *)ber->ber_ptr;
3397 sn2.bv_val = serialbuf2;
3398 sn2.bv_len = sizeof(serialbuf2);
3399 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3400 rc = LDAP_INVALID_SYNTAX;
3403 ber_skip_data( ber, len );
3405 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3406 ber_skip_data( ber, len );
3407 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3408 len = ber_ptrlen( ber );
3409 bvdn.bv_val = val->bv_val + len;
3410 bvdn.bv_len = val->bv_len - len;
3412 rc = dnX509normalize( &bvdn, &issuer_dn );
3413 if ( rc != LDAP_SUCCESS ) goto done;
3415 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3416 + sn2.bv_len + issuer_dn.bv_len;
3417 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3419 p = normalized->bv_val;
3421 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3422 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3423 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3424 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3425 p = lutil_strcopy( p, /*{*/ "\" }" );
3430 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3431 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3433 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3434 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3439 /* X.509 PKI certificateList stuff */
3441 checkTime( struct berval *in, struct berval *out )
3444 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3447 assert( in != NULL );
3448 assert( !BER_BVISNULL( in ) );
3449 assert( !BER_BVISEMPTY( in ) );
3451 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3455 if ( out != NULL ) {
3456 assert( !BER_BVISNULL( out ) );
3457 assert( out->bv_len >= sizeof( buf ) );
3458 bv.bv_val = out->bv_val;
3464 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3465 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3468 if ( in->bv_val[i] != 'Z' ) {
3473 if ( i != in->bv_len ) {
3477 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3478 lutil_strncopy( bv.bv_val, in->bv_val, i );
3481 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3482 char *p = bv.bv_val;
3483 if ( in->bv_val[0] < '7' ) {
3484 p = lutil_strcopy( p, "20" );
3487 p = lutil_strcopy( p, "19" );
3489 lutil_strncopy( p, in->bv_val, i );
3496 i = generalizedTimeValidate( NULL, &bv );
3497 if ( i == LDAP_SUCCESS && out != NULL ) {
3498 out->bv_len = bv.bv_len;
3501 return i != LDAP_SUCCESS;
3505 issuerAndThisUpdateCheck(
3512 struct berval x = *in;
3513 struct berval ni = BER_BVNULL;
3514 /* Parse GSER format */
3518 HAVE_THISUPDATE = 0x2,
3519 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3523 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3525 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3526 return LDAP_INVALID_SYNTAX;
3530 x.bv_len -= STRLENOF("{}");
3533 /* eat leading spaces */
3534 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3538 /* should be at issuer or thisUpdate */
3539 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3540 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3543 x.bv_val += STRLENOF("issuer");
3544 x.bv_len -= STRLENOF("issuer");
3546 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3550 /* eat leading spaces */
3551 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3555 /* For backward compatibility, this part is optional */
3556 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3557 return LDAP_INVALID_SYNTAX;
3559 x.bv_val += STRLENOF("rdnSequence:");
3560 x.bv_len -= STRLENOF("rdnSequence:");
3562 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3566 is->bv_val = x.bv_val;
3569 for ( ; is->bv_len < x.bv_len; ) {
3570 if ( is->bv_val[is->bv_len] != '"' ) {
3574 if ( is->bv_val[is->bv_len+1] == '"' ) {
3581 x.bv_val += is->bv_len + 1;
3582 x.bv_len -= is->bv_len + 1;
3584 have |= HAVE_ISSUER;
3586 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3588 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3590 /* parse thisUpdate */
3591 x.bv_val += STRLENOF("thisUpdate");
3592 x.bv_len -= STRLENOF("thisUpdate");
3594 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3598 /* eat leading spaces */
3599 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3603 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3607 tu->bv_val = x.bv_val;
3610 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3611 if ( tu->bv_val[tu->bv_len] == '"' ) {
3615 x.bv_val += tu->bv_len + 1;
3616 x.bv_len -= tu->bv_len + 1;
3618 have |= HAVE_THISUPDATE;
3621 return LDAP_INVALID_SYNTAX;
3624 /* eat leading spaces */
3625 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3629 if ( have == HAVE_ALL ) {
3633 if ( x.bv_val[0] != ',' ) {
3634 return LDAP_INVALID_SYNTAX;
3641 /* should have no characters left... */
3642 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3644 if ( numdquotes == 0 ) {
3645 ber_dupbv_x( &ni, is, ctx );
3650 ni.bv_len = is->bv_len - numdquotes;
3651 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3652 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3653 if ( is->bv_val[src] == '"' ) {
3656 ni.bv_val[dst] = is->bv_val[src];
3658 ni.bv_val[dst] = '\0';
3667 issuerAndThisUpdateValidate(
3672 struct berval i, tu;
3674 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3677 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3682 /* validate DN -- doesn't handle double dquote */
3683 rc = dnValidate( NULL, &i );
3685 rc = LDAP_INVALID_SYNTAX;
3687 } else if ( checkTime( &tu, NULL ) ) {
3688 rc = LDAP_INVALID_SYNTAX;
3691 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3692 slap_sl_free( i.bv_val, NULL );
3695 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3696 in->bv_val, rc, 0 );
3703 issuerAndThisUpdatePretty(
3710 struct berval i, tu, ni = BER_BVNULL;
3713 assert( in != NULL );
3714 assert( out != NULL );
3718 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3721 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3726 rc = dnPretty( syntax, &i, &ni, ctx );
3728 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3729 slap_sl_free( i.bv_val, ctx );
3732 if ( rc || checkTime( &tu, NULL ) ) {
3733 rc = LDAP_INVALID_SYNTAX;
3738 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3739 + ni.bv_len + tu.bv_len;
3740 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3742 if ( out->bv_val == NULL ) {
3749 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3750 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3751 p = lutil_strcopy( p, "\", thisUpdate \"" );
3752 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3753 p = lutil_strcopy( p, /*{*/ "\" }" );
3755 assert( p - out->bv_val == out->bv_len );
3758 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3759 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3761 slap_sl_free( ni.bv_val, ctx );
3767 issuerAndThisUpdateNormalize(
3775 struct berval i, ni, tu, tu2;
3776 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3780 assert( in != NULL );
3781 assert( out != NULL );
3783 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3786 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3791 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3793 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3794 slap_sl_free( i.bv_val, ctx );
3798 tu2.bv_len = sizeof( sbuf );
3799 if ( rc || checkTime( &tu, &tu2 ) ) {
3800 return LDAP_INVALID_SYNTAX;
3803 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3804 + ni.bv_len + tu2.bv_len;
3805 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3807 if ( out->bv_val == NULL ) {
3815 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3816 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3817 p = lutil_strcopy( p, "\", thisUpdate \"" );
3818 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3819 p = lutil_strcopy( p, /*{*/ "\" }" );
3821 assert( p - out->bv_val == out->bv_len );
3824 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3825 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3827 slap_sl_free( ni.bv_val, ctx );
3833 certificateListExactNormalize(
3838 struct berval *normalized,
3841 BerElementBuffer berbuf;
3842 BerElement *ber = (BerElement *)&berbuf;
3846 struct berval issuer_dn = BER_BVNULL, bvdn,
3848 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3849 int rc = LDAP_INVALID_SYNTAX;
3851 assert( val != NULL );
3853 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
3854 val->bv_val, val->bv_len, 0 );
3856 if ( BER_BVISEMPTY( val ) ) goto done;
3858 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3859 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
3862 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3864 ber_init2( ber, val, LBER_USE_DER );
3865 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
3866 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3867 tag = ber_skip_tag( ber, &len ); /* Sequence */
3868 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3869 tag = ber_peek_tag( ber, &len );
3870 /* Optional version */
3871 if ( tag == LBER_INTEGER ) {
3872 tag = ber_get_int( ber, &version );
3873 assert( tag == LBER_INTEGER );
3874 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
3876 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
3877 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3878 ber_skip_data( ber, len );
3880 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3881 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3882 len = ber_ptrlen( ber );
3883 bvdn.bv_val = val->bv_val + len;
3884 bvdn.bv_len = val->bv_len - len;
3885 tag = ber_skip_tag( ber, &len );
3886 ber_skip_data( ber, len );
3888 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
3889 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
3890 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
3891 bvtu.bv_val = (char *)ber->ber_ptr;
3894 rc = dnX509normalize( &bvdn, &issuer_dn );
3895 if ( rc != LDAP_SUCCESS ) goto done;
3897 thisUpdate.bv_val = tubuf;
3898 thisUpdate.bv_len = sizeof(tubuf);
3899 if ( checkTime( &bvtu, &thisUpdate ) ) {
3900 rc = LDAP_INVALID_SYNTAX;
3904 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3905 + issuer_dn.bv_len + thisUpdate.bv_len;
3906 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3908 p = normalized->bv_val;
3910 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
3911 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3912 p = lutil_strcopy( p, "\", thisUpdate \"" );
3913 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
3914 p = lutil_strcopy( p, /*{*/ "\" }" );
3919 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
3920 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3922 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3934 assert( in != NULL );
3935 assert( !BER_BVISNULL( in ) );
3937 for ( i = 0; i < in->bv_len; i++ ) {
3938 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3939 return LDAP_INVALID_SYNTAX;
3943 return LDAP_SUCCESS;
3946 /* Normalize a SID as used inside a CSN:
3947 * three-digit numeric string */
3954 struct berval *normalized,
3959 assert( val != NULL );
3960 assert( normalized != NULL );
3962 ber_dupbv_x( normalized, val, ctx );
3964 for ( i = 0; i < normalized->bv_len; i++ ) {
3965 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3966 ber_memfree_x( normalized->bv_val, ctx );
3967 BER_BVZERO( normalized );
3968 return LDAP_INVALID_SYNTAX;
3971 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3974 return LDAP_SUCCESS;
3982 assert( in != NULL );
3983 assert( !BER_BVISNULL( in ) );
3985 if ( in->bv_len != 3 ) {
3986 return LDAP_INVALID_SYNTAX;
3989 return hexValidate( NULL, in );
3992 /* Normalize a SID as used inside a CSN:
3993 * three-digit numeric string */
4000 struct berval *normalized,
4003 if ( val->bv_len != 3 ) {
4004 return LDAP_INVALID_SYNTAX;
4007 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4017 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4020 /* Normalize a SID as used inside a CSN, either as-is
4021 * (assertion value) or extracted from the CSN
4022 * (attribute value) */
4029 struct berval *normalized,
4037 if ( BER_BVISEMPTY( val ) ) {
4038 return LDAP_INVALID_SYNTAX;
4041 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4042 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4045 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4047 ptr = ber_bvchr( val, '#' );
4048 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4049 return LDAP_INVALID_SYNTAX;
4052 bv.bv_val = ptr + 1;
4053 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4055 ptr = ber_bvchr( &bv, '#' );
4056 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4057 return LDAP_INVALID_SYNTAX;
4060 bv.bv_val = ptr + 1;
4061 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4063 ptr = ber_bvchr( &bv, '#' );
4064 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4065 return LDAP_INVALID_SYNTAX;
4068 bv.bv_len = ptr - bv.bv_val;
4070 if ( bv.bv_len == 2 ) {
4071 /* OpenLDAP 2.3 SID */
4073 buf[ 1 ] = bv.bv_val[ 0 ];
4074 buf[ 2 ] = bv.bv_val[ 1 ];
4081 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4093 assert( in != NULL );
4094 assert( !BER_BVISNULL( in ) );
4096 if ( BER_BVISEMPTY( in ) ) {
4097 return LDAP_INVALID_SYNTAX;
4102 ptr = ber_bvchr( &bv, '#' );
4103 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
4104 return LDAP_INVALID_SYNTAX;
4107 bv.bv_len = ptr - bv.bv_val;
4108 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4109 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4111 return LDAP_INVALID_SYNTAX;
4114 rc = generalizedTimeValidate( NULL, &bv );
4115 if ( rc != LDAP_SUCCESS ) {
4119 bv.bv_val = ptr + 1;
4120 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4122 ptr = ber_bvchr( &bv, '#' );
4123 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
4124 return LDAP_INVALID_SYNTAX;
4127 bv.bv_len = ptr - bv.bv_val;
4128 if ( bv.bv_len != 6 ) {
4129 return LDAP_INVALID_SYNTAX;
4132 rc = hexValidate( NULL, &bv );
4133 if ( rc != LDAP_SUCCESS ) {
4137 bv.bv_val = ptr + 1;
4138 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4140 ptr = ber_bvchr( &bv, '#' );
4141 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
4142 return LDAP_INVALID_SYNTAX;
4145 bv.bv_len = ptr - bv.bv_val;
4146 if ( bv.bv_len == 2 ) {
4147 /* tolerate old 2-digit replica-id */
4148 rc = hexValidate( NULL, &bv );
4151 rc = sidValidate( NULL, &bv );
4153 if ( rc != LDAP_SUCCESS ) {
4157 bv.bv_val = ptr + 1;
4158 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4160 if ( bv.bv_len != 6 ) {
4161 return LDAP_INVALID_SYNTAX;
4164 return hexValidate( NULL, &bv );
4167 /* Normalize a CSN in OpenLDAP 2.1 format */
4174 struct berval *normalized,
4177 struct berval gt, cnt, sid, mod;
4179 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4183 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4184 assert( !BER_BVISEMPTY( val ) );
4188 ptr = ber_bvchr( >, '#' );
4189 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
4190 return LDAP_INVALID_SYNTAX;
4193 gt.bv_len = ptr - gt.bv_val;
4194 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
4195 return LDAP_INVALID_SYNTAX;
4198 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
4199 return LDAP_INVALID_SYNTAX;
4202 cnt.bv_val = ptr + 1;
4203 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
4205 ptr = ber_bvchr( &cnt, '#' );
4206 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4207 return LDAP_INVALID_SYNTAX;
4210 cnt.bv_len = ptr - cnt.bv_val;
4211 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
4212 return LDAP_INVALID_SYNTAX;
4215 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
4216 return LDAP_INVALID_SYNTAX;
4219 cnt.bv_val += STRLENOF( "0x" );
4220 cnt.bv_len -= STRLENOF( "0x" );
4222 sid.bv_val = ptr + 1;
4223 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
4225 ptr = ber_bvchr( &sid, '#' );
4226 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4227 return LDAP_INVALID_SYNTAX;
4230 sid.bv_len = ptr - sid.bv_val;
4231 if ( sid.bv_len != STRLENOF( "0" ) ) {
4232 return LDAP_INVALID_SYNTAX;
4235 mod.bv_val = ptr + 1;
4236 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
4237 if ( mod.bv_len != STRLENOF( "0000" ) ) {
4238 return LDAP_INVALID_SYNTAX;
4241 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
4245 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
4246 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
4248 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
4250 ptr = lutil_strcopy( ptr, ".000000Z#00" );
4251 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
4255 *ptr++ = sid.bv_val[ 0 ];
4259 for ( i = 0; i < mod.bv_len; i++ ) {
4260 *ptr++ = TOLOWER( mod.bv_val[ i ] );
4264 assert( ptr - bv.bv_val == bv.bv_len );
4266 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
4267 return LDAP_INVALID_SYNTAX;
4270 ber_dupbv_x( normalized, &bv, ctx );
4272 return LDAP_SUCCESS;
4275 /* Normalize a CSN in OpenLDAP 2.3 format */
4282 struct berval *normalized,
4285 struct berval gt, cnt, sid, mod;
4287 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4291 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4292 assert( !BER_BVISEMPTY( val ) );
4296 ptr = ber_bvchr( >, '#' );
4297 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
4298 return LDAP_INVALID_SYNTAX;
4301 gt.bv_len = ptr - gt.bv_val;
4302 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
4303 return LDAP_INVALID_SYNTAX;
4306 cnt.bv_val = ptr + 1;
4307 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
4309 ptr = ber_bvchr( &cnt, '#' );
4310 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4311 return LDAP_INVALID_SYNTAX;
4314 cnt.bv_len = ptr - cnt.bv_val;
4315 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
4316 return LDAP_INVALID_SYNTAX;
4319 sid.bv_val = ptr + 1;
4320 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
4322 ptr = ber_bvchr( &sid, '#' );
4323 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4324 return LDAP_INVALID_SYNTAX;
4327 sid.bv_len = ptr - sid.bv_val;
4328 if ( sid.bv_len != STRLENOF( "00" ) ) {
4329 return LDAP_INVALID_SYNTAX;
4332 mod.bv_val = ptr + 1;
4333 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
4334 if ( mod.bv_len != STRLENOF( "000000" ) ) {
4335 return LDAP_INVALID_SYNTAX;
4338 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
4342 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
4343 ptr = lutil_strcopy( ptr, ".000000Z#" );
4344 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
4347 for ( i = 0; i < sid.bv_len; i++ ) {
4348 *ptr++ = TOLOWER( sid.bv_val[ i ] );
4351 for ( i = 0; i < mod.bv_len; i++ ) {
4352 *ptr++ = TOLOWER( mod.bv_val[ i ] );
4356 assert( ptr - bv.bv_val == bv.bv_len );
4357 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
4358 return LDAP_INVALID_SYNTAX;
4361 ber_dupbv_x( normalized, &bv, ctx );
4363 return LDAP_SUCCESS;
4366 /* Normalize a CSN */
4373 struct berval *normalized,
4376 struct berval cnt, sid, mod;
4380 assert( val != NULL );
4381 assert( normalized != NULL );
4383 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4385 if ( BER_BVISEMPTY( val ) ) {
4386 return LDAP_INVALID_SYNTAX;
4389 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
4390 /* Openldap <= 2.3 */
4392 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
4395 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
4398 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
4401 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
4402 return LDAP_INVALID_SYNTAX;
4405 ptr = ber_bvchr( val, '#' );
4406 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4407 return LDAP_INVALID_SYNTAX;
4410 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
4411 return LDAP_INVALID_SYNTAX;
4414 cnt.bv_val = ptr + 1;
4415 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
4417 ptr = ber_bvchr( &cnt, '#' );
4418 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4419 return LDAP_INVALID_SYNTAX;
4422 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
4423 return LDAP_INVALID_SYNTAX;
4426 sid.bv_val = ptr + 1;
4427 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
4429 ptr = ber_bvchr( &sid, '#' );
4430 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
4431 return LDAP_INVALID_SYNTAX;
4434 sid.bv_len = ptr - sid.bv_val;
4435 if ( sid.bv_len != STRLENOF( "000" ) ) {
4436 return LDAP_INVALID_SYNTAX;
4439 mod.bv_val = ptr + 1;
4440 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
4442 if ( mod.bv_len != STRLENOF( "000000" ) ) {
4443 return LDAP_INVALID_SYNTAX;
4446 ber_dupbv_x( normalized, val, ctx );
4448 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
4449 i < normalized->bv_len; i++ )
4451 /* assume it's already validated that's all hex digits */
4452 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4455 return LDAP_SUCCESS;
4465 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4468 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
4469 /* slight optimization - does not need the start parameter */
4470 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
4475 check_time_syntax (struct berval *val,
4478 struct berval *fraction)
4481 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
4482 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
4483 * GeneralizedTime supports leap seconds, UTCTime does not.
4485 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
4486 static const int mdays[2][12] = {
4487 /* non-leap years */
4488 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
4490 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
4493 int part, c, c1, c2, tzoffset, leapyear = 0;
4496 e = p + val->bv_len;
4498 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4499 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
4501 for (part = start; part < 7 && p < e; part++) {
4503 if (!ASCII_DIGIT(c1)) {
4508 return LDAP_INVALID_SYNTAX;
4511 if (!ASCII_DIGIT(c)) {
4512 return LDAP_INVALID_SYNTAX;
4514 c += c1 * 10 - '0' * 11;
4515 if ((part | 1) == 3) {
4518 return LDAP_INVALID_SYNTAX;
4521 if (c >= ceiling[part]) {
4522 if (! (c == 60 && part == 6 && start == 0))
4523 return LDAP_INVALID_SYNTAX;
4527 if (part < 5 + start) {
4528 return LDAP_INVALID_SYNTAX;
4530 for (; part < 9; part++) {
4534 /* leapyear check for the Gregorian calendar (year>1581) */
4535 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
4539 if (parts[3] >= mdays[leapyear][parts[2]]) {
4540 return LDAP_INVALID_SYNTAX;
4544 fraction->bv_val = p;
4545 fraction->bv_len = 0;
4546 if (p < e && (*p == '.' || *p == ',')) {
4548 while (++p < e && ASCII_DIGIT(*p)) {
4551 if (p - fraction->bv_val == 1) {
4552 return LDAP_INVALID_SYNTAX;
4554 for (end_num = p; end_num[-1] == '0'; --end_num) {
4557 c = end_num - fraction->bv_val;
4558 if (c != 1) fraction->bv_len = c;
4564 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4570 return LDAP_INVALID_SYNTAX;
4576 for (part = 7; part < 9 && p < e; part++) {
4578 if (!ASCII_DIGIT(c1)) {
4583 return LDAP_INVALID_SYNTAX;
4586 if (!ASCII_DIGIT(c2)) {
4587 return LDAP_INVALID_SYNTAX;
4589 parts[part] = c1 * 10 + c2 - '0' * 11;
4590 if (parts[part] >= ceiling[part]) {
4591 return LDAP_INVALID_SYNTAX;
4594 if (part < 8 + start) {
4595 return LDAP_INVALID_SYNTAX;
4598 if (tzoffset == '-') {
4599 /* negative offset to UTC, ie west of Greenwich */
4600 parts[4] += parts[7];
4601 parts[5] += parts[8];
4602 /* offset is just hhmm, no seconds */
4603 for (part = 6; --part >= 0; ) {
4607 c = mdays[leapyear][parts[2]];
4609 if (parts[part] >= c) {
4611 return LDAP_INVALID_SYNTAX;
4616 } else if (part != 5) {
4621 /* positive offset to UTC, ie east of Greenwich */
4622 parts[4] -= parts[7];
4623 parts[5] -= parts[8];
4624 for (part = 6; --part >= 0; ) {
4625 if (parts[part] < 0) {
4627 return LDAP_INVALID_SYNTAX;
4632 /* make first arg to % non-negative */
4633 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4638 } else if (part != 5) {
4645 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4648 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4655 struct berval *normalized )
4659 rc = check_time_syntax(val, 1, parts, NULL);
4660 if (rc != LDAP_SUCCESS) {
4664 normalized->bv_val = ch_malloc( 14 );
4665 if ( normalized->bv_val == NULL ) {
4666 return LBER_ERROR_MEMORY;
4669 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4670 parts[1], parts[2] + 1, parts[3] + 1,
4671 parts[4], parts[5], parts[6] );
4672 normalized->bv_len = 13;
4674 return LDAP_SUCCESS;
4684 return check_time_syntax(in, 1, parts, NULL);
4687 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4690 generalizedTimeValidate(
4695 struct berval fraction;
4696 return check_time_syntax(in, 0, parts, &fraction);
4700 generalizedTimeNormalize(
4705 struct berval *normalized,
4710 struct berval fraction;
4712 rc = check_time_syntax(val, 0, parts, &fraction);
4713 if (rc != LDAP_SUCCESS) {
4717 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4718 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4719 if ( BER_BVISNULL( normalized ) ) {
4720 return LBER_ERROR_MEMORY;
4723 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4724 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4725 parts[4], parts[5], parts[6] );
4726 if ( !BER_BVISEMPTY( &fraction ) ) {
4727 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4728 fraction.bv_val, fraction.bv_len );
4729 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4731 strcpy( normalized->bv_val + len-1, "Z" );
4732 normalized->bv_len = len;
4734 return LDAP_SUCCESS;
4738 generalizedTimeOrderingMatch(
4743 struct berval *value,
4744 void *assertedValue )
4746 struct berval *asserted = (struct berval *) assertedValue;
4747 ber_len_t v_len = value->bv_len;
4748 ber_len_t av_len = asserted->bv_len;
4750 /* ignore trailing 'Z' when comparing */
4751 int match = memcmp( value->bv_val, asserted->bv_val,
4752 (v_len < av_len ? v_len : av_len) - 1 );
4753 if ( match == 0 ) match = v_len - av_len;
4756 return LDAP_SUCCESS;
4759 /* Index generation function */
4760 int generalizedTimeIndexer(
4765 struct berval *prefix,
4773 BerValue bvtmp; /* 40 bit index */
4775 struct lutil_timet tt;
4777 bvtmp.bv_len = sizeof(tmp);
4779 for( i=0; values[i].bv_val != NULL; i++ ) {
4780 /* just count them */
4783 /* we should have at least one value at this point */
4786 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4788 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4789 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4790 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4791 /* Use 40 bits of time for key */
4792 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4793 lutil_tm2time( &tm, &tt );
4794 tmp[0] = tt.tt_gsec & 0xff;
4795 tmp[4] = tt.tt_sec & 0xff;
4797 tmp[3] = tt.tt_sec & 0xff;
4799 tmp[2] = tt.tt_sec & 0xff;
4801 tmp[1] = tt.tt_sec & 0xff;
4803 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4807 keys[j].bv_val = NULL;
4812 return LDAP_SUCCESS;
4815 /* Index generation function */
4816 int generalizedTimeFilter(
4821 struct berval *prefix,
4822 void * assertedValue,
4828 BerValue bvtmp; /* 40 bit index */
4829 BerValue *value = (BerValue *) assertedValue;
4831 struct lutil_timet tt;
4833 bvtmp.bv_len = sizeof(tmp);
4835 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4836 /* Use 40 bits of time for key */
4837 if ( value->bv_val && value->bv_len >= 10 &&
4838 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4840 lutil_tm2time( &tm, &tt );
4841 tmp[0] = tt.tt_gsec & 0xff;
4842 tmp[4] = tt.tt_sec & 0xff;
4844 tmp[3] = tt.tt_sec & 0xff;
4846 tmp[2] = tt.tt_sec & 0xff;
4848 tmp[1] = tt.tt_sec & 0xff;
4850 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4851 ber_dupbv_x(keys, &bvtmp, ctx );
4852 keys[1].bv_val = NULL;
4860 return LDAP_SUCCESS;
4864 deliveryMethodValidate(
4866 struct berval *val )
4869 #define LENOF(s) (sizeof(s)-1)
4870 struct berval tmp = *val;
4872 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4873 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4874 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4877 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4879 switch( tmp.bv_val[0] ) {
4882 if(( tmp.bv_len >= LENOF("any") ) &&
4883 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4885 tmp.bv_len -= LENOF("any");
4886 tmp.bv_val += LENOF("any");
4889 return LDAP_INVALID_SYNTAX;
4893 if(( tmp.bv_len >= LENOF("mhs") ) &&
4894 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4896 tmp.bv_len -= LENOF("mhs");
4897 tmp.bv_val += LENOF("mhs");
4900 return LDAP_INVALID_SYNTAX;
4904 if(( tmp.bv_len >= LENOF("physical") ) &&
4905 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4907 tmp.bv_len -= LENOF("physical");
4908 tmp.bv_val += LENOF("physical");
4911 return LDAP_INVALID_SYNTAX;
4914 case 'T': /* telex or teletex or telephone */
4915 if(( tmp.bv_len >= LENOF("telex") ) &&
4916 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4918 tmp.bv_len -= LENOF("telex");
4919 tmp.bv_val += LENOF("telex");
4922 if(( tmp.bv_len >= LENOF("teletex") ) &&
4923 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4925 tmp.bv_len -= LENOF("teletex");
4926 tmp.bv_val += LENOF("teletex");
4929 if(( tmp.bv_len >= LENOF("telephone") ) &&
4930 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4932 tmp.bv_len -= LENOF("telephone");
4933 tmp.bv_val += LENOF("telephone");
4936 return LDAP_INVALID_SYNTAX;
4939 case 'G': /* g3fax or g4fax */
4940 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4941 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4942 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4944 tmp.bv_len -= LENOF("g3fax");
4945 tmp.bv_val += LENOF("g3fax");
4948 return LDAP_INVALID_SYNTAX;
4952 if(( tmp.bv_len >= LENOF("ia5") ) &&
4953 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4955 tmp.bv_len -= LENOF("ia5");
4956 tmp.bv_val += LENOF("ia5");
4959 return LDAP_INVALID_SYNTAX;
4963 if(( tmp.bv_len >= LENOF("videotex") ) &&
4964 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4966 tmp.bv_len -= LENOF("videotex");
4967 tmp.bv_val += LENOF("videotex");
4970 return LDAP_INVALID_SYNTAX;
4973 return LDAP_INVALID_SYNTAX;
4976 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4978 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4982 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4986 return LDAP_INVALID_SYNTAX;
4988 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4997 nisNetgroupTripleValidate(
4999 struct berval *val )
5004 if ( BER_BVISEMPTY( val ) ) {
5005 return LDAP_INVALID_SYNTAX;
5008 p = (char *)val->bv_val;
5009 e = p + val->bv_len;
5011 if ( *p != '(' /*')'*/ ) {
5012 return LDAP_INVALID_SYNTAX;
5015 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5019 return LDAP_INVALID_SYNTAX;
5022 } else if ( !AD_CHAR( *p ) ) {
5023 return LDAP_INVALID_SYNTAX;
5027 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5028 return LDAP_INVALID_SYNTAX;
5034 return LDAP_INVALID_SYNTAX;
5037 return LDAP_SUCCESS;
5041 bootParameterValidate(
5043 struct berval *val )
5047 if ( BER_BVISEMPTY( val ) ) {
5048 return LDAP_INVALID_SYNTAX;
5051 p = (char *)val->bv_val;
5052 e = p + val->bv_len;
5055 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5056 if ( !AD_CHAR( *p ) ) {
5057 return LDAP_INVALID_SYNTAX;
5062 return LDAP_INVALID_SYNTAX;
5066 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5067 if ( !AD_CHAR( *p ) ) {
5068 return LDAP_INVALID_SYNTAX;
5073 return LDAP_INVALID_SYNTAX;
5077 for ( p++; p < e; p++ ) {
5078 if ( !SLAP_PRINTABLE( *p ) ) {
5079 return LDAP_INVALID_SYNTAX;
5083 return LDAP_SUCCESS;
5087 firstComponentNormalize(
5092 struct berval *normalized,
5099 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5100 ber_dupbv_x( normalized, val, ctx );
5101 return LDAP_SUCCESS;
5104 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5106 if( ! ( val->bv_val[0] == '(' /*')'*/
5107 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5108 && ! ( val->bv_val[0] == '{' /*'}'*/
5109 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5111 return LDAP_INVALID_SYNTAX;
5114 /* trim leading white space */
5116 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5122 /* grab next word */
5123 comp.bv_val = &val->bv_val[len];
5124 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5125 for( comp.bv_len = 0;
5126 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5132 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5133 rc = numericoidValidate( NULL, &comp );
5134 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5135 rc = integerValidate( NULL, &comp );
5137 rc = LDAP_INVALID_SYNTAX;
5141 if( rc == LDAP_SUCCESS ) {
5142 ber_dupbv_x( normalized, &comp, ctx );
5148 static char *country_gen_syn[] = {
5149 "1.3.6.1.4.1.1466.115.121.1.15",
5150 "1.3.6.1.4.1.1466.115.121.1.26",
5151 "1.3.6.1.4.1.1466.115.121.1.44",
5155 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
5156 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
5158 static slap_syntax_defs_rec syntax_defs[] = {
5159 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
5160 X_BINARY X_NOT_H_R ")",
5161 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
5162 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
5163 0, NULL, NULL, NULL},
5164 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
5165 0, NULL, NULL, NULL},
5166 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
5168 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5169 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
5171 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5172 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
5173 0, NULL, bitStringValidate, NULL },
5174 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
5175 0, NULL, booleanValidate, NULL},
5176 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
5177 X_BINARY X_NOT_H_R ")",
5178 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5179 NULL, certificateValidate, NULL},
5180 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
5181 X_BINARY X_NOT_H_R ")",
5182 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5183 NULL, certificateListValidate, NULL},
5184 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
5185 X_BINARY X_NOT_H_R ")",
5186 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5187 NULL, sequenceValidate, NULL},
5188 #if 0 /* need to go __after__ printableString */
5189 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
5190 0, "1.3.6.1.4.1.1466.115.121.1.44",
5191 countryStringValidate, NULL},
5193 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
5194 0, NULL, dnValidate, dnPretty},
5195 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
5196 0, NULL, rdnValidate, rdnPretty},
5197 #ifdef LDAP_COMP_MATCH
5198 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
5199 0, NULL, allComponentsValidate, NULL},
5200 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
5201 0, NULL, componentFilterValidate, NULL},
5203 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
5204 0, NULL, NULL, NULL},
5205 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
5206 0, NULL, deliveryMethodValidate, NULL},
5207 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
5208 0, NULL, UTF8StringValidate, NULL},
5209 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
5210 0, NULL, NULL, NULL},
5211 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
5212 0, NULL, NULL, NULL},
5213 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
5214 0, NULL, NULL, NULL},
5215 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
5216 0, NULL, NULL, NULL},
5217 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
5218 0, NULL, NULL, NULL},
5219 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
5220 0, NULL, printablesStringValidate, NULL},
5221 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
5222 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
5223 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
5224 0, NULL, generalizedTimeValidate, NULL},
5225 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
5226 0, NULL, NULL, NULL},
5227 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
5228 0, NULL, IA5StringValidate, NULL},
5229 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
5230 0, NULL, integerValidate, NULL},
5231 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
5232 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5233 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
5234 0, NULL, NULL, NULL},
5235 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
5236 0, NULL, NULL, NULL},
5237 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
5238 0, NULL, NULL, NULL},
5239 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
5240 0, NULL, NULL, NULL},
5241 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
5242 0, NULL, NULL, NULL},
5243 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
5244 0, NULL, nameUIDValidate, nameUIDPretty },
5245 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
5246 0, NULL, NULL, NULL},
5247 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
5248 0, NULL, numericStringValidate, NULL},
5249 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
5250 0, NULL, NULL, NULL},
5251 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
5252 0, NULL, numericoidValidate, NULL},
5253 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
5254 0, NULL, IA5StringValidate, NULL},
5255 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
5256 0, NULL, blobValidate, NULL},
5257 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
5258 0, NULL, postalAddressValidate, NULL},
5259 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
5260 0, NULL, NULL, NULL},
5261 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
5262 0, NULL, NULL, NULL},
5263 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
5264 0, NULL, printableStringValidate, NULL},
5265 /* moved here because now depends on Directory String, IA5 String
5266 * and Printable String */
5267 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
5268 0, country_gen_syn, countryStringValidate, NULL},
5269 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
5270 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
5271 0, NULL, subtreeSpecificationValidate, NULL},
5272 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
5273 X_BINARY X_NOT_H_R ")",
5274 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5275 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
5276 0, NULL, printableStringValidate, NULL},
5277 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
5278 0, NULL, NULL, NULL},
5279 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
5280 0, NULL, printablesStringValidate, NULL},
5281 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5282 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
5283 0, NULL, utcTimeValidate, NULL},
5285 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
5286 0, NULL, NULL, NULL},
5287 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
5288 0, NULL, NULL, NULL},
5289 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
5290 0, NULL, NULL, NULL},
5291 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
5292 0, NULL, NULL, NULL},
5293 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
5294 0, NULL, NULL, NULL},
5296 /* RFC 2307 NIS Syntaxes */
5297 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
5298 0, NULL, nisNetgroupTripleValidate, NULL},
5299 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
5300 0, NULL, bootParameterValidate, NULL},
5302 /* draft-zeilenga-ldap-x509 */
5303 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
5304 SLAP_SYNTAX_HIDE, NULL,
5305 serialNumberAndIssuerValidate,
5306 serialNumberAndIssuerPretty},
5307 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
5308 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5309 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
5310 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5311 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
5312 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5313 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
5314 SLAP_SYNTAX_HIDE, NULL,
5315 issuerAndThisUpdateValidate,
5316 issuerAndThisUpdatePretty},
5317 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
5318 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5319 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
5320 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5322 #ifdef SLAPD_AUTHPASSWD
5323 /* needs updating */
5324 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
5325 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5328 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
5329 0, NULL, UUIDValidate, UUIDPretty},
5331 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
5332 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
5334 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
5335 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
5337 /* OpenLDAP Void Syntax */
5338 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
5339 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
5341 /* FIXME: OID is unused, but not registered yet */
5342 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
5343 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
5345 {NULL, 0, NULL, NULL, NULL}
5348 char *csnSIDMatchSyntaxes[] = {
5349 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
5352 char *certificateExactMatchSyntaxes[] = {
5353 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
5356 char *certificateListExactMatchSyntaxes[] = {
5357 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
5360 #ifdef LDAP_COMP_MATCH
5361 char *componentFilterMatchSyntaxes[] = {
5362 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
5363 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
5367 char *directoryStringSyntaxes[] = {
5368 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
5371 char *integerFirstComponentMatchSyntaxes[] = {
5372 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
5373 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
5376 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
5377 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
5378 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
5379 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
5380 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
5381 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
5382 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
5383 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
5384 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
5389 * Other matching rules in X.520 that we do not use (yet):
5391 * 2.5.13.25 uTCTimeMatch
5392 * 2.5.13.26 uTCTimeOrderingMatch
5393 * 2.5.13.31* directoryStringFirstComponentMatch
5394 * 2.5.13.32* wordMatch
5395 * 2.5.13.33* keywordMatch
5396 * 2.5.13.36+ certificatePairExactMatch
5397 * 2.5.13.37+ certificatePairMatch
5398 * 2.5.13.40+ algorithmIdentifierMatch
5399 * 2.5.13.41* storedPrefixMatch
5400 * 2.5.13.42 attributeCertificateMatch
5401 * 2.5.13.43 readerAndKeyIDMatch
5402 * 2.5.13.44 attributeIntegrityMatch
5404 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
5405 * (+) described in draft-zeilenga-ldap-x509
5407 static slap_mrule_defs_rec mrule_defs[] = {
5409 * EQUALITY matching rules must be listed after associated APPROX
5410 * matching rules. So, we list all APPROX matching rules first.
5412 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
5413 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5414 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
5415 NULL, NULL, directoryStringApproxMatch,
5416 directoryStringApproxIndexer, directoryStringApproxFilter,
5419 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
5420 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5421 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
5422 NULL, NULL, IA5StringApproxMatch,
5423 IA5StringApproxIndexer, IA5StringApproxFilter,
5427 * Other matching rules
5430 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
5431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5432 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5433 NULL, NULL, octetStringMatch,
5434 octetStringIndexer, octetStringFilter,
5437 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
5438 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5439 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5440 NULL, dnNormalize, dnMatch,
5441 octetStringIndexer, octetStringFilter,
5444 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
5445 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5446 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5447 NULL, dnNormalize, dnRelativeMatch,
5451 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
5452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5453 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5454 NULL, dnNormalize, dnRelativeMatch,
5458 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
5459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5460 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5461 NULL, dnNormalize, dnRelativeMatch,
5465 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
5466 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5467 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5468 NULL, dnNormalize, dnRelativeMatch,
5472 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
5473 "SYNTAX 1.2.36.79672281.1.5.0 )",
5474 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5475 NULL, rdnNormalize, rdnMatch,
5476 octetStringIndexer, octetStringFilter,
5479 #ifdef LDAP_COMP_MATCH
5480 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
5481 "SYNTAX 1.2.36.79672281.1.5.2 )",
5482 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
5483 NULL, NULL , componentFilterMatch,
5484 octetStringIndexer, octetStringFilter,
5487 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
5488 "SYNTAX 1.2.36.79672281.1.5.3 )",
5489 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5490 NULL, NULL , allComponentsMatch,
5491 octetStringIndexer, octetStringFilter,
5494 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
5495 "SYNTAX 1.2.36.79672281.1.5.3 )",
5496 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5497 NULL, NULL , directoryComponentsMatch,
5498 octetStringIndexer, octetStringFilter,
5502 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
5503 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5504 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5505 NULL, UTF8StringNormalize, octetStringMatch,
5506 octetStringIndexer, octetStringFilter,
5507 directoryStringApproxMatchOID },
5509 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
5510 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5511 SLAP_MR_ORDERING, directoryStringSyntaxes,
5512 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5514 "caseIgnoreMatch" },
5516 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
5517 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5518 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5519 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5520 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5521 "caseIgnoreMatch" },
5523 {"( 2.5.13.5 NAME 'caseExactMatch' "
5524 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5525 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5526 NULL, UTF8StringNormalize, octetStringMatch,
5527 octetStringIndexer, octetStringFilter,
5528 directoryStringApproxMatchOID },
5530 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
5531 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5532 SLAP_MR_ORDERING, directoryStringSyntaxes,
5533 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5537 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
5538 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5539 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5540 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5541 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5544 {"( 2.5.13.8 NAME 'numericStringMatch' "
5545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5546 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5547 NULL, numericStringNormalize, octetStringMatch,
5548 octetStringIndexer, octetStringFilter,
5551 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
5552 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5553 SLAP_MR_ORDERING, NULL,
5554 NULL, numericStringNormalize, octetStringOrderingMatch,
5556 "numericStringMatch" },
5558 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
5559 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5560 SLAP_MR_SUBSTR, NULL,
5561 NULL, numericStringNormalize, octetStringSubstringsMatch,
5562 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5563 "numericStringMatch" },
5565 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
5566 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
5567 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5568 NULL, postalAddressNormalize, octetStringMatch,
5569 octetStringIndexer, octetStringFilter,
5572 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
5573 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5574 SLAP_MR_SUBSTR, NULL,
5575 NULL, NULL, NULL, NULL, NULL,
5576 "caseIgnoreListMatch" },
5578 {"( 2.5.13.13 NAME 'booleanMatch' "
5579 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
5580 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5581 NULL, NULL, booleanMatch,
5582 octetStringIndexer, octetStringFilter,
5585 {"( 2.5.13.14 NAME 'integerMatch' "
5586 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5587 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5588 NULL, NULL, integerMatch,
5589 integerIndexer, integerFilter,
5592 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
5593 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5594 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5595 NULL, NULL, integerMatch,
5599 {"( 2.5.13.16 NAME 'bitStringMatch' "
5600 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5601 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5602 NULL, NULL, octetStringMatch,
5603 octetStringIndexer, octetStringFilter,
5606 {"( 2.5.13.17 NAME 'octetStringMatch' "
5607 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5608 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5609 NULL, NULL, octetStringMatch,
5610 octetStringIndexer, octetStringFilter,
5613 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5614 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5615 SLAP_MR_ORDERING, NULL,
5616 NULL, NULL, octetStringOrderingMatch,
5618 "octetStringMatch" },
5620 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5621 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5622 SLAP_MR_SUBSTR, NULL,
5623 NULL, NULL, octetStringSubstringsMatch,
5624 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5625 "octetStringMatch" },
5627 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5628 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5629 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5631 telephoneNumberNormalize, octetStringMatch,
5632 octetStringIndexer, octetStringFilter,
5635 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5636 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5637 SLAP_MR_SUBSTR, NULL,
5638 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5639 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5640 "telephoneNumberMatch" },
5642 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5643 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5644 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5645 NULL, NULL, NULL, NULL, NULL, NULL },
5647 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5649 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5650 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5651 uniqueMemberIndexer, uniqueMemberFilter,
5654 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5656 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5657 NULL, NULL, NULL, NULL, NULL, NULL },
5659 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5660 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5661 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5662 NULL, generalizedTimeNormalize, octetStringMatch,
5663 generalizedTimeIndexer, generalizedTimeFilter,
5666 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5667 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5668 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5669 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5671 "generalizedTimeMatch" },
5673 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5674 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5675 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5676 integerFirstComponentMatchSyntaxes,
5677 NULL, firstComponentNormalize, integerMatch,
5678 octetStringIndexer, octetStringFilter,
5681 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5682 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5683 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5684 objectIdentifierFirstComponentMatchSyntaxes,
5685 NULL, firstComponentNormalize, octetStringMatch,
5686 octetStringIndexer, octetStringFilter,
5689 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5690 "SYNTAX 1.3.6.1.1.15.1 )",
5691 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5692 NULL, certificateExactNormalize, octetStringMatch,
5693 octetStringIndexer, octetStringFilter,
5696 {"( 2.5.13.35 NAME 'certificateMatch' "
5697 "SYNTAX 1.3.6.1.1.15.2 )",
5698 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5699 NULL, NULL, NULL, NULL, NULL,
5702 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
5703 "SYNTAX 1.3.6.1.1.15.5 )",
5704 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
5705 NULL, certificateListExactNormalize, octetStringMatch,
5706 octetStringIndexer, octetStringFilter,
5709 {"( 2.5.13.39 NAME 'certificateListMatch' "
5710 "SYNTAX 1.3.6.1.1.15.6 )",
5711 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5712 NULL, NULL, NULL, NULL, NULL,
5715 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5716 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5717 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5718 NULL, IA5StringNormalize, octetStringMatch,
5719 octetStringIndexer, octetStringFilter,
5720 IA5StringApproxMatchOID },
5722 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5723 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5724 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5725 NULL, IA5StringNormalize, octetStringMatch,
5726 octetStringIndexer, octetStringFilter,
5727 IA5StringApproxMatchOID },
5729 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5730 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5731 SLAP_MR_SUBSTR, NULL,
5732 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5733 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5734 "caseIgnoreIA5Match" },
5736 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5738 SLAP_MR_SUBSTR, NULL,
5739 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5740 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5741 "caseExactIA5Match" },
5743 #ifdef SLAPD_AUTHPASSWD
5744 /* needs updating */
5745 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5746 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5747 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5748 NULL, NULL, authPasswordMatch,
5753 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5754 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5756 NULL, NULL, integerBitAndMatch,
5760 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5763 NULL, NULL, integerBitOrMatch,
5767 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5768 "SYNTAX 1.3.6.1.1.16.1 )",
5769 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5770 NULL, UUIDNormalize, octetStringMatch,
5771 octetStringIndexer, octetStringFilter,
5774 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5775 "SYNTAX 1.3.6.1.1.16.1 )",
5776 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5777 NULL, UUIDNormalize, octetStringOrderingMatch,
5778 octetStringIndexer, octetStringFilter,
5781 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5782 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5783 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5784 NULL, csnNormalize, csnMatch,
5785 csnIndexer, csnFilter,
5788 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5789 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5790 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5791 NULL, NULL, csnOrderingMatch,
5795 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5796 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5797 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5798 NULL, csnSidNormalize, octetStringMatch,
5799 octetStringIndexer, octetStringFilter,
5802 /* FIXME: OID is unused, but not registered yet */
5803 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5804 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5805 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5806 NULL, authzNormalize, authzMatch,
5810 {NULL, SLAP_MR_NONE, NULL,
5811 NULL, NULL, NULL, NULL, NULL,
5816 slap_schema_init( void )
5821 /* we should only be called once (from main) */
5822 assert( schema_init_done == 0 );
5824 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5825 res = register_syntax( &syntax_defs[i] );
5828 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5829 syntax_defs[i].sd_desc );
5834 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5835 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5836 mrule_defs[i].mrd_compat_syntaxes == NULL )
5839 "slap_schema_init: Ignoring unusable matching rule %s\n",
5840 mrule_defs[i].mrd_desc );
5844 res = register_matching_rule( &mrule_defs[i] );
5848 "slap_schema_init: Error registering matching rule %s\n",
5849 mrule_defs[i].mrd_desc );
5854 res = slap_schema_load();
5855 schema_init_done = 1;
5860 schema_destroy( void )
5869 if( schema_init_done ) {
5870 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5871 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );