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;
1546 int flags, wasspace;
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 */
2854 ber_len_t neg = 0, extra = 0;
2857 out->bv_val = in->bv_val;
2860 if ( out->bv_val[0] == '-' ) {
2865 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
2866 first = out->bv_val[2];
2869 out->bv_len += STRLENOF("0x");
2870 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2871 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2874 } else if ( out->bv_val[0] == '\'' ) {
2875 first = out->bv_val[1];
2878 out->bv_len += STRLENOF("'");
2880 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2881 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2883 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
2886 out->bv_len += STRLENOF("'H");
2889 first = out->bv_val[0];
2890 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2891 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
2895 if ( !( out->bv_len > neg ) ) {
2899 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
2907 serialNumberAndIssuerCheck(
2915 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2917 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2918 /* Parse old format */
2919 is->bv_val = ber_bvchr( in, '$' );
2920 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2922 sn->bv_val = in->bv_val;
2923 sn->bv_len = is->bv_val - in->bv_val;
2926 is->bv_len = in->bv_len - (sn->bv_len + 1);
2928 /* eat leading zeros */
2929 for( n=0; n < (sn->bv_len-1); n++ ) {
2930 if( sn->bv_val[n] != '0' ) break;
2935 for( n=0; n < sn->bv_len; n++ ) {
2936 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2940 /* Parse GSER format */
2945 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
2949 struct berval x = *in;
2955 /* eat leading spaces */
2956 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
2960 /* should be at issuer or serialNumber NamedValue */
2961 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
2962 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
2965 x.bv_val += STRLENOF("issuer");
2966 x.bv_len -= STRLENOF("issuer");
2968 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2972 /* eat leading spaces */
2973 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
2977 /* For backward compatibility, this part is optional */
2978 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
2979 x.bv_val += STRLENOF("rdnSequence:");
2980 x.bv_len -= STRLENOF("rdnSequence:");
2983 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2987 is->bv_val = x.bv_val;
2990 for ( ; is->bv_len < x.bv_len; ) {
2991 if ( is->bv_val[is->bv_len] != '"' ) {
2995 if ( is->bv_val[is->bv_len+1] == '"' ) {
3002 x.bv_val += is->bv_len + 1;
3003 x.bv_len -= is->bv_len + 1;
3005 have |= HAVE_ISSUER;
3007 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3009 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3011 /* parse serialNumber */
3012 x.bv_val += STRLENOF("serialNumber");
3013 x.bv_len -= STRLENOF("serialNumber");
3015 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3019 /* eat leading spaces */
3020 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3024 if ( checkNum( &x, sn ) ) {
3025 return LDAP_INVALID_SYNTAX;
3028 x.bv_val += sn->bv_len;
3029 x.bv_len -= sn->bv_len;
3034 return LDAP_INVALID_SYNTAX;
3037 /* eat leading spaces */
3038 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3042 if ( have == HAVE_ALL ) {
3046 if ( x.bv_val[0] != ',' ) {
3047 return LDAP_INVALID_SYNTAX;
3054 /* should have no characters left... */
3055 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3057 if ( numdquotes == 0 ) {
3058 ber_dupbv_x( &ni, is, ctx );
3063 ni.bv_len = is->bv_len - numdquotes;
3064 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3065 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3066 if ( is->bv_val[src] == '"' ) {
3069 ni.bv_val[dst] = is->bv_val[src];
3071 ni.bv_val[dst] = '\0';
3081 serialNumberAndIssuerValidate(
3086 struct berval sn, i;
3088 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3091 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3096 /* validate DN -- doesn't handle double dquote */
3097 rc = dnValidate( NULL, &i );
3099 rc = LDAP_INVALID_SYNTAX;
3102 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3103 slap_sl_free( i.bv_val, NULL );
3106 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3107 in->bv_val, rc, 0 );
3114 serialNumberAndIssuerPretty(
3121 struct berval sn, i, ni = BER_BVNULL;
3124 assert( in != NULL );
3125 assert( out != NULL );
3129 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3132 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3137 rc = dnPretty( syntax, &i, &ni, ctx );
3139 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3140 slap_sl_free( i.bv_val, ctx );
3144 rc = LDAP_INVALID_SYNTAX;
3148 /* make room from sn + "$" */
3149 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3150 + sn.bv_len + ni.bv_len;
3151 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3153 if ( out->bv_val == NULL ) {
3160 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3161 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3162 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3163 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3164 p = lutil_strcopy( p, /*{*/ "\" }" );
3166 assert( p == &out->bv_val[out->bv_len] );
3169 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3170 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3172 slap_sl_free( ni.bv_val, ctx );
3174 return LDAP_SUCCESS;
3184 /* Use hex format. '123456789abcdef'H */
3185 unsigned char *ptr, zero = '\0';
3188 ber_len_t i, len, nlen;
3190 assert( in != NULL );
3191 assert( !BER_BVISNULL( in ) );
3192 assert( out != NULL );
3193 assert( !BER_BVISNULL( out ) );
3195 ptr = (unsigned char *)in->bv_val;
3198 /* Check for minimal encodings */
3200 if ( ptr[0] & 0x80 ) {
3201 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3205 } else if ( ptr[0] == 0 ) {
3206 if ( !( ptr[1] & 0x80 ) ) {
3213 } else if ( len == 0 ) {
3214 /* FIXME: this should not be possible,
3215 * since a value of zero would have length 1 */
3220 first = !( ptr[0] & 0xf0U );
3221 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3222 if ( nlen >= out->bv_len ) {
3223 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3229 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3233 for ( ; i < len; i++ ) {
3234 sprintf( sptr, "%02X", ptr[i] );
3241 assert( sptr == &out->bv_val[nlen] );
3248 #define SLAP_SN_BUFLEN (64)
3251 * This routine is called by certificateExactNormalize when
3252 * certificateExactNormalize receives a search string instead of
3253 * a certificate. This routine checks if the search value is valid
3254 * and then returns the normalized value
3257 serialNumberAndIssuerNormalize(
3265 struct berval sn, sn2, sn3, i, ni;
3266 char sbuf2[SLAP_SN_BUFLEN];
3267 char sbuf3[SLAP_SN_BUFLEN];
3271 assert( in != NULL );
3272 assert( out != NULL );
3274 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3277 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3282 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3284 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3285 slap_sl_free( i.bv_val, ctx );
3289 return LDAP_INVALID_SYNTAX;
3292 /* Convert sn to canonical hex */
3294 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3295 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3297 sn2.bv_len = sn.bv_len;
3298 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3299 rc = LDAP_INVALID_SYNTAX;
3304 sn3.bv_len = sizeof(sbuf3);
3305 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3306 rc = LDAP_INVALID_SYNTAX;
3310 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3311 + sn3.bv_len + ni.bv_len;
3312 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3314 if ( out->bv_val == NULL ) {
3322 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3323 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3324 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3325 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3326 p = lutil_strcopy( p, /*{*/ "\" }" );
3328 assert( p == &out->bv_val[out->bv_len] );
3331 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3332 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3334 if ( sn2.bv_val != sbuf2 ) {
3335 slap_sl_free( sn2.bv_val, ctx );
3338 if ( sn3.bv_val != sbuf3 ) {
3339 slap_sl_free( sn3.bv_val, ctx );
3342 slap_sl_free( ni.bv_val, ctx );
3348 certificateExactNormalize(
3353 struct berval *normalized,
3356 BerElementBuffer berbuf;
3357 BerElement *ber = (BerElement *)&berbuf;
3361 char serialbuf2[SLAP_SN_BUFLEN];
3362 struct berval sn, sn2 = BER_BVNULL;
3363 struct berval issuer_dn = BER_BVNULL, bvdn;
3365 int rc = LDAP_INVALID_SYNTAX;
3367 assert( val != NULL );
3369 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3370 val->bv_val, val->bv_len, 0 );
3372 if ( BER_BVISEMPTY( val ) ) goto done;
3374 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3375 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3378 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3380 ber_init2( ber, val, LBER_USE_DER );
3381 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3382 tag = ber_skip_tag( ber, &len ); /* Sequence */
3383 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3384 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3385 tag = ber_skip_tag( ber, &len );
3386 tag = ber_get_int( ber, &i ); /* version */
3389 /* NOTE: move the test here from certificateValidate,
3390 * so that we can validate certs with serial longer
3391 * than sizeof(ber_int_t) */
3392 tag = ber_skip_tag( ber, &len ); /* serial */
3394 sn.bv_val = (char *)ber->ber_ptr;
3395 sn2.bv_val = serialbuf2;
3396 sn2.bv_len = sizeof(serialbuf2);
3397 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3398 rc = LDAP_INVALID_SYNTAX;
3401 ber_skip_data( ber, len );
3403 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3404 ber_skip_data( ber, len );
3405 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3406 len = ber_ptrlen( ber );
3407 bvdn.bv_val = val->bv_val + len;
3408 bvdn.bv_len = val->bv_len - len;
3410 rc = dnX509normalize( &bvdn, &issuer_dn );
3411 if ( rc != LDAP_SUCCESS ) goto done;
3413 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3414 + sn2.bv_len + issuer_dn.bv_len;
3415 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3417 p = normalized->bv_val;
3419 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3420 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3421 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3422 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3423 p = lutil_strcopy( p, /*{*/ "\" }" );
3428 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3429 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3431 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3432 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3437 /* X.509 PKI certificateList stuff */
3439 checkTime( struct berval *in, struct berval *out )
3443 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3446 assert( in != NULL );
3447 assert( !BER_BVISNULL( in ) );
3448 assert( !BER_BVISEMPTY( in ) );
3450 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3454 if ( out != NULL ) {
3455 assert( !BER_BVISNULL( out ) );
3456 assert( out->bv_len >= sizeof( buf ) );
3457 bv.bv_val = out->bv_val;
3463 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3464 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3467 if ( in->bv_val[i] != 'Z' ) {
3472 if ( i != in->bv_len ) {
3476 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3477 lutil_strncopy( bv.bv_val, in->bv_val, i );
3480 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3481 char *p = bv.bv_val;
3482 if ( in->bv_val[0] < '7' ) {
3483 p = lutil_strcopy( p, "20" );
3486 p = lutil_strcopy( p, "19" );
3488 lutil_strncopy( p, in->bv_val, i );
3495 rc = generalizedTimeValidate( NULL, &bv );
3496 if ( rc == LDAP_SUCCESS && out != NULL ) {
3497 out->bv_len = bv.bv_len;
3500 return rc != LDAP_SUCCESS;
3504 issuerAndThisUpdateCheck(
3511 struct berval x = *in;
3512 struct berval ni = BER_BVNULL;
3513 /* Parse GSER format */
3517 HAVE_THISUPDATE = 0x2,
3518 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3522 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3524 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3525 return LDAP_INVALID_SYNTAX;
3529 x.bv_len -= STRLENOF("{}");
3532 /* eat leading spaces */
3533 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3537 /* should be at issuer or thisUpdate */
3538 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3539 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3542 x.bv_val += STRLENOF("issuer");
3543 x.bv_len -= STRLENOF("issuer");
3545 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3549 /* eat leading spaces */
3550 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3554 /* For backward compatibility, this part is optional */
3555 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3556 return LDAP_INVALID_SYNTAX;
3558 x.bv_val += STRLENOF("rdnSequence:");
3559 x.bv_len -= STRLENOF("rdnSequence:");
3561 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3565 is->bv_val = x.bv_val;
3568 for ( ; is->bv_len < x.bv_len; ) {
3569 if ( is->bv_val[is->bv_len] != '"' ) {
3573 if ( is->bv_val[is->bv_len+1] == '"' ) {
3580 x.bv_val += is->bv_len + 1;
3581 x.bv_len -= is->bv_len + 1;
3583 have |= HAVE_ISSUER;
3585 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3587 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3589 /* parse thisUpdate */
3590 x.bv_val += STRLENOF("thisUpdate");
3591 x.bv_len -= STRLENOF("thisUpdate");
3593 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3597 /* eat leading spaces */
3598 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3602 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3606 tu->bv_val = x.bv_val;
3609 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3610 if ( tu->bv_val[tu->bv_len] == '"' ) {
3614 x.bv_val += tu->bv_len + 1;
3615 x.bv_len -= tu->bv_len + 1;
3617 have |= HAVE_THISUPDATE;
3620 return LDAP_INVALID_SYNTAX;
3623 /* eat leading spaces */
3624 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3628 if ( have == HAVE_ALL ) {
3632 if ( x.bv_val[0] != ',' ) {
3633 return LDAP_INVALID_SYNTAX;
3640 /* should have no characters left... */
3641 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3643 if ( numdquotes == 0 ) {
3644 ber_dupbv_x( &ni, is, ctx );
3649 ni.bv_len = is->bv_len - numdquotes;
3650 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3651 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3652 if ( is->bv_val[src] == '"' ) {
3655 ni.bv_val[dst] = is->bv_val[src];
3657 ni.bv_val[dst] = '\0';
3666 issuerAndThisUpdateValidate(
3671 struct berval i, tu;
3673 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3676 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3681 /* validate DN -- doesn't handle double dquote */
3682 rc = dnValidate( NULL, &i );
3684 rc = LDAP_INVALID_SYNTAX;
3686 } else if ( checkTime( &tu, NULL ) ) {
3687 rc = LDAP_INVALID_SYNTAX;
3690 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3691 slap_sl_free( i.bv_val, NULL );
3694 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3695 in->bv_val, rc, 0 );
3702 issuerAndThisUpdatePretty(
3709 struct berval i, tu, ni = BER_BVNULL;
3712 assert( in != NULL );
3713 assert( out != NULL );
3717 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3720 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3725 rc = dnPretty( syntax, &i, &ni, ctx );
3727 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3728 slap_sl_free( i.bv_val, ctx );
3731 if ( rc || checkTime( &tu, NULL ) ) {
3732 rc = LDAP_INVALID_SYNTAX;
3737 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3738 + ni.bv_len + tu.bv_len;
3739 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3741 if ( out->bv_val == NULL ) {
3748 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3749 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3750 p = lutil_strcopy( p, "\", thisUpdate \"" );
3751 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3752 p = lutil_strcopy( p, /*{*/ "\" }" );
3754 assert( p == &out->bv_val[out->bv_len] );
3757 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3758 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3760 slap_sl_free( ni.bv_val, ctx );
3766 issuerAndThisUpdateNormalize(
3774 struct berval i, ni, tu, tu2;
3775 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3779 assert( in != NULL );
3780 assert( out != NULL );
3782 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3785 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3790 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3792 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3793 slap_sl_free( i.bv_val, ctx );
3797 tu2.bv_len = sizeof( sbuf );
3798 if ( rc || checkTime( &tu, &tu2 ) ) {
3799 return LDAP_INVALID_SYNTAX;
3802 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3803 + ni.bv_len + tu2.bv_len;
3804 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3806 if ( out->bv_val == NULL ) {
3814 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3815 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3816 p = lutil_strcopy( p, "\", thisUpdate \"" );
3817 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3818 p = lutil_strcopy( p, /*{*/ "\" }" );
3820 assert( p == & out->bv_val[out->bv_len] );
3823 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3824 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3826 slap_sl_free( ni.bv_val, ctx );
3832 certificateListExactNormalize(
3837 struct berval *normalized,
3840 BerElementBuffer berbuf;
3841 BerElement *ber = (BerElement *)&berbuf;
3845 struct berval issuer_dn = BER_BVNULL, bvdn,
3847 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3848 int rc = LDAP_INVALID_SYNTAX;
3850 assert( val != NULL );
3852 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
3853 val->bv_val, val->bv_len, 0 );
3855 if ( BER_BVISEMPTY( val ) ) goto done;
3857 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3858 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
3861 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3863 ber_init2( ber, val, LBER_USE_DER );
3864 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
3865 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3866 tag = ber_skip_tag( ber, &len ); /* Sequence */
3867 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3868 tag = ber_peek_tag( ber, &len );
3869 /* Optional version */
3870 if ( tag == LBER_INTEGER ) {
3871 tag = ber_get_int( ber, &version );
3872 assert( tag == LBER_INTEGER );
3873 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
3875 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
3876 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3877 ber_skip_data( ber, len );
3879 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3880 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3881 len = ber_ptrlen( ber );
3882 bvdn.bv_val = val->bv_val + len;
3883 bvdn.bv_len = val->bv_len - len;
3884 tag = ber_skip_tag( ber, &len );
3885 ber_skip_data( ber, len );
3887 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
3888 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
3889 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
3890 bvtu.bv_val = (char *)ber->ber_ptr;
3893 rc = dnX509normalize( &bvdn, &issuer_dn );
3894 if ( rc != LDAP_SUCCESS ) goto done;
3896 thisUpdate.bv_val = tubuf;
3897 thisUpdate.bv_len = sizeof(tubuf);
3898 if ( checkTime( &bvtu, &thisUpdate ) ) {
3899 rc = LDAP_INVALID_SYNTAX;
3903 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3904 + issuer_dn.bv_len + thisUpdate.bv_len;
3905 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3907 p = normalized->bv_val;
3909 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
3910 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3911 p = lutil_strcopy( p, "\", thisUpdate \"" );
3912 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
3913 p = lutil_strcopy( p, /*{*/ "\" }" );
3918 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
3919 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3921 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3933 assert( in != NULL );
3934 assert( !BER_BVISNULL( in ) );
3936 for ( i = 0; i < in->bv_len; i++ ) {
3937 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3938 return LDAP_INVALID_SYNTAX;
3942 return LDAP_SUCCESS;
3945 /* Normalize a SID as used inside a CSN:
3946 * three-digit numeric string */
3953 struct berval *normalized,
3958 assert( val != NULL );
3959 assert( normalized != NULL );
3961 ber_dupbv_x( normalized, val, ctx );
3963 for ( i = 0; i < normalized->bv_len; i++ ) {
3964 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3965 ber_memfree_x( normalized->bv_val, ctx );
3966 BER_BVZERO( normalized );
3967 return LDAP_INVALID_SYNTAX;
3970 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3973 return LDAP_SUCCESS;
3981 assert( in != NULL );
3982 assert( !BER_BVISNULL( in ) );
3984 if ( in->bv_len != 3 ) {
3985 return LDAP_INVALID_SYNTAX;
3988 return hexValidate( NULL, in );
3991 /* Normalize a SID as used inside a CSN:
3992 * three-digit numeric string */
3999 struct berval *normalized,
4002 if ( val->bv_len != 3 ) {
4003 return LDAP_INVALID_SYNTAX;
4006 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4016 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4019 /* Normalize a SID as used inside a CSN, either as-is
4020 * (assertion value) or extracted from the CSN
4021 * (attribute value) */
4028 struct berval *normalized,
4036 if ( BER_BVISEMPTY( val ) ) {
4037 return LDAP_INVALID_SYNTAX;
4040 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4041 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4044 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4046 ptr = ber_bvchr( val, '#' );
4047 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4048 return LDAP_INVALID_SYNTAX;
4051 bv.bv_val = ptr + 1;
4052 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4054 ptr = ber_bvchr( &bv, '#' );
4055 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4056 return LDAP_INVALID_SYNTAX;
4059 bv.bv_val = ptr + 1;
4060 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4062 ptr = ber_bvchr( &bv, '#' );
4063 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4064 return LDAP_INVALID_SYNTAX;
4067 bv.bv_len = ptr - bv.bv_val;
4069 if ( bv.bv_len == 2 ) {
4070 /* OpenLDAP 2.3 SID */
4072 buf[ 1 ] = bv.bv_val[ 0 ];
4073 buf[ 2 ] = bv.bv_val[ 1 ];
4080 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4092 assert( in != NULL );
4093 assert( !BER_BVISNULL( in ) );
4095 if ( BER_BVISEMPTY( in ) ) {
4096 return LDAP_INVALID_SYNTAX;
4101 ptr = ber_bvchr( &bv, '#' );
4102 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4103 return LDAP_INVALID_SYNTAX;
4106 bv.bv_len = ptr - bv.bv_val;
4107 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4108 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4110 return LDAP_INVALID_SYNTAX;
4113 rc = generalizedTimeValidate( NULL, &bv );
4114 if ( rc != LDAP_SUCCESS ) {
4118 bv.bv_val = ptr + 1;
4119 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4121 ptr = ber_bvchr( &bv, '#' );
4122 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4123 return LDAP_INVALID_SYNTAX;
4126 bv.bv_len = ptr - bv.bv_val;
4127 if ( bv.bv_len != 6 ) {
4128 return LDAP_INVALID_SYNTAX;
4131 rc = hexValidate( NULL, &bv );
4132 if ( rc != LDAP_SUCCESS ) {
4136 bv.bv_val = ptr + 1;
4137 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4139 ptr = ber_bvchr( &bv, '#' );
4140 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4141 return LDAP_INVALID_SYNTAX;
4144 bv.bv_len = ptr - bv.bv_val;
4145 if ( bv.bv_len == 2 ) {
4146 /* tolerate old 2-digit replica-id */
4147 rc = hexValidate( NULL, &bv );
4150 rc = sidValidate( NULL, &bv );
4152 if ( rc != LDAP_SUCCESS ) {
4156 bv.bv_val = ptr + 1;
4157 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4159 if ( bv.bv_len != 6 ) {
4160 return LDAP_INVALID_SYNTAX;
4163 return hexValidate( NULL, &bv );
4166 /* Normalize a CSN in OpenLDAP 2.1 format */
4173 struct berval *normalized,
4176 struct berval gt, cnt, sid, mod;
4178 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4182 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4183 assert( !BER_BVISEMPTY( val ) );
4187 ptr = ber_bvchr( >, '#' );
4188 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
4189 return LDAP_INVALID_SYNTAX;
4192 gt.bv_len = ptr - gt.bv_val;
4193 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
4194 return LDAP_INVALID_SYNTAX;
4197 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
4198 return LDAP_INVALID_SYNTAX;
4201 cnt.bv_val = ptr + 1;
4202 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
4204 ptr = ber_bvchr( &cnt, '#' );
4205 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4206 return LDAP_INVALID_SYNTAX;
4209 cnt.bv_len = ptr - cnt.bv_val;
4210 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
4211 return LDAP_INVALID_SYNTAX;
4214 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
4215 return LDAP_INVALID_SYNTAX;
4218 cnt.bv_val += STRLENOF( "0x" );
4219 cnt.bv_len -= STRLENOF( "0x" );
4221 sid.bv_val = ptr + 1;
4222 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
4224 ptr = ber_bvchr( &sid, '#' );
4225 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4226 return LDAP_INVALID_SYNTAX;
4229 sid.bv_len = ptr - sid.bv_val;
4230 if ( sid.bv_len != STRLENOF( "0" ) ) {
4231 return LDAP_INVALID_SYNTAX;
4234 mod.bv_val = ptr + 1;
4235 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
4236 if ( mod.bv_len != STRLENOF( "0000" ) ) {
4237 return LDAP_INVALID_SYNTAX;
4240 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
4244 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
4245 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
4247 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
4249 ptr = lutil_strcopy( ptr, ".000000Z#00" );
4250 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
4254 *ptr++ = sid.bv_val[ 0 ];
4258 for ( i = 0; i < mod.bv_len; i++ ) {
4259 *ptr++ = TOLOWER( mod.bv_val[ i ] );
4263 assert( ptr == &bv.bv_val[bv.bv_len] );
4265 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
4266 return LDAP_INVALID_SYNTAX;
4269 ber_dupbv_x( normalized, &bv, ctx );
4271 return LDAP_SUCCESS;
4274 /* Normalize a CSN in OpenLDAP 2.3 format */
4281 struct berval *normalized,
4284 struct berval gt, cnt, sid, mod;
4286 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4290 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4291 assert( !BER_BVISEMPTY( val ) );
4295 ptr = ber_bvchr( >, '#' );
4296 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
4297 return LDAP_INVALID_SYNTAX;
4300 gt.bv_len = ptr - gt.bv_val;
4301 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
4302 return LDAP_INVALID_SYNTAX;
4305 cnt.bv_val = ptr + 1;
4306 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
4308 ptr = ber_bvchr( &cnt, '#' );
4309 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4310 return LDAP_INVALID_SYNTAX;
4313 cnt.bv_len = ptr - cnt.bv_val;
4314 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
4315 return LDAP_INVALID_SYNTAX;
4318 sid.bv_val = ptr + 1;
4319 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
4321 ptr = ber_bvchr( &sid, '#' );
4322 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4323 return LDAP_INVALID_SYNTAX;
4326 sid.bv_len = ptr - sid.bv_val;
4327 if ( sid.bv_len != STRLENOF( "00" ) ) {
4328 return LDAP_INVALID_SYNTAX;
4331 mod.bv_val = ptr + 1;
4332 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
4333 if ( mod.bv_len != STRLENOF( "000000" ) ) {
4334 return LDAP_INVALID_SYNTAX;
4337 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
4341 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
4342 ptr = lutil_strcopy( ptr, ".000000Z#" );
4343 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
4346 for ( i = 0; i < sid.bv_len; i++ ) {
4347 *ptr++ = TOLOWER( sid.bv_val[ i ] );
4350 for ( i = 0; i < mod.bv_len; i++ ) {
4351 *ptr++ = TOLOWER( mod.bv_val[ i ] );
4355 assert( ptr == &bv.bv_val[bv.bv_len] );
4356 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
4357 return LDAP_INVALID_SYNTAX;
4360 ber_dupbv_x( normalized, &bv, ctx );
4362 return LDAP_SUCCESS;
4365 /* Normalize a CSN */
4372 struct berval *normalized,
4375 struct berval cnt, sid, mod;
4379 assert( val != NULL );
4380 assert( normalized != NULL );
4382 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4384 if ( BER_BVISEMPTY( val ) ) {
4385 return LDAP_INVALID_SYNTAX;
4388 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
4389 /* Openldap <= 2.3 */
4391 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
4394 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
4397 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
4400 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
4401 return LDAP_INVALID_SYNTAX;
4404 ptr = ber_bvchr( val, '#' );
4405 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4406 return LDAP_INVALID_SYNTAX;
4409 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
4410 return LDAP_INVALID_SYNTAX;
4413 cnt.bv_val = ptr + 1;
4414 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
4416 ptr = ber_bvchr( &cnt, '#' );
4417 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4418 return LDAP_INVALID_SYNTAX;
4421 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
4422 return LDAP_INVALID_SYNTAX;
4425 sid.bv_val = ptr + 1;
4426 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
4428 ptr = ber_bvchr( &sid, '#' );
4429 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4430 return LDAP_INVALID_SYNTAX;
4433 sid.bv_len = ptr - sid.bv_val;
4434 if ( sid.bv_len != STRLENOF( "000" ) ) {
4435 return LDAP_INVALID_SYNTAX;
4438 mod.bv_val = ptr + 1;
4439 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
4441 if ( mod.bv_len != STRLENOF( "000000" ) ) {
4442 return LDAP_INVALID_SYNTAX;
4445 ber_dupbv_x( normalized, val, ctx );
4447 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
4448 i < normalized->bv_len; i++ )
4450 /* assume it's already validated that's all hex digits */
4451 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4454 return LDAP_SUCCESS;
4464 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4467 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
4468 /* slight optimization - does not need the start parameter */
4469 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
4474 check_time_syntax (struct berval *val,
4477 struct berval *fraction)
4480 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
4481 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
4482 * GeneralizedTime supports leap seconds, UTCTime does not.
4484 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
4485 static const int mdays[2][12] = {
4486 /* non-leap years */
4487 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
4489 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
4492 int part, c, c1, c2, tzoffset, leapyear = 0;
4495 e = p + val->bv_len;
4497 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4498 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
4500 for (part = start; part < 7 && p < e; part++) {
4502 if (!ASCII_DIGIT(c1)) {
4507 return LDAP_INVALID_SYNTAX;
4510 if (!ASCII_DIGIT(c)) {
4511 return LDAP_INVALID_SYNTAX;
4513 c += c1 * 10 - '0' * 11;
4514 if ((part | 1) == 3) {
4517 return LDAP_INVALID_SYNTAX;
4520 if (c >= ceiling[part]) {
4521 if (! (c == 60 && part == 6 && start == 0))
4522 return LDAP_INVALID_SYNTAX;
4526 if (part < 5 + start) {
4527 return LDAP_INVALID_SYNTAX;
4529 for (; part < 9; part++) {
4533 /* leapyear check for the Gregorian calendar (year>1581) */
4534 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
4538 if (parts[3] >= mdays[leapyear][parts[2]]) {
4539 return LDAP_INVALID_SYNTAX;
4543 fraction->bv_val = p;
4544 fraction->bv_len = 0;
4545 if (p < e && (*p == '.' || *p == ',')) {
4547 while (++p < e && ASCII_DIGIT(*p)) {
4550 if (p - fraction->bv_val == 1) {
4551 return LDAP_INVALID_SYNTAX;
4553 for (end_num = p; end_num[-1] == '0'; --end_num) {
4556 c = end_num - fraction->bv_val;
4557 if (c != 1) fraction->bv_len = c;
4563 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4569 return LDAP_INVALID_SYNTAX;
4575 for (part = 7; part < 9 && p < e; part++) {
4577 if (!ASCII_DIGIT(c1)) {
4582 return LDAP_INVALID_SYNTAX;
4585 if (!ASCII_DIGIT(c2)) {
4586 return LDAP_INVALID_SYNTAX;
4588 parts[part] = c1 * 10 + c2 - '0' * 11;
4589 if (parts[part] >= ceiling[part]) {
4590 return LDAP_INVALID_SYNTAX;
4593 if (part < 8 + start) {
4594 return LDAP_INVALID_SYNTAX;
4597 if (tzoffset == '-') {
4598 /* negative offset to UTC, ie west of Greenwich */
4599 parts[4] += parts[7];
4600 parts[5] += parts[8];
4601 /* offset is just hhmm, no seconds */
4602 for (part = 6; --part >= 0; ) {
4606 c = mdays[leapyear][parts[2]];
4608 if (parts[part] >= c) {
4610 return LDAP_INVALID_SYNTAX;
4615 } else if (part != 5) {
4620 /* positive offset to UTC, ie east of Greenwich */
4621 parts[4] -= parts[7];
4622 parts[5] -= parts[8];
4623 for (part = 6; --part >= 0; ) {
4624 if (parts[part] < 0) {
4626 return LDAP_INVALID_SYNTAX;
4631 /* make first arg to % non-negative */
4632 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4637 } else if (part != 5) {
4644 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4647 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4654 struct berval *normalized )
4658 rc = check_time_syntax(val, 1, parts, NULL);
4659 if (rc != LDAP_SUCCESS) {
4663 normalized->bv_val = ch_malloc( 14 );
4664 if ( normalized->bv_val == NULL ) {
4665 return LBER_ERROR_MEMORY;
4668 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4669 parts[1], parts[2] + 1, parts[3] + 1,
4670 parts[4], parts[5], parts[6] );
4671 normalized->bv_len = 13;
4673 return LDAP_SUCCESS;
4683 return check_time_syntax(in, 1, parts, NULL);
4686 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4689 generalizedTimeValidate(
4694 struct berval fraction;
4695 return check_time_syntax(in, 0, parts, &fraction);
4699 generalizedTimeNormalize(
4704 struct berval *normalized,
4709 struct berval fraction;
4711 rc = check_time_syntax(val, 0, parts, &fraction);
4712 if (rc != LDAP_SUCCESS) {
4716 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4717 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4718 if ( BER_BVISNULL( normalized ) ) {
4719 return LBER_ERROR_MEMORY;
4722 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4723 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4724 parts[4], parts[5], parts[6] );
4725 if ( !BER_BVISEMPTY( &fraction ) ) {
4726 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4727 fraction.bv_val, fraction.bv_len );
4728 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4730 strcpy( normalized->bv_val + len-1, "Z" );
4731 normalized->bv_len = len;
4733 return LDAP_SUCCESS;
4737 generalizedTimeOrderingMatch(
4742 struct berval *value,
4743 void *assertedValue )
4745 struct berval *asserted = (struct berval *) assertedValue;
4746 ber_len_t v_len = value->bv_len;
4747 ber_len_t av_len = asserted->bv_len;
4749 /* ignore trailing 'Z' when comparing */
4750 int match = memcmp( value->bv_val, asserted->bv_val,
4751 (v_len < av_len ? v_len : av_len) - 1 );
4752 if ( match == 0 ) match = v_len - av_len;
4755 return LDAP_SUCCESS;
4758 /* Index generation function */
4759 int generalizedTimeIndexer(
4764 struct berval *prefix,
4772 BerValue bvtmp; /* 40 bit index */
4774 struct lutil_timet tt;
4776 bvtmp.bv_len = sizeof(tmp);
4778 for( i=0; values[i].bv_val != NULL; i++ ) {
4779 /* just count them */
4782 /* we should have at least one value at this point */
4785 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4787 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4788 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4789 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4790 /* Use 40 bits of time for key */
4791 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4792 lutil_tm2time( &tm, &tt );
4793 tmp[0] = tt.tt_gsec & 0xff;
4794 tmp[4] = tt.tt_sec & 0xff;
4796 tmp[3] = tt.tt_sec & 0xff;
4798 tmp[2] = tt.tt_sec & 0xff;
4800 tmp[1] = tt.tt_sec & 0xff;
4802 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4806 keys[j].bv_val = NULL;
4811 return LDAP_SUCCESS;
4814 /* Index generation function */
4815 int generalizedTimeFilter(
4820 struct berval *prefix,
4821 void * assertedValue,
4827 BerValue bvtmp; /* 40 bit index */
4828 BerValue *value = (BerValue *) assertedValue;
4830 struct lutil_timet tt;
4832 bvtmp.bv_len = sizeof(tmp);
4834 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4835 /* Use 40 bits of time for key */
4836 if ( value->bv_val && value->bv_len >= 10 &&
4837 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4839 lutil_tm2time( &tm, &tt );
4840 tmp[0] = tt.tt_gsec & 0xff;
4841 tmp[4] = tt.tt_sec & 0xff;
4843 tmp[3] = tt.tt_sec & 0xff;
4845 tmp[2] = tt.tt_sec & 0xff;
4847 tmp[1] = tt.tt_sec & 0xff;
4849 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4850 ber_dupbv_x(keys, &bvtmp, ctx );
4851 keys[1].bv_val = NULL;
4859 return LDAP_SUCCESS;
4863 deliveryMethodValidate(
4865 struct berval *val )
4868 #define LENOF(s) (sizeof(s)-1)
4869 struct berval tmp = *val;
4871 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4872 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4873 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4876 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4878 switch( tmp.bv_val[0] ) {
4881 if(( tmp.bv_len >= LENOF("any") ) &&
4882 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4884 tmp.bv_len -= LENOF("any");
4885 tmp.bv_val += LENOF("any");
4888 return LDAP_INVALID_SYNTAX;
4892 if(( tmp.bv_len >= LENOF("mhs") ) &&
4893 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4895 tmp.bv_len -= LENOF("mhs");
4896 tmp.bv_val += LENOF("mhs");
4899 return LDAP_INVALID_SYNTAX;
4903 if(( tmp.bv_len >= LENOF("physical") ) &&
4904 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4906 tmp.bv_len -= LENOF("physical");
4907 tmp.bv_val += LENOF("physical");
4910 return LDAP_INVALID_SYNTAX;
4913 case 'T': /* telex or teletex or telephone */
4914 if(( tmp.bv_len >= LENOF("telex") ) &&
4915 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4917 tmp.bv_len -= LENOF("telex");
4918 tmp.bv_val += LENOF("telex");
4921 if(( tmp.bv_len >= LENOF("teletex") ) &&
4922 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4924 tmp.bv_len -= LENOF("teletex");
4925 tmp.bv_val += LENOF("teletex");
4928 if(( tmp.bv_len >= LENOF("telephone") ) &&
4929 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4931 tmp.bv_len -= LENOF("telephone");
4932 tmp.bv_val += LENOF("telephone");
4935 return LDAP_INVALID_SYNTAX;
4938 case 'G': /* g3fax or g4fax */
4939 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4940 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4941 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4943 tmp.bv_len -= LENOF("g3fax");
4944 tmp.bv_val += LENOF("g3fax");
4947 return LDAP_INVALID_SYNTAX;
4951 if(( tmp.bv_len >= LENOF("ia5") ) &&
4952 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4954 tmp.bv_len -= LENOF("ia5");
4955 tmp.bv_val += LENOF("ia5");
4958 return LDAP_INVALID_SYNTAX;
4962 if(( tmp.bv_len >= LENOF("videotex") ) &&
4963 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4965 tmp.bv_len -= LENOF("videotex");
4966 tmp.bv_val += LENOF("videotex");
4969 return LDAP_INVALID_SYNTAX;
4972 return LDAP_INVALID_SYNTAX;
4975 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4977 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4981 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4985 return LDAP_INVALID_SYNTAX;
4987 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4996 nisNetgroupTripleValidate(
4998 struct berval *val )
5003 if ( BER_BVISEMPTY( val ) ) {
5004 return LDAP_INVALID_SYNTAX;
5007 p = (char *)val->bv_val;
5008 e = p + val->bv_len;
5010 if ( *p != '(' /*')'*/ ) {
5011 return LDAP_INVALID_SYNTAX;
5014 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5018 return LDAP_INVALID_SYNTAX;
5021 } else if ( !AD_CHAR( *p ) ) {
5022 return LDAP_INVALID_SYNTAX;
5026 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5027 return LDAP_INVALID_SYNTAX;
5033 return LDAP_INVALID_SYNTAX;
5036 return LDAP_SUCCESS;
5040 bootParameterValidate(
5042 struct berval *val )
5046 if ( BER_BVISEMPTY( val ) ) {
5047 return LDAP_INVALID_SYNTAX;
5050 p = (char *)val->bv_val;
5051 e = p + val->bv_len;
5054 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5055 if ( !AD_CHAR( *p ) ) {
5056 return LDAP_INVALID_SYNTAX;
5061 return LDAP_INVALID_SYNTAX;
5065 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5066 if ( !AD_CHAR( *p ) ) {
5067 return LDAP_INVALID_SYNTAX;
5072 return LDAP_INVALID_SYNTAX;
5076 for ( p++; p < e; p++ ) {
5077 if ( !SLAP_PRINTABLE( *p ) ) {
5078 return LDAP_INVALID_SYNTAX;
5082 return LDAP_SUCCESS;
5086 firstComponentNormalize(
5091 struct berval *normalized,
5098 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5099 ber_dupbv_x( normalized, val, ctx );
5100 return LDAP_SUCCESS;
5103 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5105 if( ! ( val->bv_val[0] == '(' /*')'*/
5106 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5107 && ! ( val->bv_val[0] == '{' /*'}'*/
5108 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5110 return LDAP_INVALID_SYNTAX;
5113 /* trim leading white space */
5115 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5121 /* grab next word */
5122 comp.bv_val = &val->bv_val[len];
5123 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5124 for( comp.bv_len = 0;
5125 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5131 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5132 rc = numericoidValidate( NULL, &comp );
5133 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5134 rc = integerValidate( NULL, &comp );
5136 rc = LDAP_INVALID_SYNTAX;
5140 if( rc == LDAP_SUCCESS ) {
5141 ber_dupbv_x( normalized, &comp, ctx );
5147 static char *country_gen_syn[] = {
5148 "1.3.6.1.4.1.1466.115.121.1.15",
5149 "1.3.6.1.4.1.1466.115.121.1.26",
5150 "1.3.6.1.4.1.1466.115.121.1.44",
5154 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
5155 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
5157 static slap_syntax_defs_rec syntax_defs[] = {
5158 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
5159 X_BINARY X_NOT_H_R ")",
5160 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
5161 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
5162 0, NULL, NULL, NULL},
5163 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
5164 0, NULL, NULL, NULL},
5165 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
5167 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5168 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
5170 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5171 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
5172 0, NULL, bitStringValidate, NULL },
5173 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
5174 0, NULL, booleanValidate, NULL},
5175 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
5176 X_BINARY X_NOT_H_R ")",
5177 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5178 NULL, certificateValidate, NULL},
5179 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
5180 X_BINARY X_NOT_H_R ")",
5181 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5182 NULL, certificateListValidate, NULL},
5183 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
5184 X_BINARY X_NOT_H_R ")",
5185 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5186 NULL, sequenceValidate, NULL},
5187 #if 0 /* need to go __after__ printableString */
5188 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
5189 0, "1.3.6.1.4.1.1466.115.121.1.44",
5190 countryStringValidate, NULL},
5192 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
5193 0, NULL, dnValidate, dnPretty},
5194 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
5195 0, NULL, rdnValidate, rdnPretty},
5196 #ifdef LDAP_COMP_MATCH
5197 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
5198 0, NULL, allComponentsValidate, NULL},
5199 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
5200 0, NULL, componentFilterValidate, NULL},
5202 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
5203 0, NULL, NULL, NULL},
5204 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
5205 0, NULL, deliveryMethodValidate, NULL},
5206 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
5207 0, NULL, UTF8StringValidate, NULL},
5208 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
5209 0, NULL, NULL, NULL},
5210 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
5211 0, NULL, NULL, NULL},
5212 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
5213 0, NULL, NULL, NULL},
5214 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
5215 0, NULL, NULL, NULL},
5216 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
5217 0, NULL, NULL, NULL},
5218 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
5219 0, NULL, printablesStringValidate, NULL},
5220 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
5221 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
5222 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
5223 0, NULL, generalizedTimeValidate, NULL},
5224 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
5225 0, NULL, NULL, NULL},
5226 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
5227 0, NULL, IA5StringValidate, NULL},
5228 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
5229 0, NULL, integerValidate, NULL},
5230 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
5231 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5232 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
5233 0, NULL, NULL, NULL},
5234 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
5235 0, NULL, NULL, NULL},
5236 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
5237 0, NULL, NULL, NULL},
5238 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
5239 0, NULL, NULL, NULL},
5240 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
5241 0, NULL, NULL, NULL},
5242 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
5243 0, NULL, nameUIDValidate, nameUIDPretty },
5244 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
5245 0, NULL, NULL, NULL},
5246 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
5247 0, NULL, numericStringValidate, NULL},
5248 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
5249 0, NULL, NULL, NULL},
5250 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
5251 0, NULL, numericoidValidate, NULL},
5252 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
5253 0, NULL, IA5StringValidate, NULL},
5254 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
5255 0, NULL, blobValidate, NULL},
5256 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
5257 0, NULL, postalAddressValidate, NULL},
5258 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
5259 0, NULL, NULL, NULL},
5260 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
5261 0, NULL, NULL, NULL},
5262 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
5263 0, NULL, printableStringValidate, NULL},
5264 /* moved here because now depends on Directory String, IA5 String
5265 * and Printable String */
5266 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
5267 0, country_gen_syn, countryStringValidate, NULL},
5268 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
5269 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
5270 0, NULL, subtreeSpecificationValidate, NULL},
5271 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
5272 X_BINARY X_NOT_H_R ")",
5273 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5274 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
5275 0, NULL, printableStringValidate, NULL},
5276 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
5277 0, NULL, NULL, NULL},
5278 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
5279 0, NULL, printablesStringValidate, NULL},
5280 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5281 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
5282 0, NULL, utcTimeValidate, NULL},
5284 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
5285 0, NULL, NULL, NULL},
5286 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
5287 0, NULL, NULL, NULL},
5288 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
5289 0, NULL, NULL, NULL},
5290 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
5291 0, NULL, NULL, NULL},
5292 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
5293 0, NULL, NULL, NULL},
5295 /* RFC 2307 NIS Syntaxes */
5296 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
5297 0, NULL, nisNetgroupTripleValidate, NULL},
5298 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
5299 0, NULL, bootParameterValidate, NULL},
5301 /* draft-zeilenga-ldap-x509 */
5302 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
5303 SLAP_SYNTAX_HIDE, NULL,
5304 serialNumberAndIssuerValidate,
5305 serialNumberAndIssuerPretty},
5306 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
5307 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5308 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
5309 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5310 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
5311 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5312 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
5313 SLAP_SYNTAX_HIDE, NULL,
5314 issuerAndThisUpdateValidate,
5315 issuerAndThisUpdatePretty},
5316 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
5317 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5318 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
5319 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5321 #ifdef SLAPD_AUTHPASSWD
5322 /* needs updating */
5323 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
5324 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
5327 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
5328 0, NULL, UUIDValidate, UUIDPretty},
5330 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
5331 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
5333 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
5334 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
5336 /* OpenLDAP Void Syntax */
5337 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
5338 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
5340 /* FIXME: OID is unused, but not registered yet */
5341 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
5342 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
5344 {NULL, 0, NULL, NULL, NULL}
5347 char *csnSIDMatchSyntaxes[] = {
5348 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
5351 char *certificateExactMatchSyntaxes[] = {
5352 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
5355 char *certificateListExactMatchSyntaxes[] = {
5356 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
5359 #ifdef LDAP_COMP_MATCH
5360 char *componentFilterMatchSyntaxes[] = {
5361 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
5362 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
5366 char *directoryStringSyntaxes[] = {
5367 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
5370 char *integerFirstComponentMatchSyntaxes[] = {
5371 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
5372 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
5375 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
5376 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
5377 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
5378 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
5379 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
5380 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
5381 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
5382 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
5383 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
5388 * Other matching rules in X.520 that we do not use (yet):
5390 * 2.5.13.25 uTCTimeMatch
5391 * 2.5.13.26 uTCTimeOrderingMatch
5392 * 2.5.13.31* directoryStringFirstComponentMatch
5393 * 2.5.13.32* wordMatch
5394 * 2.5.13.33* keywordMatch
5395 * 2.5.13.36+ certificatePairExactMatch
5396 * 2.5.13.37+ certificatePairMatch
5397 * 2.5.13.40+ algorithmIdentifierMatch
5398 * 2.5.13.41* storedPrefixMatch
5399 * 2.5.13.42 attributeCertificateMatch
5400 * 2.5.13.43 readerAndKeyIDMatch
5401 * 2.5.13.44 attributeIntegrityMatch
5403 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
5404 * (+) described in draft-zeilenga-ldap-x509
5406 static slap_mrule_defs_rec mrule_defs[] = {
5408 * EQUALITY matching rules must be listed after associated APPROX
5409 * matching rules. So, we list all APPROX matching rules first.
5411 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
5412 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5413 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
5414 NULL, NULL, directoryStringApproxMatch,
5415 directoryStringApproxIndexer, directoryStringApproxFilter,
5418 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
5419 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5420 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
5421 NULL, NULL, IA5StringApproxMatch,
5422 IA5StringApproxIndexer, IA5StringApproxFilter,
5426 * Other matching rules
5429 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
5430 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5431 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5432 NULL, NULL, octetStringMatch,
5433 octetStringIndexer, octetStringFilter,
5436 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
5437 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5438 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5439 NULL, dnNormalize, dnMatch,
5440 octetStringIndexer, octetStringFilter,
5443 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
5444 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5445 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5446 NULL, dnNormalize, dnRelativeMatch,
5450 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
5451 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5452 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5453 NULL, dnNormalize, dnRelativeMatch,
5457 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
5458 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5459 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5460 NULL, dnNormalize, dnRelativeMatch,
5464 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
5465 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
5466 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
5467 NULL, dnNormalize, dnRelativeMatch,
5471 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
5472 "SYNTAX 1.2.36.79672281.1.5.0 )",
5473 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5474 NULL, rdnNormalize, rdnMatch,
5475 octetStringIndexer, octetStringFilter,
5478 #ifdef LDAP_COMP_MATCH
5479 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
5480 "SYNTAX 1.2.36.79672281.1.5.2 )",
5481 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
5482 NULL, NULL , componentFilterMatch,
5483 octetStringIndexer, octetStringFilter,
5486 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
5487 "SYNTAX 1.2.36.79672281.1.5.3 )",
5488 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5489 NULL, NULL , allComponentsMatch,
5490 octetStringIndexer, octetStringFilter,
5493 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
5494 "SYNTAX 1.2.36.79672281.1.5.3 )",
5495 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
5496 NULL, NULL , directoryComponentsMatch,
5497 octetStringIndexer, octetStringFilter,
5501 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
5502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5503 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5504 NULL, UTF8StringNormalize, octetStringMatch,
5505 octetStringIndexer, octetStringFilter,
5506 directoryStringApproxMatchOID },
5508 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
5509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5510 SLAP_MR_ORDERING, directoryStringSyntaxes,
5511 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5513 "caseIgnoreMatch" },
5515 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
5516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5517 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5518 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5519 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5520 "caseIgnoreMatch" },
5522 {"( 2.5.13.5 NAME 'caseExactMatch' "
5523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5524 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5525 NULL, UTF8StringNormalize, octetStringMatch,
5526 octetStringIndexer, octetStringFilter,
5527 directoryStringApproxMatchOID },
5529 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
5530 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5531 SLAP_MR_ORDERING, directoryStringSyntaxes,
5532 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5536 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
5537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5538 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5539 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5540 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5543 {"( 2.5.13.8 NAME 'numericStringMatch' "
5544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5545 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5546 NULL, numericStringNormalize, octetStringMatch,
5547 octetStringIndexer, octetStringFilter,
5550 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
5551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5552 SLAP_MR_ORDERING, NULL,
5553 NULL, numericStringNormalize, octetStringOrderingMatch,
5555 "numericStringMatch" },
5557 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
5558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5559 SLAP_MR_SUBSTR, NULL,
5560 NULL, numericStringNormalize, octetStringSubstringsMatch,
5561 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5562 "numericStringMatch" },
5564 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
5565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
5566 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5567 NULL, postalAddressNormalize, octetStringMatch,
5568 octetStringIndexer, octetStringFilter,
5571 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
5572 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5573 SLAP_MR_SUBSTR, NULL,
5574 NULL, NULL, NULL, NULL, NULL,
5575 "caseIgnoreListMatch" },
5577 {"( 2.5.13.13 NAME 'booleanMatch' "
5578 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
5579 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5580 NULL, NULL, booleanMatch,
5581 octetStringIndexer, octetStringFilter,
5584 {"( 2.5.13.14 NAME 'integerMatch' "
5585 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5586 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5587 NULL, NULL, integerMatch,
5588 integerIndexer, integerFilter,
5591 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
5592 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5593 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5594 NULL, NULL, integerMatch,
5598 {"( 2.5.13.16 NAME 'bitStringMatch' "
5599 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5600 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5601 NULL, NULL, octetStringMatch,
5602 octetStringIndexer, octetStringFilter,
5605 {"( 2.5.13.17 NAME 'octetStringMatch' "
5606 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5607 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5608 NULL, NULL, octetStringMatch,
5609 octetStringIndexer, octetStringFilter,
5612 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5613 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5614 SLAP_MR_ORDERING, NULL,
5615 NULL, NULL, octetStringOrderingMatch,
5617 "octetStringMatch" },
5619 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5621 SLAP_MR_SUBSTR, NULL,
5622 NULL, NULL, octetStringSubstringsMatch,
5623 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5624 "octetStringMatch" },
5626 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5628 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5630 telephoneNumberNormalize, octetStringMatch,
5631 octetStringIndexer, octetStringFilter,
5634 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5635 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5636 SLAP_MR_SUBSTR, NULL,
5637 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5638 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5639 "telephoneNumberMatch" },
5641 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5642 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5643 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5644 NULL, NULL, NULL, NULL, NULL, NULL },
5646 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5647 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5648 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5649 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5650 uniqueMemberIndexer, uniqueMemberFilter,
5653 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5654 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5655 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5656 NULL, NULL, NULL, NULL, NULL, NULL },
5658 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5659 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5660 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5661 NULL, generalizedTimeNormalize, octetStringMatch,
5662 generalizedTimeIndexer, generalizedTimeFilter,
5665 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5666 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5667 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5668 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5670 "generalizedTimeMatch" },
5672 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5673 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5674 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5675 integerFirstComponentMatchSyntaxes,
5676 NULL, firstComponentNormalize, integerMatch,
5677 octetStringIndexer, octetStringFilter,
5680 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5681 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5682 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5683 objectIdentifierFirstComponentMatchSyntaxes,
5684 NULL, firstComponentNormalize, octetStringMatch,
5685 octetStringIndexer, octetStringFilter,
5688 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5689 "SYNTAX 1.3.6.1.1.15.1 )",
5690 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5691 NULL, certificateExactNormalize, octetStringMatch,
5692 octetStringIndexer, octetStringFilter,
5695 {"( 2.5.13.35 NAME 'certificateMatch' "
5696 "SYNTAX 1.3.6.1.1.15.2 )",
5697 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5698 NULL, NULL, NULL, NULL, NULL,
5701 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
5702 "SYNTAX 1.3.6.1.1.15.5 )",
5703 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
5704 NULL, certificateListExactNormalize, octetStringMatch,
5705 octetStringIndexer, octetStringFilter,
5708 {"( 2.5.13.39 NAME 'certificateListMatch' "
5709 "SYNTAX 1.3.6.1.1.15.6 )",
5710 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5711 NULL, NULL, NULL, NULL, NULL,
5714 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5715 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5716 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5717 NULL, IA5StringNormalize, octetStringMatch,
5718 octetStringIndexer, octetStringFilter,
5719 IA5StringApproxMatchOID },
5721 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5722 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5723 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5724 NULL, IA5StringNormalize, octetStringMatch,
5725 octetStringIndexer, octetStringFilter,
5726 IA5StringApproxMatchOID },
5728 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5729 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5730 SLAP_MR_SUBSTR, NULL,
5731 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5732 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5733 "caseIgnoreIA5Match" },
5735 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5736 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5737 SLAP_MR_SUBSTR, NULL,
5738 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5739 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5740 "caseExactIA5Match" },
5742 #ifdef SLAPD_AUTHPASSWD
5743 /* needs updating */
5744 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5745 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5746 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5747 NULL, NULL, authPasswordMatch,
5752 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5753 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5755 NULL, NULL, integerBitAndMatch,
5759 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5760 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5762 NULL, NULL, integerBitOrMatch,
5766 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5767 "SYNTAX 1.3.6.1.1.16.1 )",
5768 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5769 NULL, UUIDNormalize, octetStringMatch,
5770 octetStringIndexer, octetStringFilter,
5773 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5774 "SYNTAX 1.3.6.1.1.16.1 )",
5775 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5776 NULL, UUIDNormalize, octetStringOrderingMatch,
5777 octetStringIndexer, octetStringFilter,
5780 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5781 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5782 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5783 NULL, csnNormalize, csnMatch,
5784 csnIndexer, csnFilter,
5787 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5788 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5789 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5790 NULL, NULL, csnOrderingMatch,
5794 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5795 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5796 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5797 NULL, csnSidNormalize, octetStringMatch,
5798 octetStringIndexer, octetStringFilter,
5801 /* FIXME: OID is unused, but not registered yet */
5802 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5803 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5804 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5805 NULL, authzNormalize, authzMatch,
5809 {NULL, SLAP_MR_NONE, NULL,
5810 NULL, NULL, NULL, NULL, NULL,
5815 slap_schema_init( void )
5820 /* we should only be called once (from main) */
5821 assert( schema_init_done == 0 );
5823 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5824 res = register_syntax( &syntax_defs[i] );
5827 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5828 syntax_defs[i].sd_desc );
5833 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5834 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5835 mrule_defs[i].mrd_compat_syntaxes == NULL )
5838 "slap_schema_init: Ignoring unusable matching rule %s\n",
5839 mrule_defs[i].mrd_desc );
5843 res = register_matching_rule( &mrule_defs[i] );
5847 "slap_schema_init: Error registering matching rule %s\n",
5848 mrule_defs[i].mrd_desc );
5853 res = slap_schema_load();
5854 schema_init_done = 1;
5859 schema_destroy( void )
5868 if( schema_init_done ) {
5869 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5870 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );