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;
2115 /* Index generation function */
2122 struct berval *prefix,
2128 struct berval iv, itmp;
2132 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2133 /* just count them */
2136 /* we should have at least one value at this point */
2139 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2140 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2141 keys[i].bv_len = index_intlen+1;
2142 keys[i].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2145 keys[i].bv_val = NULL;
2148 itmp.bv_len = sizeof(ibuf);
2150 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2151 if ( values[i].bv_len > itmp.bv_len ) {
2152 itmp.bv_len = values[i].bv_len;
2153 if ( itmp.bv_val == ibuf ) {
2154 itmp.bv_val = slap_sl_malloc( itmp.bv_len, ctx );
2156 itmp.bv_val = slap_sl_realloc( itmp.bv_val, itmp.bv_len, ctx );
2160 if ( lutil_str2bin( &values[i], &iv )) {
2161 rc = LDAP_INVALID_SYNTAX;
2164 /* If too small, sign-extend */
2165 if ( iv.bv_len < index_intlen ) {
2167 keys[i].bv_val[0] = index_intlen;
2168 if (iv.bv_val[0] & 0x80)
2172 k = index_intlen - iv.bv_len + 1;
2173 for ( j=1; j<k; j++)
2174 keys[i].bv_val[j] = pad;
2175 for ( j = 0; j<iv.bv_len; j++ )
2176 keys[i].bv_val[j+k] = iv.bv_val[j];
2178 keys[i].bv_val[0] = iv.bv_len;
2179 memcpy( keys[i].bv_val+1, iv.bv_val, index_intlen );
2181 /* convert signed to unsigned */
2182 keys[i].bv_val[1] ^= 0x80;
2187 if ( itmp.bv_val != ibuf ) {
2188 slap_sl_free( itmp.bv_val, ctx );
2193 /* Index generation function */
2200 struct berval *prefix,
2201 void * assertedValue,
2208 struct berval *value;
2211 value = (struct berval *) assertedValue;
2213 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2215 keys[0].bv_len = index_intlen + 1;
2216 keys[0].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2218 if ( value->bv_len > sizeof( ibuf )) {
2219 iv.bv_val = slap_sl_malloc( value->bv_len, ctx );
2220 iv.bv_len = value->bv_len;
2223 iv.bv_len = sizeof(ibuf);
2226 if ( lutil_str2bin( value, &iv )) {
2227 rc = LDAP_INVALID_SYNTAX;
2230 /* If too small, pad with zeros */
2231 if ( iv.bv_len < index_intlen ) {
2233 keys[0].bv_val[0] = index_intlen;
2234 k = index_intlen - iv.bv_len + 1;
2235 for ( j=1; j<k; j++)
2236 keys[0].bv_val[j] = 0;
2237 for ( j = 0; j<iv.bv_len; j++ )
2238 keys[0].bv_val[j+k] = iv.bv_val[j];
2240 keys[0].bv_val[0] = iv.bv_len;
2241 memcpy( keys[0].bv_val+1, iv.bv_val, index_intlen );
2243 /* convert signed to unsigned */
2244 keys[0].bv_val[1] ^= 0x80;
2249 if ( iv.bv_val != ibuf ) {
2250 slap_sl_free( iv.bv_val, ctx );
2256 countryStringValidate(
2258 struct berval *val )
2260 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2262 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2263 return LDAP_INVALID_SYNTAX;
2265 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2266 return LDAP_INVALID_SYNTAX;
2269 return LDAP_SUCCESS;
2273 printableStringValidate(
2275 struct berval *val )
2279 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2281 for(i=0; i < val->bv_len; i++) {
2282 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2283 return LDAP_INVALID_SYNTAX;
2287 return LDAP_SUCCESS;
2291 printablesStringValidate(
2293 struct berval *val )
2297 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2299 for(i=0,len=0; i < val->bv_len; i++) {
2300 int c = val->bv_val[i];
2304 return LDAP_INVALID_SYNTAX;
2308 } else if ( SLAP_PRINTABLE(c) ) {
2311 return LDAP_INVALID_SYNTAX;
2316 return LDAP_INVALID_SYNTAX;
2319 return LDAP_SUCCESS;
2325 struct berval *val )
2329 for(i=0; i < val->bv_len; i++) {
2330 if( !LDAP_ASCII(val->bv_val[i]) ) {
2331 return LDAP_INVALID_SYNTAX;
2335 return LDAP_SUCCESS;
2344 struct berval *normalized,
2348 int casefold = !SLAP_MR_ASSOCIATED( mr,
2349 slap_schema.si_mr_caseExactIA5Match );
2351 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2355 /* Ignore initial whitespace */
2356 while ( ASCII_SPACE( *p ) ) p++;
2358 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2359 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2360 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2361 normalized->bv_val[normalized->bv_len] = '\0';
2363 p = q = normalized->bv_val;
2366 if ( ASCII_SPACE( *p ) ) {
2369 /* Ignore the extra whitespace */
2370 while ( ASCII_SPACE( *p ) ) {
2374 } else if ( casefold ) {
2375 /* Most IA5 rules require casefolding */
2376 *q++ = TOLOWER(*p); p++;
2383 assert( normalized->bv_val <= p );
2387 * If the string ended in space, backup the pointer one
2388 * position. One is enough because the above loop collapsed
2389 * all whitespace to a single space.
2391 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2393 /* null terminate */
2396 normalized->bv_len = q - normalized->bv_val;
2398 return LDAP_SUCCESS;
2407 if( in->bv_len != 36 ) {
2408 return LDAP_INVALID_SYNTAX;
2411 for( i=0; i<36; i++ ) {
2417 if( in->bv_val[i] != '-' ) {
2418 return LDAP_INVALID_SYNTAX;
2422 if( !ASCII_HEX( in->bv_val[i]) ) {
2423 return LDAP_INVALID_SYNTAX;
2428 return LDAP_SUCCESS;
2439 int rc=LDAP_INVALID_SYNTAX;
2441 assert( in != NULL );
2442 assert( out != NULL );
2444 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2447 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2449 for( i=0; i<36; i++ ) {
2455 if( in->bv_val[i] != '-' ) {
2458 out->bv_val[i] = '-';
2462 if( !ASCII_HEX( in->bv_val[i]) ) {
2465 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2470 out->bv_val[ out->bv_len ] = '\0';
2474 slap_sl_free( out->bv_val, ctx );
2487 struct berval *normalized,
2490 unsigned char octet = '\0';
2494 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2495 /* NOTE: must be a normalized UUID */
2496 assert( val->bv_len == 16 );
2498 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2499 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2500 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2501 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2503 return LDAP_SUCCESS;
2506 normalized->bv_len = 16;
2507 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2509 for( i=0, j=0; i<36; i++ ) {
2510 unsigned char nibble;
2511 if( val->bv_val[i] == '-' ) {
2514 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2515 nibble = val->bv_val[i] - '0';
2517 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2518 nibble = val->bv_val[i] - ('a'-10);
2520 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2521 nibble = val->bv_val[i] - ('A'-10);
2524 slap_sl_free( normalized->bv_val, ctx );
2525 return LDAP_INVALID_SYNTAX;
2530 normalized->bv_val[j>>1] = octet;
2532 octet = nibble << 4;
2537 normalized->bv_val[normalized->bv_len] = 0;
2538 return LDAP_SUCCESS;
2544 numericStringValidate(
2550 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2552 for(i=0; i < in->bv_len; i++) {
2553 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2554 return LDAP_INVALID_SYNTAX;
2558 return LDAP_SUCCESS;
2562 numericStringNormalize(
2567 struct berval *normalized,
2570 /* removal all spaces */
2573 assert( !BER_BVISEMPTY( val ) );
2575 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2578 q = normalized->bv_val;
2581 if ( ASCII_SPACE( *p ) ) {
2582 /* Ignore whitespace */
2589 /* we should have copied no more than is in val */
2590 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2592 /* null terminate */
2595 normalized->bv_len = q - normalized->bv_val;
2597 if( BER_BVISEMPTY( normalized ) ) {
2598 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2599 normalized->bv_val[0] = ' ';
2600 normalized->bv_val[1] = '\0';
2601 normalized->bv_len = 1;
2604 return LDAP_SUCCESS;
2608 * Integer conversion macros that will use the largest available
2611 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2612 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2613 # define SLAP_LONG long long
2615 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2616 # define SLAP_LONG long
2617 #endif /* HAVE_STRTOLL ... */
2625 struct berval *value,
2626 void *assertedValue )
2628 SLAP_LONG lValue, lAssertedValue;
2631 /* safe to assume integers are NUL terminated? */
2632 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2633 if( errno == ERANGE )
2635 return LDAP_CONSTRAINT_VIOLATION;
2638 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2640 if( errno == ERANGE )
2642 return LDAP_CONSTRAINT_VIOLATION;
2645 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2646 return LDAP_SUCCESS;
2655 struct berval *value,
2656 void *assertedValue )
2658 SLAP_LONG lValue, lAssertedValue;
2661 /* safe to assume integers are NUL terminated? */
2662 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2663 if( errno == ERANGE )
2665 return LDAP_CONSTRAINT_VIOLATION;
2668 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2670 if( errno == ERANGE )
2672 return LDAP_CONSTRAINT_VIOLATION;
2675 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2676 return LDAP_SUCCESS;
2680 serialNumberAndIssuerCheck(
2689 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2691 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2692 /* Parse old format */
2693 is->bv_val = ber_bvchr( in, '$' );
2694 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2696 sn->bv_val = in->bv_val;
2697 sn->bv_len = is->bv_val - in->bv_val;
2700 is->bv_len = in->bv_len - (sn->bv_len + 1);
2702 /* eat leading zeros */
2703 for( n=0; n < (sn->bv_len-1); n++ ) {
2704 if( sn->bv_val[n] != '0' ) break;
2709 for( n=0; n < sn->bv_len; n++ ) {
2710 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2714 /* Parse GSER format */
2715 int havesn=0,haveissuer=0;
2716 struct berval x = *in;
2721 /* eat leading spaces */
2722 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2726 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2727 return LDAP_INVALID_SYNTAX;
2730 /* should be at issuer or serialNumber NamedValue */
2731 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2733 x.bv_val += STRLENOF("issuer");
2734 x.bv_len -= STRLENOF("issuer");
2736 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2737 x.bv_val++; x.bv_len--;
2739 /* eat leading spaces */
2740 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2744 /* For backward compatibility, this part is optional */
2745 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2746 x.bv_val += STRLENOF("rdnSequence:");
2747 x.bv_len -= STRLENOF("rdnSequence:");
2750 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2751 x.bv_val++; x.bv_len--;
2753 is->bv_val = x.bv_val;
2756 for( ; is->bv_len < x.bv_len; ) {
2757 if ( is->bv_val[is->bv_len] != '"' ) {
2761 if ( is->bv_val[is->bv_len+1] == '"' ) {
2768 x.bv_val += is->bv_len+1;
2769 x.bv_len -= is->bv_len+1;
2771 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2772 return LDAP_INVALID_SYNTAX;
2777 } else if( strncasecmp( x.bv_val, "serialNumber",
2778 STRLENOF("serialNumber")) == 0 )
2780 /* parse serialNumber */
2782 x.bv_val += STRLENOF("serialNumber");
2783 x.bv_len -= STRLENOF("serialNumber");
2785 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2786 x.bv_val++; x.bv_len--;
2788 /* eat leading spaces */
2789 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2793 sn->bv_val = x.bv_val;
2796 if( sn->bv_val[0] == '-' ) {
2801 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2802 sn->bv_val[1] == 'X' )) {
2804 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2805 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2807 } else if ( sn->bv_val[0] == '\'' ) {
2808 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2809 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2811 if ( sn->bv_val[sn->bv_len] == '\'' &&
2812 sn->bv_val[sn->bv_len+1] == 'H' )
2815 return LDAP_INVALID_SYNTAX;
2818 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2819 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2823 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2824 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2825 return LDAP_INVALID_SYNTAX;
2828 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2830 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2831 return LDAP_INVALID_SYNTAX;
2836 } else return LDAP_INVALID_SYNTAX;
2838 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2839 x.bv_val++; x.bv_len--;
2842 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2846 /* should be at remaining NamedValue */
2847 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2848 STRLENOF("issuer" )) == 0 ))
2851 x.bv_val += STRLENOF("issuer");
2852 x.bv_len -= STRLENOF("issuer");
2854 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2855 x.bv_val++; x.bv_len--;
2857 /* eat leading spaces */
2858 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2862 /* For backward compatibility, this part is optional */
2863 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2864 x.bv_val += STRLENOF("rdnSequence:");
2865 x.bv_len -= STRLENOF("rdnSequence:");
2868 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2869 x.bv_val++; x.bv_len--;
2871 is->bv_val = x.bv_val;
2874 for( ; is->bv_len < x.bv_len; ) {
2875 if ( is->bv_val[is->bv_len] != '"' ) {
2879 if ( is->bv_val[is->bv_len+1] == '"' ) {
2886 x.bv_val += is->bv_len+1;
2887 x.bv_len -= is->bv_len+1;
2889 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2890 STRLENOF("serialNumber")) == 0 ))
2892 /* parse serialNumber */
2894 x.bv_val += STRLENOF("serialNumber");
2895 x.bv_len -= STRLENOF("serialNumber");
2897 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2898 x.bv_val++; x.bv_len--;
2900 /* eat leading spaces */
2901 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2905 sn->bv_val = x.bv_val;
2908 if( sn->bv_val[0] == '-' ) {
2913 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2914 sn->bv_val[1] == 'X' )) {
2916 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2917 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2919 } else if ( sn->bv_val[0] == '\'' ) {
2920 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2921 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2923 if ( sn->bv_val[sn->bv_len] == '\'' &&
2924 sn->bv_val[sn->bv_len+1] == 'H' )
2927 return LDAP_INVALID_SYNTAX;
2930 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2931 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2935 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2936 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2937 return LDAP_INVALID_SYNTAX;
2940 x.bv_val += sn->bv_len;
2941 x.bv_len -= sn->bv_len;
2943 } else return LDAP_INVALID_SYNTAX;
2945 /* eat trailing spaces */
2946 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2950 /* should have no characters left... */
2951 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2953 ber_dupbv_x( &ni, is, ctx );
2956 /* need to handle double dquotes here */
2962 serialNumberAndIssuerValidate(
2967 struct berval sn, i;
2969 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2972 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
2976 /* validate DN -- doesn't handle double dquote */
2977 rc = dnValidate( NULL, &i );
2979 rc = LDAP_INVALID_SYNTAX;
2981 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2982 slap_sl_free( i.bv_val, NULL );
2985 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2991 serialNumberAndIssuerPretty(
2998 struct berval sn, i, ni;
3000 assert( in != NULL );
3001 assert( out != NULL );
3003 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3006 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3010 rc = dnPretty( syntax, &i, &ni, ctx );
3012 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3013 slap_sl_free( i.bv_val, ctx );
3016 if( rc ) return LDAP_INVALID_SYNTAX;
3018 /* make room from sn + "$" */
3019 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3020 + sn.bv_len + ni.bv_len;
3021 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3023 if( out->bv_val == NULL ) {
3025 slap_sl_free( ni.bv_val, ctx );
3030 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3031 STRLENOF("{ serialNumber "));
3032 n = STRLENOF("{ serialNumber ");
3034 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3037 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3038 n += STRLENOF(", issuer rdnSequence:\"");
3040 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3043 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3044 n += STRLENOF("\" }");
3046 out->bv_val[n] = '\0';
3048 assert( n == out->bv_len );
3050 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3051 out->bv_val, 0, 0 );
3053 slap_sl_free( ni.bv_val, ctx );
3055 return LDAP_SUCCESS;
3059 * This routine is called by certificateExactNormalize when
3060 * certificateExactNormalize receives a search string instead of
3061 * a certificate. This routine checks if the search value is valid
3062 * and then returns the normalized value
3065 serialNumberAndIssuerNormalize(
3073 struct berval sn, sn2, i, ni;
3074 char sbuf[64], *stmp = sbuf;
3078 assert( in != NULL );
3079 assert( out != NULL );
3081 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3084 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3088 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3090 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3091 slap_sl_free( i.bv_val, ctx );
3094 if( rc ) return LDAP_INVALID_SYNTAX;
3096 /* Convert sn to canonical hex */
3097 if ( sn.bv_len > sizeof( sbuf )) {
3098 stmp = slap_sl_malloc( sn.bv_len, ctx );
3101 sn2.bv_len = sn.bv_len;
3102 if ( lutil_str2bin( &sn, &sn2 )) {
3103 rc = LDAP_INVALID_SYNTAX;
3107 /* make room for sn + "$" */
3108 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3109 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3110 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3112 if( out->bv_val == NULL ) {
3114 slap_sl_free( ni.bv_val, ctx );
3120 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3121 STRLENOF( "{ serialNumber " ));
3122 n = STRLENOF( "{ serialNumber " );
3124 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3127 unsigned char *v = (unsigned char *)sn2.bv_val;
3128 out->bv_val[n++] = '\'';
3129 for ( j = 0; j < sn2.bv_len; j++ ) {
3130 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3134 out->bv_val[n++] = '\'';
3135 out->bv_val[n++] = 'H';
3138 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3139 n += STRLENOF( ", issuer rdnSequence:\"" );
3141 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3144 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3145 n += STRLENOF( "\" }" );
3147 out->bv_val[n] = '\0';
3149 assert( n == out->bv_len );
3151 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3152 out->bv_val, 0, 0 );
3156 slap_sl_free( stmp, ctx );
3157 slap_sl_free( ni.bv_val, ctx );
3163 certificateExactNormalize(
3168 struct berval *normalized,
3171 BerElementBuffer berbuf;
3172 BerElement *ber = (BerElement *)&berbuf;
3176 char serialbuf[64], *serial = serialbuf;
3177 ber_len_t seriallen;
3178 struct berval issuer_dn = BER_BVNULL, bvdn;
3180 int rc = LDAP_INVALID_SYNTAX;
3182 if( BER_BVISEMPTY( val ) ) goto done;
3184 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3185 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3188 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3190 ber_init2( ber, val, LBER_USE_DER );
3191 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3192 tag = ber_skip_tag( ber, &len ); /* Sequence */
3193 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3194 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3195 tag = ber_skip_tag( ber, &len );
3196 tag = ber_get_int( ber, &i ); /* version */
3199 /* NOTE: move the test here from certificateValidate,
3200 * so that we can validate certs with serial longer
3201 * than sizeof(ber_int_t) */
3202 tag = ber_peek_tag( ber, &len ); /* serial */
3204 /* Use hex format. '123456789abcdef'H
3210 tag = ber_skip_tag( ber, &len );
3211 ptr = (unsigned char *)ber->ber_ptr;
3212 ber_skip_data( ber, len );
3214 /* Check for minimal encodings */
3216 if ( ptr[0] & 0x80 ) {
3217 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3218 return LDAP_INVALID_SYNTAX;
3219 } else if ( ptr[0] == 0 ) {
3220 if (!( ptr[1] & 0x80 ))
3221 return LDAP_INVALID_SYNTAX;
3225 seriallen = len * 2 + 4; /* quotes, H, NUL */
3226 if ( seriallen > sizeof( serialbuf ))
3227 serial = slap_sl_malloc( seriallen, ctx );
3230 for ( i = 0; i<len; i++ ) {
3231 sprintf( sptr, "%02X", ptr[i] );
3238 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3239 ber_skip_data( ber, len );
3240 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3241 len = ber_ptrlen( ber );
3242 bvdn.bv_val = val->bv_val + len;
3243 bvdn.bv_len = val->bv_len - len;
3245 rc = dnX509normalize( &bvdn, &issuer_dn );
3246 if( rc != LDAP_SUCCESS ) goto done;
3248 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3249 + seriallen + issuer_dn.bv_len;
3250 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3252 p = (unsigned char *)normalized->bv_val;
3254 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3255 p += STRLENOF( "{ serialNumber " );
3257 AC_MEMCPY(p, serial, seriallen);
3260 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3261 p += STRLENOF( ", issuer rdnSequence:\"" );
3263 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3264 p += issuer_dn.bv_len;
3266 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3267 p += STRLENOF( "\" }" );
3271 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3272 normalized->bv_val, NULL, NULL );
3277 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3278 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3290 assert( in != NULL );
3291 assert( !BER_BVISNULL( in ) );
3293 for ( i = 0; i < in->bv_len; i++ ) {
3294 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3295 return LDAP_INVALID_SYNTAX;
3299 return LDAP_SUCCESS;
3302 /* Normalize a SID as used inside a CSN:
3303 * three-digit numeric string */
3310 struct berval *normalized,
3315 assert( val != NULL );
3316 assert( normalized != NULL );
3318 ber_dupbv_x( normalized, val, ctx );
3320 for ( i = 0; i < normalized->bv_len; i++ ) {
3321 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3322 ber_memfree_x( normalized->bv_val, ctx );
3323 BER_BVZERO( normalized );
3324 return LDAP_INVALID_SYNTAX;
3327 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3330 return LDAP_SUCCESS;
3338 assert( in != NULL );
3339 assert( !BER_BVISNULL( in ) );
3341 if ( in->bv_len != 3 ) {
3342 return LDAP_INVALID_SYNTAX;
3345 return hexValidate( NULL, in );
3348 /* Normalize a SID as used inside a CSN:
3349 * three-digit numeric string */
3356 struct berval *normalized,
3359 if ( val->bv_len != 3 ) {
3360 return LDAP_INVALID_SYNTAX;
3363 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3373 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3376 /* Normalize a SID as used inside a CSN, either as-is
3377 * (assertion value) or extracted from the CSN
3378 * (attribute value) */
3385 struct berval *normalized,
3393 if ( BER_BVISEMPTY( val ) ) {
3394 return LDAP_INVALID_SYNTAX;
3397 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3398 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3401 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3403 ptr = ber_bvchr( val, '#' );
3404 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3405 return LDAP_INVALID_SYNTAX;
3408 bv.bv_val = ptr + 1;
3409 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3411 ptr = ber_bvchr( &bv, '#' );
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_len = ptr - bv.bv_val;
3426 if ( bv.bv_len == 2 ) {
3427 /* OpenLDAP 2.3 SID */
3429 buf[ 1 ] = bv.bv_val[ 0 ];
3430 buf[ 2 ] = bv.bv_val[ 1 ];
3437 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3449 assert( in != NULL );
3450 assert( !BER_BVISNULL( in ) );
3452 if ( BER_BVISEMPTY( in ) ) {
3453 return LDAP_INVALID_SYNTAX;
3458 ptr = ber_bvchr( &bv, '#' );
3459 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3460 return LDAP_INVALID_SYNTAX;
3463 bv.bv_len = ptr - bv.bv_val;
3464 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3465 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3467 return LDAP_INVALID_SYNTAX;
3470 rc = generalizedTimeValidate( NULL, &bv );
3471 if ( rc != LDAP_SUCCESS ) {
3475 bv.bv_val = ptr + 1;
3476 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3478 ptr = ber_bvchr( &bv, '#' );
3479 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3480 return LDAP_INVALID_SYNTAX;
3483 bv.bv_len = ptr - bv.bv_val;
3484 if ( bv.bv_len != 6 ) {
3485 return LDAP_INVALID_SYNTAX;
3488 rc = hexValidate( NULL, &bv );
3489 if ( rc != LDAP_SUCCESS ) {
3493 bv.bv_val = ptr + 1;
3494 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3496 ptr = ber_bvchr( &bv, '#' );
3497 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3498 return LDAP_INVALID_SYNTAX;
3501 bv.bv_len = ptr - bv.bv_val;
3502 if ( bv.bv_len == 2 ) {
3503 /* tolerate old 2-digit replica-id */
3504 rc = hexValidate( NULL, &bv );
3507 rc = sidValidate( NULL, &bv );
3509 if ( rc != LDAP_SUCCESS ) {
3513 bv.bv_val = ptr + 1;
3514 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3516 if ( bv.bv_len != 6 ) {
3517 return LDAP_INVALID_SYNTAX;
3520 return hexValidate( NULL, &bv );
3523 /* Normalize a CSN in OpenLDAP 2.3 format */
3530 struct berval *normalized,
3533 struct berval gt, cnt, sid, mod;
3537 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3538 assert( !BER_BVISEMPTY( val ) );
3542 ptr = ber_bvchr( >, '#' );
3543 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3544 return LDAP_INVALID_SYNTAX;
3547 gt.bv_len = ptr - gt.bv_val;
3548 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3550 cnt.bv_val = ptr + 1;
3551 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3553 ptr = ber_bvchr( &cnt, '#' );
3554 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3555 return LDAP_INVALID_SYNTAX;
3558 cnt.bv_len = ptr - cnt.bv_val;
3559 assert( cnt.bv_len == STRLENOF( "000000" ) );
3561 sid.bv_val = ptr + 1;
3562 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3564 ptr = ber_bvchr( &sid, '#' );
3565 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3566 return LDAP_INVALID_SYNTAX;
3569 sid.bv_len = ptr - sid.bv_val;
3570 assert( sid.bv_len == STRLENOF( "00" ) );
3572 mod.bv_val = ptr + 1;
3573 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3574 assert( mod.bv_len == STRLENOF( "000000" ) );
3576 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3577 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3579 ptr = normalized->bv_val;
3580 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3581 ptr = lutil_strcopy( ptr, ".000000Z#" );
3582 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3585 for ( i = 0; i < sid.bv_len; i++ ) {
3586 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3589 for ( i = 0; i < mod.bv_len; i++ ) {
3590 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3594 assert( ptr - normalized->bv_val == normalized->bv_len );
3596 return LDAP_SUCCESS;
3599 /* Normalize a CSN */
3606 struct berval *normalized,
3609 struct berval cnt, sid, mod;
3613 assert( val != NULL );
3614 assert( normalized != NULL );
3616 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3618 if ( BER_BVISEMPTY( val ) ) {
3619 return LDAP_INVALID_SYNTAX;
3622 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3623 /* Openldap <= 2.3 */
3625 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3628 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3630 ptr = ber_bvchr( val, '#' );
3631 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3632 return LDAP_INVALID_SYNTAX;
3635 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3637 cnt.bv_val = ptr + 1;
3638 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3640 ptr = ber_bvchr( &cnt, '#' );
3641 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3642 return LDAP_INVALID_SYNTAX;
3645 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3647 sid.bv_val = ptr + 1;
3648 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3650 ptr = ber_bvchr( &sid, '#' );
3651 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3652 return LDAP_INVALID_SYNTAX;
3655 sid.bv_len = ptr - sid.bv_val;
3656 assert( sid.bv_len == STRLENOF( "000" ) );
3658 mod.bv_val = ptr + 1;
3659 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3661 assert( mod.bv_len == STRLENOF( "000000" ) );
3663 ber_dupbv_x( normalized, val, ctx );
3665 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3666 i < normalized->bv_len; i++ )
3668 /* assume it's already validated that's all hex digits */
3669 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3672 return LDAP_SUCCESS;
3682 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3685 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3686 /* slight optimization - does not need the start parameter */
3687 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3692 check_time_syntax (struct berval *val,
3695 struct berval *fraction)
3698 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3699 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3700 * GeneralizedTime supports leap seconds, UTCTime does not.
3702 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3703 static const int mdays[2][12] = {
3704 /* non-leap years */
3705 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3707 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3710 int part, c, c1, c2, tzoffset, leapyear = 0;
3713 e = p + val->bv_len;
3715 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3716 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3718 for (part = start; part < 7 && p < e; part++) {
3720 if (!ASCII_DIGIT(c1)) {
3725 return LDAP_INVALID_SYNTAX;
3728 if (!ASCII_DIGIT(c)) {
3729 return LDAP_INVALID_SYNTAX;
3731 c += c1 * 10 - '0' * 11;
3732 if ((part | 1) == 3) {
3735 return LDAP_INVALID_SYNTAX;
3738 if (c >= ceiling[part]) {
3739 if (! (c == 60 && part == 6 && start == 0))
3740 return LDAP_INVALID_SYNTAX;
3744 if (part < 5 + start) {
3745 return LDAP_INVALID_SYNTAX;
3747 for (; part < 9; part++) {
3751 /* leapyear check for the Gregorian calendar (year>1581) */
3752 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3756 if (parts[3] >= mdays[leapyear][parts[2]]) {
3757 return LDAP_INVALID_SYNTAX;
3761 fraction->bv_val = p;
3762 fraction->bv_len = 0;
3763 if (p < e && (*p == '.' || *p == ',')) {
3765 while (++p < e && ASCII_DIGIT(*p)) {
3768 if (p - fraction->bv_val == 1) {
3769 return LDAP_INVALID_SYNTAX;
3771 for (end_num = p; end_num[-1] == '0'; --end_num) {
3774 c = end_num - fraction->bv_val;
3775 if (c != 1) fraction->bv_len = c;
3781 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3787 return LDAP_INVALID_SYNTAX;
3793 for (part = 7; part < 9 && p < e; part++) {
3795 if (!ASCII_DIGIT(c1)) {
3800 return LDAP_INVALID_SYNTAX;
3803 if (!ASCII_DIGIT(c2)) {
3804 return LDAP_INVALID_SYNTAX;
3806 parts[part] = c1 * 10 + c2 - '0' * 11;
3807 if (parts[part] >= ceiling[part]) {
3808 return LDAP_INVALID_SYNTAX;
3811 if (part < 8 + start) {
3812 return LDAP_INVALID_SYNTAX;
3815 if (tzoffset == '-') {
3816 /* negative offset to UTC, ie west of Greenwich */
3817 parts[4] += parts[7];
3818 parts[5] += parts[8];
3819 /* offset is just hhmm, no seconds */
3820 for (part = 6; --part >= 0; ) {
3824 c = mdays[leapyear][parts[2]];
3826 if (parts[part] >= c) {
3828 return LDAP_INVALID_SYNTAX;
3833 } else if (part != 5) {
3838 /* positive offset to UTC, ie east of Greenwich */
3839 parts[4] -= parts[7];
3840 parts[5] -= parts[8];
3841 for (part = 6; --part >= 0; ) {
3842 if (parts[part] < 0) {
3844 return LDAP_INVALID_SYNTAX;
3849 /* make first arg to % non-negative */
3850 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3855 } else if (part != 5) {
3862 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3865 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3872 struct berval *normalized )
3876 rc = check_time_syntax(val, 1, parts, NULL);
3877 if (rc != LDAP_SUCCESS) {
3881 normalized->bv_val = ch_malloc( 14 );
3882 if ( normalized->bv_val == NULL ) {
3883 return LBER_ERROR_MEMORY;
3886 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3887 parts[1], parts[2] + 1, parts[3] + 1,
3888 parts[4], parts[5], parts[6] );
3889 normalized->bv_len = 13;
3891 return LDAP_SUCCESS;
3901 return check_time_syntax(in, 1, parts, NULL);
3904 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3907 generalizedTimeValidate(
3912 struct berval fraction;
3913 return check_time_syntax(in, 0, parts, &fraction);
3917 generalizedTimeNormalize(
3922 struct berval *normalized,
3927 struct berval fraction;
3929 rc = check_time_syntax(val, 0, parts, &fraction);
3930 if (rc != LDAP_SUCCESS) {
3934 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3935 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3936 if ( BER_BVISNULL( normalized ) ) {
3937 return LBER_ERROR_MEMORY;
3940 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3941 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3942 parts[4], parts[5], parts[6] );
3943 if ( !BER_BVISEMPTY( &fraction ) ) {
3944 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3945 fraction.bv_val, fraction.bv_len );
3946 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3948 strcpy( normalized->bv_val + len-1, "Z" );
3949 normalized->bv_len = len;
3951 return LDAP_SUCCESS;
3955 generalizedTimeOrderingMatch(
3960 struct berval *value,
3961 void *assertedValue )
3963 struct berval *asserted = (struct berval *) assertedValue;
3964 ber_len_t v_len = value->bv_len;
3965 ber_len_t av_len = asserted->bv_len;
3967 /* ignore trailing 'Z' when comparing */
3968 int match = memcmp( value->bv_val, asserted->bv_val,
3969 (v_len < av_len ? v_len : av_len) - 1 );
3970 if ( match == 0 ) match = v_len - av_len;
3973 return LDAP_SUCCESS;
3976 /* Index generation function */
3977 int generalizedTimeIndexer(
3982 struct berval *prefix,
3990 BerValue bvtmp; /* 40 bit index */
3992 struct lutil_timet tt;
3994 bvtmp.bv_len = sizeof(tmp);
3996 for( i=0; values[i].bv_val != NULL; i++ ) {
3997 /* just count them */
4000 /* we should have at least one value at this point */
4003 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4005 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4006 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4007 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4008 /* Use 40 bits of time for key */
4009 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4010 lutil_tm2time( &tm, &tt );
4011 tmp[0] = tt.tt_gsec & 0xff;
4012 tmp[4] = tt.tt_sec & 0xff;
4014 tmp[3] = tt.tt_sec & 0xff;
4016 tmp[2] = tt.tt_sec & 0xff;
4018 tmp[1] = tt.tt_sec & 0xff;
4020 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4024 keys[j].bv_val = NULL;
4029 return LDAP_SUCCESS;
4032 /* Index generation function */
4033 int generalizedTimeFilter(
4038 struct berval *prefix,
4039 void * assertedValue,
4045 BerValue bvtmp; /* 40 bit index */
4046 BerValue *value = (BerValue *) assertedValue;
4048 struct lutil_timet tt;
4050 bvtmp.bv_len = sizeof(tmp);
4052 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4053 /* Use 40 bits of time for key */
4054 if ( value->bv_val && value->bv_len >= 10 &&
4055 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4057 lutil_tm2time( &tm, &tt );
4058 tmp[0] = tt.tt_gsec & 0xff;
4059 tmp[4] = tt.tt_sec & 0xff;
4061 tmp[3] = tt.tt_sec & 0xff;
4063 tmp[2] = tt.tt_sec & 0xff;
4065 tmp[1] = tt.tt_sec & 0xff;
4067 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4068 ber_dupbv_x(keys, &bvtmp, ctx );
4069 keys[1].bv_val = NULL;
4077 return LDAP_SUCCESS;
4081 deliveryMethodValidate(
4083 struct berval *val )
4086 #define LENOF(s) (sizeof(s)-1)
4087 struct berval tmp = *val;
4089 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4090 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4091 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4094 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4096 switch( tmp.bv_val[0] ) {
4099 if(( tmp.bv_len >= LENOF("any") ) &&
4100 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4102 tmp.bv_len -= LENOF("any");
4103 tmp.bv_val += LENOF("any");
4106 return LDAP_INVALID_SYNTAX;
4110 if(( tmp.bv_len >= LENOF("mhs") ) &&
4111 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4113 tmp.bv_len -= LENOF("mhs");
4114 tmp.bv_val += LENOF("mhs");
4117 return LDAP_INVALID_SYNTAX;
4121 if(( tmp.bv_len >= LENOF("physical") ) &&
4122 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4124 tmp.bv_len -= LENOF("physical");
4125 tmp.bv_val += LENOF("physical");
4128 return LDAP_INVALID_SYNTAX;
4131 case 'T': /* telex or teletex or telephone */
4132 if(( tmp.bv_len >= LENOF("telex") ) &&
4133 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4135 tmp.bv_len -= LENOF("telex");
4136 tmp.bv_val += LENOF("telex");
4139 if(( tmp.bv_len >= LENOF("teletex") ) &&
4140 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4142 tmp.bv_len -= LENOF("teletex");
4143 tmp.bv_val += LENOF("teletex");
4146 if(( tmp.bv_len >= LENOF("telephone") ) &&
4147 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4149 tmp.bv_len -= LENOF("telephone");
4150 tmp.bv_val += LENOF("telephone");
4153 return LDAP_INVALID_SYNTAX;
4156 case 'G': /* g3fax or g4fax */
4157 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4158 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4159 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4161 tmp.bv_len -= LENOF("g3fax");
4162 tmp.bv_val += LENOF("g3fax");
4165 return LDAP_INVALID_SYNTAX;
4169 if(( tmp.bv_len >= LENOF("ia5") ) &&
4170 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4172 tmp.bv_len -= LENOF("ia5");
4173 tmp.bv_val += LENOF("ia5");
4176 return LDAP_INVALID_SYNTAX;
4180 if(( tmp.bv_len >= LENOF("videotex") ) &&
4181 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4183 tmp.bv_len -= LENOF("videotex");
4184 tmp.bv_val += LENOF("videotex");
4187 return LDAP_INVALID_SYNTAX;
4190 return LDAP_INVALID_SYNTAX;
4193 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4195 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4199 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4203 return LDAP_INVALID_SYNTAX;
4205 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4214 nisNetgroupTripleValidate(
4216 struct berval *val )
4221 if ( BER_BVISEMPTY( val ) ) {
4222 return LDAP_INVALID_SYNTAX;
4225 p = (char *)val->bv_val;
4226 e = p + val->bv_len;
4228 if ( *p != '(' /*')'*/ ) {
4229 return LDAP_INVALID_SYNTAX;
4232 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4236 return LDAP_INVALID_SYNTAX;
4239 } else if ( !AD_CHAR( *p ) ) {
4240 return LDAP_INVALID_SYNTAX;
4244 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4245 return LDAP_INVALID_SYNTAX;
4251 return LDAP_INVALID_SYNTAX;
4254 return LDAP_SUCCESS;
4258 bootParameterValidate(
4260 struct berval *val )
4264 if ( BER_BVISEMPTY( val ) ) {
4265 return LDAP_INVALID_SYNTAX;
4268 p = (char *)val->bv_val;
4269 e = p + val->bv_len;
4272 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4273 if ( !AD_CHAR( *p ) ) {
4274 return LDAP_INVALID_SYNTAX;
4279 return LDAP_INVALID_SYNTAX;
4283 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4284 if ( !AD_CHAR( *p ) ) {
4285 return LDAP_INVALID_SYNTAX;
4290 return LDAP_INVALID_SYNTAX;
4294 for ( p++; p < e; p++ ) {
4295 if ( !SLAP_PRINTABLE( *p ) ) {
4296 return LDAP_INVALID_SYNTAX;
4300 return LDAP_SUCCESS;
4304 firstComponentNormalize(
4309 struct berval *normalized,
4316 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4317 ber_dupbv_x( normalized, val, ctx );
4318 return LDAP_SUCCESS;
4321 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4323 if( val->bv_val[0] != '(' /*')'*/ &&
4324 val->bv_val[0] != '{' /*'}'*/ )
4326 return LDAP_INVALID_SYNTAX;
4329 /* trim leading white space */
4331 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4337 /* grab next word */
4338 comp.bv_val = &val->bv_val[len];
4339 len = val->bv_len - len;
4340 for( comp.bv_len = 0;
4341 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4347 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4348 rc = numericoidValidate( NULL, &comp );
4349 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4350 rc = integerValidate( NULL, &comp );
4352 rc = LDAP_INVALID_SYNTAX;
4356 if( rc == LDAP_SUCCESS ) {
4357 ber_dupbv_x( normalized, &comp, ctx );
4363 static char *country_gen_syn[] = {
4364 "1.3.6.1.4.1.1466.115.121.1.15",
4365 "1.3.6.1.4.1.1466.115.121.1.26",
4366 "1.3.6.1.4.1.1466.115.121.1.44",
4370 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4371 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4373 static slap_syntax_defs_rec syntax_defs[] = {
4374 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4375 X_BINARY X_NOT_H_R ")",
4376 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4377 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4378 0, NULL, NULL, NULL},
4379 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4380 0, NULL, NULL, NULL},
4381 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4383 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4384 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4386 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4387 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4388 0, NULL, bitStringValidate, NULL },
4389 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4390 0, NULL, booleanValidate, NULL},
4391 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4392 X_BINARY X_NOT_H_R ")",
4393 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4394 NULL, certificateValidate, NULL},
4395 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4396 X_BINARY X_NOT_H_R ")",
4397 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4398 NULL, certificateListValidate, NULL},
4399 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4400 X_BINARY X_NOT_H_R ")",
4401 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4402 NULL, sequenceValidate, NULL},
4403 #if 0 /* need to go __after__ printableString */
4404 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4405 0, "1.3.6.1.4.1.1466.115.121.1.44",
4406 countryStringValidate, NULL},
4408 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4409 0, NULL, dnValidate, dnPretty},
4410 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4411 0, NULL, rdnValidate, rdnPretty},
4412 #ifdef LDAP_COMP_MATCH
4413 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4414 0, NULL, allComponentsValidate, NULL},
4415 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4416 0, NULL, componentFilterValidate, NULL},
4418 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4419 0, NULL, NULL, NULL},
4420 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4421 0, NULL, deliveryMethodValidate, NULL},
4422 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4423 0, NULL, UTF8StringValidate, NULL},
4424 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4425 0, NULL, NULL, NULL},
4426 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4427 0, NULL, NULL, NULL},
4428 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4429 0, NULL, NULL, NULL},
4430 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4431 0, NULL, NULL, NULL},
4432 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4433 0, NULL, NULL, NULL},
4434 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4435 0, NULL, printablesStringValidate, NULL},
4436 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4437 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4438 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4439 0, NULL, generalizedTimeValidate, NULL},
4440 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4441 0, NULL, NULL, NULL},
4442 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4443 0, NULL, IA5StringValidate, NULL},
4444 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4445 0, NULL, integerValidate, NULL},
4446 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4447 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4448 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4449 0, NULL, NULL, NULL},
4450 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4451 0, NULL, NULL, NULL},
4452 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4453 0, NULL, NULL, NULL},
4454 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4455 0, NULL, NULL, NULL},
4456 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4457 0, NULL, NULL, NULL},
4458 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4459 0, NULL, nameUIDValidate, nameUIDPretty },
4460 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4461 0, NULL, NULL, NULL},
4462 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4463 0, NULL, numericStringValidate, NULL},
4464 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4465 0, NULL, NULL, NULL},
4466 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4467 0, NULL, numericoidValidate, NULL},
4468 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4469 0, NULL, IA5StringValidate, NULL},
4470 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4471 0, NULL, blobValidate, NULL},
4472 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4473 0, NULL, UTF8StringValidate, NULL},
4474 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4475 0, NULL, NULL, NULL},
4476 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4477 0, NULL, NULL, NULL},
4478 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4479 0, NULL, printableStringValidate, NULL},
4480 /* moved here because now depends on Directory String, IA5 String
4481 * and Printable String */
4482 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4483 0, country_gen_syn, countryStringValidate, NULL},
4484 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4485 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4486 0, NULL, subtreeSpecificationValidate, NULL},
4487 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4488 X_BINARY X_NOT_H_R ")",
4489 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4490 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4491 0, NULL, printableStringValidate, NULL},
4492 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4493 0, NULL, NULL, NULL},
4494 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4495 0, NULL, printablesStringValidate, NULL},
4496 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4497 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4498 0, NULL, utcTimeValidate, NULL},
4500 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4501 0, NULL, NULL, NULL},
4502 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4503 0, NULL, NULL, NULL},
4504 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4505 0, NULL, NULL, NULL},
4506 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4507 0, NULL, NULL, NULL},
4508 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4509 0, NULL, NULL, NULL},
4511 /* RFC 2307 NIS Syntaxes */
4512 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4513 0, NULL, nisNetgroupTripleValidate, NULL},
4514 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4515 0, NULL, bootParameterValidate, NULL},
4517 /* draft-zeilenga-ldap-x509 */
4518 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4519 SLAP_SYNTAX_HIDE, NULL,
4520 serialNumberAndIssuerValidate,
4521 serialNumberAndIssuerPretty},
4522 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4523 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4524 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4525 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4526 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4527 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4528 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4529 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4530 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4531 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4532 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4533 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4535 #ifdef SLAPD_AUTHPASSWD
4536 /* needs updating */
4537 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4538 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4541 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4542 0, NULL, UUIDValidate, UUIDPretty},
4544 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4545 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4547 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4548 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4550 /* OpenLDAP Void Syntax */
4551 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4552 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4554 /* FIXME: OID is unused, but not registered yet */
4555 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4556 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4558 {NULL, 0, NULL, NULL, NULL}
4561 char *csnSIDMatchSyntaxes[] = {
4562 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4565 char *certificateExactMatchSyntaxes[] = {
4566 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4569 #ifdef LDAP_COMP_MATCH
4570 char *componentFilterMatchSyntaxes[] = {
4571 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4575 char *directoryStringSyntaxes[] = {
4576 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4579 char *integerFirstComponentMatchSyntaxes[] = {
4580 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4581 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4584 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4585 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4586 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4587 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4588 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4589 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4590 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4591 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4592 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4597 * Other matching rules in X.520 that we do not use (yet):
4599 * 2.5.13.25 uTCTimeMatch
4600 * 2.5.13.26 uTCTimeOrderingMatch
4601 * 2.5.13.31* directoryStringFirstComponentMatch
4602 * 2.5.13.32* wordMatch
4603 * 2.5.13.33* keywordMatch
4604 * 2.5.13.36+ certificatePairExactMatch
4605 * 2.5.13.37+ certificatePairMatch
4606 * 2.5.13.38+ certificateListExactMatch
4607 * 2.5.13.39+ certificateListMatch
4608 * 2.5.13.40+ algorithmIdentifierMatch
4609 * 2.5.13.41* storedPrefixMatch
4610 * 2.5.13.42 attributeCertificateMatch
4611 * 2.5.13.43 readerAndKeyIDMatch
4612 * 2.5.13.44 attributeIntegrityMatch
4614 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4615 * (+) described in draft-zeilenga-ldap-x509
4617 static slap_mrule_defs_rec mrule_defs[] = {
4619 * EQUALITY matching rules must be listed after associated APPROX
4620 * matching rules. So, we list all APPROX matching rules first.
4622 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4623 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4624 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4625 NULL, NULL, directoryStringApproxMatch,
4626 directoryStringApproxIndexer, directoryStringApproxFilter,
4629 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4631 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4632 NULL, NULL, IA5StringApproxMatch,
4633 IA5StringApproxIndexer, IA5StringApproxFilter,
4637 * Other matching rules
4640 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4641 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4642 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4643 NULL, NULL, octetStringMatch,
4644 octetStringIndexer, octetStringFilter,
4647 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4649 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4650 NULL, dnNormalize, dnMatch,
4651 octetStringIndexer, octetStringFilter,
4654 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4656 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4657 NULL, dnNormalize, dnRelativeMatch,
4661 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4663 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4664 NULL, dnNormalize, dnRelativeMatch,
4668 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4669 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4670 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4671 NULL, dnNormalize, dnRelativeMatch,
4675 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4676 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4677 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4678 NULL, dnNormalize, dnRelativeMatch,
4682 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4683 "SYNTAX 1.2.36.79672281.1.5.0 )",
4684 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4685 NULL, rdnNormalize, rdnMatch,
4686 octetStringIndexer, octetStringFilter,
4689 #ifdef LDAP_COMP_MATCH
4690 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4691 "SYNTAX 1.2.36.79672281.1.5.2 )",
4692 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4693 NULL, NULL , componentFilterMatch,
4694 octetStringIndexer, octetStringFilter,
4697 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4698 "SYNTAX 1.2.36.79672281.1.5.3 )",
4699 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4700 NULL, NULL , allComponentsMatch,
4701 octetStringIndexer, octetStringFilter,
4704 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4705 "SYNTAX 1.2.36.79672281.1.5.3 )",
4706 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4707 NULL, NULL , directoryComponentsMatch,
4708 octetStringIndexer, octetStringFilter,
4712 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4713 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4714 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4715 NULL, UTF8StringNormalize, octetStringMatch,
4716 octetStringIndexer, octetStringFilter,
4717 directoryStringApproxMatchOID },
4719 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4720 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4721 SLAP_MR_ORDERING, directoryStringSyntaxes,
4722 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4724 "caseIgnoreMatch" },
4726 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4728 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4729 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4730 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4731 "caseIgnoreMatch" },
4733 {"( 2.5.13.5 NAME 'caseExactMatch' "
4734 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4735 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4736 NULL, UTF8StringNormalize, octetStringMatch,
4737 octetStringIndexer, octetStringFilter,
4738 directoryStringApproxMatchOID },
4740 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4741 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4742 SLAP_MR_ORDERING, directoryStringSyntaxes,
4743 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4747 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4748 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4749 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4750 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4751 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4754 {"( 2.5.13.8 NAME 'numericStringMatch' "
4755 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4756 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4757 NULL, numericStringNormalize, octetStringMatch,
4758 octetStringIndexer, octetStringFilter,
4761 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4762 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4763 SLAP_MR_ORDERING, NULL,
4764 NULL, numericStringNormalize, octetStringOrderingMatch,
4766 "numericStringMatch" },
4768 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4769 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4770 SLAP_MR_SUBSTR, NULL,
4771 NULL, numericStringNormalize, octetStringSubstringsMatch,
4772 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4773 "numericStringMatch" },
4775 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4776 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4777 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4778 NULL, NULL, NULL, NULL, NULL, NULL },
4780 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4781 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4782 SLAP_MR_SUBSTR, NULL,
4783 NULL, NULL, NULL, NULL, NULL,
4784 "caseIgnoreListMatch" },
4786 {"( 2.5.13.13 NAME 'booleanMatch' "
4787 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4788 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4789 NULL, NULL, booleanMatch,
4790 octetStringIndexer, octetStringFilter,
4793 {"( 2.5.13.14 NAME 'integerMatch' "
4794 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4795 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4796 NULL, NULL, integerMatch,
4797 integerIndexer, integerFilter,
4800 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4801 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4802 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4803 NULL, NULL, integerMatch,
4807 {"( 2.5.13.16 NAME 'bitStringMatch' "
4808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4809 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4810 NULL, NULL, octetStringMatch,
4811 octetStringIndexer, octetStringFilter,
4814 {"( 2.5.13.17 NAME 'octetStringMatch' "
4815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4816 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4817 NULL, NULL, octetStringMatch,
4818 octetStringIndexer, octetStringFilter,
4821 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4823 SLAP_MR_ORDERING, NULL,
4824 NULL, NULL, octetStringOrderingMatch,
4826 "octetStringMatch" },
4828 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4829 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4830 SLAP_MR_SUBSTR, NULL,
4831 NULL, NULL, octetStringSubstringsMatch,
4832 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4833 "octetStringMatch" },
4835 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4836 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4837 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4839 telephoneNumberNormalize, octetStringMatch,
4840 octetStringIndexer, octetStringFilter,
4843 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4844 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4845 SLAP_MR_SUBSTR, NULL,
4846 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4847 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4848 "telephoneNumberMatch" },
4850 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4851 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4852 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4853 NULL, NULL, NULL, NULL, NULL, NULL },
4855 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4856 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4857 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4858 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4859 uniqueMemberIndexer, uniqueMemberFilter,
4862 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4864 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4865 NULL, NULL, NULL, NULL, NULL, NULL },
4867 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4868 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4869 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4870 NULL, generalizedTimeNormalize, octetStringMatch,
4871 generalizedTimeIndexer, generalizedTimeFilter,
4874 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4876 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4877 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4879 "generalizedTimeMatch" },
4881 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4882 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4883 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4884 integerFirstComponentMatchSyntaxes,
4885 NULL, firstComponentNormalize, integerMatch,
4886 octetStringIndexer, octetStringFilter,
4889 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4890 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4891 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4892 objectIdentifierFirstComponentMatchSyntaxes,
4893 NULL, firstComponentNormalize, octetStringMatch,
4894 octetStringIndexer, octetStringFilter,
4897 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4898 "SYNTAX 1.3.6.1.1.15.1 )",
4899 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4900 NULL, certificateExactNormalize, octetStringMatch,
4901 octetStringIndexer, octetStringFilter,
4904 {"( 2.5.13.35 NAME 'certificateMatch' "
4905 "SYNTAX 1.3.6.1.1.15.2 )",
4906 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4907 NULL, NULL, NULL, NULL, NULL,
4910 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4911 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4912 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4913 NULL, IA5StringNormalize, octetStringMatch,
4914 octetStringIndexer, octetStringFilter,
4915 IA5StringApproxMatchOID },
4917 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4919 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4920 NULL, IA5StringNormalize, octetStringMatch,
4921 octetStringIndexer, octetStringFilter,
4922 IA5StringApproxMatchOID },
4924 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4926 SLAP_MR_SUBSTR, NULL,
4927 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4928 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4929 "caseIgnoreIA5Match" },
4931 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4932 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4933 SLAP_MR_SUBSTR, NULL,
4934 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4935 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4936 "caseExactIA5Match" },
4938 #ifdef SLAPD_AUTHPASSWD
4939 /* needs updating */
4940 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4941 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4942 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4943 NULL, NULL, authPasswordMatch,
4948 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4949 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4951 NULL, NULL, integerBitAndMatch,
4955 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4958 NULL, NULL, integerBitOrMatch,
4962 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4963 "SYNTAX 1.3.6.1.1.16.1 )",
4964 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4965 NULL, UUIDNormalize, octetStringMatch,
4966 octetStringIndexer, octetStringFilter,
4969 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4970 "SYNTAX 1.3.6.1.1.16.1 )",
4971 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4972 NULL, UUIDNormalize, octetStringOrderingMatch,
4973 octetStringIndexer, octetStringFilter,
4976 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4977 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4978 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4979 NULL, csnNormalize, csnMatch,
4980 csnIndexer, csnFilter,
4983 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4984 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4985 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4986 NULL, NULL, csnOrderingMatch,
4990 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
4991 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
4992 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
4993 NULL, csnSidNormalize, octetStringMatch,
4994 octetStringIndexer, octetStringFilter,
4997 /* FIXME: OID is unused, but not registered yet */
4998 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4999 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5000 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5001 NULL, authzNormalize, authzMatch,
5005 {NULL, SLAP_MR_NONE, NULL,
5006 NULL, NULL, NULL, NULL, NULL,
5011 slap_schema_init( void )
5016 /* we should only be called once (from main) */
5017 assert( schema_init_done == 0 );
5019 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5020 res = register_syntax( &syntax_defs[i] );
5023 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5024 syntax_defs[i].sd_desc );
5029 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5030 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5031 mrule_defs[i].mrd_compat_syntaxes == NULL )
5034 "slap_schema_init: Ignoring unusable matching rule %s\n",
5035 mrule_defs[i].mrd_desc );
5039 res = register_matching_rule( &mrule_defs[i] );
5043 "slap_schema_init: Error registering matching rule %s\n",
5044 mrule_defs[i].mrd_desc );
5049 res = slap_schema_load();
5050 schema_init_done = 1;
5055 schema_destroy( void )
5064 if( schema_init_done ) {
5065 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5066 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );