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, pad with zeros */
2165 if ( iv.bv_len < index_intlen ) {
2167 keys[i].bv_val[0] = index_intlen;
2168 k = index_intlen - iv.bv_len + 1;
2169 for ( j=1; j<k; j++)
2170 keys[i].bv_val[j] = 0;
2171 for ( j = 0; j<iv.bv_len; j++ )
2172 keys[i].bv_val[j+k] = iv.bv_val[j];
2174 keys[i].bv_val[0] = iv.bv_len;
2175 memcpy( keys[i].bv_val+1, iv.bv_val, index_intlen );
2177 /* convert signed to unsigned */
2178 keys[i].bv_val[1] ^= 0x80;
2183 if ( itmp.bv_val != ibuf ) {
2184 slap_sl_free( itmp.bv_val, ctx );
2189 /* Index generation function */
2196 struct berval *prefix,
2197 void * assertedValue,
2204 struct berval *value;
2207 value = (struct berval *) assertedValue;
2209 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2211 keys[0].bv_len = index_intlen + 1;
2212 keys[0].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2214 if ( value->bv_len > sizeof( ibuf )) {
2215 iv.bv_val = slap_sl_malloc( value->bv_len, ctx );
2216 iv.bv_len = value->bv_len;
2219 iv.bv_len = sizeof(ibuf);
2222 if ( lutil_str2bin( value, &iv )) {
2223 rc = LDAP_INVALID_SYNTAX;
2226 /* If too small, pad with zeros */
2227 if ( iv.bv_len < index_intlen ) {
2229 keys[0].bv_val[0] = index_intlen;
2230 k = index_intlen - iv.bv_len + 1;
2231 for ( j=1; j<k; j++)
2232 keys[0].bv_val[j] = 0;
2233 for ( j = 0; j<iv.bv_len; j++ )
2234 keys[0].bv_val[j+k] = iv.bv_val[j];
2236 keys[0].bv_val[0] = iv.bv_len;
2237 memcpy( keys[0].bv_val+1, iv.bv_val, index_intlen );
2239 /* convert signed to unsigned */
2240 keys[0].bv_val[1] ^= 0x80;
2245 if ( iv.bv_val != ibuf ) {
2246 slap_sl_free( iv.bv_val, ctx );
2252 countryStringValidate(
2254 struct berval *val )
2256 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2258 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2259 return LDAP_INVALID_SYNTAX;
2261 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2262 return LDAP_INVALID_SYNTAX;
2265 return LDAP_SUCCESS;
2269 printableStringValidate(
2271 struct berval *val )
2275 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2277 for(i=0; i < val->bv_len; i++) {
2278 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2279 return LDAP_INVALID_SYNTAX;
2283 return LDAP_SUCCESS;
2287 printablesStringValidate(
2289 struct berval *val )
2293 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2295 for(i=0,len=0; i < val->bv_len; i++) {
2296 int c = val->bv_val[i];
2300 return LDAP_INVALID_SYNTAX;
2304 } else if ( SLAP_PRINTABLE(c) ) {
2307 return LDAP_INVALID_SYNTAX;
2312 return LDAP_INVALID_SYNTAX;
2315 return LDAP_SUCCESS;
2321 struct berval *val )
2325 for(i=0; i < val->bv_len; i++) {
2326 if( !LDAP_ASCII(val->bv_val[i]) ) {
2327 return LDAP_INVALID_SYNTAX;
2331 return LDAP_SUCCESS;
2340 struct berval *normalized,
2344 int casefold = !SLAP_MR_ASSOCIATED( mr,
2345 slap_schema.si_mr_caseExactIA5Match );
2347 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2351 /* Ignore initial whitespace */
2352 while ( ASCII_SPACE( *p ) ) p++;
2354 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2355 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2356 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2357 normalized->bv_val[normalized->bv_len] = '\0';
2359 p = q = normalized->bv_val;
2362 if ( ASCII_SPACE( *p ) ) {
2365 /* Ignore the extra whitespace */
2366 while ( ASCII_SPACE( *p ) ) {
2370 } else if ( casefold ) {
2371 /* Most IA5 rules require casefolding */
2372 *q++ = TOLOWER(*p); p++;
2379 assert( normalized->bv_val <= p );
2383 * If the string ended in space, backup the pointer one
2384 * position. One is enough because the above loop collapsed
2385 * all whitespace to a single space.
2387 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2389 /* null terminate */
2392 normalized->bv_len = q - normalized->bv_val;
2394 return LDAP_SUCCESS;
2403 if( in->bv_len != 36 ) {
2404 return LDAP_INVALID_SYNTAX;
2407 for( i=0; i<36; i++ ) {
2413 if( in->bv_val[i] != '-' ) {
2414 return LDAP_INVALID_SYNTAX;
2418 if( !ASCII_HEX( in->bv_val[i]) ) {
2419 return LDAP_INVALID_SYNTAX;
2424 return LDAP_SUCCESS;
2435 int rc=LDAP_INVALID_SYNTAX;
2437 assert( in != NULL );
2438 assert( out != NULL );
2440 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2443 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2445 for( i=0; i<36; i++ ) {
2451 if( in->bv_val[i] != '-' ) {
2454 out->bv_val[i] = '-';
2458 if( !ASCII_HEX( in->bv_val[i]) ) {
2461 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2466 out->bv_val[ out->bv_len ] = '\0';
2470 slap_sl_free( out->bv_val, ctx );
2483 struct berval *normalized,
2486 unsigned char octet = '\0';
2490 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2491 /* NOTE: must be a normalized UUID */
2492 assert( val->bv_len == 16 );
2494 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2495 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2496 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2497 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2499 return LDAP_SUCCESS;
2502 normalized->bv_len = 16;
2503 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2505 for( i=0, j=0; i<36; i++ ) {
2506 unsigned char nibble;
2507 if( val->bv_val[i] == '-' ) {
2510 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2511 nibble = val->bv_val[i] - '0';
2513 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2514 nibble = val->bv_val[i] - ('a'-10);
2516 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2517 nibble = val->bv_val[i] - ('A'-10);
2520 slap_sl_free( normalized->bv_val, ctx );
2521 return LDAP_INVALID_SYNTAX;
2526 normalized->bv_val[j>>1] = octet;
2528 octet = nibble << 4;
2533 normalized->bv_val[normalized->bv_len] = 0;
2534 return LDAP_SUCCESS;
2540 numericStringValidate(
2546 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2548 for(i=0; i < in->bv_len; i++) {
2549 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2550 return LDAP_INVALID_SYNTAX;
2554 return LDAP_SUCCESS;
2558 numericStringNormalize(
2563 struct berval *normalized,
2566 /* removal all spaces */
2569 assert( !BER_BVISEMPTY( val ) );
2571 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2574 q = normalized->bv_val;
2577 if ( ASCII_SPACE( *p ) ) {
2578 /* Ignore whitespace */
2585 /* we should have copied no more than is in val */
2586 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2588 /* null terminate */
2591 normalized->bv_len = q - normalized->bv_val;
2593 if( BER_BVISEMPTY( normalized ) ) {
2594 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2595 normalized->bv_val[0] = ' ';
2596 normalized->bv_val[1] = '\0';
2597 normalized->bv_len = 1;
2600 return LDAP_SUCCESS;
2604 * Integer conversion macros that will use the largest available
2607 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2608 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2609 # define SLAP_LONG long long
2611 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2612 # define SLAP_LONG long
2613 #endif /* HAVE_STRTOLL ... */
2621 struct berval *value,
2622 void *assertedValue )
2624 SLAP_LONG lValue, lAssertedValue;
2627 /* safe to assume integers are NUL terminated? */
2628 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2629 if( errno == ERANGE )
2631 return LDAP_CONSTRAINT_VIOLATION;
2634 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2636 if( errno == ERANGE )
2638 return LDAP_CONSTRAINT_VIOLATION;
2641 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2642 return LDAP_SUCCESS;
2651 struct berval *value,
2652 void *assertedValue )
2654 SLAP_LONG lValue, lAssertedValue;
2657 /* safe to assume integers are NUL terminated? */
2658 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2659 if( errno == ERANGE )
2661 return LDAP_CONSTRAINT_VIOLATION;
2664 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2666 if( errno == ERANGE )
2668 return LDAP_CONSTRAINT_VIOLATION;
2671 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2672 return LDAP_SUCCESS;
2676 serialNumberAndIssuerCheck(
2685 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2687 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2688 /* Parse old format */
2689 is->bv_val = ber_bvchr( in, '$' );
2690 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2692 sn->bv_val = in->bv_val;
2693 sn->bv_len = is->bv_val - in->bv_val;
2696 is->bv_len = in->bv_len - (sn->bv_len + 1);
2698 /* eat leading zeros */
2699 for( n=0; n < (sn->bv_len-1); n++ ) {
2700 if( sn->bv_val[n] != '0' ) break;
2705 for( n=0; n < sn->bv_len; n++ ) {
2706 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2710 /* Parse GSER format */
2711 int havesn=0,haveissuer=0;
2712 struct berval x = *in;
2717 /* eat leading spaces */
2718 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2722 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2723 return LDAP_INVALID_SYNTAX;
2726 /* should be at issuer or serialNumber NamedValue */
2727 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2729 x.bv_val += STRLENOF("issuer");
2730 x.bv_len -= STRLENOF("issuer");
2732 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2733 x.bv_val++; x.bv_len--;
2735 /* eat leading spaces */
2736 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2740 /* For backward compatibility, this part is optional */
2741 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2742 x.bv_val += STRLENOF("rdnSequence:");
2743 x.bv_len -= STRLENOF("rdnSequence:");
2746 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2747 x.bv_val++; x.bv_len--;
2749 is->bv_val = x.bv_val;
2752 for( ; is->bv_len < x.bv_len; ) {
2753 if ( is->bv_val[is->bv_len] != '"' ) {
2757 if ( is->bv_val[is->bv_len+1] == '"' ) {
2764 x.bv_val += is->bv_len+1;
2765 x.bv_len -= is->bv_len+1;
2767 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2768 return LDAP_INVALID_SYNTAX;
2773 } else if( strncasecmp( x.bv_val, "serialNumber",
2774 STRLENOF("serialNumber")) == 0 )
2776 /* parse serialNumber */
2778 x.bv_val += STRLENOF("serialNumber");
2779 x.bv_len -= STRLENOF("serialNumber");
2781 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2782 x.bv_val++; x.bv_len--;
2784 /* eat leading spaces */
2785 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2789 sn->bv_val = x.bv_val;
2792 if( sn->bv_val[0] == '-' ) {
2797 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2798 sn->bv_val[1] == 'X' )) {
2800 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2801 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2803 } else if ( sn->bv_val[0] == '\'' ) {
2804 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2805 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2807 if ( sn->bv_val[sn->bv_len] == '\'' &&
2808 sn->bv_val[sn->bv_len+1] == 'H' )
2811 return LDAP_INVALID_SYNTAX;
2814 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2815 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2819 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2820 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2821 return LDAP_INVALID_SYNTAX;
2824 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2826 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2827 return LDAP_INVALID_SYNTAX;
2832 } else return LDAP_INVALID_SYNTAX;
2834 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2835 x.bv_val++; x.bv_len--;
2838 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2842 /* should be at remaining NamedValue */
2843 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2844 STRLENOF("issuer" )) == 0 ))
2847 x.bv_val += STRLENOF("issuer");
2848 x.bv_len -= STRLENOF("issuer");
2850 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2851 x.bv_val++; x.bv_len--;
2853 /* eat leading spaces */
2854 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2858 /* For backward compatibility, this part is optional */
2859 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2860 x.bv_val += STRLENOF("rdnSequence:");
2861 x.bv_len -= STRLENOF("rdnSequence:");
2864 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2865 x.bv_val++; x.bv_len--;
2867 is->bv_val = x.bv_val;
2870 for( ; is->bv_len < x.bv_len; ) {
2871 if ( is->bv_val[is->bv_len] != '"' ) {
2875 if ( is->bv_val[is->bv_len+1] == '"' ) {
2882 x.bv_val += is->bv_len+1;
2883 x.bv_len -= is->bv_len+1;
2885 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2886 STRLENOF("serialNumber")) == 0 ))
2888 /* parse serialNumber */
2890 x.bv_val += STRLENOF("serialNumber");
2891 x.bv_len -= STRLENOF("serialNumber");
2893 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2894 x.bv_val++; x.bv_len--;
2896 /* eat leading spaces */
2897 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2901 sn->bv_val = x.bv_val;
2904 if( sn->bv_val[0] == '-' ) {
2909 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2910 sn->bv_val[1] == 'X' )) {
2912 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2913 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2915 } else if ( sn->bv_val[0] == '\'' ) {
2916 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2917 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2919 if ( sn->bv_val[sn->bv_len] == '\'' &&
2920 sn->bv_val[sn->bv_len+1] == 'H' )
2923 return LDAP_INVALID_SYNTAX;
2926 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2927 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2931 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2932 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2933 return LDAP_INVALID_SYNTAX;
2936 x.bv_val += sn->bv_len;
2937 x.bv_len -= sn->bv_len;
2939 } else return LDAP_INVALID_SYNTAX;
2941 /* eat trailing spaces */
2942 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2946 /* should have no characters left... */
2947 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2949 ber_dupbv_x( &ni, is, ctx );
2952 /* need to handle double dquotes here */
2958 serialNumberAndIssuerValidate(
2963 struct berval sn, i;
2965 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2968 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
2972 /* validate DN -- doesn't handle double dquote */
2973 rc = dnValidate( NULL, &i );
2975 rc = LDAP_INVALID_SYNTAX;
2977 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2978 slap_sl_free( i.bv_val, NULL );
2981 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2987 serialNumberAndIssuerPretty(
2994 struct berval sn, i, ni;
2996 assert( in != NULL );
2997 assert( out != NULL );
2999 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3002 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3006 rc = dnPretty( syntax, &i, &ni, ctx );
3008 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3009 slap_sl_free( i.bv_val, ctx );
3012 if( rc ) return LDAP_INVALID_SYNTAX;
3014 /* make room from sn + "$" */
3015 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3016 + sn.bv_len + ni.bv_len;
3017 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3019 if( out->bv_val == NULL ) {
3021 slap_sl_free( ni.bv_val, ctx );
3026 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3027 STRLENOF("{ serialNumber "));
3028 n = STRLENOF("{ serialNumber ");
3030 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3033 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3034 n += STRLENOF(", issuer rdnSequence:\"");
3036 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3039 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3040 n += STRLENOF("\" }");
3042 out->bv_val[n] = '\0';
3044 assert( n == out->bv_len );
3046 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3047 out->bv_val, 0, 0 );
3049 slap_sl_free( ni.bv_val, ctx );
3051 return LDAP_SUCCESS;
3055 * This routine is called by certificateExactNormalize when
3056 * certificateExactNormalize receives a search string instead of
3057 * a certificate. This routine checks if the search value is valid
3058 * and then returns the normalized value
3061 serialNumberAndIssuerNormalize(
3069 struct berval sn, sn2, i, ni;
3070 char sbuf[64], *stmp = sbuf;
3074 assert( in != NULL );
3075 assert( out != NULL );
3077 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3080 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3084 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3086 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3087 slap_sl_free( i.bv_val, ctx );
3090 if( rc ) return LDAP_INVALID_SYNTAX;
3092 /* Convert sn to canonical hex */
3093 if ( sn.bv_len > sizeof( sbuf )) {
3094 stmp = slap_sl_malloc( sn.bv_len, ctx );
3097 sn2.bv_len = sn.bv_len;
3098 if ( lutil_str2bin( &sn, &sn2 )) {
3099 rc = LDAP_INVALID_SYNTAX;
3103 /* make room for sn + "$" */
3104 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3105 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3106 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3108 if( out->bv_val == NULL ) {
3110 slap_sl_free( ni.bv_val, ctx );
3116 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3117 STRLENOF( "{ serialNumber " ));
3118 n = STRLENOF( "{ serialNumber " );
3120 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3123 unsigned char *v = (unsigned char *)sn2.bv_val;
3124 out->bv_val[n++] = '\'';
3125 for ( j = 0; j < sn2.bv_len; j++ ) {
3126 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3130 out->bv_val[n++] = '\'';
3131 out->bv_val[n++] = 'H';
3134 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3135 n += STRLENOF( ", issuer rdnSequence:\"" );
3137 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3140 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3141 n += STRLENOF( "\" }" );
3143 out->bv_val[n] = '\0';
3145 assert( n == out->bv_len );
3147 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3148 out->bv_val, 0, 0 );
3152 slap_sl_free( stmp, ctx );
3153 slap_sl_free( ni.bv_val, ctx );
3159 certificateExactNormalize(
3164 struct berval *normalized,
3167 BerElementBuffer berbuf;
3168 BerElement *ber = (BerElement *)&berbuf;
3172 char serialbuf[64], *serial = serialbuf;
3173 ber_len_t seriallen;
3174 struct berval issuer_dn = BER_BVNULL, bvdn;
3176 int rc = LDAP_INVALID_SYNTAX;
3178 if( BER_BVISEMPTY( val ) ) goto done;
3180 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3181 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3184 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3186 ber_init2( ber, val, LBER_USE_DER );
3187 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3188 tag = ber_skip_tag( ber, &len ); /* Sequence */
3189 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3190 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3191 tag = ber_skip_tag( ber, &len );
3192 tag = ber_get_int( ber, &i ); /* version */
3195 /* NOTE: move the test here from certificateValidate,
3196 * so that we can validate certs with serial longer
3197 * than sizeof(ber_int_t) */
3198 tag = ber_peek_tag( ber, &len ); /* serial */
3200 /* Use hex format. '123456789abcdef'H
3206 tag = ber_skip_tag( ber, &len );
3207 ptr = (unsigned char *)ber->ber_ptr;
3208 ber_skip_data( ber, len );
3210 /* Check for minimal encodings */
3212 if ( ptr[0] & 0x80 ) {
3213 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3214 return LDAP_INVALID_SYNTAX;
3215 } else if ( ptr[0] == 0 ) {
3216 if (!( ptr[1] & 0x80 ))
3217 return LDAP_INVALID_SYNTAX;
3221 seriallen = len * 2 + 4; /* quotes, H, NUL */
3222 if ( seriallen > sizeof( serialbuf ))
3223 serial = slap_sl_malloc( seriallen, ctx );
3226 for ( i = 0; i<len; i++ ) {
3227 sprintf( sptr, "%02X", ptr[i] );
3234 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3235 ber_skip_data( ber, len );
3236 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3237 len = ber_ptrlen( ber );
3238 bvdn.bv_val = val->bv_val + len;
3239 bvdn.bv_len = val->bv_len - len;
3241 rc = dnX509normalize( &bvdn, &issuer_dn );
3242 if( rc != LDAP_SUCCESS ) goto done;
3244 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3245 + seriallen + issuer_dn.bv_len;
3246 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3248 p = (unsigned char *)normalized->bv_val;
3250 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3251 p += STRLENOF( "{ serialNumber " );
3253 AC_MEMCPY(p, serial, seriallen);
3256 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3257 p += STRLENOF( ", issuer rdnSequence:\"" );
3259 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3260 p += issuer_dn.bv_len;
3262 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3263 p += STRLENOF( "\" }" );
3267 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3268 normalized->bv_val, NULL, NULL );
3273 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3274 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3286 assert( in != NULL );
3287 assert( !BER_BVISNULL( in ) );
3289 for ( i = 0; i < in->bv_len; i++ ) {
3290 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3291 return LDAP_INVALID_SYNTAX;
3295 return LDAP_SUCCESS;
3298 /* Normalize a SID as used inside a CSN:
3299 * three-digit numeric string */
3306 struct berval *normalized,
3311 assert( val != NULL );
3312 assert( normalized != NULL );
3314 ber_dupbv_x( normalized, val, ctx );
3316 for ( i = 0; i < normalized->bv_len; i++ ) {
3317 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3318 ber_memfree_x( normalized->bv_val, ctx );
3319 BER_BVZERO( normalized );
3320 return LDAP_INVALID_SYNTAX;
3323 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3326 return LDAP_SUCCESS;
3334 assert( in != NULL );
3335 assert( !BER_BVISNULL( in ) );
3337 if ( in->bv_len != 3 ) {
3338 return LDAP_INVALID_SYNTAX;
3341 return hexValidate( NULL, in );
3344 /* Normalize a SID as used inside a CSN:
3345 * three-digit numeric string */
3352 struct berval *normalized,
3355 if ( val->bv_len != 3 ) {
3356 return LDAP_INVALID_SYNTAX;
3359 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3369 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3372 /* Normalize a SID as used inside a CSN, either as-is
3373 * (assertion value) or extracted from the CSN
3374 * (attribute value) */
3381 struct berval *normalized,
3389 if ( BER_BVISEMPTY( val ) ) {
3390 return LDAP_INVALID_SYNTAX;
3393 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3394 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3397 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3399 ptr = ber_bvchr( val, '#' );
3400 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3401 return LDAP_INVALID_SYNTAX;
3404 bv.bv_val = ptr + 1;
3405 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3407 ptr = ber_bvchr( &bv, '#' );
3408 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3409 return LDAP_INVALID_SYNTAX;
3412 bv.bv_val = ptr + 1;
3413 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3415 ptr = ber_bvchr( &bv, '#' );
3416 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3417 return LDAP_INVALID_SYNTAX;
3420 bv.bv_len = ptr - bv.bv_val;
3422 if ( bv.bv_len == 2 ) {
3423 /* OpenLDAP 2.3 SID */
3425 buf[ 1 ] = bv.bv_val[ 0 ];
3426 buf[ 2 ] = bv.bv_val[ 1 ];
3433 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3445 assert( in != NULL );
3446 assert( !BER_BVISNULL( in ) );
3448 if ( BER_BVISEMPTY( in ) ) {
3449 return LDAP_INVALID_SYNTAX;
3454 ptr = ber_bvchr( &bv, '#' );
3455 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3456 return LDAP_INVALID_SYNTAX;
3459 bv.bv_len = ptr - bv.bv_val;
3460 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3461 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3463 return LDAP_INVALID_SYNTAX;
3466 rc = generalizedTimeValidate( NULL, &bv );
3467 if ( rc != LDAP_SUCCESS ) {
3471 bv.bv_val = ptr + 1;
3472 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3474 ptr = ber_bvchr( &bv, '#' );
3475 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3476 return LDAP_INVALID_SYNTAX;
3479 bv.bv_len = ptr - bv.bv_val;
3480 if ( bv.bv_len != 6 ) {
3481 return LDAP_INVALID_SYNTAX;
3484 rc = hexValidate( NULL, &bv );
3485 if ( rc != LDAP_SUCCESS ) {
3489 bv.bv_val = ptr + 1;
3490 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3492 ptr = ber_bvchr( &bv, '#' );
3493 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3494 return LDAP_INVALID_SYNTAX;
3497 bv.bv_len = ptr - bv.bv_val;
3498 if ( bv.bv_len == 2 ) {
3499 /* tolerate old 2-digit replica-id */
3500 rc = hexValidate( NULL, &bv );
3503 rc = sidValidate( NULL, &bv );
3505 if ( rc != LDAP_SUCCESS ) {
3509 bv.bv_val = ptr + 1;
3510 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3512 if ( bv.bv_len != 6 ) {
3513 return LDAP_INVALID_SYNTAX;
3516 return hexValidate( NULL, &bv );
3519 /* Normalize a CSN in OpenLDAP 2.3 format */
3526 struct berval *normalized,
3529 struct berval gt, cnt, sid, mod;
3533 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3534 assert( !BER_BVISEMPTY( val ) );
3538 ptr = ber_bvchr( >, '#' );
3539 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3540 return LDAP_INVALID_SYNTAX;
3543 gt.bv_len = ptr - gt.bv_val;
3544 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3546 cnt.bv_val = ptr + 1;
3547 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3549 ptr = ber_bvchr( &cnt, '#' );
3550 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3551 return LDAP_INVALID_SYNTAX;
3554 cnt.bv_len = ptr - cnt.bv_val;
3555 assert( cnt.bv_len == STRLENOF( "000000" ) );
3557 sid.bv_val = ptr + 1;
3558 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3560 ptr = ber_bvchr( &sid, '#' );
3561 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3562 return LDAP_INVALID_SYNTAX;
3565 sid.bv_len = ptr - sid.bv_val;
3566 assert( sid.bv_len == STRLENOF( "00" ) );
3568 mod.bv_val = ptr + 1;
3569 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3570 assert( mod.bv_len == STRLENOF( "000000" ) );
3572 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3573 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3575 ptr = normalized->bv_val;
3576 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3577 ptr = lutil_strcopy( ptr, ".000000Z#" );
3578 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3581 for ( i = 0; i < sid.bv_len; i++ ) {
3582 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3585 for ( i = 0; i < mod.bv_len; i++ ) {
3586 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3590 assert( ptr - normalized->bv_val == normalized->bv_len );
3592 return LDAP_SUCCESS;
3595 /* Normalize a CSN */
3602 struct berval *normalized,
3605 struct berval cnt, sid, mod;
3609 assert( val != NULL );
3610 assert( normalized != NULL );
3612 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3614 if ( BER_BVISEMPTY( val ) ) {
3615 return LDAP_INVALID_SYNTAX;
3618 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3619 /* Openldap <= 2.3 */
3621 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3624 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3626 ptr = ber_bvchr( val, '#' );
3627 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3628 return LDAP_INVALID_SYNTAX;
3631 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3633 cnt.bv_val = ptr + 1;
3634 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3636 ptr = ber_bvchr( &cnt, '#' );
3637 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3638 return LDAP_INVALID_SYNTAX;
3641 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3643 sid.bv_val = ptr + 1;
3644 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3646 ptr = ber_bvchr( &sid, '#' );
3647 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3648 return LDAP_INVALID_SYNTAX;
3651 sid.bv_len = ptr - sid.bv_val;
3652 assert( sid.bv_len == STRLENOF( "000" ) );
3654 mod.bv_val = ptr + 1;
3655 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3657 assert( mod.bv_len == STRLENOF( "000000" ) );
3659 ber_dupbv_x( normalized, val, ctx );
3661 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3662 i < normalized->bv_len; i++ )
3664 /* assume it's already validated that's all hex digits */
3665 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3668 return LDAP_SUCCESS;
3678 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3681 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3682 /* slight optimization - does not need the start parameter */
3683 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3688 check_time_syntax (struct berval *val,
3691 struct berval *fraction)
3694 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3695 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3696 * GeneralizedTime supports leap seconds, UTCTime does not.
3698 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3699 static const int mdays[2][12] = {
3700 /* non-leap years */
3701 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3703 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3706 int part, c, c1, c2, tzoffset, leapyear = 0;
3709 e = p + val->bv_len;
3711 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3712 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3714 for (part = start; part < 7 && p < e; part++) {
3716 if (!ASCII_DIGIT(c1)) {
3721 return LDAP_INVALID_SYNTAX;
3724 if (!ASCII_DIGIT(c)) {
3725 return LDAP_INVALID_SYNTAX;
3727 c += c1 * 10 - '0' * 11;
3728 if ((part | 1) == 3) {
3731 return LDAP_INVALID_SYNTAX;
3734 if (c >= ceiling[part]) {
3735 if (! (c == 60 && part == 6 && start == 0))
3736 return LDAP_INVALID_SYNTAX;
3740 if (part < 5 + start) {
3741 return LDAP_INVALID_SYNTAX;
3743 for (; part < 9; part++) {
3747 /* leapyear check for the Gregorian calendar (year>1581) */
3748 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3752 if (parts[3] >= mdays[leapyear][parts[2]]) {
3753 return LDAP_INVALID_SYNTAX;
3757 fraction->bv_val = p;
3758 fraction->bv_len = 0;
3759 if (p < e && (*p == '.' || *p == ',')) {
3761 while (++p < e && ASCII_DIGIT(*p)) {
3764 if (p - fraction->bv_val == 1) {
3765 return LDAP_INVALID_SYNTAX;
3767 for (end_num = p; end_num[-1] == '0'; --end_num) {
3770 c = end_num - fraction->bv_val;
3771 if (c != 1) fraction->bv_len = c;
3777 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3783 return LDAP_INVALID_SYNTAX;
3789 for (part = 7; part < 9 && p < e; part++) {
3791 if (!ASCII_DIGIT(c1)) {
3796 return LDAP_INVALID_SYNTAX;
3799 if (!ASCII_DIGIT(c2)) {
3800 return LDAP_INVALID_SYNTAX;
3802 parts[part] = c1 * 10 + c2 - '0' * 11;
3803 if (parts[part] >= ceiling[part]) {
3804 return LDAP_INVALID_SYNTAX;
3807 if (part < 8 + start) {
3808 return LDAP_INVALID_SYNTAX;
3811 if (tzoffset == '-') {
3812 /* negative offset to UTC, ie west of Greenwich */
3813 parts[4] += parts[7];
3814 parts[5] += parts[8];
3815 /* offset is just hhmm, no seconds */
3816 for (part = 6; --part >= 0; ) {
3820 c = mdays[leapyear][parts[2]];
3822 if (parts[part] >= c) {
3824 return LDAP_INVALID_SYNTAX;
3829 } else if (part != 5) {
3834 /* positive offset to UTC, ie east of Greenwich */
3835 parts[4] -= parts[7];
3836 parts[5] -= parts[8];
3837 for (part = 6; --part >= 0; ) {
3838 if (parts[part] < 0) {
3840 return LDAP_INVALID_SYNTAX;
3845 /* make first arg to % non-negative */
3846 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3851 } else if (part != 5) {
3858 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3861 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3868 struct berval *normalized )
3872 rc = check_time_syntax(val, 1, parts, NULL);
3873 if (rc != LDAP_SUCCESS) {
3877 normalized->bv_val = ch_malloc( 14 );
3878 if ( normalized->bv_val == NULL ) {
3879 return LBER_ERROR_MEMORY;
3882 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3883 parts[1], parts[2] + 1, parts[3] + 1,
3884 parts[4], parts[5], parts[6] );
3885 normalized->bv_len = 13;
3887 return LDAP_SUCCESS;
3897 return check_time_syntax(in, 1, parts, NULL);
3900 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3903 generalizedTimeValidate(
3908 struct berval fraction;
3909 return check_time_syntax(in, 0, parts, &fraction);
3913 generalizedTimeNormalize(
3918 struct berval *normalized,
3923 struct berval fraction;
3925 rc = check_time_syntax(val, 0, parts, &fraction);
3926 if (rc != LDAP_SUCCESS) {
3930 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3931 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3932 if ( BER_BVISNULL( normalized ) ) {
3933 return LBER_ERROR_MEMORY;
3936 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3937 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3938 parts[4], parts[5], parts[6] );
3939 if ( !BER_BVISEMPTY( &fraction ) ) {
3940 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3941 fraction.bv_val, fraction.bv_len );
3942 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3944 strcpy( normalized->bv_val + len-1, "Z" );
3945 normalized->bv_len = len;
3947 return LDAP_SUCCESS;
3951 generalizedTimeOrderingMatch(
3956 struct berval *value,
3957 void *assertedValue )
3959 struct berval *asserted = (struct berval *) assertedValue;
3960 ber_len_t v_len = value->bv_len;
3961 ber_len_t av_len = asserted->bv_len;
3963 /* ignore trailing 'Z' when comparing */
3964 int match = memcmp( value->bv_val, asserted->bv_val,
3965 (v_len < av_len ? v_len : av_len) - 1 );
3966 if ( match == 0 ) match = v_len - av_len;
3969 return LDAP_SUCCESS;
3972 /* Index generation function */
3973 int generalizedTimeIndexer(
3978 struct berval *prefix,
3986 BerValue bvtmp; /* 40 bit index */
3988 struct lutil_timet tt;
3990 bvtmp.bv_len = sizeof(tmp);
3992 for( i=0; values[i].bv_val != NULL; i++ ) {
3993 /* just count them */
3996 /* we should have at least one value at this point */
3999 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4001 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4002 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4003 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4004 /* Use 40 bits of time for key */
4005 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4006 lutil_tm2time( &tm, &tt );
4007 tmp[0] = tt.tt_gsec & 0xff;
4008 tmp[4] = tt.tt_sec & 0xff;
4010 tmp[3] = tt.tt_sec & 0xff;
4012 tmp[2] = tt.tt_sec & 0xff;
4014 tmp[1] = tt.tt_sec & 0xff;
4016 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4020 keys[j].bv_val = NULL;
4025 return LDAP_SUCCESS;
4028 /* Index generation function */
4029 int generalizedTimeFilter(
4034 struct berval *prefix,
4035 void * assertedValue,
4041 BerValue bvtmp; /* 40 bit index */
4042 BerValue *value = (BerValue *) assertedValue;
4044 struct lutil_timet tt;
4046 bvtmp.bv_len = sizeof(tmp);
4048 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4049 /* Use 40 bits of time for key */
4050 if ( value->bv_val && value->bv_len >= 10 &&
4051 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4053 lutil_tm2time( &tm, &tt );
4054 tmp[0] = tt.tt_gsec & 0xff;
4055 tmp[4] = tt.tt_sec & 0xff;
4057 tmp[3] = tt.tt_sec & 0xff;
4059 tmp[2] = tt.tt_sec & 0xff;
4061 tmp[1] = tt.tt_sec & 0xff;
4063 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4064 ber_dupbv_x(keys, &bvtmp, ctx );
4065 keys[1].bv_val = NULL;
4073 return LDAP_SUCCESS;
4077 deliveryMethodValidate(
4079 struct berval *val )
4082 #define LENOF(s) (sizeof(s)-1)
4083 struct berval tmp = *val;
4085 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4086 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4087 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4090 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4092 switch( tmp.bv_val[0] ) {
4095 if(( tmp.bv_len >= LENOF("any") ) &&
4096 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4098 tmp.bv_len -= LENOF("any");
4099 tmp.bv_val += LENOF("any");
4102 return LDAP_INVALID_SYNTAX;
4106 if(( tmp.bv_len >= LENOF("mhs") ) &&
4107 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4109 tmp.bv_len -= LENOF("mhs");
4110 tmp.bv_val += LENOF("mhs");
4113 return LDAP_INVALID_SYNTAX;
4117 if(( tmp.bv_len >= LENOF("physical") ) &&
4118 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4120 tmp.bv_len -= LENOF("physical");
4121 tmp.bv_val += LENOF("physical");
4124 return LDAP_INVALID_SYNTAX;
4127 case 'T': /* telex or teletex or telephone */
4128 if(( tmp.bv_len >= LENOF("telex") ) &&
4129 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4131 tmp.bv_len -= LENOF("telex");
4132 tmp.bv_val += LENOF("telex");
4135 if(( tmp.bv_len >= LENOF("teletex") ) &&
4136 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4138 tmp.bv_len -= LENOF("teletex");
4139 tmp.bv_val += LENOF("teletex");
4142 if(( tmp.bv_len >= LENOF("telephone") ) &&
4143 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4145 tmp.bv_len -= LENOF("telephone");
4146 tmp.bv_val += LENOF("telephone");
4149 return LDAP_INVALID_SYNTAX;
4152 case 'G': /* g3fax or g4fax */
4153 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4154 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4155 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4157 tmp.bv_len -= LENOF("g3fax");
4158 tmp.bv_val += LENOF("g3fax");
4161 return LDAP_INVALID_SYNTAX;
4165 if(( tmp.bv_len >= LENOF("ia5") ) &&
4166 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4168 tmp.bv_len -= LENOF("ia5");
4169 tmp.bv_val += LENOF("ia5");
4172 return LDAP_INVALID_SYNTAX;
4176 if(( tmp.bv_len >= LENOF("videotex") ) &&
4177 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4179 tmp.bv_len -= LENOF("videotex");
4180 tmp.bv_val += LENOF("videotex");
4183 return LDAP_INVALID_SYNTAX;
4186 return LDAP_INVALID_SYNTAX;
4189 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4191 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4195 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4199 return LDAP_INVALID_SYNTAX;
4201 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4210 nisNetgroupTripleValidate(
4212 struct berval *val )
4217 if ( BER_BVISEMPTY( val ) ) {
4218 return LDAP_INVALID_SYNTAX;
4221 p = (char *)val->bv_val;
4222 e = p + val->bv_len;
4224 if ( *p != '(' /*')'*/ ) {
4225 return LDAP_INVALID_SYNTAX;
4228 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4232 return LDAP_INVALID_SYNTAX;
4235 } else if ( !AD_CHAR( *p ) ) {
4236 return LDAP_INVALID_SYNTAX;
4240 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4241 return LDAP_INVALID_SYNTAX;
4247 return LDAP_INVALID_SYNTAX;
4250 return LDAP_SUCCESS;
4254 bootParameterValidate(
4256 struct berval *val )
4260 if ( BER_BVISEMPTY( val ) ) {
4261 return LDAP_INVALID_SYNTAX;
4264 p = (char *)val->bv_val;
4265 e = p + val->bv_len;
4268 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4269 if ( !AD_CHAR( *p ) ) {
4270 return LDAP_INVALID_SYNTAX;
4275 return LDAP_INVALID_SYNTAX;
4279 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4280 if ( !AD_CHAR( *p ) ) {
4281 return LDAP_INVALID_SYNTAX;
4286 return LDAP_INVALID_SYNTAX;
4290 for ( p++; p < e; p++ ) {
4291 if ( !SLAP_PRINTABLE( *p ) ) {
4292 return LDAP_INVALID_SYNTAX;
4296 return LDAP_SUCCESS;
4300 firstComponentNormalize(
4305 struct berval *normalized,
4312 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4313 ber_dupbv_x( normalized, val, ctx );
4314 return LDAP_SUCCESS;
4317 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4319 if( val->bv_val[0] != '(' /*')'*/ &&
4320 val->bv_val[0] != '{' /*'}'*/ )
4322 return LDAP_INVALID_SYNTAX;
4325 /* trim leading white space */
4327 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4333 /* grab next word */
4334 comp.bv_val = &val->bv_val[len];
4335 len = val->bv_len - len;
4336 for( comp.bv_len = 0;
4337 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4343 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4344 rc = numericoidValidate( NULL, &comp );
4345 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4346 rc = integerValidate( NULL, &comp );
4348 rc = LDAP_INVALID_SYNTAX;
4352 if( rc == LDAP_SUCCESS ) {
4353 ber_dupbv_x( normalized, &comp, ctx );
4359 static char *country_gen_syn[] = {
4360 "1.3.6.1.4.1.1466.115.121.1.15",
4361 "1.3.6.1.4.1.1466.115.121.1.26",
4362 "1.3.6.1.4.1.1466.115.121.1.44",
4366 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4367 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4369 static slap_syntax_defs_rec syntax_defs[] = {
4370 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4371 X_BINARY X_NOT_H_R ")",
4372 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4373 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4374 0, NULL, NULL, NULL},
4375 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4376 0, NULL, NULL, NULL},
4377 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4379 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4380 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4382 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4383 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4384 0, NULL, bitStringValidate, NULL },
4385 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4386 0, NULL, booleanValidate, NULL},
4387 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4388 X_BINARY X_NOT_H_R ")",
4389 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4390 NULL, certificateValidate, NULL},
4391 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4392 X_BINARY X_NOT_H_R ")",
4393 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4394 NULL, certificateListValidate, NULL},
4395 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4396 X_BINARY X_NOT_H_R ")",
4397 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4398 NULL, sequenceValidate, NULL},
4399 #if 0 /* need to go __after__ printableString */
4400 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4401 0, "1.3.6.1.4.1.1466.115.121.1.44",
4402 countryStringValidate, NULL},
4404 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4405 0, NULL, dnValidate, dnPretty},
4406 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4407 0, NULL, rdnValidate, rdnPretty},
4408 #ifdef LDAP_COMP_MATCH
4409 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4410 0, NULL, allComponentsValidate, NULL},
4411 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4412 0, NULL, componentFilterValidate, NULL},
4414 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4415 0, NULL, NULL, NULL},
4416 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4417 0, NULL, deliveryMethodValidate, NULL},
4418 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4419 0, NULL, UTF8StringValidate, NULL},
4420 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4421 0, NULL, NULL, NULL},
4422 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4423 0, NULL, NULL, NULL},
4424 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4425 0, NULL, NULL, NULL},
4426 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4427 0, NULL, NULL, NULL},
4428 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4429 0, NULL, NULL, NULL},
4430 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4431 0, NULL, printablesStringValidate, NULL},
4432 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4433 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4434 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4435 0, NULL, generalizedTimeValidate, NULL},
4436 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4437 0, NULL, NULL, NULL},
4438 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4439 0, NULL, IA5StringValidate, NULL},
4440 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4441 0, NULL, integerValidate, NULL},
4442 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4443 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4444 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4445 0, NULL, NULL, NULL},
4446 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4447 0, NULL, NULL, NULL},
4448 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4449 0, NULL, NULL, NULL},
4450 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4451 0, NULL, NULL, NULL},
4452 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4453 0, NULL, NULL, NULL},
4454 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4455 0, NULL, nameUIDValidate, nameUIDPretty },
4456 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4457 0, NULL, NULL, NULL},
4458 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4459 0, NULL, numericStringValidate, NULL},
4460 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4461 0, NULL, NULL, NULL},
4462 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4463 0, NULL, numericoidValidate, NULL},
4464 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4465 0, NULL, IA5StringValidate, NULL},
4466 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4467 0, NULL, blobValidate, NULL},
4468 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4469 0, NULL, UTF8StringValidate, NULL},
4470 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4471 0, NULL, NULL, NULL},
4472 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4473 0, NULL, NULL, NULL},
4474 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4475 0, NULL, printableStringValidate, NULL},
4476 /* moved here because now depends on Directory String, IA5 String
4477 * and Printable String */
4478 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4479 0, country_gen_syn, countryStringValidate, NULL},
4480 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4481 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4482 0, NULL, subtreeSpecificationValidate, NULL},
4483 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4484 X_BINARY X_NOT_H_R ")",
4485 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4486 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4487 0, NULL, printableStringValidate, NULL},
4488 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4489 0, NULL, NULL, NULL},
4490 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4491 0, NULL, printablesStringValidate, NULL},
4492 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4493 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4494 0, NULL, utcTimeValidate, NULL},
4496 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4497 0, NULL, NULL, NULL},
4498 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4499 0, NULL, NULL, NULL},
4500 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4501 0, NULL, NULL, NULL},
4502 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4503 0, NULL, NULL, NULL},
4504 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4505 0, NULL, NULL, NULL},
4507 /* RFC 2307 NIS Syntaxes */
4508 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4509 0, NULL, nisNetgroupTripleValidate, NULL},
4510 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4511 0, NULL, bootParameterValidate, NULL},
4513 /* draft-zeilenga-ldap-x509 */
4514 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4515 SLAP_SYNTAX_HIDE, NULL,
4516 serialNumberAndIssuerValidate,
4517 serialNumberAndIssuerPretty},
4518 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4519 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4520 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4521 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4522 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4523 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4524 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4525 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4526 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4527 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4528 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4529 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4531 #ifdef SLAPD_AUTHPASSWD
4532 /* needs updating */
4533 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4534 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4537 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4538 0, NULL, UUIDValidate, UUIDPretty},
4540 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4541 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4543 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4544 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4546 /* OpenLDAP Void Syntax */
4547 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4548 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4550 /* FIXME: OID is unused, but not registered yet */
4551 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4552 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4554 {NULL, 0, NULL, NULL, NULL}
4557 char *csnSIDMatchSyntaxes[] = {
4558 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4561 char *certificateExactMatchSyntaxes[] = {
4562 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4565 #ifdef LDAP_COMP_MATCH
4566 char *componentFilterMatchSyntaxes[] = {
4567 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4571 char *directoryStringSyntaxes[] = {
4572 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4575 char *integerFirstComponentMatchSyntaxes[] = {
4576 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4577 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4580 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4581 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4582 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4583 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4584 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4585 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4586 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4587 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4588 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4593 * Other matching rules in X.520 that we do not use (yet):
4595 * 2.5.13.25 uTCTimeMatch
4596 * 2.5.13.26 uTCTimeOrderingMatch
4597 * 2.5.13.31* directoryStringFirstComponentMatch
4598 * 2.5.13.32* wordMatch
4599 * 2.5.13.33* keywordMatch
4600 * 2.5.13.36+ certificatePairExactMatch
4601 * 2.5.13.37+ certificatePairMatch
4602 * 2.5.13.38+ certificateListExactMatch
4603 * 2.5.13.39+ certificateListMatch
4604 * 2.5.13.40+ algorithmIdentifierMatch
4605 * 2.5.13.41* storedPrefixMatch
4606 * 2.5.13.42 attributeCertificateMatch
4607 * 2.5.13.43 readerAndKeyIDMatch
4608 * 2.5.13.44 attributeIntegrityMatch
4610 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4611 * (+) described in draft-zeilenga-ldap-x509
4613 static slap_mrule_defs_rec mrule_defs[] = {
4615 * EQUALITY matching rules must be listed after associated APPROX
4616 * matching rules. So, we list all APPROX matching rules first.
4618 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4619 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4620 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4621 NULL, NULL, directoryStringApproxMatch,
4622 directoryStringApproxIndexer, directoryStringApproxFilter,
4625 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4626 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4627 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4628 NULL, NULL, IA5StringApproxMatch,
4629 IA5StringApproxIndexer, IA5StringApproxFilter,
4633 * Other matching rules
4636 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4637 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4638 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4639 NULL, NULL, octetStringMatch,
4640 octetStringIndexer, octetStringFilter,
4643 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4644 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4645 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4646 NULL, dnNormalize, dnMatch,
4647 octetStringIndexer, octetStringFilter,
4650 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4651 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4652 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4653 NULL, dnNormalize, dnRelativeMatch,
4657 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4658 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4659 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4660 NULL, dnNormalize, dnRelativeMatch,
4664 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4665 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4666 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4667 NULL, dnNormalize, dnRelativeMatch,
4671 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4672 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4673 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4674 NULL, dnNormalize, dnRelativeMatch,
4678 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4679 "SYNTAX 1.2.36.79672281.1.5.0 )",
4680 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4681 NULL, rdnNormalize, rdnMatch,
4682 octetStringIndexer, octetStringFilter,
4685 #ifdef LDAP_COMP_MATCH
4686 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4687 "SYNTAX 1.2.36.79672281.1.5.2 )",
4688 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4689 NULL, NULL , componentFilterMatch,
4690 octetStringIndexer, octetStringFilter,
4693 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4694 "SYNTAX 1.2.36.79672281.1.5.3 )",
4695 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4696 NULL, NULL , allComponentsMatch,
4697 octetStringIndexer, octetStringFilter,
4700 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4701 "SYNTAX 1.2.36.79672281.1.5.3 )",
4702 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4703 NULL, NULL , directoryComponentsMatch,
4704 octetStringIndexer, octetStringFilter,
4708 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4709 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4710 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4711 NULL, UTF8StringNormalize, octetStringMatch,
4712 octetStringIndexer, octetStringFilter,
4713 directoryStringApproxMatchOID },
4715 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4716 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4717 SLAP_MR_ORDERING, directoryStringSyntaxes,
4718 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4720 "caseIgnoreMatch" },
4722 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4723 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4724 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4725 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4726 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4727 "caseIgnoreMatch" },
4729 {"( 2.5.13.5 NAME 'caseExactMatch' "
4730 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4731 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4732 NULL, UTF8StringNormalize, octetStringMatch,
4733 octetStringIndexer, octetStringFilter,
4734 directoryStringApproxMatchOID },
4736 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4738 SLAP_MR_ORDERING, directoryStringSyntaxes,
4739 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4743 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4745 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4746 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4747 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4750 {"( 2.5.13.8 NAME 'numericStringMatch' "
4751 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4752 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4753 NULL, numericStringNormalize, octetStringMatch,
4754 octetStringIndexer, octetStringFilter,
4757 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4758 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4759 SLAP_MR_ORDERING, NULL,
4760 NULL, numericStringNormalize, octetStringOrderingMatch,
4762 "numericStringMatch" },
4764 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4765 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4766 SLAP_MR_SUBSTR, NULL,
4767 NULL, numericStringNormalize, octetStringSubstringsMatch,
4768 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4769 "numericStringMatch" },
4771 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4772 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4773 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4774 NULL, NULL, NULL, NULL, NULL, NULL },
4776 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4777 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4778 SLAP_MR_SUBSTR, NULL,
4779 NULL, NULL, NULL, NULL, NULL,
4780 "caseIgnoreListMatch" },
4782 {"( 2.5.13.13 NAME 'booleanMatch' "
4783 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4784 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4785 NULL, NULL, booleanMatch,
4786 octetStringIndexer, octetStringFilter,
4789 {"( 2.5.13.14 NAME 'integerMatch' "
4790 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4791 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4792 NULL, NULL, integerMatch,
4793 integerIndexer, integerFilter,
4796 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4797 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4798 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4799 NULL, NULL, integerMatch,
4803 {"( 2.5.13.16 NAME 'bitStringMatch' "
4804 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4805 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4806 NULL, NULL, octetStringMatch,
4807 octetStringIndexer, octetStringFilter,
4810 {"( 2.5.13.17 NAME 'octetStringMatch' "
4811 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4812 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4813 NULL, NULL, octetStringMatch,
4814 octetStringIndexer, octetStringFilter,
4817 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4818 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4819 SLAP_MR_ORDERING, NULL,
4820 NULL, NULL, octetStringOrderingMatch,
4822 "octetStringMatch" },
4824 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4825 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4826 SLAP_MR_SUBSTR, NULL,
4827 NULL, NULL, octetStringSubstringsMatch,
4828 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4829 "octetStringMatch" },
4831 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4832 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4833 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4835 telephoneNumberNormalize, octetStringMatch,
4836 octetStringIndexer, octetStringFilter,
4839 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4840 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4841 SLAP_MR_SUBSTR, NULL,
4842 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4843 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4844 "telephoneNumberMatch" },
4846 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4847 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4848 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4849 NULL, NULL, NULL, NULL, NULL, NULL },
4851 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4852 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4853 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4854 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4855 uniqueMemberIndexer, uniqueMemberFilter,
4858 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4859 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4860 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4861 NULL, NULL, NULL, NULL, NULL, NULL },
4863 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4864 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4865 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4866 NULL, generalizedTimeNormalize, octetStringMatch,
4867 generalizedTimeIndexer, generalizedTimeFilter,
4870 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4871 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4872 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4873 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4875 "generalizedTimeMatch" },
4877 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4878 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4879 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4880 integerFirstComponentMatchSyntaxes,
4881 NULL, firstComponentNormalize, integerMatch,
4882 octetStringIndexer, octetStringFilter,
4885 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4886 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4887 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4888 objectIdentifierFirstComponentMatchSyntaxes,
4889 NULL, firstComponentNormalize, octetStringMatch,
4890 octetStringIndexer, octetStringFilter,
4893 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4894 "SYNTAX 1.3.6.1.1.15.1 )",
4895 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4896 NULL, certificateExactNormalize, octetStringMatch,
4897 octetStringIndexer, octetStringFilter,
4900 {"( 2.5.13.35 NAME 'certificateMatch' "
4901 "SYNTAX 1.3.6.1.1.15.2 )",
4902 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4903 NULL, NULL, NULL, NULL, NULL,
4906 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4907 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4908 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4909 NULL, IA5StringNormalize, octetStringMatch,
4910 octetStringIndexer, octetStringFilter,
4911 IA5StringApproxMatchOID },
4913 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4915 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4916 NULL, IA5StringNormalize, octetStringMatch,
4917 octetStringIndexer, octetStringFilter,
4918 IA5StringApproxMatchOID },
4920 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4922 SLAP_MR_SUBSTR, NULL,
4923 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4924 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4925 "caseIgnoreIA5Match" },
4927 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4928 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4929 SLAP_MR_SUBSTR, NULL,
4930 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4931 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4932 "caseExactIA5Match" },
4934 #ifdef SLAPD_AUTHPASSWD
4935 /* needs updating */
4936 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4937 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4938 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4939 NULL, NULL, authPasswordMatch,
4944 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4945 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4947 NULL, NULL, integerBitAndMatch,
4951 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4952 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4954 NULL, NULL, integerBitOrMatch,
4958 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4959 "SYNTAX 1.3.6.1.1.16.1 )",
4960 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4961 NULL, UUIDNormalize, octetStringMatch,
4962 octetStringIndexer, octetStringFilter,
4965 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4966 "SYNTAX 1.3.6.1.1.16.1 )",
4967 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4968 NULL, UUIDNormalize, octetStringOrderingMatch,
4969 octetStringIndexer, octetStringFilter,
4972 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4973 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4974 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4975 NULL, csnNormalize, csnMatch,
4976 csnIndexer, csnFilter,
4979 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4980 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4981 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4982 NULL, NULL, csnOrderingMatch,
4986 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
4987 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
4988 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
4989 NULL, csnSidNormalize, octetStringMatch,
4990 octetStringIndexer, octetStringFilter,
4993 /* FIXME: OID is unused, but not registered yet */
4994 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
4995 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
4996 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4997 NULL, authzNormalize, authzMatch,
5001 {NULL, SLAP_MR_NONE, NULL,
5002 NULL, NULL, NULL, NULL, NULL,
5007 slap_schema_init( void )
5012 /* we should only be called once (from main) */
5013 assert( schema_init_done == 0 );
5015 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5016 res = register_syntax( &syntax_defs[i] );
5019 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5020 syntax_defs[i].sd_desc );
5025 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5026 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5027 mrule_defs[i].mrd_compat_syntaxes == NULL )
5030 "slap_schema_init: Ignoring unusable matching rule %s\n",
5031 mrule_defs[i].mrd_desc );
5035 res = register_matching_rule( &mrule_defs[i] );
5039 "slap_schema_init: Error registering matching rule %s\n",
5040 mrule_defs[i].mrd_desc );
5045 res = slap_schema_load();
5046 schema_init_done = 1;
5051 schema_destroy( void )
5060 if( schema_init_done ) {
5061 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5062 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );