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 #define INDEX_INTLEN_CHOP 7
2128 * only if too large: one's complement <sign*length of chopped bytes>,
2129 * two's complement value (sign-extended or chopped as needed),
2130 * with 1st byte of the above adjusted as follows:
2131 * inverse sign in the top <number of length-bytes + 1> bits,
2132 * then the sign bit as delimiter.
2134 ber_slen_t k = index_intlen_strlen, chop = 0;
2135 unsigned char neg = 0xff, signmask = 0x80;
2136 unsigned char lenbuf[sizeof(k) + 2], *lenp;
2138 if ( val.bv_val[0] != '-' ) {
2143 /* Chop least significant digits, increase length instead */
2144 if ( val.bv_len > k ) {
2145 chop = (val.bv_len - k + 2) / 7; /* 2 fewer digits */
2146 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2147 chop *= 3; /* >#key bytes chopped: 256**3 > 10**7 */
2148 if ( chop > 0x7fffffff ) {
2149 memset( key->bv_val, neg ^ 0xff, index_intlen );
2154 if ( lutil_str2bin( &val, &itmp, ctx )) {
2155 return LDAP_INVALID_SYNTAX;
2158 /* Omit leading sign byte */
2159 if ( itmp.bv_val[0] == neg ) {
2164 k = (ber_slen_t) index_intlen - ((ber_slen_t) itmp.bv_len + chop);
2166 assert( chop == 0 );
2167 memset( key->bv_val, neg, k ); /* sign-extend */
2168 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2169 lenp = lenbuf + sizeof(lenbuf);
2174 } while ( (k >>= 8) != 0 || (signmask >> 1) <= (*lenp ^ neg) );
2175 /* With n bytes used in lenbuf, the top n+1 bits of signmask
2176 * are 1, and the top n+2 bits of *lenp are the sign bit. */
2177 k = (lenbuf + sizeof(lenbuf)) - lenp;
2178 if ( k > index_intlen )
2180 memcpy( key->bv_val, lenp, k );
2181 itmp.bv_len = index_intlen - k;
2183 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2184 key->bv_val[0] ^= (unsigned char) -signmask & 0xff; /* invert sign */
2188 /* Index generation function */
2195 struct berval *prefix,
2205 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2207 /* count the values and find max needed length */
2209 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2210 if ( vlen < values[i].bv_len )
2211 vlen = values[i].bv_len;
2213 if ( vlen > maxstrlen )
2216 /* we should have at least one value at this point */
2219 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2220 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2221 keys[i].bv_len = index_intlen;
2222 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2225 keys[i].bv_val = NULL;
2227 if ( vlen > sizeof(ibuf) ) {
2228 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2232 itmp.bv_len = sizeof(ibuf);
2234 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2235 if ( itmp.bv_val != ibuf ) {
2236 itmp.bv_len = values[i].bv_len;
2237 if ( itmp.bv_len <= sizeof(ibuf) )
2238 itmp.bv_len = sizeof(ibuf);
2239 else if ( itmp.bv_len > maxstrlen )
2240 itmp.bv_len = maxstrlen;
2242 rc = integerVal2Key( values[i], &keys[i], itmp, ctx );
2248 if ( itmp.bv_val != ibuf ) {
2249 slap_sl_free( itmp.bv_val, ctx );
2254 /* Index generation function */
2261 struct berval *prefix,
2262 void * assertedValue,
2269 struct berval *value;
2272 value = (struct berval *) assertedValue;
2274 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2276 keys[0].bv_len = index_intlen;
2277 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2279 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2280 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2281 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2282 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2285 iv.bv_len = sizeof(ibuf);
2288 rc = integerVal2Key( *value, keys, iv, ctx );
2292 if ( iv.bv_val != ibuf ) {
2293 slap_sl_free( iv.bv_val, ctx );
2299 countryStringValidate(
2301 struct berval *val )
2303 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2305 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2306 return LDAP_INVALID_SYNTAX;
2308 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2309 return LDAP_INVALID_SYNTAX;
2312 return LDAP_SUCCESS;
2316 printableStringValidate(
2318 struct berval *val )
2322 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2324 for(i=0; i < val->bv_len; i++) {
2325 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2326 return LDAP_INVALID_SYNTAX;
2330 return LDAP_SUCCESS;
2334 printablesStringValidate(
2336 struct berval *val )
2340 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2342 for(i=0,len=0; i < val->bv_len; i++) {
2343 int c = val->bv_val[i];
2347 return LDAP_INVALID_SYNTAX;
2351 } else if ( SLAP_PRINTABLE(c) ) {
2354 return LDAP_INVALID_SYNTAX;
2359 return LDAP_INVALID_SYNTAX;
2362 return LDAP_SUCCESS;
2368 struct berval *val )
2372 for(i=0; i < val->bv_len; i++) {
2373 if( !LDAP_ASCII(val->bv_val[i]) ) {
2374 return LDAP_INVALID_SYNTAX;
2378 return LDAP_SUCCESS;
2387 struct berval *normalized,
2391 int casefold = !SLAP_MR_ASSOCIATED( mr,
2392 slap_schema.si_mr_caseExactIA5Match );
2394 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2398 /* Ignore initial whitespace */
2399 while ( ASCII_SPACE( *p ) ) p++;
2401 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2402 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2403 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2404 normalized->bv_val[normalized->bv_len] = '\0';
2406 p = q = normalized->bv_val;
2409 if ( ASCII_SPACE( *p ) ) {
2412 /* Ignore the extra whitespace */
2413 while ( ASCII_SPACE( *p ) ) {
2417 } else if ( casefold ) {
2418 /* Most IA5 rules require casefolding */
2419 *q++ = TOLOWER(*p); p++;
2426 assert( normalized->bv_val <= p );
2430 * If the string ended in space, backup the pointer one
2431 * position. One is enough because the above loop collapsed
2432 * all whitespace to a single space.
2434 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2436 /* null terminate */
2439 normalized->bv_len = q - normalized->bv_val;
2441 return LDAP_SUCCESS;
2450 if( in->bv_len != 36 ) {
2451 return LDAP_INVALID_SYNTAX;
2454 for( i=0; i<36; i++ ) {
2460 if( in->bv_val[i] != '-' ) {
2461 return LDAP_INVALID_SYNTAX;
2465 if( !ASCII_HEX( in->bv_val[i]) ) {
2466 return LDAP_INVALID_SYNTAX;
2471 return LDAP_SUCCESS;
2482 int rc=LDAP_INVALID_SYNTAX;
2484 assert( in != NULL );
2485 assert( out != NULL );
2487 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2490 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2492 for( i=0; i<36; i++ ) {
2498 if( in->bv_val[i] != '-' ) {
2501 out->bv_val[i] = '-';
2505 if( !ASCII_HEX( in->bv_val[i]) ) {
2508 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2513 out->bv_val[ out->bv_len ] = '\0';
2517 slap_sl_free( out->bv_val, ctx );
2530 struct berval *normalized,
2533 unsigned char octet = '\0';
2537 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2538 /* NOTE: must be a normalized UUID */
2539 assert( val->bv_len == 16 );
2541 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2542 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2543 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2544 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2546 return LDAP_SUCCESS;
2549 normalized->bv_len = 16;
2550 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2552 for( i=0, j=0; i<36; i++ ) {
2553 unsigned char nibble;
2554 if( val->bv_val[i] == '-' ) {
2557 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2558 nibble = val->bv_val[i] - '0';
2560 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2561 nibble = val->bv_val[i] - ('a'-10);
2563 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2564 nibble = val->bv_val[i] - ('A'-10);
2567 slap_sl_free( normalized->bv_val, ctx );
2568 return LDAP_INVALID_SYNTAX;
2573 normalized->bv_val[j>>1] = octet;
2575 octet = nibble << 4;
2580 normalized->bv_val[normalized->bv_len] = 0;
2581 return LDAP_SUCCESS;
2587 numericStringValidate(
2593 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2595 for(i=0; i < in->bv_len; i++) {
2596 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2597 return LDAP_INVALID_SYNTAX;
2601 return LDAP_SUCCESS;
2605 numericStringNormalize(
2610 struct berval *normalized,
2613 /* removal all spaces */
2616 assert( !BER_BVISEMPTY( val ) );
2618 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2621 q = normalized->bv_val;
2624 if ( ASCII_SPACE( *p ) ) {
2625 /* Ignore whitespace */
2632 /* we should have copied no more than is in val */
2633 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2635 /* null terminate */
2638 normalized->bv_len = q - normalized->bv_val;
2640 if( BER_BVISEMPTY( normalized ) ) {
2641 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2642 normalized->bv_val[0] = ' ';
2643 normalized->bv_val[1] = '\0';
2644 normalized->bv_len = 1;
2647 return LDAP_SUCCESS;
2651 * Integer conversion macros that will use the largest available
2654 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2655 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2656 # define SLAP_LONG long long
2658 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2659 # define SLAP_LONG long
2660 #endif /* HAVE_STRTOLL ... */
2668 struct berval *value,
2669 void *assertedValue )
2671 SLAP_LONG lValue, lAssertedValue;
2674 /* safe to assume integers are NUL terminated? */
2675 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2676 if( errno == ERANGE )
2678 return LDAP_CONSTRAINT_VIOLATION;
2681 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2683 if( errno == ERANGE )
2685 return LDAP_CONSTRAINT_VIOLATION;
2688 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2689 return LDAP_SUCCESS;
2698 struct berval *value,
2699 void *assertedValue )
2701 SLAP_LONG lValue, lAssertedValue;
2704 /* safe to assume integers are NUL terminated? */
2705 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2706 if( errno == ERANGE )
2708 return LDAP_CONSTRAINT_VIOLATION;
2711 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2713 if( errno == ERANGE )
2715 return LDAP_CONSTRAINT_VIOLATION;
2718 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2719 return LDAP_SUCCESS;
2723 serialNumberAndIssuerCheck(
2732 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2734 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2735 /* Parse old format */
2736 is->bv_val = ber_bvchr( in, '$' );
2737 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2739 sn->bv_val = in->bv_val;
2740 sn->bv_len = is->bv_val - in->bv_val;
2743 is->bv_len = in->bv_len - (sn->bv_len + 1);
2745 /* eat leading zeros */
2746 for( n=0; n < (sn->bv_len-1); n++ ) {
2747 if( sn->bv_val[n] != '0' ) break;
2752 for( n=0; n < sn->bv_len; n++ ) {
2753 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2757 /* Parse GSER format */
2758 int havesn=0,haveissuer=0;
2759 struct berval x = *in;
2764 /* eat leading spaces */
2765 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2769 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2770 return LDAP_INVALID_SYNTAX;
2773 /* should be at issuer or serialNumber NamedValue */
2774 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2776 x.bv_val += STRLENOF("issuer");
2777 x.bv_len -= STRLENOF("issuer");
2779 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2780 x.bv_val++; x.bv_len--;
2782 /* eat leading spaces */
2783 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2787 /* For backward compatibility, this part is optional */
2788 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2789 x.bv_val += STRLENOF("rdnSequence:");
2790 x.bv_len -= STRLENOF("rdnSequence:");
2793 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2794 x.bv_val++; x.bv_len--;
2796 is->bv_val = x.bv_val;
2799 for( ; is->bv_len < x.bv_len; ) {
2800 if ( is->bv_val[is->bv_len] != '"' ) {
2804 if ( is->bv_val[is->bv_len+1] == '"' ) {
2811 x.bv_val += is->bv_len+1;
2812 x.bv_len -= is->bv_len+1;
2814 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2815 return LDAP_INVALID_SYNTAX;
2820 } else if( strncasecmp( x.bv_val, "serialNumber",
2821 STRLENOF("serialNumber")) == 0 )
2823 /* parse serialNumber */
2825 x.bv_val += STRLENOF("serialNumber");
2826 x.bv_len -= STRLENOF("serialNumber");
2828 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2829 x.bv_val++; x.bv_len--;
2831 /* eat leading spaces */
2832 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2836 sn->bv_val = x.bv_val;
2839 if( sn->bv_val[0] == '-' ) {
2844 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2845 sn->bv_val[1] == 'X' )) {
2847 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2848 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2850 } else if ( sn->bv_val[0] == '\'' ) {
2851 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2852 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2854 if ( sn->bv_val[sn->bv_len] == '\'' &&
2855 sn->bv_val[sn->bv_len+1] == 'H' )
2858 return LDAP_INVALID_SYNTAX;
2861 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2862 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2866 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2867 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2868 return LDAP_INVALID_SYNTAX;
2871 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2873 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2874 return LDAP_INVALID_SYNTAX;
2879 } else return LDAP_INVALID_SYNTAX;
2881 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2882 x.bv_val++; x.bv_len--;
2885 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2889 /* should be at remaining NamedValue */
2890 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2891 STRLENOF("issuer" )) == 0 ))
2894 x.bv_val += STRLENOF("issuer");
2895 x.bv_len -= STRLENOF("issuer");
2897 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2898 x.bv_val++; x.bv_len--;
2900 /* eat leading spaces */
2901 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2905 /* For backward compatibility, this part is optional */
2906 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2907 x.bv_val += STRLENOF("rdnSequence:");
2908 x.bv_len -= STRLENOF("rdnSequence:");
2911 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2912 x.bv_val++; x.bv_len--;
2914 is->bv_val = x.bv_val;
2917 for( ; is->bv_len < x.bv_len; ) {
2918 if ( is->bv_val[is->bv_len] != '"' ) {
2922 if ( is->bv_val[is->bv_len+1] == '"' ) {
2929 x.bv_val += is->bv_len+1;
2930 x.bv_len -= is->bv_len+1;
2932 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2933 STRLENOF("serialNumber")) == 0 ))
2935 /* parse serialNumber */
2937 x.bv_val += STRLENOF("serialNumber");
2938 x.bv_len -= STRLENOF("serialNumber");
2940 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2941 x.bv_val++; x.bv_len--;
2943 /* eat leading spaces */
2944 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2948 sn->bv_val = x.bv_val;
2951 if( sn->bv_val[0] == '-' ) {
2956 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2957 sn->bv_val[1] == 'X' )) {
2959 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2960 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2962 } else if ( sn->bv_val[0] == '\'' ) {
2963 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2964 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2966 if ( sn->bv_val[sn->bv_len] == '\'' &&
2967 sn->bv_val[sn->bv_len+1] == 'H' )
2970 return LDAP_INVALID_SYNTAX;
2973 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2974 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2978 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2979 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2980 return LDAP_INVALID_SYNTAX;
2983 x.bv_val += sn->bv_len;
2984 x.bv_len -= sn->bv_len;
2986 } else return LDAP_INVALID_SYNTAX;
2988 /* eat trailing spaces */
2989 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2993 /* should have no characters left... */
2994 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2996 ber_dupbv_x( &ni, is, ctx );
2999 /* need to handle double dquotes here */
3005 serialNumberAndIssuerValidate(
3010 struct berval sn, i;
3012 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3015 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3019 /* validate DN -- doesn't handle double dquote */
3020 rc = dnValidate( NULL, &i );
3022 rc = LDAP_INVALID_SYNTAX;
3024 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3025 slap_sl_free( i.bv_val, NULL );
3028 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3034 serialNumberAndIssuerPretty(
3041 struct berval sn, i, ni;
3043 assert( in != NULL );
3044 assert( out != NULL );
3046 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3049 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3053 rc = dnPretty( syntax, &i, &ni, ctx );
3055 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3056 slap_sl_free( i.bv_val, ctx );
3059 if( rc ) return LDAP_INVALID_SYNTAX;
3061 /* make room from sn + "$" */
3062 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3063 + sn.bv_len + ni.bv_len;
3064 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3066 if( out->bv_val == NULL ) {
3068 slap_sl_free( ni.bv_val, ctx );
3073 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3074 STRLENOF("{ serialNumber "));
3075 n = STRLENOF("{ serialNumber ");
3077 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3080 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3081 n += STRLENOF(", issuer rdnSequence:\"");
3083 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3086 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3087 n += STRLENOF("\" }");
3089 out->bv_val[n] = '\0';
3091 assert( n == out->bv_len );
3093 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3094 out->bv_val, 0, 0 );
3096 slap_sl_free( ni.bv_val, ctx );
3098 return LDAP_SUCCESS;
3102 * This routine is called by certificateExactNormalize when
3103 * certificateExactNormalize receives a search string instead of
3104 * a certificate. This routine checks if the search value is valid
3105 * and then returns the normalized value
3108 serialNumberAndIssuerNormalize(
3116 struct berval sn, sn2, i, ni;
3117 char sbuf[64], *stmp = sbuf;
3121 assert( in != NULL );
3122 assert( out != NULL );
3124 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3127 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3131 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3133 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3134 slap_sl_free( i.bv_val, ctx );
3137 if( rc ) return LDAP_INVALID_SYNTAX;
3139 /* Convert sn to canonical hex */
3140 if ( sn.bv_len > sizeof( sbuf )) {
3141 stmp = slap_sl_malloc( sn.bv_len, ctx );
3144 sn2.bv_len = sn.bv_len;
3145 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3146 rc = LDAP_INVALID_SYNTAX;
3150 /* make room for sn + "$" */
3151 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3152 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3153 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3155 if( out->bv_val == NULL ) {
3157 slap_sl_free( ni.bv_val, ctx );
3163 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3164 STRLENOF( "{ serialNumber " ));
3165 n = STRLENOF( "{ serialNumber " );
3167 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3170 unsigned char *v = (unsigned char *)sn2.bv_val;
3171 out->bv_val[n++] = '\'';
3172 for ( j = 0; j < sn2.bv_len; j++ ) {
3173 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3177 out->bv_val[n++] = '\'';
3178 out->bv_val[n++] = 'H';
3181 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3182 n += STRLENOF( ", issuer rdnSequence:\"" );
3184 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3187 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3188 n += STRLENOF( "\" }" );
3190 out->bv_val[n] = '\0';
3192 assert( n == out->bv_len );
3194 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3195 out->bv_val, 0, 0 );
3199 slap_sl_free( stmp, ctx );
3200 slap_sl_free( ni.bv_val, ctx );
3206 certificateExactNormalize(
3211 struct berval *normalized,
3214 BerElementBuffer berbuf;
3215 BerElement *ber = (BerElement *)&berbuf;
3219 char serialbuf[64], *serial = serialbuf;
3220 ber_len_t seriallen;
3221 struct berval issuer_dn = BER_BVNULL, bvdn;
3223 int rc = LDAP_INVALID_SYNTAX;
3225 if( BER_BVISEMPTY( val ) ) goto done;
3227 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3228 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3231 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3233 ber_init2( ber, val, LBER_USE_DER );
3234 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3235 tag = ber_skip_tag( ber, &len ); /* Sequence */
3236 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3237 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3238 tag = ber_skip_tag( ber, &len );
3239 tag = ber_get_int( ber, &i ); /* version */
3242 /* NOTE: move the test here from certificateValidate,
3243 * so that we can validate certs with serial longer
3244 * than sizeof(ber_int_t) */
3245 tag = ber_peek_tag( ber, &len ); /* serial */
3247 /* Use hex format. '123456789abcdef'H
3253 tag = ber_skip_tag( ber, &len );
3254 ptr = (unsigned char *)ber->ber_ptr;
3255 ber_skip_data( ber, len );
3257 /* Check for minimal encodings */
3259 if ( ptr[0] & 0x80 ) {
3260 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3261 return LDAP_INVALID_SYNTAX;
3262 } else if ( ptr[0] == 0 ) {
3263 if (!( ptr[1] & 0x80 ))
3264 return LDAP_INVALID_SYNTAX;
3268 seriallen = len * 2 + 4; /* quotes, H, NUL */
3269 if ( seriallen > sizeof( serialbuf ))
3270 serial = slap_sl_malloc( seriallen, ctx );
3273 for ( i = 0; i<len; i++ ) {
3274 sprintf( sptr, "%02X", ptr[i] );
3281 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3282 ber_skip_data( ber, len );
3283 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3284 len = ber_ptrlen( ber );
3285 bvdn.bv_val = val->bv_val + len;
3286 bvdn.bv_len = val->bv_len - len;
3288 rc = dnX509normalize( &bvdn, &issuer_dn );
3289 if( rc != LDAP_SUCCESS ) goto done;
3291 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3292 + seriallen + issuer_dn.bv_len;
3293 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3295 p = (unsigned char *)normalized->bv_val;
3297 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3298 p += STRLENOF( "{ serialNumber " );
3300 AC_MEMCPY(p, serial, seriallen);
3303 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3304 p += STRLENOF( ", issuer rdnSequence:\"" );
3306 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3307 p += issuer_dn.bv_len;
3309 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3310 p += STRLENOF( "\" }" );
3314 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3315 normalized->bv_val, NULL, NULL );
3320 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3321 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3333 assert( in != NULL );
3334 assert( !BER_BVISNULL( in ) );
3336 for ( i = 0; i < in->bv_len; i++ ) {
3337 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3338 return LDAP_INVALID_SYNTAX;
3342 return LDAP_SUCCESS;
3345 /* Normalize a SID as used inside a CSN:
3346 * three-digit numeric string */
3353 struct berval *normalized,
3358 assert( val != NULL );
3359 assert( normalized != NULL );
3361 ber_dupbv_x( normalized, val, ctx );
3363 for ( i = 0; i < normalized->bv_len; i++ ) {
3364 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3365 ber_memfree_x( normalized->bv_val, ctx );
3366 BER_BVZERO( normalized );
3367 return LDAP_INVALID_SYNTAX;
3370 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3373 return LDAP_SUCCESS;
3381 assert( in != NULL );
3382 assert( !BER_BVISNULL( in ) );
3384 if ( in->bv_len != 3 ) {
3385 return LDAP_INVALID_SYNTAX;
3388 return hexValidate( NULL, in );
3391 /* Normalize a SID as used inside a CSN:
3392 * three-digit numeric string */
3399 struct berval *normalized,
3402 if ( val->bv_len != 3 ) {
3403 return LDAP_INVALID_SYNTAX;
3406 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3416 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3419 /* Normalize a SID as used inside a CSN, either as-is
3420 * (assertion value) or extracted from the CSN
3421 * (attribute value) */
3428 struct berval *normalized,
3436 if ( BER_BVISEMPTY( val ) ) {
3437 return LDAP_INVALID_SYNTAX;
3440 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3441 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3444 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3446 ptr = ber_bvchr( val, '#' );
3447 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3448 return LDAP_INVALID_SYNTAX;
3451 bv.bv_val = ptr + 1;
3452 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3454 ptr = ber_bvchr( &bv, '#' );
3455 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3456 return LDAP_INVALID_SYNTAX;
3459 bv.bv_val = ptr + 1;
3460 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3462 ptr = ber_bvchr( &bv, '#' );
3463 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3464 return LDAP_INVALID_SYNTAX;
3467 bv.bv_len = ptr - bv.bv_val;
3469 if ( bv.bv_len == 2 ) {
3470 /* OpenLDAP 2.3 SID */
3472 buf[ 1 ] = bv.bv_val[ 0 ];
3473 buf[ 2 ] = bv.bv_val[ 1 ];
3480 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3492 assert( in != NULL );
3493 assert( !BER_BVISNULL( in ) );
3495 if ( BER_BVISEMPTY( in ) ) {
3496 return LDAP_INVALID_SYNTAX;
3501 ptr = ber_bvchr( &bv, '#' );
3502 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3503 return LDAP_INVALID_SYNTAX;
3506 bv.bv_len = ptr - bv.bv_val;
3507 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3508 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3510 return LDAP_INVALID_SYNTAX;
3513 rc = generalizedTimeValidate( NULL, &bv );
3514 if ( rc != LDAP_SUCCESS ) {
3518 bv.bv_val = ptr + 1;
3519 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3521 ptr = ber_bvchr( &bv, '#' );
3522 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3523 return LDAP_INVALID_SYNTAX;
3526 bv.bv_len = ptr - bv.bv_val;
3527 if ( bv.bv_len != 6 ) {
3528 return LDAP_INVALID_SYNTAX;
3531 rc = hexValidate( NULL, &bv );
3532 if ( rc != LDAP_SUCCESS ) {
3536 bv.bv_val = ptr + 1;
3537 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3539 ptr = ber_bvchr( &bv, '#' );
3540 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3541 return LDAP_INVALID_SYNTAX;
3544 bv.bv_len = ptr - bv.bv_val;
3545 if ( bv.bv_len == 2 ) {
3546 /* tolerate old 2-digit replica-id */
3547 rc = hexValidate( NULL, &bv );
3550 rc = sidValidate( NULL, &bv );
3552 if ( rc != LDAP_SUCCESS ) {
3556 bv.bv_val = ptr + 1;
3557 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3559 if ( bv.bv_len != 6 ) {
3560 return LDAP_INVALID_SYNTAX;
3563 return hexValidate( NULL, &bv );
3566 /* Normalize a CSN in OpenLDAP 2.3 format */
3573 struct berval *normalized,
3576 struct berval gt, cnt, sid, mod;
3580 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3581 assert( !BER_BVISEMPTY( val ) );
3585 ptr = ber_bvchr( >, '#' );
3586 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3587 return LDAP_INVALID_SYNTAX;
3590 gt.bv_len = ptr - gt.bv_val;
3591 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3593 cnt.bv_val = ptr + 1;
3594 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3596 ptr = ber_bvchr( &cnt, '#' );
3597 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3598 return LDAP_INVALID_SYNTAX;
3601 cnt.bv_len = ptr - cnt.bv_val;
3602 assert( cnt.bv_len == STRLENOF( "000000" ) );
3604 sid.bv_val = ptr + 1;
3605 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3607 ptr = ber_bvchr( &sid, '#' );
3608 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3609 return LDAP_INVALID_SYNTAX;
3612 sid.bv_len = ptr - sid.bv_val;
3613 assert( sid.bv_len == STRLENOF( "00" ) );
3615 mod.bv_val = ptr + 1;
3616 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3617 assert( mod.bv_len == STRLENOF( "000000" ) );
3619 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3620 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3622 ptr = normalized->bv_val;
3623 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3624 ptr = lutil_strcopy( ptr, ".000000Z#" );
3625 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3628 for ( i = 0; i < sid.bv_len; i++ ) {
3629 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3632 for ( i = 0; i < mod.bv_len; i++ ) {
3633 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3637 assert( ptr - normalized->bv_val == normalized->bv_len );
3639 return LDAP_SUCCESS;
3642 /* Normalize a CSN */
3649 struct berval *normalized,
3652 struct berval cnt, sid, mod;
3656 assert( val != NULL );
3657 assert( normalized != NULL );
3659 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3661 if ( BER_BVISEMPTY( val ) ) {
3662 return LDAP_INVALID_SYNTAX;
3665 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3666 /* Openldap <= 2.3 */
3668 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3671 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3673 ptr = ber_bvchr( val, '#' );
3674 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3675 return LDAP_INVALID_SYNTAX;
3678 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3680 cnt.bv_val = ptr + 1;
3681 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3683 ptr = ber_bvchr( &cnt, '#' );
3684 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3685 return LDAP_INVALID_SYNTAX;
3688 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3690 sid.bv_val = ptr + 1;
3691 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3693 ptr = ber_bvchr( &sid, '#' );
3694 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3695 return LDAP_INVALID_SYNTAX;
3698 sid.bv_len = ptr - sid.bv_val;
3699 assert( sid.bv_len == STRLENOF( "000" ) );
3701 mod.bv_val = ptr + 1;
3702 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3704 assert( mod.bv_len == STRLENOF( "000000" ) );
3706 ber_dupbv_x( normalized, val, ctx );
3708 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3709 i < normalized->bv_len; i++ )
3711 /* assume it's already validated that's all hex digits */
3712 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3715 return LDAP_SUCCESS;
3725 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3728 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3729 /* slight optimization - does not need the start parameter */
3730 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3735 check_time_syntax (struct berval *val,
3738 struct berval *fraction)
3741 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3742 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3743 * GeneralizedTime supports leap seconds, UTCTime does not.
3745 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3746 static const int mdays[2][12] = {
3747 /* non-leap years */
3748 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3750 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3753 int part, c, c1, c2, tzoffset, leapyear = 0;
3756 e = p + val->bv_len;
3758 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3759 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3761 for (part = start; part < 7 && p < e; part++) {
3763 if (!ASCII_DIGIT(c1)) {
3768 return LDAP_INVALID_SYNTAX;
3771 if (!ASCII_DIGIT(c)) {
3772 return LDAP_INVALID_SYNTAX;
3774 c += c1 * 10 - '0' * 11;
3775 if ((part | 1) == 3) {
3778 return LDAP_INVALID_SYNTAX;
3781 if (c >= ceiling[part]) {
3782 if (! (c == 60 && part == 6 && start == 0))
3783 return LDAP_INVALID_SYNTAX;
3787 if (part < 5 + start) {
3788 return LDAP_INVALID_SYNTAX;
3790 for (; part < 9; part++) {
3794 /* leapyear check for the Gregorian calendar (year>1581) */
3795 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3799 if (parts[3] >= mdays[leapyear][parts[2]]) {
3800 return LDAP_INVALID_SYNTAX;
3804 fraction->bv_val = p;
3805 fraction->bv_len = 0;
3806 if (p < e && (*p == '.' || *p == ',')) {
3808 while (++p < e && ASCII_DIGIT(*p)) {
3811 if (p - fraction->bv_val == 1) {
3812 return LDAP_INVALID_SYNTAX;
3814 for (end_num = p; end_num[-1] == '0'; --end_num) {
3817 c = end_num - fraction->bv_val;
3818 if (c != 1) fraction->bv_len = c;
3824 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3830 return LDAP_INVALID_SYNTAX;
3836 for (part = 7; part < 9 && p < e; part++) {
3838 if (!ASCII_DIGIT(c1)) {
3843 return LDAP_INVALID_SYNTAX;
3846 if (!ASCII_DIGIT(c2)) {
3847 return LDAP_INVALID_SYNTAX;
3849 parts[part] = c1 * 10 + c2 - '0' * 11;
3850 if (parts[part] >= ceiling[part]) {
3851 return LDAP_INVALID_SYNTAX;
3854 if (part < 8 + start) {
3855 return LDAP_INVALID_SYNTAX;
3858 if (tzoffset == '-') {
3859 /* negative offset to UTC, ie west of Greenwich */
3860 parts[4] += parts[7];
3861 parts[5] += parts[8];
3862 /* offset is just hhmm, no seconds */
3863 for (part = 6; --part >= 0; ) {
3867 c = mdays[leapyear][parts[2]];
3869 if (parts[part] >= c) {
3871 return LDAP_INVALID_SYNTAX;
3876 } else if (part != 5) {
3881 /* positive offset to UTC, ie east of Greenwich */
3882 parts[4] -= parts[7];
3883 parts[5] -= parts[8];
3884 for (part = 6; --part >= 0; ) {
3885 if (parts[part] < 0) {
3887 return LDAP_INVALID_SYNTAX;
3892 /* make first arg to % non-negative */
3893 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3898 } else if (part != 5) {
3905 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3908 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3915 struct berval *normalized )
3919 rc = check_time_syntax(val, 1, parts, NULL);
3920 if (rc != LDAP_SUCCESS) {
3924 normalized->bv_val = ch_malloc( 14 );
3925 if ( normalized->bv_val == NULL ) {
3926 return LBER_ERROR_MEMORY;
3929 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3930 parts[1], parts[2] + 1, parts[3] + 1,
3931 parts[4], parts[5], parts[6] );
3932 normalized->bv_len = 13;
3934 return LDAP_SUCCESS;
3944 return check_time_syntax(in, 1, parts, NULL);
3947 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3950 generalizedTimeValidate(
3955 struct berval fraction;
3956 return check_time_syntax(in, 0, parts, &fraction);
3960 generalizedTimeNormalize(
3965 struct berval *normalized,
3970 struct berval fraction;
3972 rc = check_time_syntax(val, 0, parts, &fraction);
3973 if (rc != LDAP_SUCCESS) {
3977 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3978 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3979 if ( BER_BVISNULL( normalized ) ) {
3980 return LBER_ERROR_MEMORY;
3983 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3984 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3985 parts[4], parts[5], parts[6] );
3986 if ( !BER_BVISEMPTY( &fraction ) ) {
3987 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3988 fraction.bv_val, fraction.bv_len );
3989 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3991 strcpy( normalized->bv_val + len-1, "Z" );
3992 normalized->bv_len = len;
3994 return LDAP_SUCCESS;
3998 generalizedTimeOrderingMatch(
4003 struct berval *value,
4004 void *assertedValue )
4006 struct berval *asserted = (struct berval *) assertedValue;
4007 ber_len_t v_len = value->bv_len;
4008 ber_len_t av_len = asserted->bv_len;
4010 /* ignore trailing 'Z' when comparing */
4011 int match = memcmp( value->bv_val, asserted->bv_val,
4012 (v_len < av_len ? v_len : av_len) - 1 );
4013 if ( match == 0 ) match = v_len - av_len;
4016 return LDAP_SUCCESS;
4019 /* Index generation function */
4020 int generalizedTimeIndexer(
4025 struct berval *prefix,
4033 BerValue bvtmp; /* 40 bit index */
4035 struct lutil_timet tt;
4037 bvtmp.bv_len = sizeof(tmp);
4039 for( i=0; values[i].bv_val != NULL; i++ ) {
4040 /* just count them */
4043 /* we should have at least one value at this point */
4046 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4048 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4049 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4050 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4051 /* Use 40 bits of time for key */
4052 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4053 lutil_tm2time( &tm, &tt );
4054 tmp[0] = tt.tt_gsec & 0xff;
4055 tmp[4] = tt.tt_sec & 0xff;
4057 tmp[3] = tt.tt_sec & 0xff;
4059 tmp[2] = tt.tt_sec & 0xff;
4061 tmp[1] = tt.tt_sec & 0xff;
4063 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4067 keys[j].bv_val = NULL;
4072 return LDAP_SUCCESS;
4075 /* Index generation function */
4076 int generalizedTimeFilter(
4081 struct berval *prefix,
4082 void * assertedValue,
4088 BerValue bvtmp; /* 40 bit index */
4089 BerValue *value = (BerValue *) assertedValue;
4091 struct lutil_timet tt;
4093 bvtmp.bv_len = sizeof(tmp);
4095 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4096 /* Use 40 bits of time for key */
4097 if ( value->bv_val && value->bv_len >= 10 &&
4098 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4100 lutil_tm2time( &tm, &tt );
4101 tmp[0] = tt.tt_gsec & 0xff;
4102 tmp[4] = tt.tt_sec & 0xff;
4104 tmp[3] = tt.tt_sec & 0xff;
4106 tmp[2] = tt.tt_sec & 0xff;
4108 tmp[1] = tt.tt_sec & 0xff;
4110 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4111 ber_dupbv_x(keys, &bvtmp, ctx );
4112 keys[1].bv_val = NULL;
4120 return LDAP_SUCCESS;
4124 deliveryMethodValidate(
4126 struct berval *val )
4129 #define LENOF(s) (sizeof(s)-1)
4130 struct berval tmp = *val;
4132 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4133 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4134 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4137 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4139 switch( tmp.bv_val[0] ) {
4142 if(( tmp.bv_len >= LENOF("any") ) &&
4143 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4145 tmp.bv_len -= LENOF("any");
4146 tmp.bv_val += LENOF("any");
4149 return LDAP_INVALID_SYNTAX;
4153 if(( tmp.bv_len >= LENOF("mhs") ) &&
4154 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4156 tmp.bv_len -= LENOF("mhs");
4157 tmp.bv_val += LENOF("mhs");
4160 return LDAP_INVALID_SYNTAX;
4164 if(( tmp.bv_len >= LENOF("physical") ) &&
4165 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4167 tmp.bv_len -= LENOF("physical");
4168 tmp.bv_val += LENOF("physical");
4171 return LDAP_INVALID_SYNTAX;
4174 case 'T': /* telex or teletex or telephone */
4175 if(( tmp.bv_len >= LENOF("telex") ) &&
4176 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4178 tmp.bv_len -= LENOF("telex");
4179 tmp.bv_val += LENOF("telex");
4182 if(( tmp.bv_len >= LENOF("teletex") ) &&
4183 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4185 tmp.bv_len -= LENOF("teletex");
4186 tmp.bv_val += LENOF("teletex");
4189 if(( tmp.bv_len >= LENOF("telephone") ) &&
4190 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4192 tmp.bv_len -= LENOF("telephone");
4193 tmp.bv_val += LENOF("telephone");
4196 return LDAP_INVALID_SYNTAX;
4199 case 'G': /* g3fax or g4fax */
4200 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4201 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4202 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4204 tmp.bv_len -= LENOF("g3fax");
4205 tmp.bv_val += LENOF("g3fax");
4208 return LDAP_INVALID_SYNTAX;
4212 if(( tmp.bv_len >= LENOF("ia5") ) &&
4213 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4215 tmp.bv_len -= LENOF("ia5");
4216 tmp.bv_val += LENOF("ia5");
4219 return LDAP_INVALID_SYNTAX;
4223 if(( tmp.bv_len >= LENOF("videotex") ) &&
4224 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4226 tmp.bv_len -= LENOF("videotex");
4227 tmp.bv_val += LENOF("videotex");
4230 return LDAP_INVALID_SYNTAX;
4233 return LDAP_INVALID_SYNTAX;
4236 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4238 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4242 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4246 return LDAP_INVALID_SYNTAX;
4248 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4257 nisNetgroupTripleValidate(
4259 struct berval *val )
4264 if ( BER_BVISEMPTY( val ) ) {
4265 return LDAP_INVALID_SYNTAX;
4268 p = (char *)val->bv_val;
4269 e = p + val->bv_len;
4271 if ( *p != '(' /*')'*/ ) {
4272 return LDAP_INVALID_SYNTAX;
4275 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4279 return LDAP_INVALID_SYNTAX;
4282 } else if ( !AD_CHAR( *p ) ) {
4283 return LDAP_INVALID_SYNTAX;
4287 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4288 return LDAP_INVALID_SYNTAX;
4294 return LDAP_INVALID_SYNTAX;
4297 return LDAP_SUCCESS;
4301 bootParameterValidate(
4303 struct berval *val )
4307 if ( BER_BVISEMPTY( val ) ) {
4308 return LDAP_INVALID_SYNTAX;
4311 p = (char *)val->bv_val;
4312 e = p + val->bv_len;
4315 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4316 if ( !AD_CHAR( *p ) ) {
4317 return LDAP_INVALID_SYNTAX;
4322 return LDAP_INVALID_SYNTAX;
4326 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4327 if ( !AD_CHAR( *p ) ) {
4328 return LDAP_INVALID_SYNTAX;
4333 return LDAP_INVALID_SYNTAX;
4337 for ( p++; p < e; p++ ) {
4338 if ( !SLAP_PRINTABLE( *p ) ) {
4339 return LDAP_INVALID_SYNTAX;
4343 return LDAP_SUCCESS;
4347 firstComponentNormalize(
4352 struct berval *normalized,
4359 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4360 ber_dupbv_x( normalized, val, ctx );
4361 return LDAP_SUCCESS;
4364 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4366 if( val->bv_val[0] != '(' /*')'*/ &&
4367 val->bv_val[0] != '{' /*'}'*/ )
4369 return LDAP_INVALID_SYNTAX;
4372 /* trim leading white space */
4374 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4380 /* grab next word */
4381 comp.bv_val = &val->bv_val[len];
4382 len = val->bv_len - len;
4383 for( comp.bv_len = 0;
4384 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4390 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4391 rc = numericoidValidate( NULL, &comp );
4392 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4393 rc = integerValidate( NULL, &comp );
4395 rc = LDAP_INVALID_SYNTAX;
4399 if( rc == LDAP_SUCCESS ) {
4400 ber_dupbv_x( normalized, &comp, ctx );
4406 static char *country_gen_syn[] = {
4407 "1.3.6.1.4.1.1466.115.121.1.15",
4408 "1.3.6.1.4.1.1466.115.121.1.26",
4409 "1.3.6.1.4.1.1466.115.121.1.44",
4413 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4414 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4416 static slap_syntax_defs_rec syntax_defs[] = {
4417 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4418 X_BINARY X_NOT_H_R ")",
4419 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4420 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4421 0, NULL, NULL, NULL},
4422 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4423 0, NULL, NULL, NULL},
4424 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4426 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4427 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4429 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4430 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4431 0, NULL, bitStringValidate, NULL },
4432 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4433 0, NULL, booleanValidate, NULL},
4434 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4435 X_BINARY X_NOT_H_R ")",
4436 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4437 NULL, certificateValidate, NULL},
4438 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4439 X_BINARY X_NOT_H_R ")",
4440 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4441 NULL, certificateListValidate, NULL},
4442 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4443 X_BINARY X_NOT_H_R ")",
4444 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4445 NULL, sequenceValidate, NULL},
4446 #if 0 /* need to go __after__ printableString */
4447 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4448 0, "1.3.6.1.4.1.1466.115.121.1.44",
4449 countryStringValidate, NULL},
4451 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4452 0, NULL, dnValidate, dnPretty},
4453 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4454 0, NULL, rdnValidate, rdnPretty},
4455 #ifdef LDAP_COMP_MATCH
4456 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4457 0, NULL, allComponentsValidate, NULL},
4458 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4459 0, NULL, componentFilterValidate, NULL},
4461 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4462 0, NULL, NULL, NULL},
4463 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4464 0, NULL, deliveryMethodValidate, NULL},
4465 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4466 0, NULL, UTF8StringValidate, NULL},
4467 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4468 0, NULL, NULL, NULL},
4469 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4470 0, NULL, NULL, NULL},
4471 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4472 0, NULL, NULL, NULL},
4473 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4474 0, NULL, NULL, NULL},
4475 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4476 0, NULL, NULL, NULL},
4477 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4478 0, NULL, printablesStringValidate, NULL},
4479 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4480 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4481 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4482 0, NULL, generalizedTimeValidate, NULL},
4483 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4484 0, NULL, NULL, NULL},
4485 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4486 0, NULL, IA5StringValidate, NULL},
4487 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4488 0, NULL, integerValidate, NULL},
4489 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4490 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4491 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4492 0, NULL, NULL, NULL},
4493 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4494 0, NULL, NULL, NULL},
4495 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4496 0, NULL, NULL, NULL},
4497 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4498 0, NULL, NULL, NULL},
4499 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4500 0, NULL, NULL, NULL},
4501 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4502 0, NULL, nameUIDValidate, nameUIDPretty },
4503 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4504 0, NULL, NULL, NULL},
4505 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4506 0, NULL, numericStringValidate, NULL},
4507 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4508 0, NULL, NULL, NULL},
4509 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4510 0, NULL, numericoidValidate, NULL},
4511 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4512 0, NULL, IA5StringValidate, NULL},
4513 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4514 0, NULL, blobValidate, NULL},
4515 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4516 0, NULL, UTF8StringValidate, NULL},
4517 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4518 0, NULL, NULL, NULL},
4519 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4520 0, NULL, NULL, NULL},
4521 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4522 0, NULL, printableStringValidate, NULL},
4523 /* moved here because now depends on Directory String, IA5 String
4524 * and Printable String */
4525 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4526 0, country_gen_syn, countryStringValidate, NULL},
4527 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4528 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4529 0, NULL, subtreeSpecificationValidate, NULL},
4530 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4531 X_BINARY X_NOT_H_R ")",
4532 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4533 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4534 0, NULL, printableStringValidate, NULL},
4535 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4536 0, NULL, NULL, NULL},
4537 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4538 0, NULL, printablesStringValidate, NULL},
4539 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4540 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4541 0, NULL, utcTimeValidate, NULL},
4543 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4544 0, NULL, NULL, NULL},
4545 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4546 0, NULL, NULL, NULL},
4547 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4548 0, NULL, NULL, NULL},
4549 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4550 0, NULL, NULL, NULL},
4551 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4552 0, NULL, NULL, NULL},
4554 /* RFC 2307 NIS Syntaxes */
4555 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4556 0, NULL, nisNetgroupTripleValidate, NULL},
4557 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4558 0, NULL, bootParameterValidate, NULL},
4560 /* draft-zeilenga-ldap-x509 */
4561 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4562 SLAP_SYNTAX_HIDE, NULL,
4563 serialNumberAndIssuerValidate,
4564 serialNumberAndIssuerPretty},
4565 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4566 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4567 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4568 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4569 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4570 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4571 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4572 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4573 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4574 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4575 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4576 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4578 #ifdef SLAPD_AUTHPASSWD
4579 /* needs updating */
4580 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4581 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4584 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4585 0, NULL, UUIDValidate, UUIDPretty},
4587 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4588 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4590 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4591 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4593 /* OpenLDAP Void Syntax */
4594 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4595 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4597 /* FIXME: OID is unused, but not registered yet */
4598 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4599 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4601 {NULL, 0, NULL, NULL, NULL}
4604 char *csnSIDMatchSyntaxes[] = {
4605 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4608 char *certificateExactMatchSyntaxes[] = {
4609 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4612 #ifdef LDAP_COMP_MATCH
4613 char *componentFilterMatchSyntaxes[] = {
4614 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4618 char *directoryStringSyntaxes[] = {
4619 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4622 char *integerFirstComponentMatchSyntaxes[] = {
4623 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4624 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4627 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4628 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4629 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4630 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4631 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4632 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4633 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4634 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4635 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4640 * Other matching rules in X.520 that we do not use (yet):
4642 * 2.5.13.25 uTCTimeMatch
4643 * 2.5.13.26 uTCTimeOrderingMatch
4644 * 2.5.13.31* directoryStringFirstComponentMatch
4645 * 2.5.13.32* wordMatch
4646 * 2.5.13.33* keywordMatch
4647 * 2.5.13.36+ certificatePairExactMatch
4648 * 2.5.13.37+ certificatePairMatch
4649 * 2.5.13.38+ certificateListExactMatch
4650 * 2.5.13.39+ certificateListMatch
4651 * 2.5.13.40+ algorithmIdentifierMatch
4652 * 2.5.13.41* storedPrefixMatch
4653 * 2.5.13.42 attributeCertificateMatch
4654 * 2.5.13.43 readerAndKeyIDMatch
4655 * 2.5.13.44 attributeIntegrityMatch
4657 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4658 * (+) described in draft-zeilenga-ldap-x509
4660 static slap_mrule_defs_rec mrule_defs[] = {
4662 * EQUALITY matching rules must be listed after associated APPROX
4663 * matching rules. So, we list all APPROX matching rules first.
4665 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4666 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4667 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4668 NULL, NULL, directoryStringApproxMatch,
4669 directoryStringApproxIndexer, directoryStringApproxFilter,
4672 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4673 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4674 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4675 NULL, NULL, IA5StringApproxMatch,
4676 IA5StringApproxIndexer, IA5StringApproxFilter,
4680 * Other matching rules
4683 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4684 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4685 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4686 NULL, NULL, octetStringMatch,
4687 octetStringIndexer, octetStringFilter,
4690 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4691 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4692 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4693 NULL, dnNormalize, dnMatch,
4694 octetStringIndexer, octetStringFilter,
4697 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4698 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4699 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4700 NULL, dnNormalize, dnRelativeMatch,
4704 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4705 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4706 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4707 NULL, dnNormalize, dnRelativeMatch,
4711 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4712 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4713 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4714 NULL, dnNormalize, dnRelativeMatch,
4718 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4719 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4720 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4721 NULL, dnNormalize, dnRelativeMatch,
4725 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4726 "SYNTAX 1.2.36.79672281.1.5.0 )",
4727 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4728 NULL, rdnNormalize, rdnMatch,
4729 octetStringIndexer, octetStringFilter,
4732 #ifdef LDAP_COMP_MATCH
4733 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4734 "SYNTAX 1.2.36.79672281.1.5.2 )",
4735 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4736 NULL, NULL , componentFilterMatch,
4737 octetStringIndexer, octetStringFilter,
4740 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4741 "SYNTAX 1.2.36.79672281.1.5.3 )",
4742 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4743 NULL, NULL , allComponentsMatch,
4744 octetStringIndexer, octetStringFilter,
4747 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4748 "SYNTAX 1.2.36.79672281.1.5.3 )",
4749 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4750 NULL, NULL , directoryComponentsMatch,
4751 octetStringIndexer, octetStringFilter,
4755 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4756 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4757 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4758 NULL, UTF8StringNormalize, octetStringMatch,
4759 octetStringIndexer, octetStringFilter,
4760 directoryStringApproxMatchOID },
4762 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4763 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4764 SLAP_MR_ORDERING, directoryStringSyntaxes,
4765 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4767 "caseIgnoreMatch" },
4769 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4770 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4771 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4772 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4773 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4774 "caseIgnoreMatch" },
4776 {"( 2.5.13.5 NAME 'caseExactMatch' "
4777 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4778 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4779 NULL, UTF8StringNormalize, octetStringMatch,
4780 octetStringIndexer, octetStringFilter,
4781 directoryStringApproxMatchOID },
4783 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4784 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4785 SLAP_MR_ORDERING, directoryStringSyntaxes,
4786 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4790 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4791 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4792 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4793 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4794 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4797 {"( 2.5.13.8 NAME 'numericStringMatch' "
4798 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4799 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4800 NULL, numericStringNormalize, octetStringMatch,
4801 octetStringIndexer, octetStringFilter,
4804 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4805 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4806 SLAP_MR_ORDERING, NULL,
4807 NULL, numericStringNormalize, octetStringOrderingMatch,
4809 "numericStringMatch" },
4811 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4812 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4813 SLAP_MR_SUBSTR, NULL,
4814 NULL, numericStringNormalize, octetStringSubstringsMatch,
4815 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4816 "numericStringMatch" },
4818 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4819 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4820 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4821 NULL, NULL, NULL, NULL, NULL, NULL },
4823 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4824 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4825 SLAP_MR_SUBSTR, NULL,
4826 NULL, NULL, NULL, NULL, NULL,
4827 "caseIgnoreListMatch" },
4829 {"( 2.5.13.13 NAME 'booleanMatch' "
4830 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4831 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4832 NULL, NULL, booleanMatch,
4833 octetStringIndexer, octetStringFilter,
4836 {"( 2.5.13.14 NAME 'integerMatch' "
4837 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4838 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4839 NULL, NULL, integerMatch,
4840 integerIndexer, integerFilter,
4843 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4844 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4845 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4846 NULL, NULL, integerMatch,
4850 {"( 2.5.13.16 NAME 'bitStringMatch' "
4851 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4852 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4853 NULL, NULL, octetStringMatch,
4854 octetStringIndexer, octetStringFilter,
4857 {"( 2.5.13.17 NAME 'octetStringMatch' "
4858 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4859 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4860 NULL, NULL, octetStringMatch,
4861 octetStringIndexer, octetStringFilter,
4864 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4865 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4866 SLAP_MR_ORDERING, NULL,
4867 NULL, NULL, octetStringOrderingMatch,
4869 "octetStringMatch" },
4871 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4872 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4873 SLAP_MR_SUBSTR, NULL,
4874 NULL, NULL, octetStringSubstringsMatch,
4875 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4876 "octetStringMatch" },
4878 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4879 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4880 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4882 telephoneNumberNormalize, octetStringMatch,
4883 octetStringIndexer, octetStringFilter,
4886 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4887 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4888 SLAP_MR_SUBSTR, NULL,
4889 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4890 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4891 "telephoneNumberMatch" },
4893 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4894 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4895 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4896 NULL, NULL, NULL, NULL, NULL, NULL },
4898 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4899 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4900 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4901 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4902 uniqueMemberIndexer, uniqueMemberFilter,
4905 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4906 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4907 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4908 NULL, NULL, NULL, NULL, NULL, NULL },
4910 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4911 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4912 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4913 NULL, generalizedTimeNormalize, octetStringMatch,
4914 generalizedTimeIndexer, generalizedTimeFilter,
4917 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4919 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4920 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4922 "generalizedTimeMatch" },
4924 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4926 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4927 integerFirstComponentMatchSyntaxes,
4928 NULL, firstComponentNormalize, integerMatch,
4929 octetStringIndexer, octetStringFilter,
4932 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4933 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4934 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4935 objectIdentifierFirstComponentMatchSyntaxes,
4936 NULL, firstComponentNormalize, octetStringMatch,
4937 octetStringIndexer, octetStringFilter,
4940 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4941 "SYNTAX 1.3.6.1.1.15.1 )",
4942 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4943 NULL, certificateExactNormalize, octetStringMatch,
4944 octetStringIndexer, octetStringFilter,
4947 {"( 2.5.13.35 NAME 'certificateMatch' "
4948 "SYNTAX 1.3.6.1.1.15.2 )",
4949 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4950 NULL, NULL, NULL, NULL, NULL,
4953 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4954 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4955 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4956 NULL, IA5StringNormalize, octetStringMatch,
4957 octetStringIndexer, octetStringFilter,
4958 IA5StringApproxMatchOID },
4960 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4962 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4963 NULL, IA5StringNormalize, octetStringMatch,
4964 octetStringIndexer, octetStringFilter,
4965 IA5StringApproxMatchOID },
4967 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4968 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4969 SLAP_MR_SUBSTR, NULL,
4970 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4971 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4972 "caseIgnoreIA5Match" },
4974 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4975 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4976 SLAP_MR_SUBSTR, NULL,
4977 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4978 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4979 "caseExactIA5Match" },
4981 #ifdef SLAPD_AUTHPASSWD
4982 /* needs updating */
4983 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4984 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4985 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4986 NULL, NULL, authPasswordMatch,
4991 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4992 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4994 NULL, NULL, integerBitAndMatch,
4998 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4999 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5001 NULL, NULL, integerBitOrMatch,
5005 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5006 "SYNTAX 1.3.6.1.1.16.1 )",
5007 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5008 NULL, UUIDNormalize, octetStringMatch,
5009 octetStringIndexer, octetStringFilter,
5012 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5013 "SYNTAX 1.3.6.1.1.16.1 )",
5014 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5015 NULL, UUIDNormalize, octetStringOrderingMatch,
5016 octetStringIndexer, octetStringFilter,
5019 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5020 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5021 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5022 NULL, csnNormalize, csnMatch,
5023 csnIndexer, csnFilter,
5026 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5027 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5028 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5029 NULL, NULL, csnOrderingMatch,
5033 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5034 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5035 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5036 NULL, csnSidNormalize, octetStringMatch,
5037 octetStringIndexer, octetStringFilter,
5040 /* FIXME: OID is unused, but not registered yet */
5041 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5042 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5043 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5044 NULL, authzNormalize, authzMatch,
5048 {NULL, SLAP_MR_NONE, NULL,
5049 NULL, NULL, NULL, NULL, NULL,
5054 slap_schema_init( void )
5059 /* we should only be called once (from main) */
5060 assert( schema_init_done == 0 );
5062 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5063 res = register_syntax( &syntax_defs[i] );
5066 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5067 syntax_defs[i].sd_desc );
5072 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5073 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5074 mrule_defs[i].mrd_compat_syntaxes == NULL )
5077 "slap_schema_init: Ignoring unusable matching rule %s\n",
5078 mrule_defs[i].mrd_desc );
5082 res = register_matching_rule( &mrule_defs[i] );
5086 "slap_schema_init: Error registering matching rule %s\n",
5087 mrule_defs[i].mrd_desc );
5092 res = slap_schema_load();
5093 schema_init_done = 1;
5098 schema_destroy( void )
5107 if( schema_init_done ) {
5108 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5109 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );