1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
67 ldap_pvt_thread_mutex_t ad_undef_mutex;
68 ldap_pvt_thread_mutex_t oc_undef_mutex;
71 generalizedTimeValidate(
80 /* no value allowed */
81 return LDAP_INVALID_SYNTAX;
89 /* any value allowed */
93 #define berValidate blobValidate
100 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
101 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
106 /* X.509 related stuff */
114 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
117 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
118 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
119 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
120 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
124 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
127 /* X.509 certificate validation */
128 static int certificateValidate( Syntax *syntax, struct berval *in )
130 BerElementBuffer berbuf;
131 BerElement *ber = (BerElement *)&berbuf;
134 ber_int_t version = SLAP_X509_V1;
136 ber_init2( ber, in, LBER_USE_DER );
137 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
138 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
139 tag = ber_skip_tag( ber, &len ); /* Sequence */
140 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 tag = ber_peek_tag( ber, &len );
142 /* Optional version */
143 if ( tag == SLAP_X509_OPT_C_VERSION ) {
144 tag = ber_skip_tag( ber, &len );
145 tag = ber_get_int( ber, &version );
146 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
148 /* NOTE: don't try to parse Serial, because it might be longer
149 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
150 tag = ber_skip_tag( ber, &len ); /* Serial */
151 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
152 ber_skip_data( ber, len );
153 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
154 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
155 ber_skip_data( ber, len );
156 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
157 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
158 ber_skip_data( ber, len );
159 tag = ber_skip_tag( ber, &len ); /* Validity */
160 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
161 ber_skip_data( ber, len );
162 tag = ber_skip_tag( ber, &len ); /* Subject DN */
163 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
164 ber_skip_data( ber, len );
165 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
166 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
167 ber_skip_data( ber, len );
168 tag = ber_skip_tag( ber, &len );
169 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
170 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
171 ber_skip_data( ber, len );
172 tag = ber_skip_tag( ber, &len );
174 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
175 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
176 ber_skip_data( ber, len );
177 tag = ber_skip_tag( ber, &len );
179 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
180 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
181 tag = ber_skip_tag( ber, &len );
182 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
183 ber_skip_data( ber, len );
184 tag = ber_skip_tag( ber, &len );
186 /* signatureAlgorithm */
187 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
188 ber_skip_data( ber, len );
189 tag = ber_skip_tag( ber, &len );
191 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
192 ber_skip_data( ber, len );
193 tag = ber_skip_tag( ber, &len );
194 /* Must be at end now */
195 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
199 /* X.509 certificate list validation */
200 static int certificateListValidate( Syntax *syntax, struct berval *in )
202 BerElementBuffer berbuf;
203 BerElement *ber = (BerElement *)&berbuf;
206 ber_int_t version = SLAP_X509_V1;
208 ber_init2( ber, in, LBER_USE_DER );
209 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
210 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
211 tag = ber_skip_tag( ber, &len ); /* Sequence */
212 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
213 tag = ber_peek_tag( ber, &len );
214 /* Optional version */
215 if ( tag == LBER_INTEGER ) {
216 tag = ber_get_int( ber, &version );
217 assert( tag == LBER_INTEGER );
218 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
220 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
221 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
222 ber_skip_data( ber, len );
223 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
224 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
225 ber_skip_data( ber, len );
226 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
227 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
228 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
229 ber_skip_data( ber, len );
230 /* Optional nextUpdate */
231 tag = ber_skip_tag( ber, &len );
232 if ( tag == 0x17U || tag == 0x18U ) {
233 ber_skip_data( ber, len );
234 tag = ber_skip_tag( ber, &len );
236 /* revokedCertificates - Sequence of Sequence, Optional */
237 if ( tag == LBER_SEQUENCE ) {
239 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
240 /* Should NOT be empty */
241 ber_skip_data( ber, len );
242 tag = ber_skip_tag( ber, &len );
245 /* Optional Extensions */
246 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
247 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
248 tag = ber_skip_tag( ber, &len );
249 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
250 ber_skip_data( ber, len );
251 tag = ber_skip_tag( ber, &len );
253 /* signatureAlgorithm */
254 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
255 ber_skip_data( ber, len );
256 tag = ber_skip_tag( ber, &len );
258 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
259 ber_skip_data( ber, len );
260 tag = ber_skip_tag( ber, &len );
261 /* Must be at end now */
262 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
272 struct berval *value,
273 void *assertedValue )
275 struct berval *asserted = (struct berval *) assertedValue;
276 int match = value->bv_len - asserted->bv_len;
279 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
287 octetStringOrderingMatch(
292 struct berval *value,
293 void *assertedValue )
295 struct berval *asserted = (struct berval *) assertedValue;
296 ber_len_t v_len = value->bv_len;
297 ber_len_t av_len = asserted->bv_len;
299 int match = memcmp( value->bv_val, asserted->bv_val,
300 (v_len < av_len ? v_len : av_len) );
302 if( match == 0 ) match = v_len - av_len;
310 HASH_CONTEXT *HASHcontext,
311 struct berval *prefix,
316 HASH_Init(HASHcontext);
317 if(prefix && prefix->bv_len > 0) {
318 HASH_Update(HASHcontext,
319 (unsigned char *)prefix->bv_val, prefix->bv_len);
321 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
322 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
323 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
329 HASH_CONTEXT *HASHcontext,
330 unsigned char *HASHdigest,
331 unsigned char *value,
334 HASH_CONTEXT ctx = *HASHcontext;
335 HASH_Update( &ctx, value, len );
336 HASH_Final( HASHdigest, &ctx );
339 /* Index generation function */
340 int octetStringIndexer(
345 struct berval *prefix,
353 HASH_CONTEXT HASHcontext;
354 unsigned char HASHdigest[HASH_BYTES];
355 struct berval digest;
356 digest.bv_val = (char *)HASHdigest;
357 digest.bv_len = sizeof(HASHdigest);
359 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
360 /* just count them */
363 /* we should have at least one value at this point */
366 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
368 slen = syntax->ssyn_oidlen;
369 mlen = mr->smr_oidlen;
371 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
372 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
373 hashIter( &HASHcontext, HASHdigest,
374 (unsigned char *)values[i].bv_val, values[i].bv_len );
375 ber_dupbv_x( &keys[i], &digest, ctx );
378 BER_BVZERO( &keys[i] );
385 /* Index generation function */
386 int octetStringFilter(
391 struct berval *prefix,
392 void * assertedValue,
398 HASH_CONTEXT HASHcontext;
399 unsigned char HASHdigest[HASH_BYTES];
400 struct berval *value = (struct berval *) assertedValue;
401 struct berval digest;
402 digest.bv_val = (char *)HASHdigest;
403 digest.bv_len = sizeof(HASHdigest);
405 slen = syntax->ssyn_oidlen;
406 mlen = mr->smr_oidlen;
408 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
410 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
411 hashIter( &HASHcontext, HASHdigest,
412 (unsigned char *)value->bv_val, value->bv_len );
414 ber_dupbv_x( keys, &digest, ctx );
415 BER_BVZERO( &keys[1] );
423 octetStringSubstringsMatch(
428 struct berval *value,
429 void *assertedValue )
432 SubstringsAssertion *sub = assertedValue;
433 struct berval left = *value;
437 /* Add up asserted input length */
438 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
439 inlen += sub->sa_initial.bv_len;
442 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
443 inlen += sub->sa_any[i].bv_len;
446 if ( !BER_BVISNULL( &sub->sa_final ) ) {
447 inlen += sub->sa_final.bv_len;
450 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
451 if ( inlen > left.bv_len ) {
456 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
457 sub->sa_initial.bv_len );
463 left.bv_val += sub->sa_initial.bv_len;
464 left.bv_len -= sub->sa_initial.bv_len;
465 inlen -= sub->sa_initial.bv_len;
468 if ( !BER_BVISNULL( &sub->sa_final ) ) {
469 if ( inlen > left.bv_len ) {
474 match = memcmp( sub->sa_final.bv_val,
475 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
476 sub->sa_final.bv_len );
482 left.bv_len -= sub->sa_final.bv_len;
483 inlen -= sub->sa_final.bv_len;
487 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
492 if ( inlen > left.bv_len ) {
493 /* not enough length */
498 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
502 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
509 idx = p - left.bv_val;
511 if ( idx >= left.bv_len ) {
512 /* this shouldn't happen */
519 if ( sub->sa_any[i].bv_len > left.bv_len ) {
520 /* not enough left */
525 match = memcmp( left.bv_val,
526 sub->sa_any[i].bv_val,
527 sub->sa_any[i].bv_len );
535 left.bv_val += sub->sa_any[i].bv_len;
536 left.bv_len -= sub->sa_any[i].bv_len;
537 inlen -= sub->sa_any[i].bv_len;
546 /* Substrings Index generation function */
548 octetStringSubstringsIndexer(
553 struct berval *prefix,
562 HASH_CONTEXT HCany, HCini, HCfin;
563 unsigned char HASHdigest[HASH_BYTES];
564 struct berval digest;
565 digest.bv_val = (char *)HASHdigest;
566 digest.bv_len = sizeof(HASHdigest);
570 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
571 /* count number of indices to generate */
572 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
573 if( values[i].bv_len >= index_substr_if_maxlen ) {
574 nkeys += index_substr_if_maxlen -
575 (index_substr_if_minlen - 1);
576 } else if( values[i].bv_len >= index_substr_if_minlen ) {
577 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
581 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
582 if( values[i].bv_len >= index_substr_any_len ) {
583 nkeys += values[i].bv_len - (index_substr_any_len - 1);
587 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
588 if( values[i].bv_len >= index_substr_if_maxlen ) {
589 nkeys += index_substr_if_maxlen -
590 (index_substr_if_minlen - 1);
591 } else if( values[i].bv_len >= index_substr_if_minlen ) {
592 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
598 /* no keys to generate */
603 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
605 slen = syntax->ssyn_oidlen;
606 mlen = mr->smr_oidlen;
608 if ( flags & SLAP_INDEX_SUBSTR_ANY )
609 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
610 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
611 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
612 if( flags & SLAP_INDEX_SUBSTR_FINAL )
613 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
616 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
619 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
620 ( values[i].bv_len >= index_substr_any_len ) )
622 max = values[i].bv_len - (index_substr_any_len - 1);
624 for( j=0; j<max; j++ ) {
625 hashIter( &HCany, HASHdigest,
626 (unsigned char *)&values[i].bv_val[j],
627 index_substr_any_len );
628 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
632 /* skip if too short */
633 if( values[i].bv_len < index_substr_if_minlen ) continue;
635 max = index_substr_if_maxlen < values[i].bv_len
636 ? index_substr_if_maxlen : values[i].bv_len;
638 for( j=index_substr_if_minlen; j<=max; j++ ) {
640 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
641 hashIter( &HCini, HASHdigest,
642 (unsigned char *)values[i].bv_val, j );
643 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
646 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
647 hashIter( &HCfin, HASHdigest,
648 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
649 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
656 BER_BVZERO( &keys[nkeys] );
667 octetStringSubstringsFilter (
672 struct berval *prefix,
673 void * assertedValue,
677 SubstringsAssertion *sa;
680 size_t slen, mlen, klen;
682 HASH_CONTEXT HASHcontext;
683 unsigned char HASHdigest[HASH_BYTES];
684 struct berval *value;
685 struct berval digest;
687 sa = (SubstringsAssertion *) assertedValue;
689 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
690 !BER_BVISNULL( &sa->sa_initial ) &&
691 sa->sa_initial.bv_len >= index_substr_if_minlen )
694 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
695 ( flags & SLAP_INDEX_SUBSTR_ANY ))
697 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
701 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
703 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
704 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
705 /* don't bother accounting with stepping */
706 nkeys += sa->sa_any[i].bv_len -
707 ( index_substr_any_len - 1 );
712 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
713 !BER_BVISNULL( &sa->sa_final ) &&
714 sa->sa_final.bv_len >= index_substr_if_minlen )
717 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
718 ( flags & SLAP_INDEX_SUBSTR_ANY ))
720 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
729 digest.bv_val = (char *)HASHdigest;
730 digest.bv_len = sizeof(HASHdigest);
732 slen = syntax->ssyn_oidlen;
733 mlen = mr->smr_oidlen;
735 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
738 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
739 !BER_BVISNULL( &sa->sa_initial ) &&
740 sa->sa_initial.bv_len >= index_substr_if_minlen )
742 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
743 value = &sa->sa_initial;
745 klen = index_substr_if_maxlen < value->bv_len
746 ? index_substr_if_maxlen : value->bv_len;
748 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
749 hashIter( &HASHcontext, HASHdigest,
750 (unsigned char *)value->bv_val, klen );
751 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
753 /* If initial is too long and we have subany indexed, use it
754 * to match the excess...
756 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
759 pre = SLAP_INDEX_SUBSTR_PREFIX;
760 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
761 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
763 hashIter( &HASHcontext, HASHdigest,
764 (unsigned char *)&value->bv_val[j], index_substr_any_len );
765 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
770 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
772 pre = SLAP_INDEX_SUBSTR_PREFIX;
773 klen = index_substr_any_len;
775 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
776 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
780 value = &sa->sa_any[i];
782 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
784 j <= value->bv_len - index_substr_any_len;
785 j += index_substr_any_step )
787 hashIter( &HASHcontext, HASHdigest,
788 (unsigned char *)&value->bv_val[j], klen );
789 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
794 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
795 !BER_BVISNULL( &sa->sa_final ) &&
796 sa->sa_final.bv_len >= index_substr_if_minlen )
798 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
799 value = &sa->sa_final;
801 klen = index_substr_if_maxlen < value->bv_len
802 ? index_substr_if_maxlen : value->bv_len;
804 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
805 hashIter( &HASHcontext, HASHdigest,
806 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
807 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
809 /* If final is too long and we have subany indexed, use it
810 * to match the excess...
812 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
815 pre = SLAP_INDEX_SUBSTR_PREFIX;
816 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
817 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
819 hashIter( &HASHcontext, HASHdigest,
820 (unsigned char *)&value->bv_val[j], index_substr_any_len );
821 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
827 BER_BVZERO( &keys[nkeys] );
844 /* very unforgiving validation, requires no normalization
845 * before simplistic matching
847 if( in->bv_len < 3 ) {
848 return LDAP_INVALID_SYNTAX;
851 /* RFC 4517 Section 3.3.2 Bit String:
852 * BitString = SQUOTE *binary-digit SQUOTE "B"
853 * binary-digit = "0" / "1"
855 * where SQUOTE [RFC4512] is
856 * SQUOTE = %x27 ; single quote ("'")
858 * Example: '0101111101'B
861 if( in->bv_val[0] != '\'' ||
862 in->bv_val[in->bv_len - 2] != '\'' ||
863 in->bv_val[in->bv_len - 1] != 'B' )
865 return LDAP_INVALID_SYNTAX;
868 for( i = in->bv_len - 3; i > 0; i-- ) {
869 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
870 return LDAP_INVALID_SYNTAX;
878 * Syntaxes from RFC 4517
883 A value of the Bit String syntax is a sequence of binary digits. The
884 LDAP-specific encoding of a value of this syntax is defined by the
887 BitString = SQUOTE *binary-digit SQUOTE "B"
889 binary-digit = "0" / "1"
891 The <SQUOTE> rule is defined in [MODELS].
896 The LDAP definition for the Bit String syntax is:
898 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
900 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
904 3.3.21. Name and Optional UID
906 A value of the Name and Optional UID syntax is the distinguished name
907 [MODELS] of an entity optionally accompanied by a unique identifier
908 that serves to differentiate the entity from others with an identical
911 The LDAP-specific encoding of a value of this syntax is defined by
914 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
916 The <BitString> rule is defined in Section 3.3.2. The
917 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
920 Note that although the '#' character may occur in the string
921 representation of a distinguished name, no additional escaping of
922 this character is performed when a <distinguishedName> is encoded in
923 a <NameAndOptionalUID>.
926 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
928 The LDAP definition for the Name and Optional UID syntax is:
930 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
932 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
939 1.4. Common ABNF Productions
942 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
944 SQUOTE = %x27 ; single quote ("'")
948 * Note: normalization strips any leading "0"s, unless the
949 * bit string is exactly "'0'B", so the normalized example,
950 * in slapd, would result in
952 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
954 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
955 * be escaped except when at the beginning of a value, the
956 * definition of Name and Optional UID appears to be flawed,
957 * because there is no clear means to determine whether the
958 * UID part is present or not.
962 * cn=Someone,dc=example,dc=com#'1'B
964 * could be either a NameAndOptionalUID with trailing UID, i.e.
966 * DN = "cn=Someone,dc=example,dc=com"
969 * or a NameAndOptionalUID with no trailing UID, and the AVA
970 * in the last RDN made of
973 * attributeValue = com#'1'B
975 * in fact "com#'1'B" is a valid IA5 string.
977 * As a consequence, current slapd code assumes that the
978 * presence of portions of a BitString at the end of the string
979 * representation of a NameAndOptionalUID means a BitString
980 * is expected, and cause an error otherwise. This is quite
981 * arbitrary, and might change in the future.
991 struct berval dn, uid;
993 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
995 ber_dupbv( &dn, in );
996 if( !dn.bv_val ) return LDAP_OTHER;
998 /* if there's a "#", try bitStringValidate()... */
999 uid.bv_val = strrchr( dn.bv_val, '#' );
1000 if ( !BER_BVISNULL( &uid ) ) {
1002 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1004 rc = bitStringValidate( NULL, &uid );
1005 if ( rc == LDAP_SUCCESS ) {
1006 /* in case of success, trim the UID,
1007 * otherwise treat it as part of the DN */
1008 dn.bv_len -= uid.bv_len + 1;
1009 uid.bv_val[-1] = '\0';
1013 rc = dnValidate( NULL, &dn );
1015 ber_memfree( dn.bv_val );
1026 assert( val != NULL );
1027 assert( out != NULL );
1030 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1032 if( BER_BVISEMPTY( val ) ) {
1033 ber_dupbv_x( out, val, ctx );
1035 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1036 return LDAP_INVALID_SYNTAX;
1040 struct berval dnval = *val;
1041 struct berval uidval = BER_BVNULL;
1043 uidval.bv_val = strrchr( val->bv_val, '#' );
1044 if ( !BER_BVISNULL( &uidval ) ) {
1046 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1048 rc = bitStringValidate( NULL, &uidval );
1050 if ( rc == LDAP_SUCCESS ) {
1051 ber_dupbv_x( &dnval, val, ctx );
1052 dnval.bv_len -= uidval.bv_len + 1;
1053 dnval.bv_val[dnval.bv_len] = '\0';
1056 BER_BVZERO( &uidval );
1060 rc = dnPretty( syntax, &dnval, out, ctx );
1061 if ( dnval.bv_val != val->bv_val ) {
1062 slap_sl_free( dnval.bv_val, ctx );
1064 if( rc != LDAP_SUCCESS ) {
1068 if( !BER_BVISNULL( &uidval ) ) {
1072 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1073 + STRLENOF( "#" ) + uidval.bv_len + 1,
1076 ber_memfree_x( out->bv_val, ctx );
1080 out->bv_val[out->bv_len++] = '#';
1081 out->bv_val[out->bv_len++] = '\'';
1083 got1 = uidval.bv_len < sizeof("'0'B");
1084 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1085 c = uidval.bv_val[i];
1088 if( got1 ) out->bv_val[out->bv_len++] = c;
1092 out->bv_val[out->bv_len++] = c;
1097 out->bv_val[out->bv_len++] = '\'';
1098 out->bv_val[out->bv_len++] = 'B';
1099 out->bv_val[out->bv_len] = '\0';
1103 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1105 return LDAP_SUCCESS;
1109 uniqueMemberNormalize(
1114 struct berval *normalized,
1120 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1122 ber_dupbv_x( &out, val, ctx );
1123 if ( BER_BVISEMPTY( &out ) ) {
1127 struct berval uid = BER_BVNULL;
1129 uid.bv_val = strrchr( out.bv_val, '#' );
1130 if ( !BER_BVISNULL( &uid ) ) {
1132 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1134 rc = bitStringValidate( NULL, &uid );
1135 if ( rc == LDAP_SUCCESS ) {
1136 uid.bv_val[-1] = '\0';
1137 out.bv_len -= uid.bv_len + 1;
1143 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1145 if( rc != LDAP_SUCCESS ) {
1146 slap_sl_free( out.bv_val, ctx );
1147 return LDAP_INVALID_SYNTAX;
1150 if( !BER_BVISNULL( &uid ) ) {
1153 tmp = ch_realloc( normalized->bv_val,
1154 normalized->bv_len + uid.bv_len
1155 + STRLENOF("#") + 1 );
1156 if ( tmp == NULL ) {
1157 ber_memfree_x( normalized->bv_val, ctx );
1161 normalized->bv_val = tmp;
1163 /* insert the separator */
1164 normalized->bv_val[normalized->bv_len++] = '#';
1166 /* append the UID */
1167 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1168 uid.bv_val, uid.bv_len );
1169 normalized->bv_len += uid.bv_len;
1172 normalized->bv_val[normalized->bv_len] = '\0';
1175 slap_sl_free( out.bv_val, ctx );
1178 return LDAP_SUCCESS;
1187 struct berval *value,
1188 void *assertedValue )
1191 struct berval *asserted = (struct berval *) assertedValue;
1192 struct berval assertedDN = *asserted;
1193 struct berval assertedUID = BER_BVNULL;
1194 struct berval valueDN = *value;
1195 struct berval valueUID = BER_BVNULL;
1196 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1198 if ( !BER_BVISEMPTY( asserted ) ) {
1199 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1200 if ( !BER_BVISNULL( &assertedUID ) ) {
1201 assertedUID.bv_val++;
1202 assertedUID.bv_len = assertedDN.bv_len
1203 - ( assertedUID.bv_val - assertedDN.bv_val );
1205 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1206 assertedDN.bv_len -= assertedUID.bv_len + 1;
1209 BER_BVZERO( &assertedUID );
1214 if ( !BER_BVISEMPTY( value ) ) {
1216 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1217 if ( !BER_BVISNULL( &valueUID ) ) {
1219 valueUID.bv_len = valueDN.bv_len
1220 - ( valueUID.bv_val - valueDN.bv_val );
1222 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1223 valueDN.bv_len -= valueUID.bv_len + 1;
1226 BER_BVZERO( &valueUID );
1231 if( valueUID.bv_len && assertedUID.bv_len ) {
1232 match = valueUID.bv_len - assertedUID.bv_len;
1235 return LDAP_SUCCESS;
1238 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1241 return LDAP_SUCCESS;
1244 } else if ( !approx && valueUID.bv_len ) {
1247 return LDAP_SUCCESS;
1249 } else if ( !approx && assertedUID.bv_len ) {
1252 return LDAP_SUCCESS;
1255 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1259 uniqueMemberIndexer(
1264 struct berval *prefix,
1272 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1273 /* just count them */
1277 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1279 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1280 struct berval assertedDN = values[i];
1281 struct berval assertedUID = BER_BVNULL;
1283 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1284 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1285 if ( !BER_BVISNULL( &assertedUID ) ) {
1286 assertedUID.bv_val++;
1287 assertedUID.bv_len = assertedDN.bv_len
1288 - ( assertedUID.bv_val - assertedDN.bv_val );
1290 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1291 assertedDN.bv_len -= assertedUID.bv_len + 1;
1294 BER_BVZERO( &assertedUID );
1299 dnvalues[i] = assertedDN;
1301 BER_BVZERO( &dnvalues[i] );
1303 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1304 dnvalues, keysp, ctx );
1306 slap_sl_free( dnvalues, ctx );
1316 struct berval *prefix,
1317 void * assertedValue,
1321 struct berval *asserted = (struct berval *) assertedValue;
1322 struct berval assertedDN = *asserted;
1323 struct berval assertedUID = BER_BVNULL;
1325 if ( !BER_BVISEMPTY( asserted ) ) {
1326 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1327 if ( !BER_BVISNULL( &assertedUID ) ) {
1328 assertedUID.bv_val++;
1329 assertedUID.bv_len = assertedDN.bv_len
1330 - ( assertedUID.bv_val - assertedDN.bv_val );
1332 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1333 assertedDN.bv_len -= assertedUID.bv_len + 1;
1336 BER_BVZERO( &assertedUID );
1341 return octetStringFilter( use, flags, syntax, mr, prefix,
1342 &assertedDN, keysp, ctx );
1347 * Handling boolean syntax and matching is quite rigid.
1348 * A more flexible approach would be to allow a variety
1349 * of strings to be normalized and prettied into TRUE
1357 /* very unforgiving validation, requires no normalization
1358 * before simplistic matching
1361 if( in->bv_len == 4 ) {
1362 if( bvmatch( in, &slap_true_bv ) ) {
1363 return LDAP_SUCCESS;
1365 } else if( in->bv_len == 5 ) {
1366 if( bvmatch( in, &slap_false_bv ) ) {
1367 return LDAP_SUCCESS;
1371 return LDAP_INVALID_SYNTAX;
1380 struct berval *value,
1381 void *assertedValue )
1383 /* simplistic matching allowed by rigid validation */
1384 struct berval *asserted = (struct berval *) assertedValue;
1385 *matchp = value->bv_len != asserted->bv_len;
1386 return LDAP_SUCCESS;
1389 /*-------------------------------------------------------------------
1390 LDAP/X.500 string syntax / matching rules have a few oddities. This
1391 comment attempts to detail how slapd(8) treats them.
1394 StringSyntax X.500 LDAP Matching/Comments
1395 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1396 PrintableString subset subset i/e + ignore insignificant spaces
1397 PrintableString subset subset i/e + ignore insignificant spaces
1398 NumericString subset subset ignore all spaces
1399 IA5String ASCII ASCII i/e + ignore insignificant spaces
1400 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1402 TelephoneNumber subset subset i + ignore all spaces and "-"
1404 See RFC 4518 for details.
1408 In X.500(93), a directory string can be either a PrintableString,
1409 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1410 In later versions, more CHOICEs were added. In all cases the string
1413 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1414 A directory string cannot be zero length.
1416 For matching, there are both case ignore and exact rules. Both
1417 also require that "insignificant" spaces be ignored.
1418 spaces before the first non-space are ignored;
1419 spaces after the last non-space are ignored;
1420 spaces after a space are ignored.
1421 Note: by these rules (and as clarified in X.520), a string of only
1422 spaces is to be treated as if held one space, not empty (which
1423 would be a syntax error).
1426 In ASN.1, numeric string is just a string of digits and spaces
1427 and could be empty. However, in X.500, all attribute values of
1428 numeric string carry a non-empty constraint. For example:
1430 internationalISDNNumber ATTRIBUTE ::= {
1431 WITH SYNTAX InternationalISDNNumber
1432 EQUALITY MATCHING RULE numericStringMatch
1433 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1434 ID id-at-internationalISDNNumber }
1435 InternationalISDNNumber ::=
1436 NumericString (SIZE(1..ub-international-isdn-number))
1438 Unforunately, some assertion values are don't carry the same
1439 constraint (but its unclear how such an assertion could ever
1440 be true). In LDAP, there is one syntax (numericString) not two
1441 (numericString with constraint, numericString without constraint).
1442 This should be treated as numericString with non-empty constraint.
1443 Note that while someone may have no ISDN number, there are no ISDN
1444 numbers which are zero length.
1446 In matching, spaces are ignored.
1449 In ASN.1, Printable string is just a string of printable characters
1450 and can be empty. In X.500, semantics much like NumericString (see
1451 serialNumber for a like example) excepting uses insignificant space
1452 handling instead of ignore all spaces. They must be non-empty.
1455 Basically same as PrintableString. There are no examples in X.500,
1456 but same logic applies. Empty strings are allowed.
1458 -------------------------------------------------------------------*/
1467 unsigned char *u = (unsigned char *)in->bv_val;
1469 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1470 /* directory strings cannot be empty */
1471 return LDAP_INVALID_SYNTAX;
1474 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1475 /* get the length indicated by the first byte */
1476 len = LDAP_UTF8_CHARLEN2( u, len );
1478 /* very basic checks */
1481 if( (u[5] & 0xC0) != 0x80 ) {
1482 return LDAP_INVALID_SYNTAX;
1485 if( (u[4] & 0xC0) != 0x80 ) {
1486 return LDAP_INVALID_SYNTAX;
1489 if( (u[3] & 0xC0) != 0x80 ) {
1490 return LDAP_INVALID_SYNTAX;
1493 if( (u[2] & 0xC0 )!= 0x80 ) {
1494 return LDAP_INVALID_SYNTAX;
1497 if( (u[1] & 0xC0) != 0x80 ) {
1498 return LDAP_INVALID_SYNTAX;
1501 /* CHARLEN already validated it */
1504 return LDAP_INVALID_SYNTAX;
1507 /* make sure len corresponds with the offset
1508 to the next character */
1509 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1513 return LDAP_INVALID_SYNTAX;
1516 return LDAP_SUCCESS;
1520 UTF8StringNormalize(
1525 struct berval *normalized,
1528 struct berval tmp, nvalue;
1532 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1534 if( BER_BVISNULL( val ) ) {
1535 /* assume we're dealing with a syntax (e.g., UTF8String)
1536 * which allows empty strings
1538 BER_BVZERO( normalized );
1539 return LDAP_SUCCESS;
1542 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1543 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1544 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1545 ? LDAP_UTF8_APPROX : 0;
1547 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1552 /* collapse spaces (in place) */
1554 nvalue.bv_val = tmp.bv_val;
1556 /* trim leading spaces? */
1557 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1558 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1560 for( i = 0; i < tmp.bv_len; i++) {
1561 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1562 if( wasspace++ == 0 ) {
1563 /* trim repeated spaces */
1564 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1568 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1572 if( !BER_BVISEMPTY( &nvalue ) ) {
1573 /* trim trailing space? */
1575 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1576 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1580 nvalue.bv_val[nvalue.bv_len] = '\0';
1583 /* string of all spaces is treated as one space */
1584 nvalue.bv_val[0] = ' ';
1585 nvalue.bv_val[1] = '\0';
1589 *normalized = nvalue;
1590 return LDAP_SUCCESS;
1594 directoryStringSubstringsMatch(
1599 struct berval *value,
1600 void *assertedValue )
1603 SubstringsAssertion *sub = assertedValue;
1604 struct berval left = *value;
1608 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1609 if ( sub->sa_initial.bv_len > left.bv_len ) {
1610 /* not enough left */
1615 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1616 sub->sa_initial.bv_len );
1622 left.bv_val += sub->sa_initial.bv_len;
1623 left.bv_len -= sub->sa_initial.bv_len;
1625 priorspace = ASCII_SPACE(
1626 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1629 if ( sub->sa_any ) {
1630 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1634 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1635 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1637 /* allow next space to match */
1644 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1648 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1649 /* not enough left */
1654 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1661 idx = p - left.bv_val;
1663 if ( idx >= left.bv_len ) {
1664 /* this shouldn't happen */
1671 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1672 /* not enough left */
1677 match = memcmp( left.bv_val,
1678 sub->sa_any[i].bv_val,
1679 sub->sa_any[i].bv_len );
1687 left.bv_val += sub->sa_any[i].bv_len;
1688 left.bv_len -= sub->sa_any[i].bv_len;
1690 priorspace = ASCII_SPACE(
1691 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1695 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1696 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1697 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1699 /* allow next space to match */
1704 if ( sub->sa_final.bv_len > left.bv_len ) {
1705 /* not enough left */
1710 match = memcmp( sub->sa_final.bv_val,
1711 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1712 sub->sa_final.bv_len );
1721 return LDAP_SUCCESS;
1724 #if defined(SLAPD_APPROX_INITIALS)
1725 # define SLAPD_APPROX_DELIMITER "._ "
1726 # define SLAPD_APPROX_WORDLEN 2
1728 # define SLAPD_APPROX_DELIMITER " "
1729 # define SLAPD_APPROX_WORDLEN 1
1738 struct berval *value,
1739 void *assertedValue )
1741 struct berval *nval, *assertv;
1742 char *val, **values, **words, *c;
1743 int i, count, len, nextchunk=0, nextavail=0;
1745 /* Yes, this is necessary */
1746 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1747 if( nval == NULL ) {
1749 return LDAP_SUCCESS;
1752 /* Yes, this is necessary */
1753 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1754 NULL, LDAP_UTF8_APPROX, NULL );
1755 if( assertv == NULL ) {
1758 return LDAP_SUCCESS;
1761 /* Isolate how many words there are */
1762 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1763 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1764 if ( c == NULL ) break;
1769 /* Get a phonetic copy of each word */
1770 words = (char **)ch_malloc( count * sizeof(char *) );
1771 values = (char **)ch_malloc( count * sizeof(char *) );
1772 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1774 values[i] = phonetic(c);
1777 /* Work through the asserted value's words, to see if at least some
1778 of the words are there, in the same order. */
1780 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1781 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1786 #if defined(SLAPD_APPROX_INITIALS)
1787 else if( len == 1 ) {
1788 /* Single letter words need to at least match one word's initial */
1789 for( i=nextavail; i<count; i++ )
1790 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1797 /* Isolate the next word in the asserted value and phonetic it */
1798 assertv->bv_val[nextchunk+len] = '\0';
1799 val = phonetic( assertv->bv_val + nextchunk );
1801 /* See if this phonetic chunk is in the remaining words of *value */
1802 for( i=nextavail; i<count; i++ ){
1803 if( !strcmp( val, values[i] ) ){
1811 /* This chunk in the asserted value was NOT within the *value. */
1817 /* Go on to the next word in the asserted value */
1821 /* If some of the words were seen, call it a match */
1822 if( nextavail > 0 ) {
1829 /* Cleanup allocs */
1830 ber_bvfree( assertv );
1831 for( i=0; i<count; i++ ) {
1832 ch_free( values[i] );
1838 return LDAP_SUCCESS;
1847 struct berval *prefix,
1853 int i,j, len, wordcount, keycount=0;
1854 struct berval *newkeys;
1855 BerVarray keys=NULL;
1857 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1858 struct berval val = BER_BVNULL;
1859 /* Yes, this is necessary */
1860 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1861 assert( !BER_BVISNULL( &val ) );
1863 /* Isolate how many words there are. There will be a key for each */
1864 for( wordcount = 0, c = val.bv_val; *c; c++) {
1865 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1866 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1868 if (*c == '\0') break;
1872 /* Allocate/increase storage to account for new keys */
1873 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1874 * sizeof(struct berval) );
1875 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1876 if( keys ) ch_free( keys );
1879 /* Get a phonetic copy of each word */
1880 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1882 if( len < SLAPD_APPROX_WORDLEN ) continue;
1883 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1888 ber_memfree( val.bv_val );
1890 BER_BVZERO( &keys[keycount] );
1893 return LDAP_SUCCESS;
1902 struct berval *prefix,
1903 void * assertedValue,
1912 /* Yes, this is necessary */
1913 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1914 NULL, LDAP_UTF8_APPROX, NULL );
1915 if( val == NULL || BER_BVISNULL( val ) ) {
1916 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1917 BER_BVZERO( &keys[0] );
1920 return LDAP_SUCCESS;
1923 /* Isolate how many words there are. There will be a key for each */
1924 for( count = 0,c = val->bv_val; *c; c++) {
1925 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1926 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1928 if (*c == '\0') break;
1932 /* Allocate storage for new keys */
1933 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1935 /* Get a phonetic copy of each word */
1936 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1938 if( len < SLAPD_APPROX_WORDLEN ) continue;
1939 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1945 BER_BVZERO( &keys[count] );
1948 return LDAP_SUCCESS;
1951 /* Remove all spaces and '-' characters */
1953 telephoneNumberNormalize(
1958 struct berval *normalized,
1963 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1965 /* validator should have refused an empty string */
1966 assert( !BER_BVISEMPTY( val ) );
1968 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1970 for( p = val->bv_val; *p; p++ ) {
1971 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1977 normalized->bv_len = q - normalized->bv_val;
1979 if( BER_BVISEMPTY( normalized ) ) {
1980 slap_sl_free( normalized->bv_val, ctx );
1981 BER_BVZERO( normalized );
1982 return LDAP_INVALID_SYNTAX;
1985 return LDAP_SUCCESS;
1993 struct berval val = *in;
1995 if( BER_BVISEMPTY( &val ) ) {
1996 /* disallow empty strings */
1997 return LDAP_INVALID_SYNTAX;
2000 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2001 if ( val.bv_len == 1 ) {
2002 return LDAP_SUCCESS;
2005 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2012 while ( OID_LEADCHAR( val.bv_val[0] )) {
2016 if ( val.bv_len == 0 ) {
2017 return LDAP_SUCCESS;
2021 if( !OID_SEPARATOR( val.bv_val[0] )) {
2029 return LDAP_INVALID_SYNTAX;
2038 struct berval val = *in;
2040 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2042 if ( val.bv_val[0] == '-' ) {
2046 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2047 return LDAP_INVALID_SYNTAX;
2050 if( val.bv_val[0] == '0' ) { /* "-0" */
2051 return LDAP_INVALID_SYNTAX;
2054 } else if ( val.bv_val[0] == '0' ) {
2055 if( val.bv_len > 1 ) { /* "0<more>" */
2056 return LDAP_INVALID_SYNTAX;
2059 return LDAP_SUCCESS;
2062 for( i=0; i < val.bv_len; i++ ) {
2063 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2064 return LDAP_INVALID_SYNTAX;
2068 return LDAP_SUCCESS;
2077 struct berval *value,
2078 void *assertedValue )
2080 struct berval *asserted = (struct berval *) assertedValue;
2081 int vsign = 1, asign = 1; /* default sign = '+' */
2086 if( v.bv_val[0] == '-' ) {
2092 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2095 if( a.bv_val[0] == '-' ) {
2101 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2103 match = vsign - asign;
2105 match = ( v.bv_len != a.bv_len
2106 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2107 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2108 if( vsign < 0 ) match = -match;
2112 return LDAP_SUCCESS;
2126 if ( lutil_str2bin( val, &iv )) {
2127 return LDAP_INVALID_SYNTAX;
2130 neg = iv.bv_val[0] & 0x80;
2132 /* Omit leading 0 pad byte */
2133 if ( !iv.bv_val[0] ) {
2138 /* If too small, sign-extend */
2139 if ( iv.bv_len < index_intlen ) {
2141 key->bv_val[0] = index_intlen;
2142 k = index_intlen - iv.bv_len + 1;
2147 for ( j=1; j<k; j++)
2148 key->bv_val[j] = pad;
2149 for ( j = 0; j<iv.bv_len; j++ )
2150 key->bv_val[j+k] = iv.bv_val[j];
2152 key->bv_val[0] = iv.bv_len;
2153 memcpy( key->bv_val+1, iv.bv_val, index_intlen );
2156 key->bv_val[0] = -key->bv_val[0];
2158 /* convert signed to unsigned */
2159 key->bv_val[0] ^= 0x80;
2163 /* Index generation function */
2170 struct berval *prefix,
2176 struct berval iv, itmp;
2180 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2181 /* just count them */
2184 /* we should have at least one value at this point */
2187 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2188 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2189 keys[i].bv_len = index_intlen+1;
2190 keys[i].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2193 keys[i].bv_val = NULL;
2196 itmp.bv_len = sizeof(ibuf);
2198 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2199 if ( values[i].bv_len > itmp.bv_len ) {
2200 itmp.bv_len = values[i].bv_len;
2201 if ( itmp.bv_val == ibuf ) {
2202 itmp.bv_val = slap_sl_malloc( itmp.bv_len, ctx );
2204 itmp.bv_val = slap_sl_realloc( itmp.bv_val, itmp.bv_len, ctx );
2208 rc = integerVal2Key( &values[i], &keys[i], &iv );
2214 if ( itmp.bv_val != ibuf ) {
2215 slap_sl_free( itmp.bv_val, ctx );
2220 /* Index generation function */
2227 struct berval *prefix,
2228 void * assertedValue,
2235 struct berval *value;
2238 value = (struct berval *) assertedValue;
2240 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2242 keys[0].bv_len = index_intlen + 1;
2243 keys[0].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2245 if ( value->bv_len > sizeof( ibuf )) {
2246 iv.bv_val = slap_sl_malloc( value->bv_len, ctx );
2247 iv.bv_len = value->bv_len;
2250 iv.bv_len = sizeof(ibuf);
2253 rc = integerVal2Key( value, keys, &iv );
2257 if ( iv.bv_val != ibuf ) {
2258 slap_sl_free( iv.bv_val, ctx );
2264 countryStringValidate(
2266 struct berval *val )
2268 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2270 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2271 return LDAP_INVALID_SYNTAX;
2273 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2274 return LDAP_INVALID_SYNTAX;
2277 return LDAP_SUCCESS;
2281 printableStringValidate(
2283 struct berval *val )
2287 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2289 for(i=0; i < val->bv_len; i++) {
2290 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2291 return LDAP_INVALID_SYNTAX;
2295 return LDAP_SUCCESS;
2299 printablesStringValidate(
2301 struct berval *val )
2305 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2307 for(i=0,len=0; i < val->bv_len; i++) {
2308 int c = val->bv_val[i];
2312 return LDAP_INVALID_SYNTAX;
2316 } else if ( SLAP_PRINTABLE(c) ) {
2319 return LDAP_INVALID_SYNTAX;
2324 return LDAP_INVALID_SYNTAX;
2327 return LDAP_SUCCESS;
2333 struct berval *val )
2337 for(i=0; i < val->bv_len; i++) {
2338 if( !LDAP_ASCII(val->bv_val[i]) ) {
2339 return LDAP_INVALID_SYNTAX;
2343 return LDAP_SUCCESS;
2352 struct berval *normalized,
2356 int casefold = !SLAP_MR_ASSOCIATED( mr,
2357 slap_schema.si_mr_caseExactIA5Match );
2359 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2363 /* Ignore initial whitespace */
2364 while ( ASCII_SPACE( *p ) ) p++;
2366 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2367 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2368 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2369 normalized->bv_val[normalized->bv_len] = '\0';
2371 p = q = normalized->bv_val;
2374 if ( ASCII_SPACE( *p ) ) {
2377 /* Ignore the extra whitespace */
2378 while ( ASCII_SPACE( *p ) ) {
2382 } else if ( casefold ) {
2383 /* Most IA5 rules require casefolding */
2384 *q++ = TOLOWER(*p); p++;
2391 assert( normalized->bv_val <= p );
2395 * If the string ended in space, backup the pointer one
2396 * position. One is enough because the above loop collapsed
2397 * all whitespace to a single space.
2399 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2401 /* null terminate */
2404 normalized->bv_len = q - normalized->bv_val;
2406 return LDAP_SUCCESS;
2415 if( in->bv_len != 36 ) {
2416 return LDAP_INVALID_SYNTAX;
2419 for( i=0; i<36; i++ ) {
2425 if( in->bv_val[i] != '-' ) {
2426 return LDAP_INVALID_SYNTAX;
2430 if( !ASCII_HEX( in->bv_val[i]) ) {
2431 return LDAP_INVALID_SYNTAX;
2436 return LDAP_SUCCESS;
2447 int rc=LDAP_INVALID_SYNTAX;
2449 assert( in != NULL );
2450 assert( out != NULL );
2452 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2455 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2457 for( i=0; i<36; i++ ) {
2463 if( in->bv_val[i] != '-' ) {
2466 out->bv_val[i] = '-';
2470 if( !ASCII_HEX( in->bv_val[i]) ) {
2473 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2478 out->bv_val[ out->bv_len ] = '\0';
2482 slap_sl_free( out->bv_val, ctx );
2495 struct berval *normalized,
2498 unsigned char octet = '\0';
2502 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2503 /* NOTE: must be a normalized UUID */
2504 assert( val->bv_len == 16 );
2506 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2507 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2508 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2509 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2511 return LDAP_SUCCESS;
2514 normalized->bv_len = 16;
2515 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2517 for( i=0, j=0; i<36; i++ ) {
2518 unsigned char nibble;
2519 if( val->bv_val[i] == '-' ) {
2522 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2523 nibble = val->bv_val[i] - '0';
2525 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2526 nibble = val->bv_val[i] - ('a'-10);
2528 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2529 nibble = val->bv_val[i] - ('A'-10);
2532 slap_sl_free( normalized->bv_val, ctx );
2533 return LDAP_INVALID_SYNTAX;
2538 normalized->bv_val[j>>1] = octet;
2540 octet = nibble << 4;
2545 normalized->bv_val[normalized->bv_len] = 0;
2546 return LDAP_SUCCESS;
2552 numericStringValidate(
2558 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2560 for(i=0; i < in->bv_len; i++) {
2561 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2562 return LDAP_INVALID_SYNTAX;
2566 return LDAP_SUCCESS;
2570 numericStringNormalize(
2575 struct berval *normalized,
2578 /* removal all spaces */
2581 assert( !BER_BVISEMPTY( val ) );
2583 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2586 q = normalized->bv_val;
2589 if ( ASCII_SPACE( *p ) ) {
2590 /* Ignore whitespace */
2597 /* we should have copied no more than is in val */
2598 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2600 /* null terminate */
2603 normalized->bv_len = q - normalized->bv_val;
2605 if( BER_BVISEMPTY( normalized ) ) {
2606 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2607 normalized->bv_val[0] = ' ';
2608 normalized->bv_val[1] = '\0';
2609 normalized->bv_len = 1;
2612 return LDAP_SUCCESS;
2616 * Integer conversion macros that will use the largest available
2619 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2620 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2621 # define SLAP_LONG long long
2623 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2624 # define SLAP_LONG long
2625 #endif /* HAVE_STRTOLL ... */
2633 struct berval *value,
2634 void *assertedValue )
2636 SLAP_LONG lValue, lAssertedValue;
2639 /* safe to assume integers are NUL terminated? */
2640 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2641 if( errno == ERANGE )
2643 return LDAP_CONSTRAINT_VIOLATION;
2646 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2648 if( errno == ERANGE )
2650 return LDAP_CONSTRAINT_VIOLATION;
2653 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2654 return LDAP_SUCCESS;
2663 struct berval *value,
2664 void *assertedValue )
2666 SLAP_LONG lValue, lAssertedValue;
2669 /* safe to assume integers are NUL terminated? */
2670 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2671 if( errno == ERANGE )
2673 return LDAP_CONSTRAINT_VIOLATION;
2676 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2678 if( errno == ERANGE )
2680 return LDAP_CONSTRAINT_VIOLATION;
2683 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2684 return LDAP_SUCCESS;
2688 serialNumberAndIssuerCheck(
2697 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2699 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2700 /* Parse old format */
2701 is->bv_val = ber_bvchr( in, '$' );
2702 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2704 sn->bv_val = in->bv_val;
2705 sn->bv_len = is->bv_val - in->bv_val;
2708 is->bv_len = in->bv_len - (sn->bv_len + 1);
2710 /* eat leading zeros */
2711 for( n=0; n < (sn->bv_len-1); n++ ) {
2712 if( sn->bv_val[n] != '0' ) break;
2717 for( n=0; n < sn->bv_len; n++ ) {
2718 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2722 /* Parse GSER format */
2723 int havesn=0,haveissuer=0;
2724 struct berval x = *in;
2729 /* eat leading spaces */
2730 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2734 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2735 return LDAP_INVALID_SYNTAX;
2738 /* should be at issuer or serialNumber NamedValue */
2739 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2741 x.bv_val += STRLENOF("issuer");
2742 x.bv_len -= STRLENOF("issuer");
2744 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2745 x.bv_val++; x.bv_len--;
2747 /* eat leading spaces */
2748 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2752 /* For backward compatibility, this part is optional */
2753 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2754 x.bv_val += STRLENOF("rdnSequence:");
2755 x.bv_len -= STRLENOF("rdnSequence:");
2758 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2759 x.bv_val++; x.bv_len--;
2761 is->bv_val = x.bv_val;
2764 for( ; is->bv_len < x.bv_len; ) {
2765 if ( is->bv_val[is->bv_len] != '"' ) {
2769 if ( is->bv_val[is->bv_len+1] == '"' ) {
2776 x.bv_val += is->bv_len+1;
2777 x.bv_len -= is->bv_len+1;
2779 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2780 return LDAP_INVALID_SYNTAX;
2785 } else if( strncasecmp( x.bv_val, "serialNumber",
2786 STRLENOF("serialNumber")) == 0 )
2788 /* parse serialNumber */
2790 x.bv_val += STRLENOF("serialNumber");
2791 x.bv_len -= STRLENOF("serialNumber");
2793 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2794 x.bv_val++; x.bv_len--;
2796 /* eat leading spaces */
2797 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2801 sn->bv_val = x.bv_val;
2804 if( sn->bv_val[0] == '-' ) {
2809 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2810 sn->bv_val[1] == 'X' )) {
2812 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2813 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2815 } else if ( sn->bv_val[0] == '\'' ) {
2816 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2817 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2819 if ( sn->bv_val[sn->bv_len] == '\'' &&
2820 sn->bv_val[sn->bv_len+1] == 'H' )
2823 return LDAP_INVALID_SYNTAX;
2826 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2827 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2831 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2832 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2833 return LDAP_INVALID_SYNTAX;
2836 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2838 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2839 return LDAP_INVALID_SYNTAX;
2844 } else return LDAP_INVALID_SYNTAX;
2846 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2847 x.bv_val++; x.bv_len--;
2850 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2854 /* should be at remaining NamedValue */
2855 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2856 STRLENOF("issuer" )) == 0 ))
2859 x.bv_val += STRLENOF("issuer");
2860 x.bv_len -= STRLENOF("issuer");
2862 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2863 x.bv_val++; x.bv_len--;
2865 /* eat leading spaces */
2866 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2870 /* For backward compatibility, this part is optional */
2871 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2872 x.bv_val += STRLENOF("rdnSequence:");
2873 x.bv_len -= STRLENOF("rdnSequence:");
2876 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2877 x.bv_val++; x.bv_len--;
2879 is->bv_val = x.bv_val;
2882 for( ; is->bv_len < x.bv_len; ) {
2883 if ( is->bv_val[is->bv_len] != '"' ) {
2887 if ( is->bv_val[is->bv_len+1] == '"' ) {
2894 x.bv_val += is->bv_len+1;
2895 x.bv_len -= is->bv_len+1;
2897 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2898 STRLENOF("serialNumber")) == 0 ))
2900 /* parse serialNumber */
2902 x.bv_val += STRLENOF("serialNumber");
2903 x.bv_len -= STRLENOF("serialNumber");
2905 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2906 x.bv_val++; x.bv_len--;
2908 /* eat leading spaces */
2909 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2913 sn->bv_val = x.bv_val;
2916 if( sn->bv_val[0] == '-' ) {
2921 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2922 sn->bv_val[1] == 'X' )) {
2924 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2925 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2927 } else if ( sn->bv_val[0] == '\'' ) {
2928 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2929 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2931 if ( sn->bv_val[sn->bv_len] == '\'' &&
2932 sn->bv_val[sn->bv_len+1] == 'H' )
2935 return LDAP_INVALID_SYNTAX;
2938 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2939 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2943 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2944 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2945 return LDAP_INVALID_SYNTAX;
2948 x.bv_val += sn->bv_len;
2949 x.bv_len -= sn->bv_len;
2951 } else return LDAP_INVALID_SYNTAX;
2953 /* eat trailing spaces */
2954 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2958 /* should have no characters left... */
2959 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2961 ber_dupbv_x( &ni, is, ctx );
2964 /* need to handle double dquotes here */
2970 serialNumberAndIssuerValidate(
2975 struct berval sn, i;
2977 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2980 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
2984 /* validate DN -- doesn't handle double dquote */
2985 rc = dnValidate( NULL, &i );
2987 rc = LDAP_INVALID_SYNTAX;
2989 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2990 slap_sl_free( i.bv_val, NULL );
2993 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2999 serialNumberAndIssuerPretty(
3006 struct berval sn, i, ni;
3008 assert( in != NULL );
3009 assert( out != NULL );
3011 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3014 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3018 rc = dnPretty( syntax, &i, &ni, ctx );
3020 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3021 slap_sl_free( i.bv_val, ctx );
3024 if( rc ) return LDAP_INVALID_SYNTAX;
3026 /* make room from sn + "$" */
3027 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3028 + sn.bv_len + ni.bv_len;
3029 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3031 if( out->bv_val == NULL ) {
3033 slap_sl_free( ni.bv_val, ctx );
3038 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3039 STRLENOF("{ serialNumber "));
3040 n = STRLENOF("{ serialNumber ");
3042 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3045 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3046 n += STRLENOF(", issuer rdnSequence:\"");
3048 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3051 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3052 n += STRLENOF("\" }");
3054 out->bv_val[n] = '\0';
3056 assert( n == out->bv_len );
3058 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3059 out->bv_val, 0, 0 );
3061 slap_sl_free( ni.bv_val, ctx );
3063 return LDAP_SUCCESS;
3067 * This routine is called by certificateExactNormalize when
3068 * certificateExactNormalize receives a search string instead of
3069 * a certificate. This routine checks if the search value is valid
3070 * and then returns the normalized value
3073 serialNumberAndIssuerNormalize(
3081 struct berval sn, sn2, i, ni;
3082 char sbuf[64], *stmp = sbuf;
3086 assert( in != NULL );
3087 assert( out != NULL );
3089 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3092 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3096 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3098 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3099 slap_sl_free( i.bv_val, ctx );
3102 if( rc ) return LDAP_INVALID_SYNTAX;
3104 /* Convert sn to canonical hex */
3105 if ( sn.bv_len > sizeof( sbuf )) {
3106 stmp = slap_sl_malloc( sn.bv_len, ctx );
3109 sn2.bv_len = sn.bv_len;
3110 if ( lutil_str2bin( &sn, &sn2 )) {
3111 rc = LDAP_INVALID_SYNTAX;
3115 /* make room for sn + "$" */
3116 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3117 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3118 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3120 if( out->bv_val == NULL ) {
3122 slap_sl_free( ni.bv_val, ctx );
3128 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3129 STRLENOF( "{ serialNumber " ));
3130 n = STRLENOF( "{ serialNumber " );
3132 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3135 unsigned char *v = (unsigned char *)sn2.bv_val;
3136 out->bv_val[n++] = '\'';
3137 for ( j = 0; j < sn2.bv_len; j++ ) {
3138 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3142 out->bv_val[n++] = '\'';
3143 out->bv_val[n++] = 'H';
3146 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3147 n += STRLENOF( ", issuer rdnSequence:\"" );
3149 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3152 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3153 n += STRLENOF( "\" }" );
3155 out->bv_val[n] = '\0';
3157 assert( n == out->bv_len );
3159 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3160 out->bv_val, 0, 0 );
3164 slap_sl_free( stmp, ctx );
3165 slap_sl_free( ni.bv_val, ctx );
3171 certificateExactNormalize(
3176 struct berval *normalized,
3179 BerElementBuffer berbuf;
3180 BerElement *ber = (BerElement *)&berbuf;
3184 char serialbuf[64], *serial = serialbuf;
3185 ber_len_t seriallen;
3186 struct berval issuer_dn = BER_BVNULL, bvdn;
3188 int rc = LDAP_INVALID_SYNTAX;
3190 if( BER_BVISEMPTY( val ) ) goto done;
3192 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3193 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3196 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3198 ber_init2( ber, val, LBER_USE_DER );
3199 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3200 tag = ber_skip_tag( ber, &len ); /* Sequence */
3201 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3202 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3203 tag = ber_skip_tag( ber, &len );
3204 tag = ber_get_int( ber, &i ); /* version */
3207 /* NOTE: move the test here from certificateValidate,
3208 * so that we can validate certs with serial longer
3209 * than sizeof(ber_int_t) */
3210 tag = ber_peek_tag( ber, &len ); /* serial */
3212 /* Use hex format. '123456789abcdef'H
3218 tag = ber_skip_tag( ber, &len );
3219 ptr = (unsigned char *)ber->ber_ptr;
3220 ber_skip_data( ber, len );
3222 /* Check for minimal encodings */
3224 if ( ptr[0] & 0x80 ) {
3225 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3226 return LDAP_INVALID_SYNTAX;
3227 } else if ( ptr[0] == 0 ) {
3228 if (!( ptr[1] & 0x80 ))
3229 return LDAP_INVALID_SYNTAX;
3233 seriallen = len * 2 + 4; /* quotes, H, NUL */
3234 if ( seriallen > sizeof( serialbuf ))
3235 serial = slap_sl_malloc( seriallen, ctx );
3238 for ( i = 0; i<len; i++ ) {
3239 sprintf( sptr, "%02X", ptr[i] );
3246 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3247 ber_skip_data( ber, len );
3248 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3249 len = ber_ptrlen( ber );
3250 bvdn.bv_val = val->bv_val + len;
3251 bvdn.bv_len = val->bv_len - len;
3253 rc = dnX509normalize( &bvdn, &issuer_dn );
3254 if( rc != LDAP_SUCCESS ) goto done;
3256 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3257 + seriallen + issuer_dn.bv_len;
3258 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3260 p = (unsigned char *)normalized->bv_val;
3262 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3263 p += STRLENOF( "{ serialNumber " );
3265 AC_MEMCPY(p, serial, seriallen);
3268 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3269 p += STRLENOF( ", issuer rdnSequence:\"" );
3271 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3272 p += issuer_dn.bv_len;
3274 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3275 p += STRLENOF( "\" }" );
3279 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3280 normalized->bv_val, NULL, NULL );
3285 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3286 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3298 assert( in != NULL );
3299 assert( !BER_BVISNULL( in ) );
3301 for ( i = 0; i < in->bv_len; i++ ) {
3302 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3303 return LDAP_INVALID_SYNTAX;
3307 return LDAP_SUCCESS;
3310 /* Normalize a SID as used inside a CSN:
3311 * three-digit numeric string */
3318 struct berval *normalized,
3323 assert( val != NULL );
3324 assert( normalized != NULL );
3326 ber_dupbv_x( normalized, val, ctx );
3328 for ( i = 0; i < normalized->bv_len; i++ ) {
3329 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3330 ber_memfree_x( normalized->bv_val, ctx );
3331 BER_BVZERO( normalized );
3332 return LDAP_INVALID_SYNTAX;
3335 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3338 return LDAP_SUCCESS;
3346 assert( in != NULL );
3347 assert( !BER_BVISNULL( in ) );
3349 if ( in->bv_len != 3 ) {
3350 return LDAP_INVALID_SYNTAX;
3353 return hexValidate( NULL, in );
3356 /* Normalize a SID as used inside a CSN:
3357 * three-digit numeric string */
3364 struct berval *normalized,
3367 if ( val->bv_len != 3 ) {
3368 return LDAP_INVALID_SYNTAX;
3371 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3381 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3384 /* Normalize a SID as used inside a CSN, either as-is
3385 * (assertion value) or extracted from the CSN
3386 * (attribute value) */
3393 struct berval *normalized,
3401 if ( BER_BVISEMPTY( val ) ) {
3402 return LDAP_INVALID_SYNTAX;
3405 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3406 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3409 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3411 ptr = ber_bvchr( val, '#' );
3412 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3413 return LDAP_INVALID_SYNTAX;
3416 bv.bv_val = ptr + 1;
3417 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3419 ptr = ber_bvchr( &bv, '#' );
3420 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3421 return LDAP_INVALID_SYNTAX;
3424 bv.bv_val = ptr + 1;
3425 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3427 ptr = ber_bvchr( &bv, '#' );
3428 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3429 return LDAP_INVALID_SYNTAX;
3432 bv.bv_len = ptr - bv.bv_val;
3434 if ( bv.bv_len == 2 ) {
3435 /* OpenLDAP 2.3 SID */
3437 buf[ 1 ] = bv.bv_val[ 0 ];
3438 buf[ 2 ] = bv.bv_val[ 1 ];
3445 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3457 assert( in != NULL );
3458 assert( !BER_BVISNULL( in ) );
3460 if ( BER_BVISEMPTY( in ) ) {
3461 return LDAP_INVALID_SYNTAX;
3466 ptr = ber_bvchr( &bv, '#' );
3467 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3468 return LDAP_INVALID_SYNTAX;
3471 bv.bv_len = ptr - bv.bv_val;
3472 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3473 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3475 return LDAP_INVALID_SYNTAX;
3478 rc = generalizedTimeValidate( NULL, &bv );
3479 if ( rc != LDAP_SUCCESS ) {
3483 bv.bv_val = ptr + 1;
3484 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3486 ptr = ber_bvchr( &bv, '#' );
3487 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3488 return LDAP_INVALID_SYNTAX;
3491 bv.bv_len = ptr - bv.bv_val;
3492 if ( bv.bv_len != 6 ) {
3493 return LDAP_INVALID_SYNTAX;
3496 rc = hexValidate( NULL, &bv );
3497 if ( rc != LDAP_SUCCESS ) {
3501 bv.bv_val = ptr + 1;
3502 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3504 ptr = ber_bvchr( &bv, '#' );
3505 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3506 return LDAP_INVALID_SYNTAX;
3509 bv.bv_len = ptr - bv.bv_val;
3510 if ( bv.bv_len == 2 ) {
3511 /* tolerate old 2-digit replica-id */
3512 rc = hexValidate( NULL, &bv );
3515 rc = sidValidate( NULL, &bv );
3517 if ( rc != LDAP_SUCCESS ) {
3521 bv.bv_val = ptr + 1;
3522 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3524 if ( bv.bv_len != 6 ) {
3525 return LDAP_INVALID_SYNTAX;
3528 return hexValidate( NULL, &bv );
3531 /* Normalize a CSN in OpenLDAP 2.3 format */
3538 struct berval *normalized,
3541 struct berval gt, cnt, sid, mod;
3545 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3546 assert( !BER_BVISEMPTY( val ) );
3550 ptr = ber_bvchr( >, '#' );
3551 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3552 return LDAP_INVALID_SYNTAX;
3555 gt.bv_len = ptr - gt.bv_val;
3556 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3558 cnt.bv_val = ptr + 1;
3559 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3561 ptr = ber_bvchr( &cnt, '#' );
3562 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3563 return LDAP_INVALID_SYNTAX;
3566 cnt.bv_len = ptr - cnt.bv_val;
3567 assert( cnt.bv_len == STRLENOF( "000000" ) );
3569 sid.bv_val = ptr + 1;
3570 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3572 ptr = ber_bvchr( &sid, '#' );
3573 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3574 return LDAP_INVALID_SYNTAX;
3577 sid.bv_len = ptr - sid.bv_val;
3578 assert( sid.bv_len == STRLENOF( "00" ) );
3580 mod.bv_val = ptr + 1;
3581 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3582 assert( mod.bv_len == STRLENOF( "000000" ) );
3584 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3585 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3587 ptr = normalized->bv_val;
3588 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3589 ptr = lutil_strcopy( ptr, ".000000Z#" );
3590 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3593 for ( i = 0; i < sid.bv_len; i++ ) {
3594 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3597 for ( i = 0; i < mod.bv_len; i++ ) {
3598 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3602 assert( ptr - normalized->bv_val == normalized->bv_len );
3604 return LDAP_SUCCESS;
3607 /* Normalize a CSN */
3614 struct berval *normalized,
3617 struct berval cnt, sid, mod;
3621 assert( val != NULL );
3622 assert( normalized != NULL );
3624 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3626 if ( BER_BVISEMPTY( val ) ) {
3627 return LDAP_INVALID_SYNTAX;
3630 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3631 /* Openldap <= 2.3 */
3633 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3636 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3638 ptr = ber_bvchr( val, '#' );
3639 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3640 return LDAP_INVALID_SYNTAX;
3643 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3645 cnt.bv_val = ptr + 1;
3646 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3648 ptr = ber_bvchr( &cnt, '#' );
3649 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3650 return LDAP_INVALID_SYNTAX;
3653 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3655 sid.bv_val = ptr + 1;
3656 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3658 ptr = ber_bvchr( &sid, '#' );
3659 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3660 return LDAP_INVALID_SYNTAX;
3663 sid.bv_len = ptr - sid.bv_val;
3664 assert( sid.bv_len == STRLENOF( "000" ) );
3666 mod.bv_val = ptr + 1;
3667 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3669 assert( mod.bv_len == STRLENOF( "000000" ) );
3671 ber_dupbv_x( normalized, val, ctx );
3673 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3674 i < normalized->bv_len; i++ )
3676 /* assume it's already validated that's all hex digits */
3677 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3680 return LDAP_SUCCESS;
3690 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3693 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3694 /* slight optimization - does not need the start parameter */
3695 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3700 check_time_syntax (struct berval *val,
3703 struct berval *fraction)
3706 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3707 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3708 * GeneralizedTime supports leap seconds, UTCTime does not.
3710 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3711 static const int mdays[2][12] = {
3712 /* non-leap years */
3713 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3715 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3718 int part, c, c1, c2, tzoffset, leapyear = 0;
3721 e = p + val->bv_len;
3723 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3724 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3726 for (part = start; part < 7 && p < e; part++) {
3728 if (!ASCII_DIGIT(c1)) {
3733 return LDAP_INVALID_SYNTAX;
3736 if (!ASCII_DIGIT(c)) {
3737 return LDAP_INVALID_SYNTAX;
3739 c += c1 * 10 - '0' * 11;
3740 if ((part | 1) == 3) {
3743 return LDAP_INVALID_SYNTAX;
3746 if (c >= ceiling[part]) {
3747 if (! (c == 60 && part == 6 && start == 0))
3748 return LDAP_INVALID_SYNTAX;
3752 if (part < 5 + start) {
3753 return LDAP_INVALID_SYNTAX;
3755 for (; part < 9; part++) {
3759 /* leapyear check for the Gregorian calendar (year>1581) */
3760 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3764 if (parts[3] >= mdays[leapyear][parts[2]]) {
3765 return LDAP_INVALID_SYNTAX;
3769 fraction->bv_val = p;
3770 fraction->bv_len = 0;
3771 if (p < e && (*p == '.' || *p == ',')) {
3773 while (++p < e && ASCII_DIGIT(*p)) {
3776 if (p - fraction->bv_val == 1) {
3777 return LDAP_INVALID_SYNTAX;
3779 for (end_num = p; end_num[-1] == '0'; --end_num) {
3782 c = end_num - fraction->bv_val;
3783 if (c != 1) fraction->bv_len = c;
3789 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3795 return LDAP_INVALID_SYNTAX;
3801 for (part = 7; part < 9 && p < e; part++) {
3803 if (!ASCII_DIGIT(c1)) {
3808 return LDAP_INVALID_SYNTAX;
3811 if (!ASCII_DIGIT(c2)) {
3812 return LDAP_INVALID_SYNTAX;
3814 parts[part] = c1 * 10 + c2 - '0' * 11;
3815 if (parts[part] >= ceiling[part]) {
3816 return LDAP_INVALID_SYNTAX;
3819 if (part < 8 + start) {
3820 return LDAP_INVALID_SYNTAX;
3823 if (tzoffset == '-') {
3824 /* negative offset to UTC, ie west of Greenwich */
3825 parts[4] += parts[7];
3826 parts[5] += parts[8];
3827 /* offset is just hhmm, no seconds */
3828 for (part = 6; --part >= 0; ) {
3832 c = mdays[leapyear][parts[2]];
3834 if (parts[part] >= c) {
3836 return LDAP_INVALID_SYNTAX;
3841 } else if (part != 5) {
3846 /* positive offset to UTC, ie east of Greenwich */
3847 parts[4] -= parts[7];
3848 parts[5] -= parts[8];
3849 for (part = 6; --part >= 0; ) {
3850 if (parts[part] < 0) {
3852 return LDAP_INVALID_SYNTAX;
3857 /* make first arg to % non-negative */
3858 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3863 } else if (part != 5) {
3870 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3873 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3880 struct berval *normalized )
3884 rc = check_time_syntax(val, 1, parts, NULL);
3885 if (rc != LDAP_SUCCESS) {
3889 normalized->bv_val = ch_malloc( 14 );
3890 if ( normalized->bv_val == NULL ) {
3891 return LBER_ERROR_MEMORY;
3894 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3895 parts[1], parts[2] + 1, parts[3] + 1,
3896 parts[4], parts[5], parts[6] );
3897 normalized->bv_len = 13;
3899 return LDAP_SUCCESS;
3909 return check_time_syntax(in, 1, parts, NULL);
3912 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3915 generalizedTimeValidate(
3920 struct berval fraction;
3921 return check_time_syntax(in, 0, parts, &fraction);
3925 generalizedTimeNormalize(
3930 struct berval *normalized,
3935 struct berval fraction;
3937 rc = check_time_syntax(val, 0, parts, &fraction);
3938 if (rc != LDAP_SUCCESS) {
3942 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3943 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3944 if ( BER_BVISNULL( normalized ) ) {
3945 return LBER_ERROR_MEMORY;
3948 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3949 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3950 parts[4], parts[5], parts[6] );
3951 if ( !BER_BVISEMPTY( &fraction ) ) {
3952 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3953 fraction.bv_val, fraction.bv_len );
3954 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3956 strcpy( normalized->bv_val + len-1, "Z" );
3957 normalized->bv_len = len;
3959 return LDAP_SUCCESS;
3963 generalizedTimeOrderingMatch(
3968 struct berval *value,
3969 void *assertedValue )
3971 struct berval *asserted = (struct berval *) assertedValue;
3972 ber_len_t v_len = value->bv_len;
3973 ber_len_t av_len = asserted->bv_len;
3975 /* ignore trailing 'Z' when comparing */
3976 int match = memcmp( value->bv_val, asserted->bv_val,
3977 (v_len < av_len ? v_len : av_len) - 1 );
3978 if ( match == 0 ) match = v_len - av_len;
3981 return LDAP_SUCCESS;
3984 /* Index generation function */
3985 int generalizedTimeIndexer(
3990 struct berval *prefix,
3998 BerValue bvtmp; /* 40 bit index */
4000 struct lutil_timet tt;
4002 bvtmp.bv_len = sizeof(tmp);
4004 for( i=0; values[i].bv_val != NULL; i++ ) {
4005 /* just count them */
4008 /* we should have at least one value at this point */
4011 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4013 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4014 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4015 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4016 /* Use 40 bits of time for key */
4017 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4018 lutil_tm2time( &tm, &tt );
4019 tmp[0] = tt.tt_gsec & 0xff;
4020 tmp[4] = tt.tt_sec & 0xff;
4022 tmp[3] = tt.tt_sec & 0xff;
4024 tmp[2] = tt.tt_sec & 0xff;
4026 tmp[1] = tt.tt_sec & 0xff;
4028 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4032 keys[j].bv_val = NULL;
4037 return LDAP_SUCCESS;
4040 /* Index generation function */
4041 int generalizedTimeFilter(
4046 struct berval *prefix,
4047 void * assertedValue,
4053 BerValue bvtmp; /* 40 bit index */
4054 BerValue *value = (BerValue *) assertedValue;
4056 struct lutil_timet tt;
4058 bvtmp.bv_len = sizeof(tmp);
4060 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4061 /* Use 40 bits of time for key */
4062 if ( value->bv_val && value->bv_len >= 10 &&
4063 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4065 lutil_tm2time( &tm, &tt );
4066 tmp[0] = tt.tt_gsec & 0xff;
4067 tmp[4] = tt.tt_sec & 0xff;
4069 tmp[3] = tt.tt_sec & 0xff;
4071 tmp[2] = tt.tt_sec & 0xff;
4073 tmp[1] = tt.tt_sec & 0xff;
4075 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4076 ber_dupbv_x(keys, &bvtmp, ctx );
4077 keys[1].bv_val = NULL;
4085 return LDAP_SUCCESS;
4089 deliveryMethodValidate(
4091 struct berval *val )
4094 #define LENOF(s) (sizeof(s)-1)
4095 struct berval tmp = *val;
4097 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4098 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4099 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4102 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4104 switch( tmp.bv_val[0] ) {
4107 if(( tmp.bv_len >= LENOF("any") ) &&
4108 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4110 tmp.bv_len -= LENOF("any");
4111 tmp.bv_val += LENOF("any");
4114 return LDAP_INVALID_SYNTAX;
4118 if(( tmp.bv_len >= LENOF("mhs") ) &&
4119 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4121 tmp.bv_len -= LENOF("mhs");
4122 tmp.bv_val += LENOF("mhs");
4125 return LDAP_INVALID_SYNTAX;
4129 if(( tmp.bv_len >= LENOF("physical") ) &&
4130 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4132 tmp.bv_len -= LENOF("physical");
4133 tmp.bv_val += LENOF("physical");
4136 return LDAP_INVALID_SYNTAX;
4139 case 'T': /* telex or teletex or telephone */
4140 if(( tmp.bv_len >= LENOF("telex") ) &&
4141 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4143 tmp.bv_len -= LENOF("telex");
4144 tmp.bv_val += LENOF("telex");
4147 if(( tmp.bv_len >= LENOF("teletex") ) &&
4148 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4150 tmp.bv_len -= LENOF("teletex");
4151 tmp.bv_val += LENOF("teletex");
4154 if(( tmp.bv_len >= LENOF("telephone") ) &&
4155 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4157 tmp.bv_len -= LENOF("telephone");
4158 tmp.bv_val += LENOF("telephone");
4161 return LDAP_INVALID_SYNTAX;
4164 case 'G': /* g3fax or g4fax */
4165 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4166 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4167 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4169 tmp.bv_len -= LENOF("g3fax");
4170 tmp.bv_val += LENOF("g3fax");
4173 return LDAP_INVALID_SYNTAX;
4177 if(( tmp.bv_len >= LENOF("ia5") ) &&
4178 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4180 tmp.bv_len -= LENOF("ia5");
4181 tmp.bv_val += LENOF("ia5");
4184 return LDAP_INVALID_SYNTAX;
4188 if(( tmp.bv_len >= LENOF("videotex") ) &&
4189 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4191 tmp.bv_len -= LENOF("videotex");
4192 tmp.bv_val += LENOF("videotex");
4195 return LDAP_INVALID_SYNTAX;
4198 return LDAP_INVALID_SYNTAX;
4201 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4203 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4207 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4211 return LDAP_INVALID_SYNTAX;
4213 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4222 nisNetgroupTripleValidate(
4224 struct berval *val )
4229 if ( BER_BVISEMPTY( val ) ) {
4230 return LDAP_INVALID_SYNTAX;
4233 p = (char *)val->bv_val;
4234 e = p + val->bv_len;
4236 if ( *p != '(' /*')'*/ ) {
4237 return LDAP_INVALID_SYNTAX;
4240 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4244 return LDAP_INVALID_SYNTAX;
4247 } else if ( !AD_CHAR( *p ) ) {
4248 return LDAP_INVALID_SYNTAX;
4252 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4253 return LDAP_INVALID_SYNTAX;
4259 return LDAP_INVALID_SYNTAX;
4262 return LDAP_SUCCESS;
4266 bootParameterValidate(
4268 struct berval *val )
4272 if ( BER_BVISEMPTY( val ) ) {
4273 return LDAP_INVALID_SYNTAX;
4276 p = (char *)val->bv_val;
4277 e = p + val->bv_len;
4280 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4281 if ( !AD_CHAR( *p ) ) {
4282 return LDAP_INVALID_SYNTAX;
4287 return LDAP_INVALID_SYNTAX;
4291 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4292 if ( !AD_CHAR( *p ) ) {
4293 return LDAP_INVALID_SYNTAX;
4298 return LDAP_INVALID_SYNTAX;
4302 for ( p++; p < e; p++ ) {
4303 if ( !SLAP_PRINTABLE( *p ) ) {
4304 return LDAP_INVALID_SYNTAX;
4308 return LDAP_SUCCESS;
4312 firstComponentNormalize(
4317 struct berval *normalized,
4324 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4325 ber_dupbv_x( normalized, val, ctx );
4326 return LDAP_SUCCESS;
4329 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4331 if( val->bv_val[0] != '(' /*')'*/ &&
4332 val->bv_val[0] != '{' /*'}'*/ )
4334 return LDAP_INVALID_SYNTAX;
4337 /* trim leading white space */
4339 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4345 /* grab next word */
4346 comp.bv_val = &val->bv_val[len];
4347 len = val->bv_len - len;
4348 for( comp.bv_len = 0;
4349 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4355 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4356 rc = numericoidValidate( NULL, &comp );
4357 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4358 rc = integerValidate( NULL, &comp );
4360 rc = LDAP_INVALID_SYNTAX;
4364 if( rc == LDAP_SUCCESS ) {
4365 ber_dupbv_x( normalized, &comp, ctx );
4371 static char *country_gen_syn[] = {
4372 "1.3.6.1.4.1.1466.115.121.1.15",
4373 "1.3.6.1.4.1.1466.115.121.1.26",
4374 "1.3.6.1.4.1.1466.115.121.1.44",
4378 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4379 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4381 static slap_syntax_defs_rec syntax_defs[] = {
4382 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4383 X_BINARY X_NOT_H_R ")",
4384 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4385 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4386 0, NULL, NULL, NULL},
4387 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4388 0, NULL, NULL, NULL},
4389 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4391 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4392 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4394 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4395 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4396 0, NULL, bitStringValidate, NULL },
4397 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4398 0, NULL, booleanValidate, NULL},
4399 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4400 X_BINARY X_NOT_H_R ")",
4401 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4402 NULL, certificateValidate, NULL},
4403 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4404 X_BINARY X_NOT_H_R ")",
4405 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4406 NULL, certificateListValidate, NULL},
4407 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4408 X_BINARY X_NOT_H_R ")",
4409 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4410 NULL, sequenceValidate, NULL},
4411 #if 0 /* need to go __after__ printableString */
4412 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4413 0, "1.3.6.1.4.1.1466.115.121.1.44",
4414 countryStringValidate, NULL},
4416 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4417 0, NULL, dnValidate, dnPretty},
4418 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4419 0, NULL, rdnValidate, rdnPretty},
4420 #ifdef LDAP_COMP_MATCH
4421 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4422 0, NULL, allComponentsValidate, NULL},
4423 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4424 0, NULL, componentFilterValidate, NULL},
4426 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4427 0, NULL, NULL, NULL},
4428 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4429 0, NULL, deliveryMethodValidate, NULL},
4430 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4431 0, NULL, UTF8StringValidate, NULL},
4432 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4433 0, NULL, NULL, NULL},
4434 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4435 0, NULL, NULL, NULL},
4436 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4437 0, NULL, NULL, NULL},
4438 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4439 0, NULL, NULL, NULL},
4440 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4441 0, NULL, NULL, NULL},
4442 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4443 0, NULL, printablesStringValidate, NULL},
4444 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4445 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4446 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4447 0, NULL, generalizedTimeValidate, NULL},
4448 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4449 0, NULL, NULL, NULL},
4450 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4451 0, NULL, IA5StringValidate, NULL},
4452 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4453 0, NULL, integerValidate, NULL},
4454 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4455 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4456 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4457 0, NULL, NULL, NULL},
4458 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4459 0, NULL, NULL, NULL},
4460 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4461 0, NULL, NULL, NULL},
4462 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4463 0, NULL, NULL, NULL},
4464 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4465 0, NULL, NULL, NULL},
4466 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4467 0, NULL, nameUIDValidate, nameUIDPretty },
4468 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4469 0, NULL, NULL, NULL},
4470 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4471 0, NULL, numericStringValidate, NULL},
4472 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4473 0, NULL, NULL, NULL},
4474 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4475 0, NULL, numericoidValidate, NULL},
4476 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4477 0, NULL, IA5StringValidate, NULL},
4478 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4479 0, NULL, blobValidate, NULL},
4480 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4481 0, NULL, UTF8StringValidate, NULL},
4482 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4483 0, NULL, NULL, NULL},
4484 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4485 0, NULL, NULL, NULL},
4486 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4487 0, NULL, printableStringValidate, NULL},
4488 /* moved here because now depends on Directory String, IA5 String
4489 * and Printable String */
4490 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4491 0, country_gen_syn, countryStringValidate, NULL},
4492 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4493 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4494 0, NULL, subtreeSpecificationValidate, NULL},
4495 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4496 X_BINARY X_NOT_H_R ")",
4497 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4498 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4499 0, NULL, printableStringValidate, NULL},
4500 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4501 0, NULL, NULL, NULL},
4502 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4503 0, NULL, printablesStringValidate, NULL},
4504 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4505 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4506 0, NULL, utcTimeValidate, NULL},
4508 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4509 0, NULL, NULL, NULL},
4510 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4511 0, NULL, NULL, NULL},
4512 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4513 0, NULL, NULL, NULL},
4514 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4515 0, NULL, NULL, NULL},
4516 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4517 0, NULL, NULL, NULL},
4519 /* RFC 2307 NIS Syntaxes */
4520 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4521 0, NULL, nisNetgroupTripleValidate, NULL},
4522 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4523 0, NULL, bootParameterValidate, NULL},
4525 /* draft-zeilenga-ldap-x509 */
4526 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4527 SLAP_SYNTAX_HIDE, NULL,
4528 serialNumberAndIssuerValidate,
4529 serialNumberAndIssuerPretty},
4530 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4531 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4532 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4533 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4534 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4535 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4536 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4537 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4538 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4539 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4540 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4541 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4543 #ifdef SLAPD_AUTHPASSWD
4544 /* needs updating */
4545 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4546 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4549 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4550 0, NULL, UUIDValidate, UUIDPretty},
4552 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4553 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4555 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4556 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4558 /* OpenLDAP Void Syntax */
4559 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4560 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4562 /* FIXME: OID is unused, but not registered yet */
4563 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4564 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4566 {NULL, 0, NULL, NULL, NULL}
4569 char *csnSIDMatchSyntaxes[] = {
4570 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4573 char *certificateExactMatchSyntaxes[] = {
4574 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4577 #ifdef LDAP_COMP_MATCH
4578 char *componentFilterMatchSyntaxes[] = {
4579 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4583 char *directoryStringSyntaxes[] = {
4584 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4587 char *integerFirstComponentMatchSyntaxes[] = {
4588 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4589 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4592 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4593 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4594 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4595 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4596 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4597 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4598 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4599 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4600 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4605 * Other matching rules in X.520 that we do not use (yet):
4607 * 2.5.13.25 uTCTimeMatch
4608 * 2.5.13.26 uTCTimeOrderingMatch
4609 * 2.5.13.31* directoryStringFirstComponentMatch
4610 * 2.5.13.32* wordMatch
4611 * 2.5.13.33* keywordMatch
4612 * 2.5.13.36+ certificatePairExactMatch
4613 * 2.5.13.37+ certificatePairMatch
4614 * 2.5.13.38+ certificateListExactMatch
4615 * 2.5.13.39+ certificateListMatch
4616 * 2.5.13.40+ algorithmIdentifierMatch
4617 * 2.5.13.41* storedPrefixMatch
4618 * 2.5.13.42 attributeCertificateMatch
4619 * 2.5.13.43 readerAndKeyIDMatch
4620 * 2.5.13.44 attributeIntegrityMatch
4622 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4623 * (+) described in draft-zeilenga-ldap-x509
4625 static slap_mrule_defs_rec mrule_defs[] = {
4627 * EQUALITY matching rules must be listed after associated APPROX
4628 * matching rules. So, we list all APPROX matching rules first.
4630 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4631 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4632 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4633 NULL, NULL, directoryStringApproxMatch,
4634 directoryStringApproxIndexer, directoryStringApproxFilter,
4637 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4638 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4639 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4640 NULL, NULL, IA5StringApproxMatch,
4641 IA5StringApproxIndexer, IA5StringApproxFilter,
4645 * Other matching rules
4648 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4649 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4650 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4651 NULL, NULL, octetStringMatch,
4652 octetStringIndexer, octetStringFilter,
4655 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4656 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4657 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4658 NULL, dnNormalize, dnMatch,
4659 octetStringIndexer, octetStringFilter,
4662 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4663 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4664 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4665 NULL, dnNormalize, dnRelativeMatch,
4669 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4670 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4671 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4672 NULL, dnNormalize, dnRelativeMatch,
4676 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4677 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4678 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4679 NULL, dnNormalize, dnRelativeMatch,
4683 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4684 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4685 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4686 NULL, dnNormalize, dnRelativeMatch,
4690 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4691 "SYNTAX 1.2.36.79672281.1.5.0 )",
4692 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4693 NULL, rdnNormalize, rdnMatch,
4694 octetStringIndexer, octetStringFilter,
4697 #ifdef LDAP_COMP_MATCH
4698 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4699 "SYNTAX 1.2.36.79672281.1.5.2 )",
4700 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4701 NULL, NULL , componentFilterMatch,
4702 octetStringIndexer, octetStringFilter,
4705 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4706 "SYNTAX 1.2.36.79672281.1.5.3 )",
4707 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4708 NULL, NULL , allComponentsMatch,
4709 octetStringIndexer, octetStringFilter,
4712 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4713 "SYNTAX 1.2.36.79672281.1.5.3 )",
4714 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4715 NULL, NULL , directoryComponentsMatch,
4716 octetStringIndexer, octetStringFilter,
4720 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4721 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4722 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4723 NULL, UTF8StringNormalize, octetStringMatch,
4724 octetStringIndexer, octetStringFilter,
4725 directoryStringApproxMatchOID },
4727 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4728 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4729 SLAP_MR_ORDERING, directoryStringSyntaxes,
4730 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4732 "caseIgnoreMatch" },
4734 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4735 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4736 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4737 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4738 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4739 "caseIgnoreMatch" },
4741 {"( 2.5.13.5 NAME 'caseExactMatch' "
4742 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4743 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4744 NULL, UTF8StringNormalize, octetStringMatch,
4745 octetStringIndexer, octetStringFilter,
4746 directoryStringApproxMatchOID },
4748 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4749 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4750 SLAP_MR_ORDERING, directoryStringSyntaxes,
4751 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4755 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4756 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4757 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4758 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4759 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4762 {"( 2.5.13.8 NAME 'numericStringMatch' "
4763 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4764 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4765 NULL, numericStringNormalize, octetStringMatch,
4766 octetStringIndexer, octetStringFilter,
4769 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4770 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4771 SLAP_MR_ORDERING, NULL,
4772 NULL, numericStringNormalize, octetStringOrderingMatch,
4774 "numericStringMatch" },
4776 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4777 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4778 SLAP_MR_SUBSTR, NULL,
4779 NULL, numericStringNormalize, octetStringSubstringsMatch,
4780 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4781 "numericStringMatch" },
4783 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4784 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4785 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4786 NULL, NULL, NULL, NULL, NULL, NULL },
4788 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4789 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4790 SLAP_MR_SUBSTR, NULL,
4791 NULL, NULL, NULL, NULL, NULL,
4792 "caseIgnoreListMatch" },
4794 {"( 2.5.13.13 NAME 'booleanMatch' "
4795 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4796 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4797 NULL, NULL, booleanMatch,
4798 octetStringIndexer, octetStringFilter,
4801 {"( 2.5.13.14 NAME 'integerMatch' "
4802 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4803 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4804 NULL, NULL, integerMatch,
4805 integerIndexer, integerFilter,
4808 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4809 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4810 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4811 NULL, NULL, integerMatch,
4815 {"( 2.5.13.16 NAME 'bitStringMatch' "
4816 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4817 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4818 NULL, NULL, octetStringMatch,
4819 octetStringIndexer, octetStringFilter,
4822 {"( 2.5.13.17 NAME 'octetStringMatch' "
4823 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4824 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4825 NULL, NULL, octetStringMatch,
4826 octetStringIndexer, octetStringFilter,
4829 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4830 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4831 SLAP_MR_ORDERING, NULL,
4832 NULL, NULL, octetStringOrderingMatch,
4834 "octetStringMatch" },
4836 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4837 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4838 SLAP_MR_SUBSTR, NULL,
4839 NULL, NULL, octetStringSubstringsMatch,
4840 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4841 "octetStringMatch" },
4843 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4844 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4845 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4847 telephoneNumberNormalize, octetStringMatch,
4848 octetStringIndexer, octetStringFilter,
4851 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4852 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4853 SLAP_MR_SUBSTR, NULL,
4854 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4855 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4856 "telephoneNumberMatch" },
4858 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4859 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4860 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4861 NULL, NULL, NULL, NULL, NULL, NULL },
4863 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4864 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4865 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4866 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4867 uniqueMemberIndexer, uniqueMemberFilter,
4870 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4871 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4872 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4873 NULL, NULL, NULL, NULL, NULL, NULL },
4875 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4876 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4877 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4878 NULL, generalizedTimeNormalize, octetStringMatch,
4879 generalizedTimeIndexer, generalizedTimeFilter,
4882 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4883 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4884 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4885 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4887 "generalizedTimeMatch" },
4889 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4890 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4891 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4892 integerFirstComponentMatchSyntaxes,
4893 NULL, firstComponentNormalize, integerMatch,
4894 octetStringIndexer, octetStringFilter,
4897 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4898 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4899 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4900 objectIdentifierFirstComponentMatchSyntaxes,
4901 NULL, firstComponentNormalize, octetStringMatch,
4902 octetStringIndexer, octetStringFilter,
4905 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4906 "SYNTAX 1.3.6.1.1.15.1 )",
4907 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4908 NULL, certificateExactNormalize, octetStringMatch,
4909 octetStringIndexer, octetStringFilter,
4912 {"( 2.5.13.35 NAME 'certificateMatch' "
4913 "SYNTAX 1.3.6.1.1.15.2 )",
4914 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4915 NULL, NULL, NULL, NULL, NULL,
4918 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4919 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4920 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4921 NULL, IA5StringNormalize, octetStringMatch,
4922 octetStringIndexer, octetStringFilter,
4923 IA5StringApproxMatchOID },
4925 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4926 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4927 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4928 NULL, IA5StringNormalize, octetStringMatch,
4929 octetStringIndexer, octetStringFilter,
4930 IA5StringApproxMatchOID },
4932 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4933 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4934 SLAP_MR_SUBSTR, NULL,
4935 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4936 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4937 "caseIgnoreIA5Match" },
4939 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4940 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4941 SLAP_MR_SUBSTR, NULL,
4942 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4943 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4944 "caseExactIA5Match" },
4946 #ifdef SLAPD_AUTHPASSWD
4947 /* needs updating */
4948 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4949 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4950 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4951 NULL, NULL, authPasswordMatch,
4956 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4957 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4959 NULL, NULL, integerBitAndMatch,
4963 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4964 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4966 NULL, NULL, integerBitOrMatch,
4970 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4971 "SYNTAX 1.3.6.1.1.16.1 )",
4972 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4973 NULL, UUIDNormalize, octetStringMatch,
4974 octetStringIndexer, octetStringFilter,
4977 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4978 "SYNTAX 1.3.6.1.1.16.1 )",
4979 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4980 NULL, UUIDNormalize, octetStringOrderingMatch,
4981 octetStringIndexer, octetStringFilter,
4984 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4985 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4986 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4987 NULL, csnNormalize, csnMatch,
4988 csnIndexer, csnFilter,
4991 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4992 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4993 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4994 NULL, NULL, csnOrderingMatch,
4998 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
4999 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5000 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5001 NULL, csnSidNormalize, octetStringMatch,
5002 octetStringIndexer, octetStringFilter,
5005 /* FIXME: OID is unused, but not registered yet */
5006 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5007 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5008 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5009 NULL, authzNormalize, authzMatch,
5013 {NULL, SLAP_MR_NONE, NULL,
5014 NULL, NULL, NULL, NULL, NULL,
5019 slap_schema_init( void )
5024 /* we should only be called once (from main) */
5025 assert( schema_init_done == 0 );
5027 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5028 res = register_syntax( &syntax_defs[i] );
5031 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5032 syntax_defs[i].sd_desc );
5037 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5038 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5039 mrule_defs[i].mrd_compat_syntaxes == NULL )
5042 "slap_schema_init: Ignoring unusable matching rule %s\n",
5043 mrule_defs[i].mrd_desc );
5047 res = register_matching_rule( &mrule_defs[i] );
5051 "slap_schema_init: Error registering matching rule %s\n",
5052 mrule_defs[i].mrd_desc );
5057 res = slap_schema_load();
5058 schema_init_done = 1;
5063 schema_destroy( void )
5072 if( schema_init_done ) {
5073 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5074 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );