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;
66 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
67 SLAP_INDEX_INTLEN_DEFAULT );
69 ldap_pvt_thread_mutex_t ad_undef_mutex;
70 ldap_pvt_thread_mutex_t oc_undef_mutex;
73 generalizedTimeValidate(
82 /* no value allowed */
83 return LDAP_INVALID_SYNTAX;
91 /* any value allowed */
95 #define berValidate blobValidate
102 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
103 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
108 /* X.509 related stuff */
116 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
119 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
120 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
121 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
122 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
126 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
129 /* X.509 certificate validation */
130 static int certificateValidate( Syntax *syntax, struct berval *in )
132 BerElementBuffer berbuf;
133 BerElement *ber = (BerElement *)&berbuf;
136 ber_int_t version = SLAP_X509_V1;
138 ber_init2( ber, in, LBER_USE_DER );
139 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
140 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 tag = ber_skip_tag( ber, &len ); /* Sequence */
142 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
143 tag = ber_peek_tag( ber, &len );
144 /* Optional version */
145 if ( tag == SLAP_X509_OPT_C_VERSION ) {
146 tag = ber_skip_tag( ber, &len );
147 tag = ber_get_int( ber, &version );
148 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
150 /* NOTE: don't try to parse Serial, because it might be longer
151 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
152 tag = ber_skip_tag( ber, &len ); /* Serial */
153 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
154 ber_skip_data( ber, len );
155 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
157 ber_skip_data( ber, len );
158 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
159 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
160 ber_skip_data( ber, len );
161 tag = ber_skip_tag( ber, &len ); /* Validity */
162 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
163 ber_skip_data( ber, len );
164 tag = ber_skip_tag( ber, &len ); /* Subject DN */
165 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
166 ber_skip_data( ber, len );
167 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
168 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
169 ber_skip_data( ber, len );
170 tag = ber_skip_tag( ber, &len );
171 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
172 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
173 ber_skip_data( ber, len );
174 tag = ber_skip_tag( ber, &len );
176 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
177 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
178 ber_skip_data( ber, len );
179 tag = ber_skip_tag( ber, &len );
181 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
182 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
183 tag = ber_skip_tag( ber, &len );
184 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
185 ber_skip_data( ber, len );
186 tag = ber_skip_tag( ber, &len );
188 /* signatureAlgorithm */
189 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
190 ber_skip_data( ber, len );
191 tag = ber_skip_tag( ber, &len );
193 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
194 ber_skip_data( ber, len );
195 tag = ber_skip_tag( ber, &len );
196 /* Must be at end now */
197 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
201 /* X.509 certificate list validation */
202 static int certificateListValidate( Syntax *syntax, struct berval *in )
204 BerElementBuffer berbuf;
205 BerElement *ber = (BerElement *)&berbuf;
208 ber_int_t version = SLAP_X509_V1;
210 ber_init2( ber, in, LBER_USE_DER );
211 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
212 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
213 tag = ber_skip_tag( ber, &len ); /* Sequence */
214 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
215 tag = ber_peek_tag( ber, &len );
216 /* Optional version */
217 if ( tag == LBER_INTEGER ) {
218 tag = ber_get_int( ber, &version );
219 assert( tag == LBER_INTEGER );
220 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
222 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
223 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
224 ber_skip_data( ber, len );
225 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
226 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
227 ber_skip_data( ber, len );
228 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
229 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
230 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
231 ber_skip_data( ber, len );
232 /* Optional nextUpdate */
233 tag = ber_skip_tag( ber, &len );
234 if ( tag == 0x17U || tag == 0x18U ) {
235 ber_skip_data( ber, len );
236 tag = ber_skip_tag( ber, &len );
238 /* revokedCertificates - Sequence of Sequence, Optional */
239 if ( tag == LBER_SEQUENCE ) {
241 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
242 /* Should NOT be empty */
243 ber_skip_data( ber, len );
244 tag = ber_skip_tag( ber, &len );
247 /* Optional Extensions */
248 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
249 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
250 tag = ber_skip_tag( ber, &len );
251 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
252 ber_skip_data( ber, len );
253 tag = ber_skip_tag( ber, &len );
255 /* signatureAlgorithm */
256 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
257 ber_skip_data( ber, len );
258 tag = ber_skip_tag( ber, &len );
260 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
261 ber_skip_data( ber, len );
262 tag = ber_skip_tag( ber, &len );
263 /* Must be at end now */
264 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
274 struct berval *value,
275 void *assertedValue )
277 struct berval *asserted = (struct berval *) assertedValue;
278 int match = value->bv_len - asserted->bv_len;
281 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
289 octetStringOrderingMatch(
294 struct berval *value,
295 void *assertedValue )
297 struct berval *asserted = (struct berval *) assertedValue;
298 ber_len_t v_len = value->bv_len;
299 ber_len_t av_len = asserted->bv_len;
301 int match = memcmp( value->bv_val, asserted->bv_val,
302 (v_len < av_len ? v_len : av_len) );
304 if( match == 0 ) match = v_len - av_len;
312 HASH_CONTEXT *HASHcontext,
313 struct berval *prefix,
318 HASH_Init(HASHcontext);
319 if(prefix && prefix->bv_len > 0) {
320 HASH_Update(HASHcontext,
321 (unsigned char *)prefix->bv_val, prefix->bv_len);
323 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
324 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
325 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
331 HASH_CONTEXT *HASHcontext,
332 unsigned char *HASHdigest,
333 unsigned char *value,
336 HASH_CONTEXT ctx = *HASHcontext;
337 HASH_Update( &ctx, value, len );
338 HASH_Final( HASHdigest, &ctx );
341 /* Index generation function */
342 int octetStringIndexer(
347 struct berval *prefix,
355 HASH_CONTEXT HASHcontext;
356 unsigned char HASHdigest[HASH_BYTES];
357 struct berval digest;
358 digest.bv_val = (char *)HASHdigest;
359 digest.bv_len = sizeof(HASHdigest);
361 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
362 /* just count them */
365 /* we should have at least one value at this point */
368 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
370 slen = syntax->ssyn_oidlen;
371 mlen = mr->smr_oidlen;
373 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
374 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
375 hashIter( &HASHcontext, HASHdigest,
376 (unsigned char *)values[i].bv_val, values[i].bv_len );
377 ber_dupbv_x( &keys[i], &digest, ctx );
380 BER_BVZERO( &keys[i] );
387 /* Index generation function */
388 int octetStringFilter(
393 struct berval *prefix,
394 void * assertedValue,
400 HASH_CONTEXT HASHcontext;
401 unsigned char HASHdigest[HASH_BYTES];
402 struct berval *value = (struct berval *) assertedValue;
403 struct berval digest;
404 digest.bv_val = (char *)HASHdigest;
405 digest.bv_len = sizeof(HASHdigest);
407 slen = syntax->ssyn_oidlen;
408 mlen = mr->smr_oidlen;
410 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
412 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
413 hashIter( &HASHcontext, HASHdigest,
414 (unsigned char *)value->bv_val, value->bv_len );
416 ber_dupbv_x( keys, &digest, ctx );
417 BER_BVZERO( &keys[1] );
425 octetStringSubstringsMatch(
430 struct berval *value,
431 void *assertedValue )
434 SubstringsAssertion *sub = assertedValue;
435 struct berval left = *value;
439 /* Add up asserted input length */
440 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
441 inlen += sub->sa_initial.bv_len;
444 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
445 inlen += sub->sa_any[i].bv_len;
448 if ( !BER_BVISNULL( &sub->sa_final ) ) {
449 inlen += sub->sa_final.bv_len;
452 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
453 if ( inlen > left.bv_len ) {
458 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
459 sub->sa_initial.bv_len );
465 left.bv_val += sub->sa_initial.bv_len;
466 left.bv_len -= sub->sa_initial.bv_len;
467 inlen -= sub->sa_initial.bv_len;
470 if ( !BER_BVISNULL( &sub->sa_final ) ) {
471 if ( inlen > left.bv_len ) {
476 match = memcmp( sub->sa_final.bv_val,
477 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
478 sub->sa_final.bv_len );
484 left.bv_len -= sub->sa_final.bv_len;
485 inlen -= sub->sa_final.bv_len;
489 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
494 if ( inlen > left.bv_len ) {
495 /* not enough length */
500 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
504 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
511 idx = p - left.bv_val;
513 if ( idx >= left.bv_len ) {
514 /* this shouldn't happen */
521 if ( sub->sa_any[i].bv_len > left.bv_len ) {
522 /* not enough left */
527 match = memcmp( left.bv_val,
528 sub->sa_any[i].bv_val,
529 sub->sa_any[i].bv_len );
537 left.bv_val += sub->sa_any[i].bv_len;
538 left.bv_len -= sub->sa_any[i].bv_len;
539 inlen -= sub->sa_any[i].bv_len;
548 /* Substrings Index generation function */
550 octetStringSubstringsIndexer(
555 struct berval *prefix,
564 HASH_CONTEXT HCany, HCini, HCfin;
565 unsigned char HASHdigest[HASH_BYTES];
566 struct berval digest;
567 digest.bv_val = (char *)HASHdigest;
568 digest.bv_len = sizeof(HASHdigest);
572 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
573 /* count number of indices to generate */
574 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
575 if( values[i].bv_len >= index_substr_if_maxlen ) {
576 nkeys += index_substr_if_maxlen -
577 (index_substr_if_minlen - 1);
578 } else if( values[i].bv_len >= index_substr_if_minlen ) {
579 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
583 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
584 if( values[i].bv_len >= index_substr_any_len ) {
585 nkeys += values[i].bv_len - (index_substr_any_len - 1);
589 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
590 if( values[i].bv_len >= index_substr_if_maxlen ) {
591 nkeys += index_substr_if_maxlen -
592 (index_substr_if_minlen - 1);
593 } else if( values[i].bv_len >= index_substr_if_minlen ) {
594 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
600 /* no keys to generate */
605 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
607 slen = syntax->ssyn_oidlen;
608 mlen = mr->smr_oidlen;
610 if ( flags & SLAP_INDEX_SUBSTR_ANY )
611 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
612 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
613 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
614 if( flags & SLAP_INDEX_SUBSTR_FINAL )
615 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
618 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
621 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
622 ( values[i].bv_len >= index_substr_any_len ) )
624 max = values[i].bv_len - (index_substr_any_len - 1);
626 for( j=0; j<max; j++ ) {
627 hashIter( &HCany, HASHdigest,
628 (unsigned char *)&values[i].bv_val[j],
629 index_substr_any_len );
630 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
634 /* skip if too short */
635 if( values[i].bv_len < index_substr_if_minlen ) continue;
637 max = index_substr_if_maxlen < values[i].bv_len
638 ? index_substr_if_maxlen : values[i].bv_len;
640 for( j=index_substr_if_minlen; j<=max; j++ ) {
642 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
643 hashIter( &HCini, HASHdigest,
644 (unsigned char *)values[i].bv_val, j );
645 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
648 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
649 hashIter( &HCfin, HASHdigest,
650 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
651 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
658 BER_BVZERO( &keys[nkeys] );
669 octetStringSubstringsFilter (
674 struct berval *prefix,
675 void * assertedValue,
679 SubstringsAssertion *sa;
682 size_t slen, mlen, klen;
684 HASH_CONTEXT HASHcontext;
685 unsigned char HASHdigest[HASH_BYTES];
686 struct berval *value;
687 struct berval digest;
689 sa = (SubstringsAssertion *) assertedValue;
691 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
692 !BER_BVISNULL( &sa->sa_initial ) &&
693 sa->sa_initial.bv_len >= index_substr_if_minlen )
696 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
697 ( flags & SLAP_INDEX_SUBSTR_ANY ))
699 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
703 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
705 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
706 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
707 /* don't bother accounting with stepping */
708 nkeys += sa->sa_any[i].bv_len -
709 ( index_substr_any_len - 1 );
714 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
715 !BER_BVISNULL( &sa->sa_final ) &&
716 sa->sa_final.bv_len >= index_substr_if_minlen )
719 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
720 ( flags & SLAP_INDEX_SUBSTR_ANY ))
722 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
731 digest.bv_val = (char *)HASHdigest;
732 digest.bv_len = sizeof(HASHdigest);
734 slen = syntax->ssyn_oidlen;
735 mlen = mr->smr_oidlen;
737 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
740 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
741 !BER_BVISNULL( &sa->sa_initial ) &&
742 sa->sa_initial.bv_len >= index_substr_if_minlen )
744 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
745 value = &sa->sa_initial;
747 klen = index_substr_if_maxlen < value->bv_len
748 ? index_substr_if_maxlen : value->bv_len;
750 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
751 hashIter( &HASHcontext, HASHdigest,
752 (unsigned char *)value->bv_val, klen );
753 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
755 /* If initial is too long and we have subany indexed, use it
756 * to match the excess...
758 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
761 pre = SLAP_INDEX_SUBSTR_PREFIX;
762 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
763 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
765 hashIter( &HASHcontext, HASHdigest,
766 (unsigned char *)&value->bv_val[j], index_substr_any_len );
767 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
772 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
774 pre = SLAP_INDEX_SUBSTR_PREFIX;
775 klen = index_substr_any_len;
777 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
778 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
782 value = &sa->sa_any[i];
784 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
786 j <= value->bv_len - index_substr_any_len;
787 j += index_substr_any_step )
789 hashIter( &HASHcontext, HASHdigest,
790 (unsigned char *)&value->bv_val[j], klen );
791 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
796 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
797 !BER_BVISNULL( &sa->sa_final ) &&
798 sa->sa_final.bv_len >= index_substr_if_minlen )
800 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
801 value = &sa->sa_final;
803 klen = index_substr_if_maxlen < value->bv_len
804 ? index_substr_if_maxlen : value->bv_len;
806 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
807 hashIter( &HASHcontext, HASHdigest,
808 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
809 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
811 /* If final is too long and we have subany indexed, use it
812 * to match the excess...
814 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
817 pre = SLAP_INDEX_SUBSTR_PREFIX;
818 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
819 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
821 hashIter( &HASHcontext, HASHdigest,
822 (unsigned char *)&value->bv_val[j], index_substr_any_len );
823 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
829 BER_BVZERO( &keys[nkeys] );
846 /* very unforgiving validation, requires no normalization
847 * before simplistic matching
849 if( in->bv_len < 3 ) {
850 return LDAP_INVALID_SYNTAX;
853 /* RFC 4517 Section 3.3.2 Bit String:
854 * BitString = SQUOTE *binary-digit SQUOTE "B"
855 * binary-digit = "0" / "1"
857 * where SQUOTE [RFC4512] is
858 * SQUOTE = %x27 ; single quote ("'")
860 * Example: '0101111101'B
863 if( in->bv_val[0] != '\'' ||
864 in->bv_val[in->bv_len - 2] != '\'' ||
865 in->bv_val[in->bv_len - 1] != 'B' )
867 return LDAP_INVALID_SYNTAX;
870 for( i = in->bv_len - 3; i > 0; i-- ) {
871 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
872 return LDAP_INVALID_SYNTAX;
880 * Syntaxes from RFC 4517
885 A value of the Bit String syntax is a sequence of binary digits. The
886 LDAP-specific encoding of a value of this syntax is defined by the
889 BitString = SQUOTE *binary-digit SQUOTE "B"
891 binary-digit = "0" / "1"
893 The <SQUOTE> rule is defined in [MODELS].
898 The LDAP definition for the Bit String syntax is:
900 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
902 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
906 3.3.21. Name and Optional UID
908 A value of the Name and Optional UID syntax is the distinguished name
909 [MODELS] of an entity optionally accompanied by a unique identifier
910 that serves to differentiate the entity from others with an identical
913 The LDAP-specific encoding of a value of this syntax is defined by
916 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
918 The <BitString> rule is defined in Section 3.3.2. The
919 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
922 Note that although the '#' character may occur in the string
923 representation of a distinguished name, no additional escaping of
924 this character is performed when a <distinguishedName> is encoded in
925 a <NameAndOptionalUID>.
928 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
930 The LDAP definition for the Name and Optional UID syntax is:
932 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
934 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
941 1.4. Common ABNF Productions
944 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
946 SQUOTE = %x27 ; single quote ("'")
950 * Note: normalization strips any leading "0"s, unless the
951 * bit string is exactly "'0'B", so the normalized example,
952 * in slapd, would result in
954 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
956 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
957 * be escaped except when at the beginning of a value, the
958 * definition of Name and Optional UID appears to be flawed,
959 * because there is no clear means to determine whether the
960 * UID part is present or not.
964 * cn=Someone,dc=example,dc=com#'1'B
966 * could be either a NameAndOptionalUID with trailing UID, i.e.
968 * DN = "cn=Someone,dc=example,dc=com"
971 * or a NameAndOptionalUID with no trailing UID, and the AVA
972 * in the last RDN made of
975 * attributeValue = com#'1'B
977 * in fact "com#'1'B" is a valid IA5 string.
979 * As a consequence, current slapd code assumes that the
980 * presence of portions of a BitString at the end of the string
981 * representation of a NameAndOptionalUID means a BitString
982 * is expected, and cause an error otherwise. This is quite
983 * arbitrary, and might change in the future.
993 struct berval dn, uid;
995 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
997 ber_dupbv( &dn, in );
998 if( !dn.bv_val ) return LDAP_OTHER;
1000 /* if there's a "#", try bitStringValidate()... */
1001 uid.bv_val = strrchr( dn.bv_val, '#' );
1002 if ( !BER_BVISNULL( &uid ) ) {
1004 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1006 rc = bitStringValidate( NULL, &uid );
1007 if ( rc == LDAP_SUCCESS ) {
1008 /* in case of success, trim the UID,
1009 * otherwise treat it as part of the DN */
1010 dn.bv_len -= uid.bv_len + 1;
1011 uid.bv_val[-1] = '\0';
1015 rc = dnValidate( NULL, &dn );
1017 ber_memfree( dn.bv_val );
1028 assert( val != NULL );
1029 assert( out != NULL );
1032 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1034 if( BER_BVISEMPTY( val ) ) {
1035 ber_dupbv_x( out, val, ctx );
1037 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1038 return LDAP_INVALID_SYNTAX;
1042 struct berval dnval = *val;
1043 struct berval uidval = BER_BVNULL;
1045 uidval.bv_val = strrchr( val->bv_val, '#' );
1046 if ( !BER_BVISNULL( &uidval ) ) {
1048 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1050 rc = bitStringValidate( NULL, &uidval );
1052 if ( rc == LDAP_SUCCESS ) {
1053 ber_dupbv_x( &dnval, val, ctx );
1054 dnval.bv_len -= uidval.bv_len + 1;
1055 dnval.bv_val[dnval.bv_len] = '\0';
1058 BER_BVZERO( &uidval );
1062 rc = dnPretty( syntax, &dnval, out, ctx );
1063 if ( dnval.bv_val != val->bv_val ) {
1064 slap_sl_free( dnval.bv_val, ctx );
1066 if( rc != LDAP_SUCCESS ) {
1070 if( !BER_BVISNULL( &uidval ) ) {
1074 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1075 + STRLENOF( "#" ) + uidval.bv_len + 1,
1078 ber_memfree_x( out->bv_val, ctx );
1082 out->bv_val[out->bv_len++] = '#';
1083 out->bv_val[out->bv_len++] = '\'';
1085 got1 = uidval.bv_len < sizeof("'0'B");
1086 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1087 c = uidval.bv_val[i];
1090 if( got1 ) out->bv_val[out->bv_len++] = c;
1094 out->bv_val[out->bv_len++] = c;
1099 out->bv_val[out->bv_len++] = '\'';
1100 out->bv_val[out->bv_len++] = 'B';
1101 out->bv_val[out->bv_len] = '\0';
1105 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1107 return LDAP_SUCCESS;
1111 uniqueMemberNormalize(
1116 struct berval *normalized,
1122 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1124 ber_dupbv_x( &out, val, ctx );
1125 if ( BER_BVISEMPTY( &out ) ) {
1129 struct berval uid = BER_BVNULL;
1131 uid.bv_val = strrchr( out.bv_val, '#' );
1132 if ( !BER_BVISNULL( &uid ) ) {
1134 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1136 rc = bitStringValidate( NULL, &uid );
1137 if ( rc == LDAP_SUCCESS ) {
1138 uid.bv_val[-1] = '\0';
1139 out.bv_len -= uid.bv_len + 1;
1145 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1147 if( rc != LDAP_SUCCESS ) {
1148 slap_sl_free( out.bv_val, ctx );
1149 return LDAP_INVALID_SYNTAX;
1152 if( !BER_BVISNULL( &uid ) ) {
1155 tmp = ch_realloc( normalized->bv_val,
1156 normalized->bv_len + uid.bv_len
1157 + STRLENOF("#") + 1 );
1158 if ( tmp == NULL ) {
1159 ber_memfree_x( normalized->bv_val, ctx );
1163 normalized->bv_val = tmp;
1165 /* insert the separator */
1166 normalized->bv_val[normalized->bv_len++] = '#';
1168 /* append the UID */
1169 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1170 uid.bv_val, uid.bv_len );
1171 normalized->bv_len += uid.bv_len;
1174 normalized->bv_val[normalized->bv_len] = '\0';
1177 slap_sl_free( out.bv_val, ctx );
1180 return LDAP_SUCCESS;
1189 struct berval *value,
1190 void *assertedValue )
1193 struct berval *asserted = (struct berval *) assertedValue;
1194 struct berval assertedDN = *asserted;
1195 struct berval assertedUID = BER_BVNULL;
1196 struct berval valueDN = *value;
1197 struct berval valueUID = BER_BVNULL;
1198 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1200 if ( !BER_BVISEMPTY( asserted ) ) {
1201 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1202 if ( !BER_BVISNULL( &assertedUID ) ) {
1203 assertedUID.bv_val++;
1204 assertedUID.bv_len = assertedDN.bv_len
1205 - ( assertedUID.bv_val - assertedDN.bv_val );
1207 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1208 assertedDN.bv_len -= assertedUID.bv_len + 1;
1211 BER_BVZERO( &assertedUID );
1216 if ( !BER_BVISEMPTY( value ) ) {
1218 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1219 if ( !BER_BVISNULL( &valueUID ) ) {
1221 valueUID.bv_len = valueDN.bv_len
1222 - ( valueUID.bv_val - valueDN.bv_val );
1224 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1225 valueDN.bv_len -= valueUID.bv_len + 1;
1228 BER_BVZERO( &valueUID );
1233 if( valueUID.bv_len && assertedUID.bv_len ) {
1234 match = valueUID.bv_len - assertedUID.bv_len;
1237 return LDAP_SUCCESS;
1240 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1243 return LDAP_SUCCESS;
1246 } else if ( !approx && valueUID.bv_len ) {
1249 return LDAP_SUCCESS;
1251 } else if ( !approx && assertedUID.bv_len ) {
1254 return LDAP_SUCCESS;
1257 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1261 uniqueMemberIndexer(
1266 struct berval *prefix,
1274 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1275 /* just count them */
1279 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1281 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1282 struct berval assertedDN = values[i];
1283 struct berval assertedUID = BER_BVNULL;
1285 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1286 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1287 if ( !BER_BVISNULL( &assertedUID ) ) {
1288 assertedUID.bv_val++;
1289 assertedUID.bv_len = assertedDN.bv_len
1290 - ( assertedUID.bv_val - assertedDN.bv_val );
1292 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1293 assertedDN.bv_len -= assertedUID.bv_len + 1;
1296 BER_BVZERO( &assertedUID );
1301 dnvalues[i] = assertedDN;
1303 BER_BVZERO( &dnvalues[i] );
1305 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1306 dnvalues, keysp, ctx );
1308 slap_sl_free( dnvalues, ctx );
1318 struct berval *prefix,
1319 void * assertedValue,
1323 struct berval *asserted = (struct berval *) assertedValue;
1324 struct berval assertedDN = *asserted;
1325 struct berval assertedUID = BER_BVNULL;
1327 if ( !BER_BVISEMPTY( asserted ) ) {
1328 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1329 if ( !BER_BVISNULL( &assertedUID ) ) {
1330 assertedUID.bv_val++;
1331 assertedUID.bv_len = assertedDN.bv_len
1332 - ( assertedUID.bv_val - assertedDN.bv_val );
1334 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1335 assertedDN.bv_len -= assertedUID.bv_len + 1;
1338 BER_BVZERO( &assertedUID );
1343 return octetStringFilter( use, flags, syntax, mr, prefix,
1344 &assertedDN, keysp, ctx );
1349 * Handling boolean syntax and matching is quite rigid.
1350 * A more flexible approach would be to allow a variety
1351 * of strings to be normalized and prettied into TRUE
1359 /* very unforgiving validation, requires no normalization
1360 * before simplistic matching
1363 if( in->bv_len == 4 ) {
1364 if( bvmatch( in, &slap_true_bv ) ) {
1365 return LDAP_SUCCESS;
1367 } else if( in->bv_len == 5 ) {
1368 if( bvmatch( in, &slap_false_bv ) ) {
1369 return LDAP_SUCCESS;
1373 return LDAP_INVALID_SYNTAX;
1382 struct berval *value,
1383 void *assertedValue )
1385 /* simplistic matching allowed by rigid validation */
1386 struct berval *asserted = (struct berval *) assertedValue;
1387 *matchp = value->bv_len != asserted->bv_len;
1388 return LDAP_SUCCESS;
1391 /*-------------------------------------------------------------------
1392 LDAP/X.500 string syntax / matching rules have a few oddities. This
1393 comment attempts to detail how slapd(8) treats them.
1396 StringSyntax X.500 LDAP Matching/Comments
1397 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1398 PrintableString subset subset i/e + ignore insignificant spaces
1399 PrintableString subset subset i/e + ignore insignificant spaces
1400 NumericString subset subset ignore all spaces
1401 IA5String ASCII ASCII i/e + ignore insignificant spaces
1402 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1404 TelephoneNumber subset subset i + ignore all spaces and "-"
1406 See RFC 4518 for details.
1410 In X.500(93), a directory string can be either a PrintableString,
1411 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1412 In later versions, more CHOICEs were added. In all cases the string
1415 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1416 A directory string cannot be zero length.
1418 For matching, there are both case ignore and exact rules. Both
1419 also require that "insignificant" spaces be ignored.
1420 spaces before the first non-space are ignored;
1421 spaces after the last non-space are ignored;
1422 spaces after a space are ignored.
1423 Note: by these rules (and as clarified in X.520), a string of only
1424 spaces is to be treated as if held one space, not empty (which
1425 would be a syntax error).
1428 In ASN.1, numeric string is just a string of digits and spaces
1429 and could be empty. However, in X.500, all attribute values of
1430 numeric string carry a non-empty constraint. For example:
1432 internationalISDNNumber ATTRIBUTE ::= {
1433 WITH SYNTAX InternationalISDNNumber
1434 EQUALITY MATCHING RULE numericStringMatch
1435 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1436 ID id-at-internationalISDNNumber }
1437 InternationalISDNNumber ::=
1438 NumericString (SIZE(1..ub-international-isdn-number))
1440 Unforunately, some assertion values are don't carry the same
1441 constraint (but its unclear how such an assertion could ever
1442 be true). In LDAP, there is one syntax (numericString) not two
1443 (numericString with constraint, numericString without constraint).
1444 This should be treated as numericString with non-empty constraint.
1445 Note that while someone may have no ISDN number, there are no ISDN
1446 numbers which are zero length.
1448 In matching, spaces are ignored.
1451 In ASN.1, Printable string is just a string of printable characters
1452 and can be empty. In X.500, semantics much like NumericString (see
1453 serialNumber for a like example) excepting uses insignificant space
1454 handling instead of ignore all spaces. They must be non-empty.
1457 Basically same as PrintableString. There are no examples in X.500,
1458 but same logic applies. Empty strings are allowed.
1460 -------------------------------------------------------------------*/
1469 unsigned char *u = (unsigned char *)in->bv_val;
1471 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1472 /* directory strings cannot be empty */
1473 return LDAP_INVALID_SYNTAX;
1476 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1477 /* get the length indicated by the first byte */
1478 len = LDAP_UTF8_CHARLEN2( u, len );
1480 /* very basic checks */
1483 if( (u[5] & 0xC0) != 0x80 ) {
1484 return LDAP_INVALID_SYNTAX;
1487 if( (u[4] & 0xC0) != 0x80 ) {
1488 return LDAP_INVALID_SYNTAX;
1491 if( (u[3] & 0xC0) != 0x80 ) {
1492 return LDAP_INVALID_SYNTAX;
1495 if( (u[2] & 0xC0 )!= 0x80 ) {
1496 return LDAP_INVALID_SYNTAX;
1499 if( (u[1] & 0xC0) != 0x80 ) {
1500 return LDAP_INVALID_SYNTAX;
1503 /* CHARLEN already validated it */
1506 return LDAP_INVALID_SYNTAX;
1509 /* make sure len corresponds with the offset
1510 to the next character */
1511 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1515 return LDAP_INVALID_SYNTAX;
1518 return LDAP_SUCCESS;
1522 UTF8StringNormalize(
1527 struct berval *normalized,
1530 struct berval tmp, nvalue;
1534 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1536 if( BER_BVISNULL( val ) ) {
1537 /* assume we're dealing with a syntax (e.g., UTF8String)
1538 * which allows empty strings
1540 BER_BVZERO( normalized );
1541 return LDAP_SUCCESS;
1544 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1545 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1546 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1547 ? LDAP_UTF8_APPROX : 0;
1549 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1554 /* collapse spaces (in place) */
1556 nvalue.bv_val = tmp.bv_val;
1558 /* trim leading spaces? */
1559 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1560 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1562 for( i = 0; i < tmp.bv_len; i++) {
1563 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1564 if( wasspace++ == 0 ) {
1565 /* trim repeated spaces */
1566 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1570 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1574 if( !BER_BVISEMPTY( &nvalue ) ) {
1575 /* trim trailing space? */
1577 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1578 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1582 nvalue.bv_val[nvalue.bv_len] = '\0';
1585 /* string of all spaces is treated as one space */
1586 nvalue.bv_val[0] = ' ';
1587 nvalue.bv_val[1] = '\0';
1591 *normalized = nvalue;
1592 return LDAP_SUCCESS;
1596 directoryStringSubstringsMatch(
1601 struct berval *value,
1602 void *assertedValue )
1605 SubstringsAssertion *sub = assertedValue;
1606 struct berval left = *value;
1610 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1611 if ( sub->sa_initial.bv_len > left.bv_len ) {
1612 /* not enough left */
1617 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1618 sub->sa_initial.bv_len );
1624 left.bv_val += sub->sa_initial.bv_len;
1625 left.bv_len -= sub->sa_initial.bv_len;
1627 priorspace = ASCII_SPACE(
1628 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1631 if ( sub->sa_any ) {
1632 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1636 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1637 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1639 /* allow next space to match */
1646 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1650 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1651 /* not enough left */
1656 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1663 idx = p - left.bv_val;
1665 if ( idx >= left.bv_len ) {
1666 /* this shouldn't happen */
1673 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1674 /* not enough left */
1679 match = memcmp( left.bv_val,
1680 sub->sa_any[i].bv_val,
1681 sub->sa_any[i].bv_len );
1689 left.bv_val += sub->sa_any[i].bv_len;
1690 left.bv_len -= sub->sa_any[i].bv_len;
1692 priorspace = ASCII_SPACE(
1693 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1697 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1698 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1699 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1701 /* allow next space to match */
1706 if ( sub->sa_final.bv_len > left.bv_len ) {
1707 /* not enough left */
1712 match = memcmp( sub->sa_final.bv_val,
1713 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1714 sub->sa_final.bv_len );
1723 return LDAP_SUCCESS;
1726 #if defined(SLAPD_APPROX_INITIALS)
1727 # define SLAPD_APPROX_DELIMITER "._ "
1728 # define SLAPD_APPROX_WORDLEN 2
1730 # define SLAPD_APPROX_DELIMITER " "
1731 # define SLAPD_APPROX_WORDLEN 1
1740 struct berval *value,
1741 void *assertedValue )
1743 struct berval *nval, *assertv;
1744 char *val, **values, **words, *c;
1745 int i, count, len, nextchunk=0, nextavail=0;
1747 /* Yes, this is necessary */
1748 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1749 if( nval == NULL ) {
1751 return LDAP_SUCCESS;
1754 /* Yes, this is necessary */
1755 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1756 NULL, LDAP_UTF8_APPROX, NULL );
1757 if( assertv == NULL ) {
1760 return LDAP_SUCCESS;
1763 /* Isolate how many words there are */
1764 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1765 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1766 if ( c == NULL ) break;
1771 /* Get a phonetic copy of each word */
1772 words = (char **)ch_malloc( count * sizeof(char *) );
1773 values = (char **)ch_malloc( count * sizeof(char *) );
1774 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1776 values[i] = phonetic(c);
1779 /* Work through the asserted value's words, to see if at least some
1780 of the words are there, in the same order. */
1782 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1783 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1788 #if defined(SLAPD_APPROX_INITIALS)
1789 else if( len == 1 ) {
1790 /* Single letter words need to at least match one word's initial */
1791 for( i=nextavail; i<count; i++ )
1792 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1799 /* Isolate the next word in the asserted value and phonetic it */
1800 assertv->bv_val[nextchunk+len] = '\0';
1801 val = phonetic( assertv->bv_val + nextchunk );
1803 /* See if this phonetic chunk is in the remaining words of *value */
1804 for( i=nextavail; i<count; i++ ){
1805 if( !strcmp( val, values[i] ) ){
1813 /* This chunk in the asserted value was NOT within the *value. */
1819 /* Go on to the next word in the asserted value */
1823 /* If some of the words were seen, call it a match */
1824 if( nextavail > 0 ) {
1831 /* Cleanup allocs */
1832 ber_bvfree( assertv );
1833 for( i=0; i<count; i++ ) {
1834 ch_free( values[i] );
1840 return LDAP_SUCCESS;
1849 struct berval *prefix,
1855 int i,j, len, wordcount, keycount=0;
1856 struct berval *newkeys;
1857 BerVarray keys=NULL;
1859 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1860 struct berval val = BER_BVNULL;
1861 /* Yes, this is necessary */
1862 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1863 assert( !BER_BVISNULL( &val ) );
1865 /* Isolate how many words there are. There will be a key for each */
1866 for( wordcount = 0, c = val.bv_val; *c; c++) {
1867 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1868 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1870 if (*c == '\0') break;
1874 /* Allocate/increase storage to account for new keys */
1875 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1876 * sizeof(struct berval) );
1877 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1878 if( keys ) ch_free( keys );
1881 /* Get a phonetic copy of each word */
1882 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1884 if( len < SLAPD_APPROX_WORDLEN ) continue;
1885 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1890 ber_memfree( val.bv_val );
1892 BER_BVZERO( &keys[keycount] );
1895 return LDAP_SUCCESS;
1904 struct berval *prefix,
1905 void * assertedValue,
1914 /* Yes, this is necessary */
1915 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1916 NULL, LDAP_UTF8_APPROX, NULL );
1917 if( val == NULL || BER_BVISNULL( val ) ) {
1918 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1919 BER_BVZERO( &keys[0] );
1922 return LDAP_SUCCESS;
1925 /* Isolate how many words there are. There will be a key for each */
1926 for( count = 0,c = val->bv_val; *c; c++) {
1927 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1928 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1930 if (*c == '\0') break;
1934 /* Allocate storage for new keys */
1935 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1937 /* Get a phonetic copy of each word */
1938 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1940 if( len < SLAPD_APPROX_WORDLEN ) continue;
1941 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1947 BER_BVZERO( &keys[count] );
1950 return LDAP_SUCCESS;
1953 /* Remove all spaces and '-' characters */
1955 telephoneNumberNormalize(
1960 struct berval *normalized,
1965 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1967 /* validator should have refused an empty string */
1968 assert( !BER_BVISEMPTY( val ) );
1970 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1972 for( p = val->bv_val; *p; p++ ) {
1973 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1979 normalized->bv_len = q - normalized->bv_val;
1981 if( BER_BVISEMPTY( normalized ) ) {
1982 slap_sl_free( normalized->bv_val, ctx );
1983 BER_BVZERO( normalized );
1984 return LDAP_INVALID_SYNTAX;
1987 return LDAP_SUCCESS;
1995 struct berval val = *in;
1997 if( BER_BVISEMPTY( &val ) ) {
1998 /* disallow empty strings */
1999 return LDAP_INVALID_SYNTAX;
2002 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2003 if ( val.bv_len == 1 ) {
2004 return LDAP_SUCCESS;
2007 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2014 while ( OID_LEADCHAR( val.bv_val[0] )) {
2018 if ( val.bv_len == 0 ) {
2019 return LDAP_SUCCESS;
2023 if( !OID_SEPARATOR( val.bv_val[0] )) {
2031 return LDAP_INVALID_SYNTAX;
2040 struct berval val = *in;
2042 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2044 if ( val.bv_val[0] == '-' ) {
2048 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2049 return LDAP_INVALID_SYNTAX;
2052 if( val.bv_val[0] == '0' ) { /* "-0" */
2053 return LDAP_INVALID_SYNTAX;
2056 } else if ( val.bv_val[0] == '0' ) {
2057 if( val.bv_len > 1 ) { /* "0<more>" */
2058 return LDAP_INVALID_SYNTAX;
2061 return LDAP_SUCCESS;
2064 for( i=0; i < val.bv_len; i++ ) {
2065 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2066 return LDAP_INVALID_SYNTAX;
2070 return LDAP_SUCCESS;
2079 struct berval *value,
2080 void *assertedValue )
2082 struct berval *asserted = (struct berval *) assertedValue;
2083 int vsign = 1, asign = 1; /* default sign = '+' */
2088 if( v.bv_val[0] == '-' ) {
2094 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2097 if( a.bv_val[0] == '-' ) {
2103 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2105 match = vsign - asign;
2107 match = ( v.bv_len != a.bv_len
2108 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2109 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2110 if( vsign < 0 ) match = -match;
2114 return LDAP_SUCCESS;
2117 /* 10**INDEX_INTLEN_CHOP < 256**INDEX_INTLEN_CHOPBYTES */
2118 #define INDEX_INTLEN_CHOP 7
2119 #define INDEX_INTLEN_CHOPBYTES 3
2130 * only if too large: one's complement <sign*length of chopped bytes>,
2131 * two's complement value (sign-extended or chopped as needed),
2132 * with 1st byte of the above adjusted as follows:
2133 * inverse sign in the top <number of length-bytes + 1> bits,
2134 * then the sign bit as delimiter.
2136 ber_slen_t k = index_intlen_strlen, chop = 0;
2137 unsigned char neg = 0xff, signmask = 0x80;
2138 unsigned char lenbuf[sizeof(k) + 2], *lenp;
2139 struct berval val = *in, itmp = *tmp;
2141 if ( val.bv_val[0] != '-' ) {
2146 /* Chop least significant digits, increase length instead */
2147 if ( val.bv_len > k ) {
2148 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2149 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2150 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2151 if ( chop > 0x7fffffff ) {
2152 memset( key->bv_val, neg ^ 0xff, index_intlen );
2157 if ( lutil_str2bin( &val, &itmp, ctx )) {
2158 return LDAP_INVALID_SYNTAX;
2161 /* Omit leading sign byte */
2162 if ( itmp.bv_val[0] == neg ) {
2167 k = (ber_slen_t) index_intlen - ((ber_slen_t) itmp.bv_len + chop);
2169 assert( chop == 0 );
2170 memset( key->bv_val, neg, k ); /* sign-extend */
2171 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2172 lenp = lenbuf + sizeof(lenbuf);
2177 } while ( (k >>= 8) != 0 || (signmask >> 1) <= (*lenp ^ neg) );
2178 /* With n bytes used in lenbuf, the top n+1 bits of signmask
2179 * are 1, and the top n+2 bits of *lenp are the sign bit. */
2180 k = (lenbuf + sizeof(lenbuf)) - lenp;
2181 if ( k > index_intlen )
2183 memcpy( key->bv_val, lenp, k );
2184 itmp.bv_len = index_intlen - k;
2186 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2187 key->bv_val[0] ^= (unsigned char) -signmask & 0xff; /* invert sign */
2191 /* Index generation function */
2198 struct berval *prefix,
2208 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2210 /* count the values and find max needed length */
2212 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2213 if ( vlen < values[i].bv_len )
2214 vlen = values[i].bv_len;
2216 if ( vlen > maxstrlen )
2219 /* we should have at least one value at this point */
2222 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2223 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2224 keys[i].bv_len = index_intlen;
2225 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2228 keys[i].bv_val = NULL;
2230 if ( vlen > sizeof(ibuf) ) {
2231 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2235 itmp.bv_len = sizeof(ibuf);
2237 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2238 if ( itmp.bv_val != ibuf ) {
2239 itmp.bv_len = values[i].bv_len;
2240 if ( itmp.bv_len <= sizeof(ibuf) )
2241 itmp.bv_len = sizeof(ibuf);
2242 else if ( itmp.bv_len > maxstrlen )
2243 itmp.bv_len = maxstrlen;
2245 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2251 if ( itmp.bv_val != ibuf ) {
2252 slap_sl_free( itmp.bv_val, ctx );
2257 /* Index generation function */
2264 struct berval *prefix,
2265 void * assertedValue,
2272 struct berval *value;
2275 value = (struct berval *) assertedValue;
2277 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2279 keys[0].bv_len = index_intlen;
2280 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2282 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2283 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2284 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2285 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2288 iv.bv_len = sizeof(ibuf);
2291 rc = integerVal2Key( value, keys, &iv, ctx );
2295 if ( iv.bv_val != ibuf ) {
2296 slap_sl_free( iv.bv_val, ctx );
2302 countryStringValidate(
2304 struct berval *val )
2306 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2308 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2309 return LDAP_INVALID_SYNTAX;
2311 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2312 return LDAP_INVALID_SYNTAX;
2315 return LDAP_SUCCESS;
2319 printableStringValidate(
2321 struct berval *val )
2325 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2327 for(i=0; i < val->bv_len; i++) {
2328 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2329 return LDAP_INVALID_SYNTAX;
2333 return LDAP_SUCCESS;
2337 printablesStringValidate(
2339 struct berval *val )
2343 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2345 for(i=0,len=0; i < val->bv_len; i++) {
2346 int c = val->bv_val[i];
2350 return LDAP_INVALID_SYNTAX;
2354 } else if ( SLAP_PRINTABLE(c) ) {
2357 return LDAP_INVALID_SYNTAX;
2362 return LDAP_INVALID_SYNTAX;
2365 return LDAP_SUCCESS;
2371 struct berval *val )
2375 for(i=0; i < val->bv_len; i++) {
2376 if( !LDAP_ASCII(val->bv_val[i]) ) {
2377 return LDAP_INVALID_SYNTAX;
2381 return LDAP_SUCCESS;
2390 struct berval *normalized,
2394 int casefold = !SLAP_MR_ASSOCIATED( mr,
2395 slap_schema.si_mr_caseExactIA5Match );
2397 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2401 /* Ignore initial whitespace */
2402 while ( ASCII_SPACE( *p ) ) p++;
2404 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2405 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2406 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2407 normalized->bv_val[normalized->bv_len] = '\0';
2409 p = q = normalized->bv_val;
2412 if ( ASCII_SPACE( *p ) ) {
2415 /* Ignore the extra whitespace */
2416 while ( ASCII_SPACE( *p ) ) {
2420 } else if ( casefold ) {
2421 /* Most IA5 rules require casefolding */
2422 *q++ = TOLOWER(*p); p++;
2429 assert( normalized->bv_val <= p );
2433 * If the string ended in space, backup the pointer one
2434 * position. One is enough because the above loop collapsed
2435 * all whitespace to a single space.
2437 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2439 /* null terminate */
2442 normalized->bv_len = q - normalized->bv_val;
2444 return LDAP_SUCCESS;
2453 if( in->bv_len != 36 ) {
2454 return LDAP_INVALID_SYNTAX;
2457 for( i=0; i<36; i++ ) {
2463 if( in->bv_val[i] != '-' ) {
2464 return LDAP_INVALID_SYNTAX;
2468 if( !ASCII_HEX( in->bv_val[i]) ) {
2469 return LDAP_INVALID_SYNTAX;
2474 return LDAP_SUCCESS;
2485 int rc=LDAP_INVALID_SYNTAX;
2487 assert( in != NULL );
2488 assert( out != NULL );
2490 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2493 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2495 for( i=0; i<36; i++ ) {
2501 if( in->bv_val[i] != '-' ) {
2504 out->bv_val[i] = '-';
2508 if( !ASCII_HEX( in->bv_val[i]) ) {
2511 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2516 out->bv_val[ out->bv_len ] = '\0';
2520 slap_sl_free( out->bv_val, ctx );
2533 struct berval *normalized,
2536 unsigned char octet = '\0';
2540 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2541 /* NOTE: must be a normalized UUID */
2542 assert( val->bv_len == 16 );
2544 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2545 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2546 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2547 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2549 return LDAP_SUCCESS;
2552 normalized->bv_len = 16;
2553 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2555 for( i=0, j=0; i<36; i++ ) {
2556 unsigned char nibble;
2557 if( val->bv_val[i] == '-' ) {
2560 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2561 nibble = val->bv_val[i] - '0';
2563 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2564 nibble = val->bv_val[i] - ('a'-10);
2566 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2567 nibble = val->bv_val[i] - ('A'-10);
2570 slap_sl_free( normalized->bv_val, ctx );
2571 return LDAP_INVALID_SYNTAX;
2576 normalized->bv_val[j>>1] = octet;
2578 octet = nibble << 4;
2583 normalized->bv_val[normalized->bv_len] = 0;
2584 return LDAP_SUCCESS;
2590 numericStringValidate(
2596 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2598 for(i=0; i < in->bv_len; i++) {
2599 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2600 return LDAP_INVALID_SYNTAX;
2604 return LDAP_SUCCESS;
2608 numericStringNormalize(
2613 struct berval *normalized,
2616 /* removal all spaces */
2619 assert( !BER_BVISEMPTY( val ) );
2621 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2624 q = normalized->bv_val;
2627 if ( ASCII_SPACE( *p ) ) {
2628 /* Ignore whitespace */
2635 /* we should have copied no more than is in val */
2636 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2638 /* null terminate */
2641 normalized->bv_len = q - normalized->bv_val;
2643 if( BER_BVISEMPTY( normalized ) ) {
2644 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2645 normalized->bv_val[0] = ' ';
2646 normalized->bv_val[1] = '\0';
2647 normalized->bv_len = 1;
2650 return LDAP_SUCCESS;
2654 * Integer conversion macros that will use the largest available
2657 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2658 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2659 # define SLAP_LONG long long
2661 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2662 # define SLAP_LONG long
2663 #endif /* HAVE_STRTOLL ... */
2671 struct berval *value,
2672 void *assertedValue )
2674 SLAP_LONG lValue, lAssertedValue;
2677 /* safe to assume integers are NUL terminated? */
2678 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2679 if( errno == ERANGE )
2681 return LDAP_CONSTRAINT_VIOLATION;
2684 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2686 if( errno == ERANGE )
2688 return LDAP_CONSTRAINT_VIOLATION;
2691 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2692 return LDAP_SUCCESS;
2701 struct berval *value,
2702 void *assertedValue )
2704 SLAP_LONG lValue, lAssertedValue;
2707 /* safe to assume integers are NUL terminated? */
2708 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2709 if( errno == ERANGE )
2711 return LDAP_CONSTRAINT_VIOLATION;
2714 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2716 if( errno == ERANGE )
2718 return LDAP_CONSTRAINT_VIOLATION;
2721 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2722 return LDAP_SUCCESS;
2726 serialNumberAndIssuerCheck(
2735 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2737 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2738 /* Parse old format */
2739 is->bv_val = ber_bvchr( in, '$' );
2740 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2742 sn->bv_val = in->bv_val;
2743 sn->bv_len = is->bv_val - in->bv_val;
2746 is->bv_len = in->bv_len - (sn->bv_len + 1);
2748 /* eat leading zeros */
2749 for( n=0; n < (sn->bv_len-1); n++ ) {
2750 if( sn->bv_val[n] != '0' ) break;
2755 for( n=0; n < sn->bv_len; n++ ) {
2756 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2760 /* Parse GSER format */
2761 int havesn=0,haveissuer=0;
2762 struct berval x = *in;
2767 /* eat leading spaces */
2768 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2772 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2773 return LDAP_INVALID_SYNTAX;
2776 /* should be at issuer or serialNumber NamedValue */
2777 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2779 x.bv_val += STRLENOF("issuer");
2780 x.bv_len -= STRLENOF("issuer");
2782 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2783 x.bv_val++; x.bv_len--;
2785 /* eat leading spaces */
2786 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2790 /* For backward compatibility, this part is optional */
2791 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2792 x.bv_val += STRLENOF("rdnSequence:");
2793 x.bv_len -= STRLENOF("rdnSequence:");
2796 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2797 x.bv_val++; x.bv_len--;
2799 is->bv_val = x.bv_val;
2802 for( ; is->bv_len < x.bv_len; ) {
2803 if ( is->bv_val[is->bv_len] != '"' ) {
2807 if ( is->bv_val[is->bv_len+1] == '"' ) {
2814 x.bv_val += is->bv_len+1;
2815 x.bv_len -= is->bv_len+1;
2817 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2818 return LDAP_INVALID_SYNTAX;
2823 } else if( strncasecmp( x.bv_val, "serialNumber",
2824 STRLENOF("serialNumber")) == 0 )
2826 /* parse serialNumber */
2828 x.bv_val += STRLENOF("serialNumber");
2829 x.bv_len -= STRLENOF("serialNumber");
2831 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2832 x.bv_val++; x.bv_len--;
2834 /* eat leading spaces */
2835 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2839 sn->bv_val = x.bv_val;
2842 if( sn->bv_val[0] == '-' ) {
2847 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2848 sn->bv_val[1] == 'X' )) {
2850 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2851 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2853 } else if ( sn->bv_val[0] == '\'' ) {
2854 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2855 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2857 if ( sn->bv_val[sn->bv_len] == '\'' &&
2858 sn->bv_val[sn->bv_len+1] == 'H' )
2861 return LDAP_INVALID_SYNTAX;
2864 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2865 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2869 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2870 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2871 return LDAP_INVALID_SYNTAX;
2874 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2876 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2877 return LDAP_INVALID_SYNTAX;
2882 } else return LDAP_INVALID_SYNTAX;
2884 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2885 x.bv_val++; x.bv_len--;
2888 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2892 /* should be at remaining NamedValue */
2893 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2894 STRLENOF("issuer" )) == 0 ))
2897 x.bv_val += STRLENOF("issuer");
2898 x.bv_len -= STRLENOF("issuer");
2900 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2901 x.bv_val++; x.bv_len--;
2903 /* eat leading spaces */
2904 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2908 /* For backward compatibility, this part is optional */
2909 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2910 x.bv_val += STRLENOF("rdnSequence:");
2911 x.bv_len -= STRLENOF("rdnSequence:");
2914 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2915 x.bv_val++; x.bv_len--;
2917 is->bv_val = x.bv_val;
2920 for( ; is->bv_len < x.bv_len; ) {
2921 if ( is->bv_val[is->bv_len] != '"' ) {
2925 if ( is->bv_val[is->bv_len+1] == '"' ) {
2932 x.bv_val += is->bv_len+1;
2933 x.bv_len -= is->bv_len+1;
2935 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2936 STRLENOF("serialNumber")) == 0 ))
2938 /* parse serialNumber */
2940 x.bv_val += STRLENOF("serialNumber");
2941 x.bv_len -= STRLENOF("serialNumber");
2943 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2944 x.bv_val++; x.bv_len--;
2946 /* eat leading spaces */
2947 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2951 sn->bv_val = x.bv_val;
2954 if( sn->bv_val[0] == '-' ) {
2959 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2960 sn->bv_val[1] == 'X' )) {
2962 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2963 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2965 } else if ( sn->bv_val[0] == '\'' ) {
2966 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2967 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2969 if ( sn->bv_val[sn->bv_len] == '\'' &&
2970 sn->bv_val[sn->bv_len+1] == 'H' )
2973 return LDAP_INVALID_SYNTAX;
2976 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2977 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2981 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2982 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2983 return LDAP_INVALID_SYNTAX;
2986 x.bv_val += sn->bv_len;
2987 x.bv_len -= sn->bv_len;
2989 } else return LDAP_INVALID_SYNTAX;
2991 /* eat trailing spaces */
2992 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2996 /* should have no characters left... */
2997 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2999 ber_dupbv_x( &ni, is, ctx );
3002 /* need to handle double dquotes here */
3008 serialNumberAndIssuerValidate(
3013 struct berval sn, i;
3015 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3018 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3022 /* validate DN -- doesn't handle double dquote */
3023 rc = dnValidate( NULL, &i );
3025 rc = LDAP_INVALID_SYNTAX;
3027 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3028 slap_sl_free( i.bv_val, NULL );
3031 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3037 serialNumberAndIssuerPretty(
3044 struct berval sn, i, ni;
3046 assert( in != NULL );
3047 assert( out != NULL );
3049 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3052 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3056 rc = dnPretty( syntax, &i, &ni, ctx );
3058 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3059 slap_sl_free( i.bv_val, ctx );
3062 if( rc ) return LDAP_INVALID_SYNTAX;
3064 /* make room from sn + "$" */
3065 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3066 + sn.bv_len + ni.bv_len;
3067 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3069 if( out->bv_val == NULL ) {
3071 slap_sl_free( ni.bv_val, ctx );
3076 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3077 STRLENOF("{ serialNumber "));
3078 n = STRLENOF("{ serialNumber ");
3080 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3083 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3084 n += STRLENOF(", issuer rdnSequence:\"");
3086 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3089 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3090 n += STRLENOF("\" }");
3092 out->bv_val[n] = '\0';
3094 assert( n == out->bv_len );
3096 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3097 out->bv_val, 0, 0 );
3099 slap_sl_free( ni.bv_val, ctx );
3101 return LDAP_SUCCESS;
3105 * This routine is called by certificateExactNormalize when
3106 * certificateExactNormalize receives a search string instead of
3107 * a certificate. This routine checks if the search value is valid
3108 * and then returns the normalized value
3111 serialNumberAndIssuerNormalize(
3119 struct berval sn, sn2, i, ni;
3120 char sbuf[64], *stmp = sbuf;
3124 assert( in != NULL );
3125 assert( out != NULL );
3127 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3130 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3134 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3136 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3137 slap_sl_free( i.bv_val, ctx );
3140 if( rc ) return LDAP_INVALID_SYNTAX;
3142 /* Convert sn to canonical hex */
3143 if ( sn.bv_len > sizeof( sbuf )) {
3144 stmp = slap_sl_malloc( sn.bv_len, ctx );
3147 sn2.bv_len = sn.bv_len;
3148 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3149 rc = LDAP_INVALID_SYNTAX;
3153 /* make room for sn + "$" */
3154 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3155 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3156 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3158 if( out->bv_val == NULL ) {
3160 slap_sl_free( ni.bv_val, ctx );
3166 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3167 STRLENOF( "{ serialNumber " ));
3168 n = STRLENOF( "{ serialNumber " );
3170 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3173 unsigned char *v = (unsigned char *)sn2.bv_val;
3174 out->bv_val[n++] = '\'';
3175 for ( j = 0; j < sn2.bv_len; j++ ) {
3176 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3180 out->bv_val[n++] = '\'';
3181 out->bv_val[n++] = 'H';
3184 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3185 n += STRLENOF( ", issuer rdnSequence:\"" );
3187 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3190 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3191 n += STRLENOF( "\" }" );
3193 out->bv_val[n] = '\0';
3195 assert( n == out->bv_len );
3197 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3198 out->bv_val, 0, 0 );
3202 slap_sl_free( stmp, ctx );
3203 slap_sl_free( ni.bv_val, ctx );
3209 certificateExactNormalize(
3214 struct berval *normalized,
3217 BerElementBuffer berbuf;
3218 BerElement *ber = (BerElement *)&berbuf;
3222 char serialbuf[64], *serial = serialbuf;
3223 ber_len_t seriallen;
3224 struct berval issuer_dn = BER_BVNULL, bvdn;
3226 int rc = LDAP_INVALID_SYNTAX;
3228 if( BER_BVISEMPTY( val ) ) goto done;
3230 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3231 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3234 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3236 ber_init2( ber, val, LBER_USE_DER );
3237 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3238 tag = ber_skip_tag( ber, &len ); /* Sequence */
3239 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3240 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3241 tag = ber_skip_tag( ber, &len );
3242 tag = ber_get_int( ber, &i ); /* version */
3245 /* NOTE: move the test here from certificateValidate,
3246 * so that we can validate certs with serial longer
3247 * than sizeof(ber_int_t) */
3248 tag = ber_peek_tag( ber, &len ); /* serial */
3250 /* Use hex format. '123456789abcdef'H
3256 tag = ber_skip_tag( ber, &len );
3257 ptr = (unsigned char *)ber->ber_ptr;
3258 ber_skip_data( ber, len );
3260 /* Check for minimal encodings */
3262 if ( ptr[0] & 0x80 ) {
3263 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3264 return LDAP_INVALID_SYNTAX;
3265 } else if ( ptr[0] == 0 ) {
3266 if (!( ptr[1] & 0x80 ))
3267 return LDAP_INVALID_SYNTAX;
3271 seriallen = len * 2 + 4; /* quotes, H, NUL */
3272 if ( seriallen > sizeof( serialbuf ))
3273 serial = slap_sl_malloc( seriallen, ctx );
3276 for ( i = 0; i<len; i++ ) {
3277 sprintf( sptr, "%02X", ptr[i] );
3284 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3285 ber_skip_data( ber, len );
3286 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3287 len = ber_ptrlen( ber );
3288 bvdn.bv_val = val->bv_val + len;
3289 bvdn.bv_len = val->bv_len - len;
3291 rc = dnX509normalize( &bvdn, &issuer_dn );
3292 if( rc != LDAP_SUCCESS ) goto done;
3294 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3295 + seriallen + issuer_dn.bv_len;
3296 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3298 p = (unsigned char *)normalized->bv_val;
3300 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3301 p += STRLENOF( "{ serialNumber " );
3303 AC_MEMCPY(p, serial, seriallen);
3306 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3307 p += STRLENOF( ", issuer rdnSequence:\"" );
3309 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3310 p += issuer_dn.bv_len;
3312 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3313 p += STRLENOF( "\" }" );
3317 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3318 normalized->bv_val, NULL, NULL );
3323 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3324 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3336 assert( in != NULL );
3337 assert( !BER_BVISNULL( in ) );
3339 for ( i = 0; i < in->bv_len; i++ ) {
3340 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3341 return LDAP_INVALID_SYNTAX;
3345 return LDAP_SUCCESS;
3348 /* Normalize a SID as used inside a CSN:
3349 * three-digit numeric string */
3356 struct berval *normalized,
3361 assert( val != NULL );
3362 assert( normalized != NULL );
3364 ber_dupbv_x( normalized, val, ctx );
3366 for ( i = 0; i < normalized->bv_len; i++ ) {
3367 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3368 ber_memfree_x( normalized->bv_val, ctx );
3369 BER_BVZERO( normalized );
3370 return LDAP_INVALID_SYNTAX;
3373 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3376 return LDAP_SUCCESS;
3384 assert( in != NULL );
3385 assert( !BER_BVISNULL( in ) );
3387 if ( in->bv_len != 3 ) {
3388 return LDAP_INVALID_SYNTAX;
3391 return hexValidate( NULL, in );
3394 /* Normalize a SID as used inside a CSN:
3395 * three-digit numeric string */
3402 struct berval *normalized,
3405 if ( val->bv_len != 3 ) {
3406 return LDAP_INVALID_SYNTAX;
3409 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3419 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3422 /* Normalize a SID as used inside a CSN, either as-is
3423 * (assertion value) or extracted from the CSN
3424 * (attribute value) */
3431 struct berval *normalized,
3439 if ( BER_BVISEMPTY( val ) ) {
3440 return LDAP_INVALID_SYNTAX;
3443 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3444 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3447 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3449 ptr = ber_bvchr( val, '#' );
3450 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3451 return LDAP_INVALID_SYNTAX;
3454 bv.bv_val = ptr + 1;
3455 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3457 ptr = ber_bvchr( &bv, '#' );
3458 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3459 return LDAP_INVALID_SYNTAX;
3462 bv.bv_val = ptr + 1;
3463 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3465 ptr = ber_bvchr( &bv, '#' );
3466 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3467 return LDAP_INVALID_SYNTAX;
3470 bv.bv_len = ptr - bv.bv_val;
3472 if ( bv.bv_len == 2 ) {
3473 /* OpenLDAP 2.3 SID */
3475 buf[ 1 ] = bv.bv_val[ 0 ];
3476 buf[ 2 ] = bv.bv_val[ 1 ];
3483 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3495 assert( in != NULL );
3496 assert( !BER_BVISNULL( in ) );
3498 if ( BER_BVISEMPTY( in ) ) {
3499 return LDAP_INVALID_SYNTAX;
3504 ptr = ber_bvchr( &bv, '#' );
3505 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3506 return LDAP_INVALID_SYNTAX;
3509 bv.bv_len = ptr - bv.bv_val;
3510 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3511 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3513 return LDAP_INVALID_SYNTAX;
3516 rc = generalizedTimeValidate( NULL, &bv );
3517 if ( rc != LDAP_SUCCESS ) {
3521 bv.bv_val = ptr + 1;
3522 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3524 ptr = ber_bvchr( &bv, '#' );
3525 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3526 return LDAP_INVALID_SYNTAX;
3529 bv.bv_len = ptr - bv.bv_val;
3530 if ( bv.bv_len != 6 ) {
3531 return LDAP_INVALID_SYNTAX;
3534 rc = hexValidate( NULL, &bv );
3535 if ( rc != LDAP_SUCCESS ) {
3539 bv.bv_val = ptr + 1;
3540 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3542 ptr = ber_bvchr( &bv, '#' );
3543 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3544 return LDAP_INVALID_SYNTAX;
3547 bv.bv_len = ptr - bv.bv_val;
3548 if ( bv.bv_len == 2 ) {
3549 /* tolerate old 2-digit replica-id */
3550 rc = hexValidate( NULL, &bv );
3553 rc = sidValidate( NULL, &bv );
3555 if ( rc != LDAP_SUCCESS ) {
3559 bv.bv_val = ptr + 1;
3560 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3562 if ( bv.bv_len != 6 ) {
3563 return LDAP_INVALID_SYNTAX;
3566 return hexValidate( NULL, &bv );
3569 /* Normalize a CSN in OpenLDAP 2.3 format */
3576 struct berval *normalized,
3579 struct berval gt, cnt, sid, mod;
3583 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3584 assert( !BER_BVISEMPTY( val ) );
3588 ptr = ber_bvchr( >, '#' );
3589 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3590 return LDAP_INVALID_SYNTAX;
3593 gt.bv_len = ptr - gt.bv_val;
3594 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3596 cnt.bv_val = ptr + 1;
3597 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3599 ptr = ber_bvchr( &cnt, '#' );
3600 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3601 return LDAP_INVALID_SYNTAX;
3604 cnt.bv_len = ptr - cnt.bv_val;
3605 assert( cnt.bv_len == STRLENOF( "000000" ) );
3607 sid.bv_val = ptr + 1;
3608 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3610 ptr = ber_bvchr( &sid, '#' );
3611 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3612 return LDAP_INVALID_SYNTAX;
3615 sid.bv_len = ptr - sid.bv_val;
3616 assert( sid.bv_len == STRLENOF( "00" ) );
3618 mod.bv_val = ptr + 1;
3619 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3620 assert( mod.bv_len == STRLENOF( "000000" ) );
3622 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3623 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3625 ptr = normalized->bv_val;
3626 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3627 ptr = lutil_strcopy( ptr, ".000000Z#" );
3628 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3631 for ( i = 0; i < sid.bv_len; i++ ) {
3632 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3635 for ( i = 0; i < mod.bv_len; i++ ) {
3636 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3640 assert( ptr - normalized->bv_val == normalized->bv_len );
3642 return LDAP_SUCCESS;
3645 /* Normalize a CSN */
3652 struct berval *normalized,
3655 struct berval cnt, sid, mod;
3659 assert( val != NULL );
3660 assert( normalized != NULL );
3662 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3664 if ( BER_BVISEMPTY( val ) ) {
3665 return LDAP_INVALID_SYNTAX;
3668 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3669 /* Openldap <= 2.3 */
3671 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3674 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3676 ptr = ber_bvchr( val, '#' );
3677 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3678 return LDAP_INVALID_SYNTAX;
3681 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3683 cnt.bv_val = ptr + 1;
3684 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3686 ptr = ber_bvchr( &cnt, '#' );
3687 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3688 return LDAP_INVALID_SYNTAX;
3691 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3693 sid.bv_val = ptr + 1;
3694 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3696 ptr = ber_bvchr( &sid, '#' );
3697 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3698 return LDAP_INVALID_SYNTAX;
3701 sid.bv_len = ptr - sid.bv_val;
3702 assert( sid.bv_len == STRLENOF( "000" ) );
3704 mod.bv_val = ptr + 1;
3705 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3707 assert( mod.bv_len == STRLENOF( "000000" ) );
3709 ber_dupbv_x( normalized, val, ctx );
3711 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3712 i < normalized->bv_len; i++ )
3714 /* assume it's already validated that's all hex digits */
3715 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3718 return LDAP_SUCCESS;
3728 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3731 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3732 /* slight optimization - does not need the start parameter */
3733 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3738 check_time_syntax (struct berval *val,
3741 struct berval *fraction)
3744 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3745 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3746 * GeneralizedTime supports leap seconds, UTCTime does not.
3748 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3749 static const int mdays[2][12] = {
3750 /* non-leap years */
3751 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3753 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3756 int part, c, c1, c2, tzoffset, leapyear = 0;
3759 e = p + val->bv_len;
3761 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3762 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3764 for (part = start; part < 7 && p < e; part++) {
3766 if (!ASCII_DIGIT(c1)) {
3771 return LDAP_INVALID_SYNTAX;
3774 if (!ASCII_DIGIT(c)) {
3775 return LDAP_INVALID_SYNTAX;
3777 c += c1 * 10 - '0' * 11;
3778 if ((part | 1) == 3) {
3781 return LDAP_INVALID_SYNTAX;
3784 if (c >= ceiling[part]) {
3785 if (! (c == 60 && part == 6 && start == 0))
3786 return LDAP_INVALID_SYNTAX;
3790 if (part < 5 + start) {
3791 return LDAP_INVALID_SYNTAX;
3793 for (; part < 9; part++) {
3797 /* leapyear check for the Gregorian calendar (year>1581) */
3798 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3802 if (parts[3] >= mdays[leapyear][parts[2]]) {
3803 return LDAP_INVALID_SYNTAX;
3807 fraction->bv_val = p;
3808 fraction->bv_len = 0;
3809 if (p < e && (*p == '.' || *p == ',')) {
3811 while (++p < e && ASCII_DIGIT(*p)) {
3814 if (p - fraction->bv_val == 1) {
3815 return LDAP_INVALID_SYNTAX;
3817 for (end_num = p; end_num[-1] == '0'; --end_num) {
3820 c = end_num - fraction->bv_val;
3821 if (c != 1) fraction->bv_len = c;
3827 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3833 return LDAP_INVALID_SYNTAX;
3839 for (part = 7; part < 9 && p < e; part++) {
3841 if (!ASCII_DIGIT(c1)) {
3846 return LDAP_INVALID_SYNTAX;
3849 if (!ASCII_DIGIT(c2)) {
3850 return LDAP_INVALID_SYNTAX;
3852 parts[part] = c1 * 10 + c2 - '0' * 11;
3853 if (parts[part] >= ceiling[part]) {
3854 return LDAP_INVALID_SYNTAX;
3857 if (part < 8 + start) {
3858 return LDAP_INVALID_SYNTAX;
3861 if (tzoffset == '-') {
3862 /* negative offset to UTC, ie west of Greenwich */
3863 parts[4] += parts[7];
3864 parts[5] += parts[8];
3865 /* offset is just hhmm, no seconds */
3866 for (part = 6; --part >= 0; ) {
3870 c = mdays[leapyear][parts[2]];
3872 if (parts[part] >= c) {
3874 return LDAP_INVALID_SYNTAX;
3879 } else if (part != 5) {
3884 /* positive offset to UTC, ie east of Greenwich */
3885 parts[4] -= parts[7];
3886 parts[5] -= parts[8];
3887 for (part = 6; --part >= 0; ) {
3888 if (parts[part] < 0) {
3890 return LDAP_INVALID_SYNTAX;
3895 /* make first arg to % non-negative */
3896 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3901 } else if (part != 5) {
3908 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3911 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3918 struct berval *normalized )
3922 rc = check_time_syntax(val, 1, parts, NULL);
3923 if (rc != LDAP_SUCCESS) {
3927 normalized->bv_val = ch_malloc( 14 );
3928 if ( normalized->bv_val == NULL ) {
3929 return LBER_ERROR_MEMORY;
3932 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3933 parts[1], parts[2] + 1, parts[3] + 1,
3934 parts[4], parts[5], parts[6] );
3935 normalized->bv_len = 13;
3937 return LDAP_SUCCESS;
3947 return check_time_syntax(in, 1, parts, NULL);
3950 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3953 generalizedTimeValidate(
3958 struct berval fraction;
3959 return check_time_syntax(in, 0, parts, &fraction);
3963 generalizedTimeNormalize(
3968 struct berval *normalized,
3973 struct berval fraction;
3975 rc = check_time_syntax(val, 0, parts, &fraction);
3976 if (rc != LDAP_SUCCESS) {
3980 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3981 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3982 if ( BER_BVISNULL( normalized ) ) {
3983 return LBER_ERROR_MEMORY;
3986 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3987 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3988 parts[4], parts[5], parts[6] );
3989 if ( !BER_BVISEMPTY( &fraction ) ) {
3990 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3991 fraction.bv_val, fraction.bv_len );
3992 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3994 strcpy( normalized->bv_val + len-1, "Z" );
3995 normalized->bv_len = len;
3997 return LDAP_SUCCESS;
4001 generalizedTimeOrderingMatch(
4006 struct berval *value,
4007 void *assertedValue )
4009 struct berval *asserted = (struct berval *) assertedValue;
4010 ber_len_t v_len = value->bv_len;
4011 ber_len_t av_len = asserted->bv_len;
4013 /* ignore trailing 'Z' when comparing */
4014 int match = memcmp( value->bv_val, asserted->bv_val,
4015 (v_len < av_len ? v_len : av_len) - 1 );
4016 if ( match == 0 ) match = v_len - av_len;
4019 return LDAP_SUCCESS;
4022 /* Index generation function */
4023 int generalizedTimeIndexer(
4028 struct berval *prefix,
4036 BerValue bvtmp; /* 40 bit index */
4038 struct lutil_timet tt;
4040 bvtmp.bv_len = sizeof(tmp);
4042 for( i=0; values[i].bv_val != NULL; i++ ) {
4043 /* just count them */
4046 /* we should have at least one value at this point */
4049 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4051 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4052 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4053 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4054 /* Use 40 bits of time for key */
4055 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4056 lutil_tm2time( &tm, &tt );
4057 tmp[0] = tt.tt_gsec & 0xff;
4058 tmp[4] = tt.tt_sec & 0xff;
4060 tmp[3] = tt.tt_sec & 0xff;
4062 tmp[2] = tt.tt_sec & 0xff;
4064 tmp[1] = tt.tt_sec & 0xff;
4066 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4070 keys[j].bv_val = NULL;
4075 return LDAP_SUCCESS;
4078 /* Index generation function */
4079 int generalizedTimeFilter(
4084 struct berval *prefix,
4085 void * assertedValue,
4091 BerValue bvtmp; /* 40 bit index */
4092 BerValue *value = (BerValue *) assertedValue;
4094 struct lutil_timet tt;
4096 bvtmp.bv_len = sizeof(tmp);
4098 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4099 /* Use 40 bits of time for key */
4100 if ( value->bv_val && value->bv_len >= 10 &&
4101 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4103 lutil_tm2time( &tm, &tt );
4104 tmp[0] = tt.tt_gsec & 0xff;
4105 tmp[4] = tt.tt_sec & 0xff;
4107 tmp[3] = tt.tt_sec & 0xff;
4109 tmp[2] = tt.tt_sec & 0xff;
4111 tmp[1] = tt.tt_sec & 0xff;
4113 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4114 ber_dupbv_x(keys, &bvtmp, ctx );
4115 keys[1].bv_val = NULL;
4123 return LDAP_SUCCESS;
4127 deliveryMethodValidate(
4129 struct berval *val )
4132 #define LENOF(s) (sizeof(s)-1)
4133 struct berval tmp = *val;
4135 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4136 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4137 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4140 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4142 switch( tmp.bv_val[0] ) {
4145 if(( tmp.bv_len >= LENOF("any") ) &&
4146 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4148 tmp.bv_len -= LENOF("any");
4149 tmp.bv_val += LENOF("any");
4152 return LDAP_INVALID_SYNTAX;
4156 if(( tmp.bv_len >= LENOF("mhs") ) &&
4157 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4159 tmp.bv_len -= LENOF("mhs");
4160 tmp.bv_val += LENOF("mhs");
4163 return LDAP_INVALID_SYNTAX;
4167 if(( tmp.bv_len >= LENOF("physical") ) &&
4168 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4170 tmp.bv_len -= LENOF("physical");
4171 tmp.bv_val += LENOF("physical");
4174 return LDAP_INVALID_SYNTAX;
4177 case 'T': /* telex or teletex or telephone */
4178 if(( tmp.bv_len >= LENOF("telex") ) &&
4179 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4181 tmp.bv_len -= LENOF("telex");
4182 tmp.bv_val += LENOF("telex");
4185 if(( tmp.bv_len >= LENOF("teletex") ) &&
4186 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4188 tmp.bv_len -= LENOF("teletex");
4189 tmp.bv_val += LENOF("teletex");
4192 if(( tmp.bv_len >= LENOF("telephone") ) &&
4193 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4195 tmp.bv_len -= LENOF("telephone");
4196 tmp.bv_val += LENOF("telephone");
4199 return LDAP_INVALID_SYNTAX;
4202 case 'G': /* g3fax or g4fax */
4203 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4204 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4205 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4207 tmp.bv_len -= LENOF("g3fax");
4208 tmp.bv_val += LENOF("g3fax");
4211 return LDAP_INVALID_SYNTAX;
4215 if(( tmp.bv_len >= LENOF("ia5") ) &&
4216 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4218 tmp.bv_len -= LENOF("ia5");
4219 tmp.bv_val += LENOF("ia5");
4222 return LDAP_INVALID_SYNTAX;
4226 if(( tmp.bv_len >= LENOF("videotex") ) &&
4227 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4229 tmp.bv_len -= LENOF("videotex");
4230 tmp.bv_val += LENOF("videotex");
4233 return LDAP_INVALID_SYNTAX;
4236 return LDAP_INVALID_SYNTAX;
4239 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4241 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4245 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4249 return LDAP_INVALID_SYNTAX;
4251 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4260 nisNetgroupTripleValidate(
4262 struct berval *val )
4267 if ( BER_BVISEMPTY( val ) ) {
4268 return LDAP_INVALID_SYNTAX;
4271 p = (char *)val->bv_val;
4272 e = p + val->bv_len;
4274 if ( *p != '(' /*')'*/ ) {
4275 return LDAP_INVALID_SYNTAX;
4278 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4282 return LDAP_INVALID_SYNTAX;
4285 } else if ( !AD_CHAR( *p ) ) {
4286 return LDAP_INVALID_SYNTAX;
4290 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4291 return LDAP_INVALID_SYNTAX;
4297 return LDAP_INVALID_SYNTAX;
4300 return LDAP_SUCCESS;
4304 bootParameterValidate(
4306 struct berval *val )
4310 if ( BER_BVISEMPTY( val ) ) {
4311 return LDAP_INVALID_SYNTAX;
4314 p = (char *)val->bv_val;
4315 e = p + val->bv_len;
4318 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4319 if ( !AD_CHAR( *p ) ) {
4320 return LDAP_INVALID_SYNTAX;
4325 return LDAP_INVALID_SYNTAX;
4329 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4330 if ( !AD_CHAR( *p ) ) {
4331 return LDAP_INVALID_SYNTAX;
4336 return LDAP_INVALID_SYNTAX;
4340 for ( p++; p < e; p++ ) {
4341 if ( !SLAP_PRINTABLE( *p ) ) {
4342 return LDAP_INVALID_SYNTAX;
4346 return LDAP_SUCCESS;
4350 firstComponentNormalize(
4355 struct berval *normalized,
4362 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4363 ber_dupbv_x( normalized, val, ctx );
4364 return LDAP_SUCCESS;
4367 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4369 if( val->bv_val[0] != '(' /*')'*/ &&
4370 val->bv_val[0] != '{' /*'}'*/ )
4372 return LDAP_INVALID_SYNTAX;
4375 /* trim leading white space */
4377 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4383 /* grab next word */
4384 comp.bv_val = &val->bv_val[len];
4385 len = val->bv_len - len;
4386 for( comp.bv_len = 0;
4387 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4393 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4394 rc = numericoidValidate( NULL, &comp );
4395 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4396 rc = integerValidate( NULL, &comp );
4398 rc = LDAP_INVALID_SYNTAX;
4402 if( rc == LDAP_SUCCESS ) {
4403 ber_dupbv_x( normalized, &comp, ctx );
4409 static char *country_gen_syn[] = {
4410 "1.3.6.1.4.1.1466.115.121.1.15",
4411 "1.3.6.1.4.1.1466.115.121.1.26",
4412 "1.3.6.1.4.1.1466.115.121.1.44",
4416 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4417 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4419 static slap_syntax_defs_rec syntax_defs[] = {
4420 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4421 X_BINARY X_NOT_H_R ")",
4422 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4423 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4424 0, NULL, NULL, NULL},
4425 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4426 0, NULL, NULL, NULL},
4427 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4429 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4430 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4432 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4433 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4434 0, NULL, bitStringValidate, NULL },
4435 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4436 0, NULL, booleanValidate, NULL},
4437 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4438 X_BINARY X_NOT_H_R ")",
4439 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4440 NULL, certificateValidate, NULL},
4441 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4442 X_BINARY X_NOT_H_R ")",
4443 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4444 NULL, certificateListValidate, NULL},
4445 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4446 X_BINARY X_NOT_H_R ")",
4447 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4448 NULL, sequenceValidate, NULL},
4449 #if 0 /* need to go __after__ printableString */
4450 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4451 0, "1.3.6.1.4.1.1466.115.121.1.44",
4452 countryStringValidate, NULL},
4454 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4455 0, NULL, dnValidate, dnPretty},
4456 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4457 0, NULL, rdnValidate, rdnPretty},
4458 #ifdef LDAP_COMP_MATCH
4459 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4460 0, NULL, allComponentsValidate, NULL},
4461 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4462 0, NULL, componentFilterValidate, NULL},
4464 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4465 0, NULL, NULL, NULL},
4466 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4467 0, NULL, deliveryMethodValidate, NULL},
4468 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4469 0, NULL, UTF8StringValidate, NULL},
4470 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4471 0, NULL, NULL, NULL},
4472 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4473 0, NULL, NULL, NULL},
4474 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4475 0, NULL, NULL, NULL},
4476 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4477 0, NULL, NULL, NULL},
4478 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4479 0, NULL, NULL, NULL},
4480 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4481 0, NULL, printablesStringValidate, NULL},
4482 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4483 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4484 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4485 0, NULL, generalizedTimeValidate, NULL},
4486 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4487 0, NULL, NULL, NULL},
4488 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4489 0, NULL, IA5StringValidate, NULL},
4490 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4491 0, NULL, integerValidate, NULL},
4492 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4493 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4494 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4495 0, NULL, NULL, NULL},
4496 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4497 0, NULL, NULL, NULL},
4498 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4499 0, NULL, NULL, NULL},
4500 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4501 0, NULL, NULL, NULL},
4502 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4503 0, NULL, NULL, NULL},
4504 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4505 0, NULL, nameUIDValidate, nameUIDPretty },
4506 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4507 0, NULL, NULL, NULL},
4508 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4509 0, NULL, numericStringValidate, NULL},
4510 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4511 0, NULL, NULL, NULL},
4512 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4513 0, NULL, numericoidValidate, NULL},
4514 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4515 0, NULL, IA5StringValidate, NULL},
4516 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4517 0, NULL, blobValidate, NULL},
4518 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4519 0, NULL, UTF8StringValidate, NULL},
4520 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4521 0, NULL, NULL, NULL},
4522 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4523 0, NULL, NULL, NULL},
4524 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4525 0, NULL, printableStringValidate, NULL},
4526 /* moved here because now depends on Directory String, IA5 String
4527 * and Printable String */
4528 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4529 0, country_gen_syn, countryStringValidate, NULL},
4530 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4531 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4532 0, NULL, subtreeSpecificationValidate, NULL},
4533 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4534 X_BINARY X_NOT_H_R ")",
4535 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4536 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4537 0, NULL, printableStringValidate, NULL},
4538 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4539 0, NULL, NULL, NULL},
4540 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4541 0, NULL, printablesStringValidate, NULL},
4542 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4543 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4544 0, NULL, utcTimeValidate, NULL},
4546 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4547 0, NULL, NULL, NULL},
4548 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4549 0, NULL, NULL, NULL},
4550 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4551 0, NULL, NULL, NULL},
4552 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4553 0, NULL, NULL, NULL},
4554 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4555 0, NULL, NULL, NULL},
4557 /* RFC 2307 NIS Syntaxes */
4558 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4559 0, NULL, nisNetgroupTripleValidate, NULL},
4560 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4561 0, NULL, bootParameterValidate, NULL},
4563 /* draft-zeilenga-ldap-x509 */
4564 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4565 SLAP_SYNTAX_HIDE, NULL,
4566 serialNumberAndIssuerValidate,
4567 serialNumberAndIssuerPretty},
4568 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4569 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4570 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4571 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4572 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4573 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4574 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4575 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4576 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4577 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4578 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4579 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4581 #ifdef SLAPD_AUTHPASSWD
4582 /* needs updating */
4583 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4584 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4587 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4588 0, NULL, UUIDValidate, UUIDPretty},
4590 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4591 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4593 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4594 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4596 /* OpenLDAP Void Syntax */
4597 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4598 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4600 /* FIXME: OID is unused, but not registered yet */
4601 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4602 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4604 {NULL, 0, NULL, NULL, NULL}
4607 char *csnSIDMatchSyntaxes[] = {
4608 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4611 char *certificateExactMatchSyntaxes[] = {
4612 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4615 #ifdef LDAP_COMP_MATCH
4616 char *componentFilterMatchSyntaxes[] = {
4617 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4621 char *directoryStringSyntaxes[] = {
4622 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4625 char *integerFirstComponentMatchSyntaxes[] = {
4626 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4627 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4630 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4631 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4632 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4633 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4634 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4635 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4636 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4637 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4638 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4643 * Other matching rules in X.520 that we do not use (yet):
4645 * 2.5.13.25 uTCTimeMatch
4646 * 2.5.13.26 uTCTimeOrderingMatch
4647 * 2.5.13.31* directoryStringFirstComponentMatch
4648 * 2.5.13.32* wordMatch
4649 * 2.5.13.33* keywordMatch
4650 * 2.5.13.36+ certificatePairExactMatch
4651 * 2.5.13.37+ certificatePairMatch
4652 * 2.5.13.38+ certificateListExactMatch
4653 * 2.5.13.39+ certificateListMatch
4654 * 2.5.13.40+ algorithmIdentifierMatch
4655 * 2.5.13.41* storedPrefixMatch
4656 * 2.5.13.42 attributeCertificateMatch
4657 * 2.5.13.43 readerAndKeyIDMatch
4658 * 2.5.13.44 attributeIntegrityMatch
4660 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4661 * (+) described in draft-zeilenga-ldap-x509
4663 static slap_mrule_defs_rec mrule_defs[] = {
4665 * EQUALITY matching rules must be listed after associated APPROX
4666 * matching rules. So, we list all APPROX matching rules first.
4668 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4669 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4670 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4671 NULL, NULL, directoryStringApproxMatch,
4672 directoryStringApproxIndexer, directoryStringApproxFilter,
4675 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4676 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4677 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4678 NULL, NULL, IA5StringApproxMatch,
4679 IA5StringApproxIndexer, IA5StringApproxFilter,
4683 * Other matching rules
4686 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4687 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4688 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4689 NULL, NULL, octetStringMatch,
4690 octetStringIndexer, octetStringFilter,
4693 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4695 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4696 NULL, dnNormalize, dnMatch,
4697 octetStringIndexer, octetStringFilter,
4700 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4702 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4703 NULL, dnNormalize, dnRelativeMatch,
4707 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4708 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4709 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4710 NULL, dnNormalize, dnRelativeMatch,
4714 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4715 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4716 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4717 NULL, dnNormalize, dnRelativeMatch,
4721 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4722 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4723 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4724 NULL, dnNormalize, dnRelativeMatch,
4728 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4729 "SYNTAX 1.2.36.79672281.1.5.0 )",
4730 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4731 NULL, rdnNormalize, rdnMatch,
4732 octetStringIndexer, octetStringFilter,
4735 #ifdef LDAP_COMP_MATCH
4736 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4737 "SYNTAX 1.2.36.79672281.1.5.2 )",
4738 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4739 NULL, NULL , componentFilterMatch,
4740 octetStringIndexer, octetStringFilter,
4743 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4744 "SYNTAX 1.2.36.79672281.1.5.3 )",
4745 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4746 NULL, NULL , allComponentsMatch,
4747 octetStringIndexer, octetStringFilter,
4750 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4751 "SYNTAX 1.2.36.79672281.1.5.3 )",
4752 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4753 NULL, NULL , directoryComponentsMatch,
4754 octetStringIndexer, octetStringFilter,
4758 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4759 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4760 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4761 NULL, UTF8StringNormalize, octetStringMatch,
4762 octetStringIndexer, octetStringFilter,
4763 directoryStringApproxMatchOID },
4765 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4766 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4767 SLAP_MR_ORDERING, directoryStringSyntaxes,
4768 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4770 "caseIgnoreMatch" },
4772 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4773 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4774 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4775 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4776 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4777 "caseIgnoreMatch" },
4779 {"( 2.5.13.5 NAME 'caseExactMatch' "
4780 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4781 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4782 NULL, UTF8StringNormalize, octetStringMatch,
4783 octetStringIndexer, octetStringFilter,
4784 directoryStringApproxMatchOID },
4786 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4787 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4788 SLAP_MR_ORDERING, directoryStringSyntaxes,
4789 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4793 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4794 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4795 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4796 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4797 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4800 {"( 2.5.13.8 NAME 'numericStringMatch' "
4801 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4802 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4803 NULL, numericStringNormalize, octetStringMatch,
4804 octetStringIndexer, octetStringFilter,
4807 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4809 SLAP_MR_ORDERING, NULL,
4810 NULL, numericStringNormalize, octetStringOrderingMatch,
4812 "numericStringMatch" },
4814 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4816 SLAP_MR_SUBSTR, NULL,
4817 NULL, numericStringNormalize, octetStringSubstringsMatch,
4818 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4819 "numericStringMatch" },
4821 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4823 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4824 NULL, NULL, NULL, NULL, NULL, NULL },
4826 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4827 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4828 SLAP_MR_SUBSTR, NULL,
4829 NULL, NULL, NULL, NULL, NULL,
4830 "caseIgnoreListMatch" },
4832 {"( 2.5.13.13 NAME 'booleanMatch' "
4833 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4834 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4835 NULL, NULL, booleanMatch,
4836 octetStringIndexer, octetStringFilter,
4839 {"( 2.5.13.14 NAME 'integerMatch' "
4840 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4841 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4842 NULL, NULL, integerMatch,
4843 integerIndexer, integerFilter,
4846 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4847 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4848 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4849 NULL, NULL, integerMatch,
4853 {"( 2.5.13.16 NAME 'bitStringMatch' "
4854 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4855 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4856 NULL, NULL, octetStringMatch,
4857 octetStringIndexer, octetStringFilter,
4860 {"( 2.5.13.17 NAME 'octetStringMatch' "
4861 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4862 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4863 NULL, NULL, octetStringMatch,
4864 octetStringIndexer, octetStringFilter,
4867 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4868 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4869 SLAP_MR_ORDERING, NULL,
4870 NULL, NULL, octetStringOrderingMatch,
4872 "octetStringMatch" },
4874 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4876 SLAP_MR_SUBSTR, NULL,
4877 NULL, NULL, octetStringSubstringsMatch,
4878 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4879 "octetStringMatch" },
4881 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4882 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4883 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4885 telephoneNumberNormalize, octetStringMatch,
4886 octetStringIndexer, octetStringFilter,
4889 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4890 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4891 SLAP_MR_SUBSTR, NULL,
4892 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4893 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4894 "telephoneNumberMatch" },
4896 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4897 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4898 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4899 NULL, NULL, NULL, NULL, NULL, NULL },
4901 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4902 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4903 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4904 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4905 uniqueMemberIndexer, uniqueMemberFilter,
4908 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4909 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4910 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4911 NULL, NULL, NULL, NULL, NULL, NULL },
4913 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4915 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4916 NULL, generalizedTimeNormalize, octetStringMatch,
4917 generalizedTimeIndexer, generalizedTimeFilter,
4920 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4922 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4923 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4925 "generalizedTimeMatch" },
4927 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4928 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4929 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4930 integerFirstComponentMatchSyntaxes,
4931 NULL, firstComponentNormalize, integerMatch,
4932 octetStringIndexer, octetStringFilter,
4935 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4936 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4937 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4938 objectIdentifierFirstComponentMatchSyntaxes,
4939 NULL, firstComponentNormalize, octetStringMatch,
4940 octetStringIndexer, octetStringFilter,
4943 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4944 "SYNTAX 1.3.6.1.1.15.1 )",
4945 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4946 NULL, certificateExactNormalize, octetStringMatch,
4947 octetStringIndexer, octetStringFilter,
4950 {"( 2.5.13.35 NAME 'certificateMatch' "
4951 "SYNTAX 1.3.6.1.1.15.2 )",
4952 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4953 NULL, NULL, NULL, NULL, NULL,
4956 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4957 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4958 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4959 NULL, IA5StringNormalize, octetStringMatch,
4960 octetStringIndexer, octetStringFilter,
4961 IA5StringApproxMatchOID },
4963 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4964 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4965 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4966 NULL, IA5StringNormalize, octetStringMatch,
4967 octetStringIndexer, octetStringFilter,
4968 IA5StringApproxMatchOID },
4970 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4971 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4972 SLAP_MR_SUBSTR, NULL,
4973 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4974 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4975 "caseIgnoreIA5Match" },
4977 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4978 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4979 SLAP_MR_SUBSTR, NULL,
4980 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4981 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4982 "caseExactIA5Match" },
4984 #ifdef SLAPD_AUTHPASSWD
4985 /* needs updating */
4986 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4987 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4988 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4989 NULL, NULL, authPasswordMatch,
4994 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4995 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4997 NULL, NULL, integerBitAndMatch,
5001 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5002 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5004 NULL, NULL, integerBitOrMatch,
5008 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5009 "SYNTAX 1.3.6.1.1.16.1 )",
5010 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5011 NULL, UUIDNormalize, octetStringMatch,
5012 octetStringIndexer, octetStringFilter,
5015 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5016 "SYNTAX 1.3.6.1.1.16.1 )",
5017 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5018 NULL, UUIDNormalize, octetStringOrderingMatch,
5019 octetStringIndexer, octetStringFilter,
5022 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5023 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5024 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5025 NULL, csnNormalize, csnMatch,
5026 csnIndexer, csnFilter,
5029 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5030 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5031 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5032 NULL, NULL, csnOrderingMatch,
5036 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5037 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5038 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5039 NULL, csnSidNormalize, octetStringMatch,
5040 octetStringIndexer, octetStringFilter,
5043 /* FIXME: OID is unused, but not registered yet */
5044 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5045 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5046 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5047 NULL, authzNormalize, authzMatch,
5051 {NULL, SLAP_MR_NONE, NULL,
5052 NULL, NULL, NULL, NULL, NULL,
5057 slap_schema_init( void )
5062 /* we should only be called once (from main) */
5063 assert( schema_init_done == 0 );
5065 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5066 res = register_syntax( &syntax_defs[i] );
5069 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5070 syntax_defs[i].sd_desc );
5075 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5076 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5077 mrule_defs[i].mrd_compat_syntaxes == NULL )
5080 "slap_schema_init: Ignoring unusable matching rule %s\n",
5081 mrule_defs[i].mrd_desc );
5085 res = register_matching_rule( &mrule_defs[i] );
5089 "slap_schema_init: Error registering matching rule %s\n",
5090 mrule_defs[i].mrd_desc );
5095 res = slap_schema_load();
5096 schema_init_done = 1;
5101 schema_destroy( void )
5110 if( schema_init_done ) {
5111 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5112 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );