1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
67 ldap_pvt_thread_mutex_t ad_undef_mutex;
68 ldap_pvt_thread_mutex_t oc_undef_mutex;
71 generalizedTimeValidate(
80 /* no value allowed */
81 return LDAP_INVALID_SYNTAX;
89 /* any value allowed */
93 #define berValidate blobValidate
100 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
101 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
106 /* X.509 related stuff */
114 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
117 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
118 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
119 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
120 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
124 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
127 /* X.509 certificate validation */
128 static int certificateValidate( Syntax *syntax, struct berval *in )
130 BerElementBuffer berbuf;
131 BerElement *ber = (BerElement *)&berbuf;
134 ber_int_t version = SLAP_X509_V1;
136 ber_init2( ber, in, LBER_USE_DER );
137 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
138 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
139 tag = ber_skip_tag( ber, &len ); /* Sequence */
140 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 tag = ber_peek_tag( ber, &len );
142 /* Optional version */
143 if ( tag == SLAP_X509_OPT_C_VERSION ) {
144 tag = ber_skip_tag( ber, &len );
145 tag = ber_get_int( ber, &version );
146 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
148 /* NOTE: don't try to parse Serial, because it might be longer
149 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
150 tag = ber_skip_tag( ber, &len ); /* Serial */
151 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
152 ber_skip_data( ber, len );
153 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
154 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
155 ber_skip_data( ber, len );
156 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
157 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
158 ber_skip_data( ber, len );
159 tag = ber_skip_tag( ber, &len ); /* Validity */
160 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
161 ber_skip_data( ber, len );
162 tag = ber_skip_tag( ber, &len ); /* Subject DN */
163 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
164 ber_skip_data( ber, len );
165 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
166 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
167 ber_skip_data( ber, len );
168 tag = ber_skip_tag( ber, &len );
169 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
170 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
171 ber_skip_data( ber, len );
172 tag = ber_skip_tag( ber, &len );
174 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
175 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
176 ber_skip_data( ber, len );
177 tag = ber_skip_tag( ber, &len );
179 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
180 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
181 tag = ber_skip_tag( ber, &len );
182 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
183 ber_skip_data( ber, len );
184 tag = ber_skip_tag( ber, &len );
186 /* signatureAlgorithm */
187 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
188 ber_skip_data( ber, len );
189 tag = ber_skip_tag( ber, &len );
191 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
192 ber_skip_data( ber, len );
193 tag = ber_skip_tag( ber, &len );
194 /* Must be at end now */
195 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
199 /* X.509 certificate list validation */
200 static int certificateListValidate( Syntax *syntax, struct berval *in )
202 BerElementBuffer berbuf;
203 BerElement *ber = (BerElement *)&berbuf;
206 ber_int_t version = SLAP_X509_V1;
208 ber_init2( ber, in, LBER_USE_DER );
209 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
210 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
211 tag = ber_skip_tag( ber, &len ); /* Sequence */
212 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
213 tag = ber_peek_tag( ber, &len );
214 /* Optional version */
215 if ( tag == LBER_INTEGER ) {
216 tag = ber_get_int( ber, &version );
217 assert( tag == LBER_INTEGER );
218 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
220 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
221 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
222 ber_skip_data( ber, len );
223 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
224 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
225 ber_skip_data( ber, len );
226 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
227 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
228 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
229 ber_skip_data( ber, len );
230 /* Optional nextUpdate */
231 tag = ber_skip_tag( ber, &len );
232 if ( tag == 0x17U || tag == 0x18U ) {
233 ber_skip_data( ber, len );
234 tag = ber_skip_tag( ber, &len );
236 /* revokedCertificates - Sequence of Sequence, Optional */
237 if ( tag == LBER_SEQUENCE ) {
239 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
240 /* Should NOT be empty */
241 ber_skip_data( ber, len );
242 tag = ber_skip_tag( ber, &len );
245 /* Optional Extensions */
246 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
247 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
248 tag = ber_skip_tag( ber, &len );
249 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
250 ber_skip_data( ber, len );
251 tag = ber_skip_tag( ber, &len );
253 /* signatureAlgorithm */
254 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
255 ber_skip_data( ber, len );
256 tag = ber_skip_tag( ber, &len );
258 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
259 ber_skip_data( ber, len );
260 tag = ber_skip_tag( ber, &len );
261 /* Must be at end now */
262 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
272 struct berval *value,
273 void *assertedValue )
275 struct berval *asserted = (struct berval *) assertedValue;
276 int match = value->bv_len - asserted->bv_len;
279 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
287 octetStringOrderingMatch(
292 struct berval *value,
293 void *assertedValue )
295 struct berval *asserted = (struct berval *) assertedValue;
296 ber_len_t v_len = value->bv_len;
297 ber_len_t av_len = asserted->bv_len;
299 int match = memcmp( value->bv_val, asserted->bv_val,
300 (v_len < av_len ? v_len : av_len) );
302 if( match == 0 ) match = v_len - av_len;
310 HASH_CONTEXT *HASHcontext,
311 struct berval *prefix,
316 HASH_Init(HASHcontext);
317 if(prefix && prefix->bv_len > 0) {
318 HASH_Update(HASHcontext,
319 (unsigned char *)prefix->bv_val, prefix->bv_len);
321 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
322 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
323 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
329 HASH_CONTEXT *HASHcontext,
330 unsigned char *HASHdigest,
331 unsigned char *value,
334 HASH_CONTEXT ctx = *HASHcontext;
335 HASH_Update( &ctx, value, len );
336 HASH_Final( HASHdigest, &ctx );
339 /* Index generation function */
340 int octetStringIndexer(
345 struct berval *prefix,
353 HASH_CONTEXT HASHcontext;
354 unsigned char HASHdigest[HASH_BYTES];
355 struct berval digest;
356 digest.bv_val = (char *)HASHdigest;
357 digest.bv_len = sizeof(HASHdigest);
359 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
360 /* just count them */
363 /* we should have at least one value at this point */
366 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
368 slen = syntax->ssyn_oidlen;
369 mlen = mr->smr_oidlen;
371 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
372 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
373 hashIter( &HASHcontext, HASHdigest,
374 (unsigned char *)values[i].bv_val, values[i].bv_len );
375 ber_dupbv_x( &keys[i], &digest, ctx );
378 BER_BVZERO( &keys[i] );
385 /* Index generation function */
386 int octetStringFilter(
391 struct berval *prefix,
392 void * assertedValue,
398 HASH_CONTEXT HASHcontext;
399 unsigned char HASHdigest[HASH_BYTES];
400 struct berval *value = (struct berval *) assertedValue;
401 struct berval digest;
402 digest.bv_val = (char *)HASHdigest;
403 digest.bv_len = sizeof(HASHdigest);
405 slen = syntax->ssyn_oidlen;
406 mlen = mr->smr_oidlen;
408 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
410 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
411 hashIter( &HASHcontext, HASHdigest,
412 (unsigned char *)value->bv_val, value->bv_len );
414 ber_dupbv_x( keys, &digest, ctx );
415 BER_BVZERO( &keys[1] );
423 octetStringSubstringsMatch(
428 struct berval *value,
429 void *assertedValue )
432 SubstringsAssertion *sub = assertedValue;
433 struct berval left = *value;
437 /* Add up asserted input length */
438 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
439 inlen += sub->sa_initial.bv_len;
442 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
443 inlen += sub->sa_any[i].bv_len;
446 if ( !BER_BVISNULL( &sub->sa_final ) ) {
447 inlen += sub->sa_final.bv_len;
450 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
451 if ( inlen > left.bv_len ) {
456 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
457 sub->sa_initial.bv_len );
463 left.bv_val += sub->sa_initial.bv_len;
464 left.bv_len -= sub->sa_initial.bv_len;
465 inlen -= sub->sa_initial.bv_len;
468 if ( !BER_BVISNULL( &sub->sa_final ) ) {
469 if ( inlen > left.bv_len ) {
474 match = memcmp( sub->sa_final.bv_val,
475 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
476 sub->sa_final.bv_len );
482 left.bv_len -= sub->sa_final.bv_len;
483 inlen -= sub->sa_final.bv_len;
487 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
492 if ( inlen > left.bv_len ) {
493 /* not enough length */
498 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
502 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
509 idx = p - left.bv_val;
511 if ( idx >= left.bv_len ) {
512 /* this shouldn't happen */
519 if ( sub->sa_any[i].bv_len > left.bv_len ) {
520 /* not enough left */
525 match = memcmp( left.bv_val,
526 sub->sa_any[i].bv_val,
527 sub->sa_any[i].bv_len );
535 left.bv_val += sub->sa_any[i].bv_len;
536 left.bv_len -= sub->sa_any[i].bv_len;
537 inlen -= sub->sa_any[i].bv_len;
546 /* Substrings Index generation function */
548 octetStringSubstringsIndexer(
553 struct berval *prefix,
562 HASH_CONTEXT HCany, HCini, HCfin;
563 unsigned char HASHdigest[HASH_BYTES];
564 struct berval digest;
565 digest.bv_val = (char *)HASHdigest;
566 digest.bv_len = sizeof(HASHdigest);
570 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
571 /* count number of indices to generate */
572 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
573 if( values[i].bv_len >= index_substr_if_maxlen ) {
574 nkeys += index_substr_if_maxlen -
575 (index_substr_if_minlen - 1);
576 } else if( values[i].bv_len >= index_substr_if_minlen ) {
577 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
581 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
582 if( values[i].bv_len >= index_substr_any_len ) {
583 nkeys += values[i].bv_len - (index_substr_any_len - 1);
587 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
588 if( values[i].bv_len >= index_substr_if_maxlen ) {
589 nkeys += index_substr_if_maxlen -
590 (index_substr_if_minlen - 1);
591 } else if( values[i].bv_len >= index_substr_if_minlen ) {
592 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
598 /* no keys to generate */
603 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
605 slen = syntax->ssyn_oidlen;
606 mlen = mr->smr_oidlen;
608 if ( flags & SLAP_INDEX_SUBSTR_ANY )
609 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
610 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
611 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
612 if( flags & SLAP_INDEX_SUBSTR_FINAL )
613 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
616 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
619 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
620 ( values[i].bv_len >= index_substr_any_len ) )
622 max = values[i].bv_len - (index_substr_any_len - 1);
624 for( j=0; j<max; j++ ) {
625 hashIter( &HCany, HASHdigest,
626 (unsigned char *)&values[i].bv_val[j],
627 index_substr_any_len );
628 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
632 /* skip if too short */
633 if( values[i].bv_len < index_substr_if_minlen ) continue;
635 max = index_substr_if_maxlen < values[i].bv_len
636 ? index_substr_if_maxlen : values[i].bv_len;
638 for( j=index_substr_if_minlen; j<=max; j++ ) {
640 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
641 hashIter( &HCini, HASHdigest,
642 (unsigned char *)values[i].bv_val, j );
643 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
646 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
647 hashIter( &HCfin, HASHdigest,
648 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
649 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
656 BER_BVZERO( &keys[nkeys] );
667 octetStringSubstringsFilter (
672 struct berval *prefix,
673 void * assertedValue,
677 SubstringsAssertion *sa;
680 size_t slen, mlen, klen;
682 HASH_CONTEXT HASHcontext;
683 unsigned char HASHdigest[HASH_BYTES];
684 struct berval *value;
685 struct berval digest;
687 sa = (SubstringsAssertion *) assertedValue;
689 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
690 !BER_BVISNULL( &sa->sa_initial ) &&
691 sa->sa_initial.bv_len >= index_substr_if_minlen )
694 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
695 ( flags & SLAP_INDEX_SUBSTR_ANY ))
697 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
701 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
703 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
704 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
705 /* don't bother accounting with stepping */
706 nkeys += sa->sa_any[i].bv_len -
707 ( index_substr_any_len - 1 );
712 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
713 !BER_BVISNULL( &sa->sa_final ) &&
714 sa->sa_final.bv_len >= index_substr_if_minlen )
717 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
718 ( flags & SLAP_INDEX_SUBSTR_ANY ))
720 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
729 digest.bv_val = (char *)HASHdigest;
730 digest.bv_len = sizeof(HASHdigest);
732 slen = syntax->ssyn_oidlen;
733 mlen = mr->smr_oidlen;
735 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
738 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
739 !BER_BVISNULL( &sa->sa_initial ) &&
740 sa->sa_initial.bv_len >= index_substr_if_minlen )
742 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
743 value = &sa->sa_initial;
745 klen = index_substr_if_maxlen < value->bv_len
746 ? index_substr_if_maxlen : value->bv_len;
748 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
749 hashIter( &HASHcontext, HASHdigest,
750 (unsigned char *)value->bv_val, klen );
751 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
753 /* If initial is too long and we have subany indexed, use it
754 * to match the excess...
756 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
759 pre = SLAP_INDEX_SUBSTR_PREFIX;
760 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
761 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
763 hashIter( &HASHcontext, HASHdigest,
764 (unsigned char *)&value->bv_val[j], index_substr_any_len );
765 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
770 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
772 pre = SLAP_INDEX_SUBSTR_PREFIX;
773 klen = index_substr_any_len;
775 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
776 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
780 value = &sa->sa_any[i];
782 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
784 j <= value->bv_len - index_substr_any_len;
785 j += index_substr_any_step )
787 hashIter( &HASHcontext, HASHdigest,
788 (unsigned char *)&value->bv_val[j], klen );
789 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
794 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
795 !BER_BVISNULL( &sa->sa_final ) &&
796 sa->sa_final.bv_len >= index_substr_if_minlen )
798 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
799 value = &sa->sa_final;
801 klen = index_substr_if_maxlen < value->bv_len
802 ? index_substr_if_maxlen : value->bv_len;
804 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
805 hashIter( &HASHcontext, HASHdigest,
806 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
807 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
809 /* If final is too long and we have subany indexed, use it
810 * to match the excess...
812 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
815 pre = SLAP_INDEX_SUBSTR_PREFIX;
816 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
817 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
819 hashIter( &HASHcontext, HASHdigest,
820 (unsigned char *)&value->bv_val[j], index_substr_any_len );
821 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
827 BER_BVZERO( &keys[nkeys] );
844 /* very unforgiving validation, requires no normalization
845 * before simplistic matching
847 if( in->bv_len < 3 ) {
848 return LDAP_INVALID_SYNTAX;
851 /* RFC 4517 Section 3.3.2 Bit String:
852 * BitString = SQUOTE *binary-digit SQUOTE "B"
853 * binary-digit = "0" / "1"
855 * where SQUOTE [RFC4512] is
856 * SQUOTE = %x27 ; single quote ("'")
858 * Example: '0101111101'B
861 if( in->bv_val[0] != '\'' ||
862 in->bv_val[in->bv_len - 2] != '\'' ||
863 in->bv_val[in->bv_len - 1] != 'B' )
865 return LDAP_INVALID_SYNTAX;
868 for( i = in->bv_len - 3; i > 0; i-- ) {
869 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
870 return LDAP_INVALID_SYNTAX;
878 * Syntaxes from RFC 4517
883 A value of the Bit String syntax is a sequence of binary digits. The
884 LDAP-specific encoding of a value of this syntax is defined by the
887 BitString = SQUOTE *binary-digit SQUOTE "B"
889 binary-digit = "0" / "1"
891 The <SQUOTE> rule is defined in [MODELS].
896 The LDAP definition for the Bit String syntax is:
898 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
900 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
904 3.3.21. Name and Optional UID
906 A value of the Name and Optional UID syntax is the distinguished name
907 [MODELS] of an entity optionally accompanied by a unique identifier
908 that serves to differentiate the entity from others with an identical
911 The LDAP-specific encoding of a value of this syntax is defined by
914 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
916 The <BitString> rule is defined in Section 3.3.2. The
917 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
920 Note that although the '#' character may occur in the string
921 representation of a distinguished name, no additional escaping of
922 this character is performed when a <distinguishedName> is encoded in
923 a <NameAndOptionalUID>.
926 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
928 The LDAP definition for the Name and Optional UID syntax is:
930 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
932 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
939 1.4. Common ABNF Productions
942 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
944 SQUOTE = %x27 ; single quote ("'")
948 * Note: normalization strips any leading "0"s, unless the
949 * bit string is exactly "'0'B", so the normalized example,
950 * in slapd, would result in
952 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
954 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
955 * be escaped except when at the beginning of a value, the
956 * definition of Name and Optional UID appears to be flawed,
957 * because there is no clear means to determine whether the
958 * UID part is present or not.
962 * cn=Someone,dc=example,dc=com#'1'B
964 * could be either a NameAndOptionalUID with trailing UID, i.e.
966 * DN = "cn=Someone,dc=example,dc=com"
969 * or a NameAndOptionalUID with no trailing UID, and the AVA
970 * in the last RDN made of
973 * attributeValue = com#'1'B
975 * in fact "com#'1'B" is a valid IA5 string.
977 * As a consequence, current slapd code assumes that the
978 * presence of portions of a BitString at the end of the string
979 * representation of a NameAndOptionalUID means a BitString
980 * is expected, and cause an error otherwise. This is quite
981 * arbitrary, and might change in the future.
991 struct berval dn, uid;
993 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
995 ber_dupbv( &dn, in );
996 if( !dn.bv_val ) return LDAP_OTHER;
998 /* if there's a "#", try bitStringValidate()... */
999 uid.bv_val = strrchr( dn.bv_val, '#' );
1000 if ( !BER_BVISNULL( &uid ) ) {
1002 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1004 rc = bitStringValidate( NULL, &uid );
1005 if ( rc == LDAP_SUCCESS ) {
1006 /* in case of success, trim the UID,
1007 * otherwise treat it as part of the DN */
1008 dn.bv_len -= uid.bv_len + 1;
1009 uid.bv_val[-1] = '\0';
1013 rc = dnValidate( NULL, &dn );
1015 ber_memfree( dn.bv_val );
1026 assert( val != NULL );
1027 assert( out != NULL );
1030 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1032 if( BER_BVISEMPTY( val ) ) {
1033 ber_dupbv_x( out, val, ctx );
1035 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1036 return LDAP_INVALID_SYNTAX;
1040 struct berval dnval = *val;
1041 struct berval uidval = BER_BVNULL;
1043 uidval.bv_val = strrchr( val->bv_val, '#' );
1044 if ( !BER_BVISNULL( &uidval ) ) {
1046 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1048 rc = bitStringValidate( NULL, &uidval );
1050 if ( rc == LDAP_SUCCESS ) {
1051 ber_dupbv_x( &dnval, val, ctx );
1052 dnval.bv_len -= uidval.bv_len + 1;
1053 dnval.bv_val[dnval.bv_len] = '\0';
1056 BER_BVZERO( &uidval );
1060 rc = dnPretty( syntax, &dnval, out, ctx );
1061 if ( dnval.bv_val != val->bv_val ) {
1062 slap_sl_free( dnval.bv_val, ctx );
1064 if( rc != LDAP_SUCCESS ) {
1068 if( !BER_BVISNULL( &uidval ) ) {
1072 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1073 + STRLENOF( "#" ) + uidval.bv_len + 1,
1076 ber_memfree_x( out->bv_val, ctx );
1080 out->bv_val[out->bv_len++] = '#';
1081 out->bv_val[out->bv_len++] = '\'';
1083 got1 = uidval.bv_len < sizeof("'0'B");
1084 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1085 c = uidval.bv_val[i];
1088 if( got1 ) out->bv_val[out->bv_len++] = c;
1092 out->bv_val[out->bv_len++] = c;
1097 out->bv_val[out->bv_len++] = '\'';
1098 out->bv_val[out->bv_len++] = 'B';
1099 out->bv_val[out->bv_len] = '\0';
1103 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1105 return LDAP_SUCCESS;
1109 uniqueMemberNormalize(
1114 struct berval *normalized,
1120 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1122 ber_dupbv_x( &out, val, ctx );
1123 if ( BER_BVISEMPTY( &out ) ) {
1127 struct berval uid = BER_BVNULL;
1129 uid.bv_val = strrchr( out.bv_val, '#' );
1130 if ( !BER_BVISNULL( &uid ) ) {
1132 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1134 rc = bitStringValidate( NULL, &uid );
1135 if ( rc == LDAP_SUCCESS ) {
1136 uid.bv_val[-1] = '\0';
1137 out.bv_len -= uid.bv_len + 1;
1143 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1145 if( rc != LDAP_SUCCESS ) {
1146 slap_sl_free( out.bv_val, ctx );
1147 return LDAP_INVALID_SYNTAX;
1150 if( !BER_BVISNULL( &uid ) ) {
1153 tmp = ch_realloc( normalized->bv_val,
1154 normalized->bv_len + uid.bv_len
1155 + STRLENOF("#") + 1 );
1156 if ( tmp == NULL ) {
1157 ber_memfree_x( normalized->bv_val, ctx );
1161 normalized->bv_val = tmp;
1163 /* insert the separator */
1164 normalized->bv_val[normalized->bv_len++] = '#';
1166 /* append the UID */
1167 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1168 uid.bv_val, uid.bv_len );
1169 normalized->bv_len += uid.bv_len;
1172 normalized->bv_val[normalized->bv_len] = '\0';
1175 slap_sl_free( out.bv_val, ctx );
1178 return LDAP_SUCCESS;
1187 struct berval *value,
1188 void *assertedValue )
1191 struct berval *asserted = (struct berval *) assertedValue;
1192 struct berval assertedDN = *asserted;
1193 struct berval assertedUID = BER_BVNULL;
1194 struct berval valueDN = *value;
1195 struct berval valueUID = BER_BVNULL;
1196 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1198 if ( !BER_BVISEMPTY( asserted ) ) {
1199 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1200 if ( !BER_BVISNULL( &assertedUID ) ) {
1201 assertedUID.bv_val++;
1202 assertedUID.bv_len = assertedDN.bv_len
1203 - ( assertedUID.bv_val - assertedDN.bv_val );
1205 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1206 assertedDN.bv_len -= assertedUID.bv_len + 1;
1209 BER_BVZERO( &assertedUID );
1214 if ( !BER_BVISEMPTY( value ) ) {
1216 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1217 if ( !BER_BVISNULL( &valueUID ) ) {
1219 valueUID.bv_len = valueDN.bv_len
1220 - ( valueUID.bv_val - valueDN.bv_val );
1222 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1223 valueDN.bv_len -= valueUID.bv_len + 1;
1226 BER_BVZERO( &valueUID );
1231 if( valueUID.bv_len && assertedUID.bv_len ) {
1232 match = valueUID.bv_len - assertedUID.bv_len;
1235 return LDAP_SUCCESS;
1238 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1241 return LDAP_SUCCESS;
1244 } else if ( !approx && valueUID.bv_len ) {
1247 return LDAP_SUCCESS;
1249 } else if ( !approx && assertedUID.bv_len ) {
1252 return LDAP_SUCCESS;
1255 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1259 uniqueMemberIndexer(
1264 struct berval *prefix,
1272 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1273 /* just count them */
1277 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1279 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1280 struct berval assertedDN = values[i];
1281 struct berval assertedUID = BER_BVNULL;
1283 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1284 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1285 if ( !BER_BVISNULL( &assertedUID ) ) {
1286 assertedUID.bv_val++;
1287 assertedUID.bv_len = assertedDN.bv_len
1288 - ( assertedUID.bv_val - assertedDN.bv_val );
1290 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1291 assertedDN.bv_len -= assertedUID.bv_len + 1;
1294 BER_BVZERO( &assertedUID );
1299 dnvalues[i] = assertedDN;
1301 BER_BVZERO( &dnvalues[i] );
1303 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1304 dnvalues, keysp, ctx );
1306 slap_sl_free( dnvalues, ctx );
1316 struct berval *prefix,
1317 void * assertedValue,
1321 struct berval *asserted = (struct berval *) assertedValue;
1322 struct berval assertedDN = *asserted;
1323 struct berval assertedUID = BER_BVNULL;
1325 if ( !BER_BVISEMPTY( asserted ) ) {
1326 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1327 if ( !BER_BVISNULL( &assertedUID ) ) {
1328 assertedUID.bv_val++;
1329 assertedUID.bv_len = assertedDN.bv_len
1330 - ( assertedUID.bv_val - assertedDN.bv_val );
1332 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1333 assertedDN.bv_len -= assertedUID.bv_len + 1;
1336 BER_BVZERO( &assertedUID );
1341 return octetStringFilter( use, flags, syntax, mr, prefix,
1342 &assertedDN, keysp, ctx );
1347 * Handling boolean syntax and matching is quite rigid.
1348 * A more flexible approach would be to allow a variety
1349 * of strings to be normalized and prettied into TRUE
1357 /* very unforgiving validation, requires no normalization
1358 * before simplistic matching
1361 if( in->bv_len == 4 ) {
1362 if( bvmatch( in, &slap_true_bv ) ) {
1363 return LDAP_SUCCESS;
1365 } else if( in->bv_len == 5 ) {
1366 if( bvmatch( in, &slap_false_bv ) ) {
1367 return LDAP_SUCCESS;
1371 return LDAP_INVALID_SYNTAX;
1380 struct berval *value,
1381 void *assertedValue )
1383 /* simplistic matching allowed by rigid validation */
1384 struct berval *asserted = (struct berval *) assertedValue;
1385 *matchp = value->bv_len != asserted->bv_len;
1386 return LDAP_SUCCESS;
1389 /*-------------------------------------------------------------------
1390 LDAP/X.500 string syntax / matching rules have a few oddities. This
1391 comment attempts to detail how slapd(8) treats them.
1394 StringSyntax X.500 LDAP Matching/Comments
1395 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1396 PrintableString subset subset i/e + ignore insignificant spaces
1397 PrintableString subset subset i/e + ignore insignificant spaces
1398 NumericString subset subset ignore all spaces
1399 IA5String ASCII ASCII i/e + ignore insignificant spaces
1400 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1402 TelephoneNumber subset subset i + ignore all spaces and "-"
1404 See RFC 4518 for details.
1408 In X.500(93), a directory string can be either a PrintableString,
1409 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1410 In later versions, more CHOICEs were added. In all cases the string
1413 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1414 A directory string cannot be zero length.
1416 For matching, there are both case ignore and exact rules. Both
1417 also require that "insignificant" spaces be ignored.
1418 spaces before the first non-space are ignored;
1419 spaces after the last non-space are ignored;
1420 spaces after a space are ignored.
1421 Note: by these rules (and as clarified in X.520), a string of only
1422 spaces is to be treated as if held one space, not empty (which
1423 would be a syntax error).
1426 In ASN.1, numeric string is just a string of digits and spaces
1427 and could be empty. However, in X.500, all attribute values of
1428 numeric string carry a non-empty constraint. For example:
1430 internationalISDNNumber ATTRIBUTE ::= {
1431 WITH SYNTAX InternationalISDNNumber
1432 EQUALITY MATCHING RULE numericStringMatch
1433 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1434 ID id-at-internationalISDNNumber }
1435 InternationalISDNNumber ::=
1436 NumericString (SIZE(1..ub-international-isdn-number))
1438 Unforunately, some assertion values are don't carry the same
1439 constraint (but its unclear how such an assertion could ever
1440 be true). In LDAP, there is one syntax (numericString) not two
1441 (numericString with constraint, numericString without constraint).
1442 This should be treated as numericString with non-empty constraint.
1443 Note that while someone may have no ISDN number, there are no ISDN
1444 numbers which are zero length.
1446 In matching, spaces are ignored.
1449 In ASN.1, Printable string is just a string of printable characters
1450 and can be empty. In X.500, semantics much like NumericString (see
1451 serialNumber for a like example) excepting uses insignificant space
1452 handling instead of ignore all spaces. They must be non-empty.
1455 Basically same as PrintableString. There are no examples in X.500,
1456 but same logic applies. Empty strings are allowed.
1458 -------------------------------------------------------------------*/
1467 unsigned char *u = (unsigned char *)in->bv_val;
1469 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1470 /* directory strings cannot be empty */
1471 return LDAP_INVALID_SYNTAX;
1474 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1475 /* get the length indicated by the first byte */
1476 len = LDAP_UTF8_CHARLEN2( u, len );
1478 /* very basic checks */
1481 if( (u[5] & 0xC0) != 0x80 ) {
1482 return LDAP_INVALID_SYNTAX;
1485 if( (u[4] & 0xC0) != 0x80 ) {
1486 return LDAP_INVALID_SYNTAX;
1489 if( (u[3] & 0xC0) != 0x80 ) {
1490 return LDAP_INVALID_SYNTAX;
1493 if( (u[2] & 0xC0 )!= 0x80 ) {
1494 return LDAP_INVALID_SYNTAX;
1497 if( (u[1] & 0xC0) != 0x80 ) {
1498 return LDAP_INVALID_SYNTAX;
1501 /* CHARLEN already validated it */
1504 return LDAP_INVALID_SYNTAX;
1507 /* make sure len corresponds with the offset
1508 to the next character */
1509 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1513 return LDAP_INVALID_SYNTAX;
1516 return LDAP_SUCCESS;
1520 UTF8StringNormalize(
1525 struct berval *normalized,
1528 struct berval tmp, nvalue;
1532 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1534 if( BER_BVISNULL( val ) ) {
1535 /* assume we're dealing with a syntax (e.g., UTF8String)
1536 * which allows empty strings
1538 BER_BVZERO( normalized );
1539 return LDAP_SUCCESS;
1542 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1543 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1544 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1545 ? LDAP_UTF8_APPROX : 0;
1547 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1552 /* collapse spaces (in place) */
1554 nvalue.bv_val = tmp.bv_val;
1556 /* trim leading spaces? */
1557 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1558 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1560 for( i = 0; i < tmp.bv_len; i++) {
1561 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1562 if( wasspace++ == 0 ) {
1563 /* trim repeated spaces */
1564 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1568 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1572 if( !BER_BVISEMPTY( &nvalue ) ) {
1573 /* trim trailing space? */
1575 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1576 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1580 nvalue.bv_val[nvalue.bv_len] = '\0';
1583 /* string of all spaces is treated as one space */
1584 nvalue.bv_val[0] = ' ';
1585 nvalue.bv_val[1] = '\0';
1589 *normalized = nvalue;
1590 return LDAP_SUCCESS;
1594 directoryStringSubstringsMatch(
1599 struct berval *value,
1600 void *assertedValue )
1603 SubstringsAssertion *sub = assertedValue;
1604 struct berval left = *value;
1608 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1609 if ( sub->sa_initial.bv_len > left.bv_len ) {
1610 /* not enough left */
1615 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1616 sub->sa_initial.bv_len );
1622 left.bv_val += sub->sa_initial.bv_len;
1623 left.bv_len -= sub->sa_initial.bv_len;
1625 priorspace = ASCII_SPACE(
1626 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1629 if ( sub->sa_any ) {
1630 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1634 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1635 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1637 /* allow next space to match */
1644 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1648 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1649 /* not enough left */
1654 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1661 idx = p - left.bv_val;
1663 if ( idx >= left.bv_len ) {
1664 /* this shouldn't happen */
1671 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1672 /* not enough left */
1677 match = memcmp( left.bv_val,
1678 sub->sa_any[i].bv_val,
1679 sub->sa_any[i].bv_len );
1687 left.bv_val += sub->sa_any[i].bv_len;
1688 left.bv_len -= sub->sa_any[i].bv_len;
1690 priorspace = ASCII_SPACE(
1691 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1695 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1696 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1697 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1699 /* allow next space to match */
1704 if ( sub->sa_final.bv_len > left.bv_len ) {
1705 /* not enough left */
1710 match = memcmp( sub->sa_final.bv_val,
1711 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1712 sub->sa_final.bv_len );
1721 return LDAP_SUCCESS;
1724 #if defined(SLAPD_APPROX_INITIALS)
1725 # define SLAPD_APPROX_DELIMITER "._ "
1726 # define SLAPD_APPROX_WORDLEN 2
1728 # define SLAPD_APPROX_DELIMITER " "
1729 # define SLAPD_APPROX_WORDLEN 1
1738 struct berval *value,
1739 void *assertedValue )
1741 struct berval *nval, *assertv;
1742 char *val, **values, **words, *c;
1743 int i, count, len, nextchunk=0, nextavail=0;
1745 /* Yes, this is necessary */
1746 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1747 if( nval == NULL ) {
1749 return LDAP_SUCCESS;
1752 /* Yes, this is necessary */
1753 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1754 NULL, LDAP_UTF8_APPROX, NULL );
1755 if( assertv == NULL ) {
1758 return LDAP_SUCCESS;
1761 /* Isolate how many words there are */
1762 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1763 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1764 if ( c == NULL ) break;
1769 /* Get a phonetic copy of each word */
1770 words = (char **)ch_malloc( count * sizeof(char *) );
1771 values = (char **)ch_malloc( count * sizeof(char *) );
1772 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1774 values[i] = phonetic(c);
1777 /* Work through the asserted value's words, to see if at least some
1778 of the words are there, in the same order. */
1780 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1781 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1786 #if defined(SLAPD_APPROX_INITIALS)
1787 else if( len == 1 ) {
1788 /* Single letter words need to at least match one word's initial */
1789 for( i=nextavail; i<count; i++ )
1790 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1797 /* Isolate the next word in the asserted value and phonetic it */
1798 assertv->bv_val[nextchunk+len] = '\0';
1799 val = phonetic( assertv->bv_val + nextchunk );
1801 /* See if this phonetic chunk is in the remaining words of *value */
1802 for( i=nextavail; i<count; i++ ){
1803 if( !strcmp( val, values[i] ) ){
1811 /* This chunk in the asserted value was NOT within the *value. */
1817 /* Go on to the next word in the asserted value */
1821 /* If some of the words were seen, call it a match */
1822 if( nextavail > 0 ) {
1829 /* Cleanup allocs */
1830 ber_bvfree( assertv );
1831 for( i=0; i<count; i++ ) {
1832 ch_free( values[i] );
1838 return LDAP_SUCCESS;
1847 struct berval *prefix,
1853 int i,j, len, wordcount, keycount=0;
1854 struct berval *newkeys;
1855 BerVarray keys=NULL;
1857 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1858 struct berval val = BER_BVNULL;
1859 /* Yes, this is necessary */
1860 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1861 assert( !BER_BVISNULL( &val ) );
1863 /* Isolate how many words there are. There will be a key for each */
1864 for( wordcount = 0, c = val.bv_val; *c; c++) {
1865 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1866 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1868 if (*c == '\0') break;
1872 /* Allocate/increase storage to account for new keys */
1873 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1874 * sizeof(struct berval) );
1875 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1876 if( keys ) ch_free( keys );
1879 /* Get a phonetic copy of each word */
1880 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1882 if( len < SLAPD_APPROX_WORDLEN ) continue;
1883 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1888 ber_memfree( val.bv_val );
1890 BER_BVZERO( &keys[keycount] );
1893 return LDAP_SUCCESS;
1902 struct berval *prefix,
1903 void * assertedValue,
1912 /* Yes, this is necessary */
1913 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1914 NULL, LDAP_UTF8_APPROX, NULL );
1915 if( val == NULL || BER_BVISNULL( val ) ) {
1916 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1917 BER_BVZERO( &keys[0] );
1920 return LDAP_SUCCESS;
1923 /* Isolate how many words there are. There will be a key for each */
1924 for( count = 0,c = val->bv_val; *c; c++) {
1925 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1926 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1928 if (*c == '\0') break;
1932 /* Allocate storage for new keys */
1933 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1935 /* Get a phonetic copy of each word */
1936 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1938 if( len < SLAPD_APPROX_WORDLEN ) continue;
1939 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1945 BER_BVZERO( &keys[count] );
1948 return LDAP_SUCCESS;
1951 /* Remove all spaces and '-' characters */
1953 telephoneNumberNormalize(
1958 struct berval *normalized,
1963 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1965 /* validator should have refused an empty string */
1966 assert( !BER_BVISEMPTY( val ) );
1968 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1970 for( p = val->bv_val; *p; p++ ) {
1971 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1977 normalized->bv_len = q - normalized->bv_val;
1979 if( BER_BVISEMPTY( normalized ) ) {
1980 slap_sl_free( normalized->bv_val, ctx );
1981 BER_BVZERO( normalized );
1982 return LDAP_INVALID_SYNTAX;
1985 return LDAP_SUCCESS;
1993 struct berval val = *in;
1995 if( BER_BVISEMPTY( &val ) ) {
1996 /* disallow empty strings */
1997 return LDAP_INVALID_SYNTAX;
2000 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2001 if ( val.bv_len == 1 ) {
2002 return LDAP_SUCCESS;
2005 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2012 while ( OID_LEADCHAR( val.bv_val[0] )) {
2016 if ( val.bv_len == 0 ) {
2017 return LDAP_SUCCESS;
2021 if( !OID_SEPARATOR( val.bv_val[0] )) {
2029 return LDAP_INVALID_SYNTAX;
2038 struct berval val = *in;
2040 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2042 if ( val.bv_val[0] == '-' ) {
2046 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2047 return LDAP_INVALID_SYNTAX;
2050 if( val.bv_val[0] == '0' ) { /* "-0" */
2051 return LDAP_INVALID_SYNTAX;
2054 } else if ( val.bv_val[0] == '0' ) {
2055 if( val.bv_len > 1 ) { /* "0<more>" */
2056 return LDAP_INVALID_SYNTAX;
2059 return LDAP_SUCCESS;
2062 for( i=0; i < val.bv_len; i++ ) {
2063 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2064 return LDAP_INVALID_SYNTAX;
2068 return LDAP_SUCCESS;
2077 struct berval *value,
2078 void *assertedValue )
2080 struct berval *asserted = (struct berval *) assertedValue;
2081 int vsign = 1, asign = 1; /* default sign = '+' */
2086 if( v.bv_val[0] == '-' ) {
2092 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2095 if( a.bv_val[0] == '-' ) {
2101 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2103 match = vsign - asign;
2105 match = ( v.bv_len != a.bv_len
2106 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2107 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2108 if( vsign < 0 ) match = -match;
2112 return LDAP_SUCCESS;
2126 if ( lutil_str2bin( val, &iv )) {
2127 return LDAP_INVALID_SYNTAX;
2130 neg = iv.bv_val[0] & 0x80;
2132 /* Omit leading 0 pad byte */
2133 if ( !iv.bv_val[0] ) {
2138 /* If too small, sign-extend */
2139 if ( iv.bv_len < index_intlen ) {
2141 key->bv_val[0] = index_intlen;
2142 k = index_intlen - iv.bv_len + 1;
2147 for ( j=1; j<k; j++)
2148 key->bv_val[j] = pad;
2149 for ( j = 0; j<iv.bv_len; j++ )
2150 key->bv_val[j+k] = iv.bv_val[j];
2152 key->bv_val[0] = iv.bv_len;
2153 memcpy( key->bv_val+1, iv.bv_val, index_intlen );
2156 key->bv_val[0] = -key->bv_val[0];
2158 /* convert signed to unsigned */
2159 key->bv_val[0] ^= 0x80;
2163 /* Index generation function */
2170 struct berval *prefix,
2180 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2181 /* just count them */
2184 /* we should have at least one value at this point */
2187 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2188 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2189 keys[i].bv_len = index_intlen+1;
2190 keys[i].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2193 keys[i].bv_val = NULL;
2196 itmp.bv_len = sizeof(ibuf);
2198 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2199 if ( values[i].bv_len > itmp.bv_len ) {
2200 itmp.bv_len = values[i].bv_len;
2201 if ( itmp.bv_val == ibuf ) {
2202 itmp.bv_val = slap_sl_malloc( itmp.bv_len, ctx );
2204 itmp.bv_val = slap_sl_realloc( itmp.bv_val, itmp.bv_len, ctx );
2207 rc = integerVal2Key( &values[i], &keys[i], &itmp );
2213 if ( itmp.bv_val != ibuf ) {
2214 slap_sl_free( itmp.bv_val, ctx );
2219 /* Index generation function */
2226 struct berval *prefix,
2227 void * assertedValue,
2234 struct berval *value;
2237 value = (struct berval *) assertedValue;
2239 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2241 keys[0].bv_len = index_intlen + 1;
2242 keys[0].bv_val = slap_sl_malloc( index_intlen+1, ctx );
2244 if ( value->bv_len > sizeof( ibuf )) {
2245 iv.bv_val = slap_sl_malloc( value->bv_len, ctx );
2246 iv.bv_len = value->bv_len;
2249 iv.bv_len = sizeof(ibuf);
2252 rc = integerVal2Key( value, keys, &iv );
2256 if ( iv.bv_val != ibuf ) {
2257 slap_sl_free( iv.bv_val, ctx );
2263 countryStringValidate(
2265 struct berval *val )
2267 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2269 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2270 return LDAP_INVALID_SYNTAX;
2272 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2273 return LDAP_INVALID_SYNTAX;
2276 return LDAP_SUCCESS;
2280 printableStringValidate(
2282 struct berval *val )
2286 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2288 for(i=0; i < val->bv_len; i++) {
2289 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2290 return LDAP_INVALID_SYNTAX;
2294 return LDAP_SUCCESS;
2298 printablesStringValidate(
2300 struct berval *val )
2304 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2306 for(i=0,len=0; i < val->bv_len; i++) {
2307 int c = val->bv_val[i];
2311 return LDAP_INVALID_SYNTAX;
2315 } else if ( SLAP_PRINTABLE(c) ) {
2318 return LDAP_INVALID_SYNTAX;
2323 return LDAP_INVALID_SYNTAX;
2326 return LDAP_SUCCESS;
2332 struct berval *val )
2336 for(i=0; i < val->bv_len; i++) {
2337 if( !LDAP_ASCII(val->bv_val[i]) ) {
2338 return LDAP_INVALID_SYNTAX;
2342 return LDAP_SUCCESS;
2351 struct berval *normalized,
2355 int casefold = !SLAP_MR_ASSOCIATED( mr,
2356 slap_schema.si_mr_caseExactIA5Match );
2358 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2362 /* Ignore initial whitespace */
2363 while ( ASCII_SPACE( *p ) ) p++;
2365 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2366 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2367 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2368 normalized->bv_val[normalized->bv_len] = '\0';
2370 p = q = normalized->bv_val;
2373 if ( ASCII_SPACE( *p ) ) {
2376 /* Ignore the extra whitespace */
2377 while ( ASCII_SPACE( *p ) ) {
2381 } else if ( casefold ) {
2382 /* Most IA5 rules require casefolding */
2383 *q++ = TOLOWER(*p); p++;
2390 assert( normalized->bv_val <= p );
2394 * If the string ended in space, backup the pointer one
2395 * position. One is enough because the above loop collapsed
2396 * all whitespace to a single space.
2398 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2400 /* null terminate */
2403 normalized->bv_len = q - normalized->bv_val;
2405 return LDAP_SUCCESS;
2414 if( in->bv_len != 36 ) {
2415 return LDAP_INVALID_SYNTAX;
2418 for( i=0; i<36; i++ ) {
2424 if( in->bv_val[i] != '-' ) {
2425 return LDAP_INVALID_SYNTAX;
2429 if( !ASCII_HEX( in->bv_val[i]) ) {
2430 return LDAP_INVALID_SYNTAX;
2435 return LDAP_SUCCESS;
2446 int rc=LDAP_INVALID_SYNTAX;
2448 assert( in != NULL );
2449 assert( out != NULL );
2451 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2454 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2456 for( i=0; i<36; i++ ) {
2462 if( in->bv_val[i] != '-' ) {
2465 out->bv_val[i] = '-';
2469 if( !ASCII_HEX( in->bv_val[i]) ) {
2472 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2477 out->bv_val[ out->bv_len ] = '\0';
2481 slap_sl_free( out->bv_val, ctx );
2494 struct berval *normalized,
2497 unsigned char octet = '\0';
2501 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2502 /* NOTE: must be a normalized UUID */
2503 assert( val->bv_len == 16 );
2505 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2506 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2507 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2508 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2510 return LDAP_SUCCESS;
2513 normalized->bv_len = 16;
2514 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2516 for( i=0, j=0; i<36; i++ ) {
2517 unsigned char nibble;
2518 if( val->bv_val[i] == '-' ) {
2521 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2522 nibble = val->bv_val[i] - '0';
2524 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2525 nibble = val->bv_val[i] - ('a'-10);
2527 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2528 nibble = val->bv_val[i] - ('A'-10);
2531 slap_sl_free( normalized->bv_val, ctx );
2532 return LDAP_INVALID_SYNTAX;
2537 normalized->bv_val[j>>1] = octet;
2539 octet = nibble << 4;
2544 normalized->bv_val[normalized->bv_len] = 0;
2545 return LDAP_SUCCESS;
2551 numericStringValidate(
2557 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2559 for(i=0; i < in->bv_len; i++) {
2560 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2561 return LDAP_INVALID_SYNTAX;
2565 return LDAP_SUCCESS;
2569 numericStringNormalize(
2574 struct berval *normalized,
2577 /* removal all spaces */
2580 assert( !BER_BVISEMPTY( val ) );
2582 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2585 q = normalized->bv_val;
2588 if ( ASCII_SPACE( *p ) ) {
2589 /* Ignore whitespace */
2596 /* we should have copied no more than is in val */
2597 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2599 /* null terminate */
2602 normalized->bv_len = q - normalized->bv_val;
2604 if( BER_BVISEMPTY( normalized ) ) {
2605 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2606 normalized->bv_val[0] = ' ';
2607 normalized->bv_val[1] = '\0';
2608 normalized->bv_len = 1;
2611 return LDAP_SUCCESS;
2615 * Integer conversion macros that will use the largest available
2618 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2619 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2620 # define SLAP_LONG long long
2622 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2623 # define SLAP_LONG long
2624 #endif /* HAVE_STRTOLL ... */
2632 struct berval *value,
2633 void *assertedValue )
2635 SLAP_LONG lValue, lAssertedValue;
2638 /* safe to assume integers are NUL terminated? */
2639 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2640 if( errno == ERANGE )
2642 return LDAP_CONSTRAINT_VIOLATION;
2645 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2647 if( errno == ERANGE )
2649 return LDAP_CONSTRAINT_VIOLATION;
2652 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2653 return LDAP_SUCCESS;
2662 struct berval *value,
2663 void *assertedValue )
2665 SLAP_LONG lValue, lAssertedValue;
2668 /* safe to assume integers are NUL terminated? */
2669 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2670 if( errno == ERANGE )
2672 return LDAP_CONSTRAINT_VIOLATION;
2675 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2677 if( errno == ERANGE )
2679 return LDAP_CONSTRAINT_VIOLATION;
2682 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2683 return LDAP_SUCCESS;
2687 serialNumberAndIssuerCheck(
2696 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2698 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2699 /* Parse old format */
2700 is->bv_val = ber_bvchr( in, '$' );
2701 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2703 sn->bv_val = in->bv_val;
2704 sn->bv_len = is->bv_val - in->bv_val;
2707 is->bv_len = in->bv_len - (sn->bv_len + 1);
2709 /* eat leading zeros */
2710 for( n=0; n < (sn->bv_len-1); n++ ) {
2711 if( sn->bv_val[n] != '0' ) break;
2716 for( n=0; n < sn->bv_len; n++ ) {
2717 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2721 /* Parse GSER format */
2722 int havesn=0,haveissuer=0;
2723 struct berval x = *in;
2728 /* eat leading spaces */
2729 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2733 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2734 return LDAP_INVALID_SYNTAX;
2737 /* should be at issuer or serialNumber NamedValue */
2738 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2740 x.bv_val += STRLENOF("issuer");
2741 x.bv_len -= STRLENOF("issuer");
2743 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2744 x.bv_val++; x.bv_len--;
2746 /* eat leading spaces */
2747 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2751 /* For backward compatibility, this part is optional */
2752 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2753 x.bv_val += STRLENOF("rdnSequence:");
2754 x.bv_len -= STRLENOF("rdnSequence:");
2757 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2758 x.bv_val++; x.bv_len--;
2760 is->bv_val = x.bv_val;
2763 for( ; is->bv_len < x.bv_len; ) {
2764 if ( is->bv_val[is->bv_len] != '"' ) {
2768 if ( is->bv_val[is->bv_len+1] == '"' ) {
2775 x.bv_val += is->bv_len+1;
2776 x.bv_len -= is->bv_len+1;
2778 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2779 return LDAP_INVALID_SYNTAX;
2784 } else if( strncasecmp( x.bv_val, "serialNumber",
2785 STRLENOF("serialNumber")) == 0 )
2787 /* parse serialNumber */
2789 x.bv_val += STRLENOF("serialNumber");
2790 x.bv_len -= STRLENOF("serialNumber");
2792 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2793 x.bv_val++; x.bv_len--;
2795 /* eat leading spaces */
2796 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2800 sn->bv_val = x.bv_val;
2803 if( sn->bv_val[0] == '-' ) {
2808 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2809 sn->bv_val[1] == 'X' )) {
2811 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2812 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2814 } else if ( sn->bv_val[0] == '\'' ) {
2815 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2816 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2818 if ( sn->bv_val[sn->bv_len] == '\'' &&
2819 sn->bv_val[sn->bv_len+1] == 'H' )
2822 return LDAP_INVALID_SYNTAX;
2825 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2826 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2830 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2831 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2832 return LDAP_INVALID_SYNTAX;
2835 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2837 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2838 return LDAP_INVALID_SYNTAX;
2843 } else return LDAP_INVALID_SYNTAX;
2845 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2846 x.bv_val++; x.bv_len--;
2849 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2853 /* should be at remaining NamedValue */
2854 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2855 STRLENOF("issuer" )) == 0 ))
2858 x.bv_val += STRLENOF("issuer");
2859 x.bv_len -= STRLENOF("issuer");
2861 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2862 x.bv_val++; x.bv_len--;
2864 /* eat leading spaces */
2865 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2869 /* For backward compatibility, this part is optional */
2870 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2871 x.bv_val += STRLENOF("rdnSequence:");
2872 x.bv_len -= STRLENOF("rdnSequence:");
2875 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2876 x.bv_val++; x.bv_len--;
2878 is->bv_val = x.bv_val;
2881 for( ; is->bv_len < x.bv_len; ) {
2882 if ( is->bv_val[is->bv_len] != '"' ) {
2886 if ( is->bv_val[is->bv_len+1] == '"' ) {
2893 x.bv_val += is->bv_len+1;
2894 x.bv_len -= is->bv_len+1;
2896 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2897 STRLENOF("serialNumber")) == 0 ))
2899 /* parse serialNumber */
2901 x.bv_val += STRLENOF("serialNumber");
2902 x.bv_len -= STRLENOF("serialNumber");
2904 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2905 x.bv_val++; x.bv_len--;
2907 /* eat leading spaces */
2908 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2912 sn->bv_val = x.bv_val;
2915 if( sn->bv_val[0] == '-' ) {
2920 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2921 sn->bv_val[1] == 'X' )) {
2923 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2924 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2926 } else if ( sn->bv_val[0] == '\'' ) {
2927 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2928 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2930 if ( sn->bv_val[sn->bv_len] == '\'' &&
2931 sn->bv_val[sn->bv_len+1] == 'H' )
2934 return LDAP_INVALID_SYNTAX;
2937 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2938 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2942 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2943 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2944 return LDAP_INVALID_SYNTAX;
2947 x.bv_val += sn->bv_len;
2948 x.bv_len -= sn->bv_len;
2950 } else return LDAP_INVALID_SYNTAX;
2952 /* eat trailing spaces */
2953 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2957 /* should have no characters left... */
2958 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2960 ber_dupbv_x( &ni, is, ctx );
2963 /* need to handle double dquotes here */
2969 serialNumberAndIssuerValidate(
2974 struct berval sn, i;
2976 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2979 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
2983 /* validate DN -- doesn't handle double dquote */
2984 rc = dnValidate( NULL, &i );
2986 rc = LDAP_INVALID_SYNTAX;
2988 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
2989 slap_sl_free( i.bv_val, NULL );
2992 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2998 serialNumberAndIssuerPretty(
3005 struct berval sn, i, ni;
3007 assert( in != NULL );
3008 assert( out != NULL );
3010 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3013 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3017 rc = dnPretty( syntax, &i, &ni, ctx );
3019 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3020 slap_sl_free( i.bv_val, ctx );
3023 if( rc ) return LDAP_INVALID_SYNTAX;
3025 /* make room from sn + "$" */
3026 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3027 + sn.bv_len + ni.bv_len;
3028 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3030 if( out->bv_val == NULL ) {
3032 slap_sl_free( ni.bv_val, ctx );
3037 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3038 STRLENOF("{ serialNumber "));
3039 n = STRLENOF("{ serialNumber ");
3041 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3044 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3045 n += STRLENOF(", issuer rdnSequence:\"");
3047 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3050 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3051 n += STRLENOF("\" }");
3053 out->bv_val[n] = '\0';
3055 assert( n == out->bv_len );
3057 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3058 out->bv_val, 0, 0 );
3060 slap_sl_free( ni.bv_val, ctx );
3062 return LDAP_SUCCESS;
3066 * This routine is called by certificateExactNormalize when
3067 * certificateExactNormalize receives a search string instead of
3068 * a certificate. This routine checks if the search value is valid
3069 * and then returns the normalized value
3072 serialNumberAndIssuerNormalize(
3080 struct berval sn, sn2, i, ni;
3081 char sbuf[64], *stmp = sbuf;
3085 assert( in != NULL );
3086 assert( out != NULL );
3088 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3091 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3095 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3097 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3098 slap_sl_free( i.bv_val, ctx );
3101 if( rc ) return LDAP_INVALID_SYNTAX;
3103 /* Convert sn to canonical hex */
3104 if ( sn.bv_len > sizeof( sbuf )) {
3105 stmp = slap_sl_malloc( sn.bv_len, ctx );
3108 sn2.bv_len = sn.bv_len;
3109 if ( lutil_str2bin( &sn, &sn2 )) {
3110 rc = LDAP_INVALID_SYNTAX;
3114 /* make room for sn + "$" */
3115 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3116 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3117 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3119 if( out->bv_val == NULL ) {
3121 slap_sl_free( ni.bv_val, ctx );
3127 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3128 STRLENOF( "{ serialNumber " ));
3129 n = STRLENOF( "{ serialNumber " );
3131 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3134 unsigned char *v = (unsigned char *)sn2.bv_val;
3135 out->bv_val[n++] = '\'';
3136 for ( j = 0; j < sn2.bv_len; j++ ) {
3137 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3141 out->bv_val[n++] = '\'';
3142 out->bv_val[n++] = 'H';
3145 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3146 n += STRLENOF( ", issuer rdnSequence:\"" );
3148 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3151 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3152 n += STRLENOF( "\" }" );
3154 out->bv_val[n] = '\0';
3156 assert( n == out->bv_len );
3158 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3159 out->bv_val, 0, 0 );
3163 slap_sl_free( stmp, ctx );
3164 slap_sl_free( ni.bv_val, ctx );
3170 certificateExactNormalize(
3175 struct berval *normalized,
3178 BerElementBuffer berbuf;
3179 BerElement *ber = (BerElement *)&berbuf;
3183 char serialbuf[64], *serial = serialbuf;
3184 ber_len_t seriallen;
3185 struct berval issuer_dn = BER_BVNULL, bvdn;
3187 int rc = LDAP_INVALID_SYNTAX;
3189 if( BER_BVISEMPTY( val ) ) goto done;
3191 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3192 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3195 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3197 ber_init2( ber, val, LBER_USE_DER );
3198 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3199 tag = ber_skip_tag( ber, &len ); /* Sequence */
3200 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3201 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3202 tag = ber_skip_tag( ber, &len );
3203 tag = ber_get_int( ber, &i ); /* version */
3206 /* NOTE: move the test here from certificateValidate,
3207 * so that we can validate certs with serial longer
3208 * than sizeof(ber_int_t) */
3209 tag = ber_peek_tag( ber, &len ); /* serial */
3211 /* Use hex format. '123456789abcdef'H
3217 tag = ber_skip_tag( ber, &len );
3218 ptr = (unsigned char *)ber->ber_ptr;
3219 ber_skip_data( ber, len );
3221 /* Check for minimal encodings */
3223 if ( ptr[0] & 0x80 ) {
3224 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3225 return LDAP_INVALID_SYNTAX;
3226 } else if ( ptr[0] == 0 ) {
3227 if (!( ptr[1] & 0x80 ))
3228 return LDAP_INVALID_SYNTAX;
3232 seriallen = len * 2 + 4; /* quotes, H, NUL */
3233 if ( seriallen > sizeof( serialbuf ))
3234 serial = slap_sl_malloc( seriallen, ctx );
3237 for ( i = 0; i<len; i++ ) {
3238 sprintf( sptr, "%02X", ptr[i] );
3245 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3246 ber_skip_data( ber, len );
3247 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3248 len = ber_ptrlen( ber );
3249 bvdn.bv_val = val->bv_val + len;
3250 bvdn.bv_len = val->bv_len - len;
3252 rc = dnX509normalize( &bvdn, &issuer_dn );
3253 if( rc != LDAP_SUCCESS ) goto done;
3255 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3256 + seriallen + issuer_dn.bv_len;
3257 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3259 p = (unsigned char *)normalized->bv_val;
3261 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3262 p += STRLENOF( "{ serialNumber " );
3264 AC_MEMCPY(p, serial, seriallen);
3267 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3268 p += STRLENOF( ", issuer rdnSequence:\"" );
3270 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3271 p += issuer_dn.bv_len;
3273 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3274 p += STRLENOF( "\" }" );
3278 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3279 normalized->bv_val, NULL, NULL );
3284 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3285 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3297 assert( in != NULL );
3298 assert( !BER_BVISNULL( in ) );
3300 for ( i = 0; i < in->bv_len; i++ ) {
3301 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3302 return LDAP_INVALID_SYNTAX;
3306 return LDAP_SUCCESS;
3309 /* Normalize a SID as used inside a CSN:
3310 * three-digit numeric string */
3317 struct berval *normalized,
3322 assert( val != NULL );
3323 assert( normalized != NULL );
3325 ber_dupbv_x( normalized, val, ctx );
3327 for ( i = 0; i < normalized->bv_len; i++ ) {
3328 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3329 ber_memfree_x( normalized->bv_val, ctx );
3330 BER_BVZERO( normalized );
3331 return LDAP_INVALID_SYNTAX;
3334 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3337 return LDAP_SUCCESS;
3345 assert( in != NULL );
3346 assert( !BER_BVISNULL( in ) );
3348 if ( in->bv_len != 3 ) {
3349 return LDAP_INVALID_SYNTAX;
3352 return hexValidate( NULL, in );
3355 /* Normalize a SID as used inside a CSN:
3356 * three-digit numeric string */
3363 struct berval *normalized,
3366 if ( val->bv_len != 3 ) {
3367 return LDAP_INVALID_SYNTAX;
3370 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3380 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3383 /* Normalize a SID as used inside a CSN, either as-is
3384 * (assertion value) or extracted from the CSN
3385 * (attribute value) */
3392 struct berval *normalized,
3400 if ( BER_BVISEMPTY( val ) ) {
3401 return LDAP_INVALID_SYNTAX;
3404 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3405 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3408 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3410 ptr = ber_bvchr( val, '#' );
3411 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3412 return LDAP_INVALID_SYNTAX;
3415 bv.bv_val = ptr + 1;
3416 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3418 ptr = ber_bvchr( &bv, '#' );
3419 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3420 return LDAP_INVALID_SYNTAX;
3423 bv.bv_val = ptr + 1;
3424 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3426 ptr = ber_bvchr( &bv, '#' );
3427 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3428 return LDAP_INVALID_SYNTAX;
3431 bv.bv_len = ptr - bv.bv_val;
3433 if ( bv.bv_len == 2 ) {
3434 /* OpenLDAP 2.3 SID */
3436 buf[ 1 ] = bv.bv_val[ 0 ];
3437 buf[ 2 ] = bv.bv_val[ 1 ];
3444 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3456 assert( in != NULL );
3457 assert( !BER_BVISNULL( in ) );
3459 if ( BER_BVISEMPTY( in ) ) {
3460 return LDAP_INVALID_SYNTAX;
3465 ptr = ber_bvchr( &bv, '#' );
3466 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3467 return LDAP_INVALID_SYNTAX;
3470 bv.bv_len = ptr - bv.bv_val;
3471 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3472 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3474 return LDAP_INVALID_SYNTAX;
3477 rc = generalizedTimeValidate( NULL, &bv );
3478 if ( rc != LDAP_SUCCESS ) {
3482 bv.bv_val = ptr + 1;
3483 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3485 ptr = ber_bvchr( &bv, '#' );
3486 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3487 return LDAP_INVALID_SYNTAX;
3490 bv.bv_len = ptr - bv.bv_val;
3491 if ( bv.bv_len != 6 ) {
3492 return LDAP_INVALID_SYNTAX;
3495 rc = hexValidate( NULL, &bv );
3496 if ( rc != LDAP_SUCCESS ) {
3500 bv.bv_val = ptr + 1;
3501 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3503 ptr = ber_bvchr( &bv, '#' );
3504 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3505 return LDAP_INVALID_SYNTAX;
3508 bv.bv_len = ptr - bv.bv_val;
3509 if ( bv.bv_len == 2 ) {
3510 /* tolerate old 2-digit replica-id */
3511 rc = hexValidate( NULL, &bv );
3514 rc = sidValidate( NULL, &bv );
3516 if ( rc != LDAP_SUCCESS ) {
3520 bv.bv_val = ptr + 1;
3521 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3523 if ( bv.bv_len != 6 ) {
3524 return LDAP_INVALID_SYNTAX;
3527 return hexValidate( NULL, &bv );
3530 /* Normalize a CSN in OpenLDAP 2.3 format */
3537 struct berval *normalized,
3540 struct berval gt, cnt, sid, mod;
3544 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3545 assert( !BER_BVISEMPTY( val ) );
3549 ptr = ber_bvchr( >, '#' );
3550 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3551 return LDAP_INVALID_SYNTAX;
3554 gt.bv_len = ptr - gt.bv_val;
3555 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3557 cnt.bv_val = ptr + 1;
3558 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3560 ptr = ber_bvchr( &cnt, '#' );
3561 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3562 return LDAP_INVALID_SYNTAX;
3565 cnt.bv_len = ptr - cnt.bv_val;
3566 assert( cnt.bv_len == STRLENOF( "000000" ) );
3568 sid.bv_val = ptr + 1;
3569 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3571 ptr = ber_bvchr( &sid, '#' );
3572 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3573 return LDAP_INVALID_SYNTAX;
3576 sid.bv_len = ptr - sid.bv_val;
3577 assert( sid.bv_len == STRLENOF( "00" ) );
3579 mod.bv_val = ptr + 1;
3580 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3581 assert( mod.bv_len == STRLENOF( "000000" ) );
3583 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3584 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3586 ptr = normalized->bv_val;
3587 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3588 ptr = lutil_strcopy( ptr, ".000000Z#" );
3589 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3592 for ( i = 0; i < sid.bv_len; i++ ) {
3593 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3596 for ( i = 0; i < mod.bv_len; i++ ) {
3597 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3601 assert( ptr - normalized->bv_val == normalized->bv_len );
3603 return LDAP_SUCCESS;
3606 /* Normalize a CSN */
3613 struct berval *normalized,
3616 struct berval cnt, sid, mod;
3620 assert( val != NULL );
3621 assert( normalized != NULL );
3623 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3625 if ( BER_BVISEMPTY( val ) ) {
3626 return LDAP_INVALID_SYNTAX;
3629 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3630 /* Openldap <= 2.3 */
3632 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3635 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3637 ptr = ber_bvchr( val, '#' );
3638 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3639 return LDAP_INVALID_SYNTAX;
3642 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3644 cnt.bv_val = ptr + 1;
3645 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3647 ptr = ber_bvchr( &cnt, '#' );
3648 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3649 return LDAP_INVALID_SYNTAX;
3652 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3654 sid.bv_val = ptr + 1;
3655 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3657 ptr = ber_bvchr( &sid, '#' );
3658 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3659 return LDAP_INVALID_SYNTAX;
3662 sid.bv_len = ptr - sid.bv_val;
3663 assert( sid.bv_len == STRLENOF( "000" ) );
3665 mod.bv_val = ptr + 1;
3666 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3668 assert( mod.bv_len == STRLENOF( "000000" ) );
3670 ber_dupbv_x( normalized, val, ctx );
3672 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3673 i < normalized->bv_len; i++ )
3675 /* assume it's already validated that's all hex digits */
3676 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3679 return LDAP_SUCCESS;
3689 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3692 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3693 /* slight optimization - does not need the start parameter */
3694 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3699 check_time_syntax (struct berval *val,
3702 struct berval *fraction)
3705 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3706 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3707 * GeneralizedTime supports leap seconds, UTCTime does not.
3709 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3710 static const int mdays[2][12] = {
3711 /* non-leap years */
3712 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3714 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3717 int part, c, c1, c2, tzoffset, leapyear = 0;
3720 e = p + val->bv_len;
3722 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3723 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3725 for (part = start; part < 7 && p < e; part++) {
3727 if (!ASCII_DIGIT(c1)) {
3732 return LDAP_INVALID_SYNTAX;
3735 if (!ASCII_DIGIT(c)) {
3736 return LDAP_INVALID_SYNTAX;
3738 c += c1 * 10 - '0' * 11;
3739 if ((part | 1) == 3) {
3742 return LDAP_INVALID_SYNTAX;
3745 if (c >= ceiling[part]) {
3746 if (! (c == 60 && part == 6 && start == 0))
3747 return LDAP_INVALID_SYNTAX;
3751 if (part < 5 + start) {
3752 return LDAP_INVALID_SYNTAX;
3754 for (; part < 9; part++) {
3758 /* leapyear check for the Gregorian calendar (year>1581) */
3759 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3763 if (parts[3] >= mdays[leapyear][parts[2]]) {
3764 return LDAP_INVALID_SYNTAX;
3768 fraction->bv_val = p;
3769 fraction->bv_len = 0;
3770 if (p < e && (*p == '.' || *p == ',')) {
3772 while (++p < e && ASCII_DIGIT(*p)) {
3775 if (p - fraction->bv_val == 1) {
3776 return LDAP_INVALID_SYNTAX;
3778 for (end_num = p; end_num[-1] == '0'; --end_num) {
3781 c = end_num - fraction->bv_val;
3782 if (c != 1) fraction->bv_len = c;
3788 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3794 return LDAP_INVALID_SYNTAX;
3800 for (part = 7; part < 9 && p < e; part++) {
3802 if (!ASCII_DIGIT(c1)) {
3807 return LDAP_INVALID_SYNTAX;
3810 if (!ASCII_DIGIT(c2)) {
3811 return LDAP_INVALID_SYNTAX;
3813 parts[part] = c1 * 10 + c2 - '0' * 11;
3814 if (parts[part] >= ceiling[part]) {
3815 return LDAP_INVALID_SYNTAX;
3818 if (part < 8 + start) {
3819 return LDAP_INVALID_SYNTAX;
3822 if (tzoffset == '-') {
3823 /* negative offset to UTC, ie west of Greenwich */
3824 parts[4] += parts[7];
3825 parts[5] += parts[8];
3826 /* offset is just hhmm, no seconds */
3827 for (part = 6; --part >= 0; ) {
3831 c = mdays[leapyear][parts[2]];
3833 if (parts[part] >= c) {
3835 return LDAP_INVALID_SYNTAX;
3840 } else if (part != 5) {
3845 /* positive offset to UTC, ie east of Greenwich */
3846 parts[4] -= parts[7];
3847 parts[5] -= parts[8];
3848 for (part = 6; --part >= 0; ) {
3849 if (parts[part] < 0) {
3851 return LDAP_INVALID_SYNTAX;
3856 /* make first arg to % non-negative */
3857 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3862 } else if (part != 5) {
3869 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3872 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3879 struct berval *normalized )
3883 rc = check_time_syntax(val, 1, parts, NULL);
3884 if (rc != LDAP_SUCCESS) {
3888 normalized->bv_val = ch_malloc( 14 );
3889 if ( normalized->bv_val == NULL ) {
3890 return LBER_ERROR_MEMORY;
3893 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3894 parts[1], parts[2] + 1, parts[3] + 1,
3895 parts[4], parts[5], parts[6] );
3896 normalized->bv_len = 13;
3898 return LDAP_SUCCESS;
3908 return check_time_syntax(in, 1, parts, NULL);
3911 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3914 generalizedTimeValidate(
3919 struct berval fraction;
3920 return check_time_syntax(in, 0, parts, &fraction);
3924 generalizedTimeNormalize(
3929 struct berval *normalized,
3934 struct berval fraction;
3936 rc = check_time_syntax(val, 0, parts, &fraction);
3937 if (rc != LDAP_SUCCESS) {
3941 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3942 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3943 if ( BER_BVISNULL( normalized ) ) {
3944 return LBER_ERROR_MEMORY;
3947 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3948 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3949 parts[4], parts[5], parts[6] );
3950 if ( !BER_BVISEMPTY( &fraction ) ) {
3951 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3952 fraction.bv_val, fraction.bv_len );
3953 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3955 strcpy( normalized->bv_val + len-1, "Z" );
3956 normalized->bv_len = len;
3958 return LDAP_SUCCESS;
3962 generalizedTimeOrderingMatch(
3967 struct berval *value,
3968 void *assertedValue )
3970 struct berval *asserted = (struct berval *) assertedValue;
3971 ber_len_t v_len = value->bv_len;
3972 ber_len_t av_len = asserted->bv_len;
3974 /* ignore trailing 'Z' when comparing */
3975 int match = memcmp( value->bv_val, asserted->bv_val,
3976 (v_len < av_len ? v_len : av_len) - 1 );
3977 if ( match == 0 ) match = v_len - av_len;
3980 return LDAP_SUCCESS;
3983 /* Index generation function */
3984 int generalizedTimeIndexer(
3989 struct berval *prefix,
3997 BerValue bvtmp; /* 40 bit index */
3999 struct lutil_timet tt;
4001 bvtmp.bv_len = sizeof(tmp);
4003 for( i=0; values[i].bv_val != NULL; i++ ) {
4004 /* just count them */
4007 /* we should have at least one value at this point */
4010 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4012 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4013 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4014 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4015 /* Use 40 bits of time for key */
4016 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4017 lutil_tm2time( &tm, &tt );
4018 tmp[0] = tt.tt_gsec & 0xff;
4019 tmp[4] = tt.tt_sec & 0xff;
4021 tmp[3] = tt.tt_sec & 0xff;
4023 tmp[2] = tt.tt_sec & 0xff;
4025 tmp[1] = tt.tt_sec & 0xff;
4027 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4031 keys[j].bv_val = NULL;
4036 return LDAP_SUCCESS;
4039 /* Index generation function */
4040 int generalizedTimeFilter(
4045 struct berval *prefix,
4046 void * assertedValue,
4052 BerValue bvtmp; /* 40 bit index */
4053 BerValue *value = (BerValue *) assertedValue;
4055 struct lutil_timet tt;
4057 bvtmp.bv_len = sizeof(tmp);
4059 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4060 /* Use 40 bits of time for key */
4061 if ( value->bv_val && value->bv_len >= 10 &&
4062 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4064 lutil_tm2time( &tm, &tt );
4065 tmp[0] = tt.tt_gsec & 0xff;
4066 tmp[4] = tt.tt_sec & 0xff;
4068 tmp[3] = tt.tt_sec & 0xff;
4070 tmp[2] = tt.tt_sec & 0xff;
4072 tmp[1] = tt.tt_sec & 0xff;
4074 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4075 ber_dupbv_x(keys, &bvtmp, ctx );
4076 keys[1].bv_val = NULL;
4084 return LDAP_SUCCESS;
4088 deliveryMethodValidate(
4090 struct berval *val )
4093 #define LENOF(s) (sizeof(s)-1)
4094 struct berval tmp = *val;
4096 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4097 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4098 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4101 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4103 switch( tmp.bv_val[0] ) {
4106 if(( tmp.bv_len >= LENOF("any") ) &&
4107 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4109 tmp.bv_len -= LENOF("any");
4110 tmp.bv_val += LENOF("any");
4113 return LDAP_INVALID_SYNTAX;
4117 if(( tmp.bv_len >= LENOF("mhs") ) &&
4118 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4120 tmp.bv_len -= LENOF("mhs");
4121 tmp.bv_val += LENOF("mhs");
4124 return LDAP_INVALID_SYNTAX;
4128 if(( tmp.bv_len >= LENOF("physical") ) &&
4129 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4131 tmp.bv_len -= LENOF("physical");
4132 tmp.bv_val += LENOF("physical");
4135 return LDAP_INVALID_SYNTAX;
4138 case 'T': /* telex or teletex or telephone */
4139 if(( tmp.bv_len >= LENOF("telex") ) &&
4140 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4142 tmp.bv_len -= LENOF("telex");
4143 tmp.bv_val += LENOF("telex");
4146 if(( tmp.bv_len >= LENOF("teletex") ) &&
4147 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4149 tmp.bv_len -= LENOF("teletex");
4150 tmp.bv_val += LENOF("teletex");
4153 if(( tmp.bv_len >= LENOF("telephone") ) &&
4154 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4156 tmp.bv_len -= LENOF("telephone");
4157 tmp.bv_val += LENOF("telephone");
4160 return LDAP_INVALID_SYNTAX;
4163 case 'G': /* g3fax or g4fax */
4164 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4165 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4166 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4168 tmp.bv_len -= LENOF("g3fax");
4169 tmp.bv_val += LENOF("g3fax");
4172 return LDAP_INVALID_SYNTAX;
4176 if(( tmp.bv_len >= LENOF("ia5") ) &&
4177 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4179 tmp.bv_len -= LENOF("ia5");
4180 tmp.bv_val += LENOF("ia5");
4183 return LDAP_INVALID_SYNTAX;
4187 if(( tmp.bv_len >= LENOF("videotex") ) &&
4188 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4190 tmp.bv_len -= LENOF("videotex");
4191 tmp.bv_val += LENOF("videotex");
4194 return LDAP_INVALID_SYNTAX;
4197 return LDAP_INVALID_SYNTAX;
4200 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4202 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4206 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4210 return LDAP_INVALID_SYNTAX;
4212 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4221 nisNetgroupTripleValidate(
4223 struct berval *val )
4228 if ( BER_BVISEMPTY( val ) ) {
4229 return LDAP_INVALID_SYNTAX;
4232 p = (char *)val->bv_val;
4233 e = p + val->bv_len;
4235 if ( *p != '(' /*')'*/ ) {
4236 return LDAP_INVALID_SYNTAX;
4239 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4243 return LDAP_INVALID_SYNTAX;
4246 } else if ( !AD_CHAR( *p ) ) {
4247 return LDAP_INVALID_SYNTAX;
4251 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4252 return LDAP_INVALID_SYNTAX;
4258 return LDAP_INVALID_SYNTAX;
4261 return LDAP_SUCCESS;
4265 bootParameterValidate(
4267 struct berval *val )
4271 if ( BER_BVISEMPTY( val ) ) {
4272 return LDAP_INVALID_SYNTAX;
4275 p = (char *)val->bv_val;
4276 e = p + val->bv_len;
4279 for (; ( 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 != ':' ); p++ ) {
4291 if ( !AD_CHAR( *p ) ) {
4292 return LDAP_INVALID_SYNTAX;
4297 return LDAP_INVALID_SYNTAX;
4301 for ( p++; p < e; p++ ) {
4302 if ( !SLAP_PRINTABLE( *p ) ) {
4303 return LDAP_INVALID_SYNTAX;
4307 return LDAP_SUCCESS;
4311 firstComponentNormalize(
4316 struct berval *normalized,
4323 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4324 ber_dupbv_x( normalized, val, ctx );
4325 return LDAP_SUCCESS;
4328 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4330 if( val->bv_val[0] != '(' /*')'*/ &&
4331 val->bv_val[0] != '{' /*'}'*/ )
4333 return LDAP_INVALID_SYNTAX;
4336 /* trim leading white space */
4338 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4344 /* grab next word */
4345 comp.bv_val = &val->bv_val[len];
4346 len = val->bv_len - len;
4347 for( comp.bv_len = 0;
4348 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4354 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4355 rc = numericoidValidate( NULL, &comp );
4356 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4357 rc = integerValidate( NULL, &comp );
4359 rc = LDAP_INVALID_SYNTAX;
4363 if( rc == LDAP_SUCCESS ) {
4364 ber_dupbv_x( normalized, &comp, ctx );
4370 static char *country_gen_syn[] = {
4371 "1.3.6.1.4.1.1466.115.121.1.15",
4372 "1.3.6.1.4.1.1466.115.121.1.26",
4373 "1.3.6.1.4.1.1466.115.121.1.44",
4377 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4378 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4380 static slap_syntax_defs_rec syntax_defs[] = {
4381 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4382 X_BINARY X_NOT_H_R ")",
4383 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4384 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4385 0, NULL, NULL, NULL},
4386 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4387 0, NULL, NULL, NULL},
4388 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4390 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4391 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4393 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4394 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4395 0, NULL, bitStringValidate, NULL },
4396 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4397 0, NULL, booleanValidate, NULL},
4398 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4399 X_BINARY X_NOT_H_R ")",
4400 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4401 NULL, certificateValidate, NULL},
4402 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4403 X_BINARY X_NOT_H_R ")",
4404 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4405 NULL, certificateListValidate, NULL},
4406 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4407 X_BINARY X_NOT_H_R ")",
4408 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4409 NULL, sequenceValidate, NULL},
4410 #if 0 /* need to go __after__ printableString */
4411 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4412 0, "1.3.6.1.4.1.1466.115.121.1.44",
4413 countryStringValidate, NULL},
4415 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4416 0, NULL, dnValidate, dnPretty},
4417 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4418 0, NULL, rdnValidate, rdnPretty},
4419 #ifdef LDAP_COMP_MATCH
4420 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4421 0, NULL, allComponentsValidate, NULL},
4422 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4423 0, NULL, componentFilterValidate, NULL},
4425 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4426 0, NULL, NULL, NULL},
4427 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4428 0, NULL, deliveryMethodValidate, NULL},
4429 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4430 0, NULL, UTF8StringValidate, NULL},
4431 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4432 0, NULL, NULL, NULL},
4433 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4434 0, NULL, NULL, NULL},
4435 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4436 0, NULL, NULL, NULL},
4437 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4438 0, NULL, NULL, NULL},
4439 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4440 0, NULL, NULL, NULL},
4441 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4442 0, NULL, printablesStringValidate, NULL},
4443 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4444 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4445 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4446 0, NULL, generalizedTimeValidate, NULL},
4447 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4448 0, NULL, NULL, NULL},
4449 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4450 0, NULL, IA5StringValidate, NULL},
4451 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4452 0, NULL, integerValidate, NULL},
4453 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4454 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4455 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4456 0, NULL, NULL, NULL},
4457 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4458 0, NULL, NULL, NULL},
4459 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4460 0, NULL, NULL, NULL},
4461 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4462 0, NULL, NULL, NULL},
4463 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4464 0, NULL, NULL, NULL},
4465 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4466 0, NULL, nameUIDValidate, nameUIDPretty },
4467 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4468 0, NULL, NULL, NULL},
4469 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4470 0, NULL, numericStringValidate, NULL},
4471 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4472 0, NULL, NULL, NULL},
4473 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4474 0, NULL, numericoidValidate, NULL},
4475 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4476 0, NULL, IA5StringValidate, NULL},
4477 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4478 0, NULL, blobValidate, NULL},
4479 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4480 0, NULL, UTF8StringValidate, NULL},
4481 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4482 0, NULL, NULL, NULL},
4483 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4484 0, NULL, NULL, NULL},
4485 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4486 0, NULL, printableStringValidate, NULL},
4487 /* moved here because now depends on Directory String, IA5 String
4488 * and Printable String */
4489 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4490 0, country_gen_syn, countryStringValidate, NULL},
4491 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4492 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4493 0, NULL, subtreeSpecificationValidate, NULL},
4494 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4495 X_BINARY X_NOT_H_R ")",
4496 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4497 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4498 0, NULL, printableStringValidate, NULL},
4499 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4500 0, NULL, NULL, NULL},
4501 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4502 0, NULL, printablesStringValidate, NULL},
4503 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4504 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4505 0, NULL, utcTimeValidate, NULL},
4507 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4508 0, NULL, NULL, NULL},
4509 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4510 0, NULL, NULL, NULL},
4511 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4512 0, NULL, NULL, NULL},
4513 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4514 0, NULL, NULL, NULL},
4515 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4516 0, NULL, NULL, NULL},
4518 /* RFC 2307 NIS Syntaxes */
4519 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4520 0, NULL, nisNetgroupTripleValidate, NULL},
4521 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4522 0, NULL, bootParameterValidate, NULL},
4524 /* draft-zeilenga-ldap-x509 */
4525 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4526 SLAP_SYNTAX_HIDE, NULL,
4527 serialNumberAndIssuerValidate,
4528 serialNumberAndIssuerPretty},
4529 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4530 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4531 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4532 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4533 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4534 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4535 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4536 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4537 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4538 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4539 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4540 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4542 #ifdef SLAPD_AUTHPASSWD
4543 /* needs updating */
4544 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4545 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4548 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4549 0, NULL, UUIDValidate, UUIDPretty},
4551 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4552 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4554 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4555 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4557 /* OpenLDAP Void Syntax */
4558 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4559 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4561 /* FIXME: OID is unused, but not registered yet */
4562 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4563 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4565 {NULL, 0, NULL, NULL, NULL}
4568 char *csnSIDMatchSyntaxes[] = {
4569 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4572 char *certificateExactMatchSyntaxes[] = {
4573 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4576 #ifdef LDAP_COMP_MATCH
4577 char *componentFilterMatchSyntaxes[] = {
4578 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4582 char *directoryStringSyntaxes[] = {
4583 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4586 char *integerFirstComponentMatchSyntaxes[] = {
4587 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4588 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4591 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4592 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4593 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4594 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4595 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4596 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4597 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4598 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4599 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4604 * Other matching rules in X.520 that we do not use (yet):
4606 * 2.5.13.25 uTCTimeMatch
4607 * 2.5.13.26 uTCTimeOrderingMatch
4608 * 2.5.13.31* directoryStringFirstComponentMatch
4609 * 2.5.13.32* wordMatch
4610 * 2.5.13.33* keywordMatch
4611 * 2.5.13.36+ certificatePairExactMatch
4612 * 2.5.13.37+ certificatePairMatch
4613 * 2.5.13.38+ certificateListExactMatch
4614 * 2.5.13.39+ certificateListMatch
4615 * 2.5.13.40+ algorithmIdentifierMatch
4616 * 2.5.13.41* storedPrefixMatch
4617 * 2.5.13.42 attributeCertificateMatch
4618 * 2.5.13.43 readerAndKeyIDMatch
4619 * 2.5.13.44 attributeIntegrityMatch
4621 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4622 * (+) described in draft-zeilenga-ldap-x509
4624 static slap_mrule_defs_rec mrule_defs[] = {
4626 * EQUALITY matching rules must be listed after associated APPROX
4627 * matching rules. So, we list all APPROX matching rules first.
4629 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4631 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4632 NULL, NULL, directoryStringApproxMatch,
4633 directoryStringApproxIndexer, directoryStringApproxFilter,
4636 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4637 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4638 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4639 NULL, NULL, IA5StringApproxMatch,
4640 IA5StringApproxIndexer, IA5StringApproxFilter,
4644 * Other matching rules
4647 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4649 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4650 NULL, NULL, octetStringMatch,
4651 octetStringIndexer, octetStringFilter,
4654 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4656 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4657 NULL, dnNormalize, dnMatch,
4658 octetStringIndexer, octetStringFilter,
4661 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4663 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4664 NULL, dnNormalize, dnRelativeMatch,
4668 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4669 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4670 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4671 NULL, dnNormalize, dnRelativeMatch,
4675 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4676 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4677 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4678 NULL, dnNormalize, dnRelativeMatch,
4682 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4683 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4684 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4685 NULL, dnNormalize, dnRelativeMatch,
4689 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4690 "SYNTAX 1.2.36.79672281.1.5.0 )",
4691 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4692 NULL, rdnNormalize, rdnMatch,
4693 octetStringIndexer, octetStringFilter,
4696 #ifdef LDAP_COMP_MATCH
4697 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4698 "SYNTAX 1.2.36.79672281.1.5.2 )",
4699 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4700 NULL, NULL , componentFilterMatch,
4701 octetStringIndexer, octetStringFilter,
4704 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4705 "SYNTAX 1.2.36.79672281.1.5.3 )",
4706 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4707 NULL, NULL , allComponentsMatch,
4708 octetStringIndexer, octetStringFilter,
4711 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4712 "SYNTAX 1.2.36.79672281.1.5.3 )",
4713 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4714 NULL, NULL , directoryComponentsMatch,
4715 octetStringIndexer, octetStringFilter,
4719 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4720 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4721 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4722 NULL, UTF8StringNormalize, octetStringMatch,
4723 octetStringIndexer, octetStringFilter,
4724 directoryStringApproxMatchOID },
4726 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4728 SLAP_MR_ORDERING, directoryStringSyntaxes,
4729 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4731 "caseIgnoreMatch" },
4733 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4734 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4735 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4736 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4737 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4738 "caseIgnoreMatch" },
4740 {"( 2.5.13.5 NAME 'caseExactMatch' "
4741 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4742 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4743 NULL, UTF8StringNormalize, octetStringMatch,
4744 octetStringIndexer, octetStringFilter,
4745 directoryStringApproxMatchOID },
4747 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4748 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4749 SLAP_MR_ORDERING, directoryStringSyntaxes,
4750 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4754 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4755 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4756 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4757 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4758 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4761 {"( 2.5.13.8 NAME 'numericStringMatch' "
4762 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4763 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4764 NULL, numericStringNormalize, octetStringMatch,
4765 octetStringIndexer, octetStringFilter,
4768 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4769 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4770 SLAP_MR_ORDERING, NULL,
4771 NULL, numericStringNormalize, octetStringOrderingMatch,
4773 "numericStringMatch" },
4775 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4776 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4777 SLAP_MR_SUBSTR, NULL,
4778 NULL, numericStringNormalize, octetStringSubstringsMatch,
4779 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4780 "numericStringMatch" },
4782 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4783 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4784 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4785 NULL, NULL, NULL, NULL, NULL, NULL },
4787 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4788 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4789 SLAP_MR_SUBSTR, NULL,
4790 NULL, NULL, NULL, NULL, NULL,
4791 "caseIgnoreListMatch" },
4793 {"( 2.5.13.13 NAME 'booleanMatch' "
4794 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4795 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4796 NULL, NULL, booleanMatch,
4797 octetStringIndexer, octetStringFilter,
4800 {"( 2.5.13.14 NAME 'integerMatch' "
4801 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4802 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4803 NULL, NULL, integerMatch,
4804 integerIndexer, integerFilter,
4807 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4809 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4810 NULL, NULL, integerMatch,
4814 {"( 2.5.13.16 NAME 'bitStringMatch' "
4815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4816 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4817 NULL, NULL, octetStringMatch,
4818 octetStringIndexer, octetStringFilter,
4821 {"( 2.5.13.17 NAME 'octetStringMatch' "
4822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4823 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4824 NULL, NULL, octetStringMatch,
4825 octetStringIndexer, octetStringFilter,
4828 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4829 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4830 SLAP_MR_ORDERING, NULL,
4831 NULL, NULL, octetStringOrderingMatch,
4833 "octetStringMatch" },
4835 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4836 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4837 SLAP_MR_SUBSTR, NULL,
4838 NULL, NULL, octetStringSubstringsMatch,
4839 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4840 "octetStringMatch" },
4842 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4843 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4844 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4846 telephoneNumberNormalize, octetStringMatch,
4847 octetStringIndexer, octetStringFilter,
4850 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4851 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4852 SLAP_MR_SUBSTR, NULL,
4853 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4854 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4855 "telephoneNumberMatch" },
4857 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4858 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4859 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4860 NULL, NULL, NULL, NULL, NULL, NULL },
4862 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4864 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4865 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4866 uniqueMemberIndexer, uniqueMemberFilter,
4869 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4870 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4871 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4872 NULL, NULL, NULL, NULL, NULL, NULL },
4874 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4876 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4877 NULL, generalizedTimeNormalize, octetStringMatch,
4878 generalizedTimeIndexer, generalizedTimeFilter,
4881 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4882 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4883 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4884 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4886 "generalizedTimeMatch" },
4888 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4889 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4890 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4891 integerFirstComponentMatchSyntaxes,
4892 NULL, firstComponentNormalize, integerMatch,
4893 octetStringIndexer, octetStringFilter,
4896 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4897 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4898 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4899 objectIdentifierFirstComponentMatchSyntaxes,
4900 NULL, firstComponentNormalize, octetStringMatch,
4901 octetStringIndexer, octetStringFilter,
4904 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4905 "SYNTAX 1.3.6.1.1.15.1 )",
4906 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4907 NULL, certificateExactNormalize, octetStringMatch,
4908 octetStringIndexer, octetStringFilter,
4911 {"( 2.5.13.35 NAME 'certificateMatch' "
4912 "SYNTAX 1.3.6.1.1.15.2 )",
4913 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4914 NULL, NULL, NULL, NULL, NULL,
4917 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4919 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4920 NULL, IA5StringNormalize, octetStringMatch,
4921 octetStringIndexer, octetStringFilter,
4922 IA5StringApproxMatchOID },
4924 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4926 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4927 NULL, IA5StringNormalize, octetStringMatch,
4928 octetStringIndexer, octetStringFilter,
4929 IA5StringApproxMatchOID },
4931 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4932 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4933 SLAP_MR_SUBSTR, NULL,
4934 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4935 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4936 "caseIgnoreIA5Match" },
4938 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4939 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4940 SLAP_MR_SUBSTR, NULL,
4941 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4942 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4943 "caseExactIA5Match" },
4945 #ifdef SLAPD_AUTHPASSWD
4946 /* needs updating */
4947 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4948 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4949 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4950 NULL, NULL, authPasswordMatch,
4955 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4958 NULL, NULL, integerBitAndMatch,
4962 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4963 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4965 NULL, NULL, integerBitOrMatch,
4969 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4970 "SYNTAX 1.3.6.1.1.16.1 )",
4971 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4972 NULL, UUIDNormalize, octetStringMatch,
4973 octetStringIndexer, octetStringFilter,
4976 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
4977 "SYNTAX 1.3.6.1.1.16.1 )",
4978 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
4979 NULL, UUIDNormalize, octetStringOrderingMatch,
4980 octetStringIndexer, octetStringFilter,
4983 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
4984 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4985 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
4986 NULL, csnNormalize, csnMatch,
4987 csnIndexer, csnFilter,
4990 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
4991 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
4992 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4993 NULL, NULL, csnOrderingMatch,
4997 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
4998 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
4999 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5000 NULL, csnSidNormalize, octetStringMatch,
5001 octetStringIndexer, octetStringFilter,
5004 /* FIXME: OID is unused, but not registered yet */
5005 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5006 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5007 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5008 NULL, authzNormalize, authzMatch,
5012 {NULL, SLAP_MR_NONE, NULL,
5013 NULL, NULL, NULL, NULL, NULL,
5018 slap_schema_init( void )
5023 /* we should only be called once (from main) */
5024 assert( schema_init_done == 0 );
5026 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5027 res = register_syntax( &syntax_defs[i] );
5030 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5031 syntax_defs[i].sd_desc );
5036 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5037 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5038 mrule_defs[i].mrd_compat_syntaxes == NULL )
5041 "slap_schema_init: Ignoring unusable matching rule %s\n",
5042 mrule_defs[i].mrd_desc );
5046 res = register_matching_rule( &mrule_defs[i] );
5050 "slap_schema_init: Error registering matching rule %s\n",
5051 mrule_defs[i].mrd_desc );
5056 res = slap_schema_load();
5057 schema_init_done = 1;
5062 schema_destroy( void )
5071 if( schema_init_done ) {
5072 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5073 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );