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;
2125 * only if too large: one's complement <sign*length of chopped bytes>,
2126 * two's complement value (sign-extended or chopped as needed),
2127 * with 1st byte of the above adjusted as follows:
2128 * inverse sign in the top <number of length-bytes + 1> bits,
2129 * then the sign bit as delimiter.
2131 ber_slen_t k = index_intlen_strlen, chop = 0;
2132 unsigned char neg = 0xff, signmask = 0x80;
2133 unsigned char lenbuf[sizeof(k) + 2], *lenp;
2135 if ( val.bv_val[0] != '-' ) {
2140 /* Chop least significant digits, increase length instead */
2141 if ( val.bv_len > k ) {
2142 chop = (val.bv_len - k + 2) / 7; /* 2 fewer digits */
2143 val.bv_len -= chop * 7; /* #digits chopped */
2144 chop *= 3; /* >#key bytes chopped: 256**3 > 10**7 */
2145 if ( chop > 0x7fffffff ) {
2146 memset( key->bv_val, neg ^ 0xff, index_intlen );
2151 if ( lutil_str2bin( &val, &itmp )) {
2152 return LDAP_INVALID_SYNTAX;
2155 /* Omit leading sign byte */
2156 if ( itmp.bv_val[0] == neg ) {
2161 k = (ber_slen_t) index_intlen - ((ber_slen_t) itmp.bv_len + chop);
2163 assert( chop == 0 );
2164 memset( key->bv_val, neg, k ); /* sign-extend */
2165 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2166 lenp = lenbuf + sizeof(lenbuf);
2171 } while ( (k >>= 8) != 0 || (signmask >> 1) <= (*lenp ^ neg) );
2172 /* With n bytes used in lenbuf, the top n+1 bits of signmask
2173 * are 1, and the top n+2 bits of *lenp are the sign bit. */
2174 k = (lenbuf + sizeof(lenbuf)) - lenp;
2175 if ( k > index_intlen )
2177 memcpy( key->bv_val, lenp, k );
2178 itmp.bv_len = index_intlen - k;
2180 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2181 key->bv_val[0] ^= (unsigned char) -signmask & 0xff; /* invert sign */
2185 /* Index generation function */
2192 struct berval *prefix,
2202 /* count the values and find max needed length */
2204 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2205 if ( itmp.bv_len < values[i].bv_len )
2206 itmp.bv_len = values[i].bv_len;
2208 if ( itmp.bv_len > index_intlen_strlen )
2209 itmp.bv_len > index_intlen_strlen;
2211 /* we should have at least one value at this point */
2214 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2215 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2216 keys[i].bv_len = index_intlen;
2217 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2220 keys[i].bv_val = NULL;
2222 if ( itmp.bv_len > (int) sizeof(ibuf) ) {
2223 itmp.bv_val = slap_sl_malloc( itmp.bv_len, ctx );
2226 itmp.bv_len = sizeof(ibuf);
2229 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2230 rc = integerVal2Key( values[i], &keys[i], itmp );
2236 if ( itmp.bv_val != ibuf ) {
2237 slap_sl_free( itmp.bv_val, ctx );
2242 /* Index generation function */
2249 struct berval *prefix,
2250 void * assertedValue,
2257 struct berval *value;
2260 value = (struct berval *) assertedValue;
2262 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2264 keys[0].bv_len = index_intlen;
2265 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2267 iv.bv_len = value->bv_len < index_intlen_strlen
2268 ? value->bv_len : index_intlen_strlen;
2269 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2270 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2273 iv.bv_len = sizeof(ibuf);
2276 rc = integerVal2Key( *value, keys, iv );
2280 if ( iv.bv_val != ibuf ) {
2281 slap_sl_free( iv.bv_val, ctx );
2287 countryStringValidate(
2289 struct berval *val )
2291 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2293 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2294 return LDAP_INVALID_SYNTAX;
2296 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2297 return LDAP_INVALID_SYNTAX;
2300 return LDAP_SUCCESS;
2304 printableStringValidate(
2306 struct berval *val )
2310 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2312 for(i=0; i < val->bv_len; i++) {
2313 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2314 return LDAP_INVALID_SYNTAX;
2318 return LDAP_SUCCESS;
2322 printablesStringValidate(
2324 struct berval *val )
2328 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2330 for(i=0,len=0; i < val->bv_len; i++) {
2331 int c = val->bv_val[i];
2335 return LDAP_INVALID_SYNTAX;
2339 } else if ( SLAP_PRINTABLE(c) ) {
2342 return LDAP_INVALID_SYNTAX;
2347 return LDAP_INVALID_SYNTAX;
2350 return LDAP_SUCCESS;
2356 struct berval *val )
2360 for(i=0; i < val->bv_len; i++) {
2361 if( !LDAP_ASCII(val->bv_val[i]) ) {
2362 return LDAP_INVALID_SYNTAX;
2366 return LDAP_SUCCESS;
2375 struct berval *normalized,
2379 int casefold = !SLAP_MR_ASSOCIATED( mr,
2380 slap_schema.si_mr_caseExactIA5Match );
2382 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2386 /* Ignore initial whitespace */
2387 while ( ASCII_SPACE( *p ) ) p++;
2389 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2390 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2391 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2392 normalized->bv_val[normalized->bv_len] = '\0';
2394 p = q = normalized->bv_val;
2397 if ( ASCII_SPACE( *p ) ) {
2400 /* Ignore the extra whitespace */
2401 while ( ASCII_SPACE( *p ) ) {
2405 } else if ( casefold ) {
2406 /* Most IA5 rules require casefolding */
2407 *q++ = TOLOWER(*p); p++;
2414 assert( normalized->bv_val <= p );
2418 * If the string ended in space, backup the pointer one
2419 * position. One is enough because the above loop collapsed
2420 * all whitespace to a single space.
2422 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2424 /* null terminate */
2427 normalized->bv_len = q - normalized->bv_val;
2429 return LDAP_SUCCESS;
2438 if( in->bv_len != 36 ) {
2439 return LDAP_INVALID_SYNTAX;
2442 for( i=0; i<36; i++ ) {
2448 if( in->bv_val[i] != '-' ) {
2449 return LDAP_INVALID_SYNTAX;
2453 if( !ASCII_HEX( in->bv_val[i]) ) {
2454 return LDAP_INVALID_SYNTAX;
2459 return LDAP_SUCCESS;
2470 int rc=LDAP_INVALID_SYNTAX;
2472 assert( in != NULL );
2473 assert( out != NULL );
2475 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2478 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2480 for( i=0; i<36; i++ ) {
2486 if( in->bv_val[i] != '-' ) {
2489 out->bv_val[i] = '-';
2493 if( !ASCII_HEX( in->bv_val[i]) ) {
2496 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2501 out->bv_val[ out->bv_len ] = '\0';
2505 slap_sl_free( out->bv_val, ctx );
2518 struct berval *normalized,
2521 unsigned char octet = '\0';
2525 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2526 /* NOTE: must be a normalized UUID */
2527 assert( val->bv_len == 16 );
2529 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2530 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2531 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2532 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2534 return LDAP_SUCCESS;
2537 normalized->bv_len = 16;
2538 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2540 for( i=0, j=0; i<36; i++ ) {
2541 unsigned char nibble;
2542 if( val->bv_val[i] == '-' ) {
2545 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2546 nibble = val->bv_val[i] - '0';
2548 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2549 nibble = val->bv_val[i] - ('a'-10);
2551 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2552 nibble = val->bv_val[i] - ('A'-10);
2555 slap_sl_free( normalized->bv_val, ctx );
2556 return LDAP_INVALID_SYNTAX;
2561 normalized->bv_val[j>>1] = octet;
2563 octet = nibble << 4;
2568 normalized->bv_val[normalized->bv_len] = 0;
2569 return LDAP_SUCCESS;
2575 numericStringValidate(
2581 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2583 for(i=0; i < in->bv_len; i++) {
2584 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2585 return LDAP_INVALID_SYNTAX;
2589 return LDAP_SUCCESS;
2593 numericStringNormalize(
2598 struct berval *normalized,
2601 /* removal all spaces */
2604 assert( !BER_BVISEMPTY( val ) );
2606 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2609 q = normalized->bv_val;
2612 if ( ASCII_SPACE( *p ) ) {
2613 /* Ignore whitespace */
2620 /* we should have copied no more than is in val */
2621 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2623 /* null terminate */
2626 normalized->bv_len = q - normalized->bv_val;
2628 if( BER_BVISEMPTY( normalized ) ) {
2629 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2630 normalized->bv_val[0] = ' ';
2631 normalized->bv_val[1] = '\0';
2632 normalized->bv_len = 1;
2635 return LDAP_SUCCESS;
2639 * Integer conversion macros that will use the largest available
2642 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2643 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2644 # define SLAP_LONG long long
2646 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2647 # define SLAP_LONG long
2648 #endif /* HAVE_STRTOLL ... */
2656 struct berval *value,
2657 void *assertedValue )
2659 SLAP_LONG lValue, lAssertedValue;
2662 /* safe to assume integers are NUL terminated? */
2663 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2664 if( errno == ERANGE )
2666 return LDAP_CONSTRAINT_VIOLATION;
2669 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2671 if( errno == ERANGE )
2673 return LDAP_CONSTRAINT_VIOLATION;
2676 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2677 return LDAP_SUCCESS;
2686 struct berval *value,
2687 void *assertedValue )
2689 SLAP_LONG lValue, lAssertedValue;
2692 /* safe to assume integers are NUL terminated? */
2693 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2694 if( errno == ERANGE )
2696 return LDAP_CONSTRAINT_VIOLATION;
2699 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2701 if( errno == ERANGE )
2703 return LDAP_CONSTRAINT_VIOLATION;
2706 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2707 return LDAP_SUCCESS;
2711 serialNumberAndIssuerCheck(
2720 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2722 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2723 /* Parse old format */
2724 is->bv_val = ber_bvchr( in, '$' );
2725 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2727 sn->bv_val = in->bv_val;
2728 sn->bv_len = is->bv_val - in->bv_val;
2731 is->bv_len = in->bv_len - (sn->bv_len + 1);
2733 /* eat leading zeros */
2734 for( n=0; n < (sn->bv_len-1); n++ ) {
2735 if( sn->bv_val[n] != '0' ) break;
2740 for( n=0; n < sn->bv_len; n++ ) {
2741 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2745 /* Parse GSER format */
2746 int havesn=0,haveissuer=0;
2747 struct berval x = *in;
2752 /* eat leading spaces */
2753 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2757 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2758 return LDAP_INVALID_SYNTAX;
2761 /* should be at issuer or serialNumber NamedValue */
2762 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2764 x.bv_val += STRLENOF("issuer");
2765 x.bv_len -= STRLENOF("issuer");
2767 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2768 x.bv_val++; x.bv_len--;
2770 /* eat leading spaces */
2771 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2775 /* For backward compatibility, this part is optional */
2776 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2777 x.bv_val += STRLENOF("rdnSequence:");
2778 x.bv_len -= STRLENOF("rdnSequence:");
2781 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2782 x.bv_val++; x.bv_len--;
2784 is->bv_val = x.bv_val;
2787 for( ; is->bv_len < x.bv_len; ) {
2788 if ( is->bv_val[is->bv_len] != '"' ) {
2792 if ( is->bv_val[is->bv_len+1] == '"' ) {
2799 x.bv_val += is->bv_len+1;
2800 x.bv_len -= is->bv_len+1;
2802 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2803 return LDAP_INVALID_SYNTAX;
2808 } else if( strncasecmp( x.bv_val, "serialNumber",
2809 STRLENOF("serialNumber")) == 0 )
2811 /* parse serialNumber */
2813 x.bv_val += STRLENOF("serialNumber");
2814 x.bv_len -= STRLENOF("serialNumber");
2816 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2817 x.bv_val++; x.bv_len--;
2819 /* eat leading spaces */
2820 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2824 sn->bv_val = x.bv_val;
2827 if( sn->bv_val[0] == '-' ) {
2832 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2833 sn->bv_val[1] == 'X' )) {
2835 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2836 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2838 } else if ( sn->bv_val[0] == '\'' ) {
2839 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2840 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2842 if ( sn->bv_val[sn->bv_len] == '\'' &&
2843 sn->bv_val[sn->bv_len+1] == 'H' )
2846 return LDAP_INVALID_SYNTAX;
2849 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2850 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2854 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2855 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2856 return LDAP_INVALID_SYNTAX;
2859 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2861 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2862 return LDAP_INVALID_SYNTAX;
2867 } else return LDAP_INVALID_SYNTAX;
2869 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2870 x.bv_val++; x.bv_len--;
2873 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2877 /* should be at remaining NamedValue */
2878 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2879 STRLENOF("issuer" )) == 0 ))
2882 x.bv_val += STRLENOF("issuer");
2883 x.bv_len -= STRLENOF("issuer");
2885 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2886 x.bv_val++; x.bv_len--;
2888 /* eat leading spaces */
2889 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2893 /* For backward compatibility, this part is optional */
2894 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2895 x.bv_val += STRLENOF("rdnSequence:");
2896 x.bv_len -= STRLENOF("rdnSequence:");
2899 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2900 x.bv_val++; x.bv_len--;
2902 is->bv_val = x.bv_val;
2905 for( ; is->bv_len < x.bv_len; ) {
2906 if ( is->bv_val[is->bv_len] != '"' ) {
2910 if ( is->bv_val[is->bv_len+1] == '"' ) {
2917 x.bv_val += is->bv_len+1;
2918 x.bv_len -= is->bv_len+1;
2920 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2921 STRLENOF("serialNumber")) == 0 ))
2923 /* parse serialNumber */
2925 x.bv_val += STRLENOF("serialNumber");
2926 x.bv_len -= STRLENOF("serialNumber");
2928 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2929 x.bv_val++; x.bv_len--;
2931 /* eat leading spaces */
2932 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2936 sn->bv_val = x.bv_val;
2939 if( sn->bv_val[0] == '-' ) {
2944 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2945 sn->bv_val[1] == 'X' )) {
2947 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2948 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2950 } else if ( sn->bv_val[0] == '\'' ) {
2951 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2952 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2954 if ( sn->bv_val[sn->bv_len] == '\'' &&
2955 sn->bv_val[sn->bv_len+1] == 'H' )
2958 return LDAP_INVALID_SYNTAX;
2961 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2962 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2966 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2967 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2968 return LDAP_INVALID_SYNTAX;
2971 x.bv_val += sn->bv_len;
2972 x.bv_len -= sn->bv_len;
2974 } else return LDAP_INVALID_SYNTAX;
2976 /* eat trailing spaces */
2977 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2981 /* should have no characters left... */
2982 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2984 ber_dupbv_x( &ni, is, ctx );
2987 /* need to handle double dquotes here */
2993 serialNumberAndIssuerValidate(
2998 struct berval sn, i;
3000 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3003 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3007 /* validate DN -- doesn't handle double dquote */
3008 rc = dnValidate( NULL, &i );
3010 rc = LDAP_INVALID_SYNTAX;
3012 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3013 slap_sl_free( i.bv_val, NULL );
3016 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3022 serialNumberAndIssuerPretty(
3029 struct berval sn, i, ni;
3031 assert( in != NULL );
3032 assert( out != NULL );
3034 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3037 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3041 rc = dnPretty( syntax, &i, &ni, ctx );
3043 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3044 slap_sl_free( i.bv_val, ctx );
3047 if( rc ) return LDAP_INVALID_SYNTAX;
3049 /* make room from sn + "$" */
3050 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3051 + sn.bv_len + ni.bv_len;
3052 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3054 if( out->bv_val == NULL ) {
3056 slap_sl_free( ni.bv_val, ctx );
3061 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3062 STRLENOF("{ serialNumber "));
3063 n = STRLENOF("{ serialNumber ");
3065 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3068 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3069 n += STRLENOF(", issuer rdnSequence:\"");
3071 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3074 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3075 n += STRLENOF("\" }");
3077 out->bv_val[n] = '\0';
3079 assert( n == out->bv_len );
3081 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3082 out->bv_val, 0, 0 );
3084 slap_sl_free( ni.bv_val, ctx );
3086 return LDAP_SUCCESS;
3090 * This routine is called by certificateExactNormalize when
3091 * certificateExactNormalize receives a search string instead of
3092 * a certificate. This routine checks if the search value is valid
3093 * and then returns the normalized value
3096 serialNumberAndIssuerNormalize(
3104 struct berval sn, sn2, i, ni;
3105 char sbuf[64], *stmp = sbuf;
3109 assert( in != NULL );
3110 assert( out != NULL );
3112 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3115 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3119 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3121 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3122 slap_sl_free( i.bv_val, ctx );
3125 if( rc ) return LDAP_INVALID_SYNTAX;
3127 /* Convert sn to canonical hex */
3128 if ( sn.bv_len > sizeof( sbuf )) {
3129 stmp = slap_sl_malloc( sn.bv_len, ctx );
3132 sn2.bv_len = sn.bv_len;
3133 if ( lutil_str2bin( &sn, &sn2 )) {
3134 rc = LDAP_INVALID_SYNTAX;
3138 /* make room for sn + "$" */
3139 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3140 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3141 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3143 if( out->bv_val == NULL ) {
3145 slap_sl_free( ni.bv_val, ctx );
3151 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3152 STRLENOF( "{ serialNumber " ));
3153 n = STRLENOF( "{ serialNumber " );
3155 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3158 unsigned char *v = (unsigned char *)sn2.bv_val;
3159 out->bv_val[n++] = '\'';
3160 for ( j = 0; j < sn2.bv_len; j++ ) {
3161 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3165 out->bv_val[n++] = '\'';
3166 out->bv_val[n++] = 'H';
3169 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3170 n += STRLENOF( ", issuer rdnSequence:\"" );
3172 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3175 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3176 n += STRLENOF( "\" }" );
3178 out->bv_val[n] = '\0';
3180 assert( n == out->bv_len );
3182 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3183 out->bv_val, 0, 0 );
3187 slap_sl_free( stmp, ctx );
3188 slap_sl_free( ni.bv_val, ctx );
3194 certificateExactNormalize(
3199 struct berval *normalized,
3202 BerElementBuffer berbuf;
3203 BerElement *ber = (BerElement *)&berbuf;
3207 char serialbuf[64], *serial = serialbuf;
3208 ber_len_t seriallen;
3209 struct berval issuer_dn = BER_BVNULL, bvdn;
3211 int rc = LDAP_INVALID_SYNTAX;
3213 if( BER_BVISEMPTY( val ) ) goto done;
3215 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3216 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3219 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3221 ber_init2( ber, val, LBER_USE_DER );
3222 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3223 tag = ber_skip_tag( ber, &len ); /* Sequence */
3224 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3225 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3226 tag = ber_skip_tag( ber, &len );
3227 tag = ber_get_int( ber, &i ); /* version */
3230 /* NOTE: move the test here from certificateValidate,
3231 * so that we can validate certs with serial longer
3232 * than sizeof(ber_int_t) */
3233 tag = ber_peek_tag( ber, &len ); /* serial */
3235 /* Use hex format. '123456789abcdef'H
3241 tag = ber_skip_tag( ber, &len );
3242 ptr = (unsigned char *)ber->ber_ptr;
3243 ber_skip_data( ber, len );
3245 /* Check for minimal encodings */
3247 if ( ptr[0] & 0x80 ) {
3248 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3249 return LDAP_INVALID_SYNTAX;
3250 } else if ( ptr[0] == 0 ) {
3251 if (!( ptr[1] & 0x80 ))
3252 return LDAP_INVALID_SYNTAX;
3256 seriallen = len * 2 + 4; /* quotes, H, NUL */
3257 if ( seriallen > sizeof( serialbuf ))
3258 serial = slap_sl_malloc( seriallen, ctx );
3261 for ( i = 0; i<len; i++ ) {
3262 sprintf( sptr, "%02X", ptr[i] );
3269 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3270 ber_skip_data( ber, len );
3271 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3272 len = ber_ptrlen( ber );
3273 bvdn.bv_val = val->bv_val + len;
3274 bvdn.bv_len = val->bv_len - len;
3276 rc = dnX509normalize( &bvdn, &issuer_dn );
3277 if( rc != LDAP_SUCCESS ) goto done;
3279 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3280 + seriallen + issuer_dn.bv_len;
3281 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3283 p = (unsigned char *)normalized->bv_val;
3285 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3286 p += STRLENOF( "{ serialNumber " );
3288 AC_MEMCPY(p, serial, seriallen);
3291 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3292 p += STRLENOF( ", issuer rdnSequence:\"" );
3294 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3295 p += issuer_dn.bv_len;
3297 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3298 p += STRLENOF( "\" }" );
3302 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3303 normalized->bv_val, NULL, NULL );
3308 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3309 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3321 assert( in != NULL );
3322 assert( !BER_BVISNULL( in ) );
3324 for ( i = 0; i < in->bv_len; i++ ) {
3325 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3326 return LDAP_INVALID_SYNTAX;
3330 return LDAP_SUCCESS;
3333 /* Normalize a SID as used inside a CSN:
3334 * three-digit numeric string */
3341 struct berval *normalized,
3346 assert( val != NULL );
3347 assert( normalized != NULL );
3349 ber_dupbv_x( normalized, val, ctx );
3351 for ( i = 0; i < normalized->bv_len; i++ ) {
3352 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3353 ber_memfree_x( normalized->bv_val, ctx );
3354 BER_BVZERO( normalized );
3355 return LDAP_INVALID_SYNTAX;
3358 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3361 return LDAP_SUCCESS;
3369 assert( in != NULL );
3370 assert( !BER_BVISNULL( in ) );
3372 if ( in->bv_len != 3 ) {
3373 return LDAP_INVALID_SYNTAX;
3376 return hexValidate( NULL, in );
3379 /* Normalize a SID as used inside a CSN:
3380 * three-digit numeric string */
3387 struct berval *normalized,
3390 if ( val->bv_len != 3 ) {
3391 return LDAP_INVALID_SYNTAX;
3394 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3404 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3407 /* Normalize a SID as used inside a CSN, either as-is
3408 * (assertion value) or extracted from the CSN
3409 * (attribute value) */
3416 struct berval *normalized,
3424 if ( BER_BVISEMPTY( val ) ) {
3425 return LDAP_INVALID_SYNTAX;
3428 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3429 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3432 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3434 ptr = ber_bvchr( val, '#' );
3435 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3436 return LDAP_INVALID_SYNTAX;
3439 bv.bv_val = ptr + 1;
3440 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3442 ptr = ber_bvchr( &bv, '#' );
3443 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3444 return LDAP_INVALID_SYNTAX;
3447 bv.bv_val = ptr + 1;
3448 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3450 ptr = ber_bvchr( &bv, '#' );
3451 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3452 return LDAP_INVALID_SYNTAX;
3455 bv.bv_len = ptr - bv.bv_val;
3457 if ( bv.bv_len == 2 ) {
3458 /* OpenLDAP 2.3 SID */
3460 buf[ 1 ] = bv.bv_val[ 0 ];
3461 buf[ 2 ] = bv.bv_val[ 1 ];
3468 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3480 assert( in != NULL );
3481 assert( !BER_BVISNULL( in ) );
3483 if ( BER_BVISEMPTY( in ) ) {
3484 return LDAP_INVALID_SYNTAX;
3489 ptr = ber_bvchr( &bv, '#' );
3490 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3491 return LDAP_INVALID_SYNTAX;
3494 bv.bv_len = ptr - bv.bv_val;
3495 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3496 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3498 return LDAP_INVALID_SYNTAX;
3501 rc = generalizedTimeValidate( NULL, &bv );
3502 if ( rc != LDAP_SUCCESS ) {
3506 bv.bv_val = ptr + 1;
3507 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3509 ptr = ber_bvchr( &bv, '#' );
3510 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3511 return LDAP_INVALID_SYNTAX;
3514 bv.bv_len = ptr - bv.bv_val;
3515 if ( bv.bv_len != 6 ) {
3516 return LDAP_INVALID_SYNTAX;
3519 rc = hexValidate( NULL, &bv );
3520 if ( rc != LDAP_SUCCESS ) {
3524 bv.bv_val = ptr + 1;
3525 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3527 ptr = ber_bvchr( &bv, '#' );
3528 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3529 return LDAP_INVALID_SYNTAX;
3532 bv.bv_len = ptr - bv.bv_val;
3533 if ( bv.bv_len == 2 ) {
3534 /* tolerate old 2-digit replica-id */
3535 rc = hexValidate( NULL, &bv );
3538 rc = sidValidate( NULL, &bv );
3540 if ( rc != LDAP_SUCCESS ) {
3544 bv.bv_val = ptr + 1;
3545 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3547 if ( bv.bv_len != 6 ) {
3548 return LDAP_INVALID_SYNTAX;
3551 return hexValidate( NULL, &bv );
3554 /* Normalize a CSN in OpenLDAP 2.3 format */
3561 struct berval *normalized,
3564 struct berval gt, cnt, sid, mod;
3568 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3569 assert( !BER_BVISEMPTY( val ) );
3573 ptr = ber_bvchr( >, '#' );
3574 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3575 return LDAP_INVALID_SYNTAX;
3578 gt.bv_len = ptr - gt.bv_val;
3579 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3581 cnt.bv_val = ptr + 1;
3582 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3584 ptr = ber_bvchr( &cnt, '#' );
3585 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3586 return LDAP_INVALID_SYNTAX;
3589 cnt.bv_len = ptr - cnt.bv_val;
3590 assert( cnt.bv_len == STRLENOF( "000000" ) );
3592 sid.bv_val = ptr + 1;
3593 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3595 ptr = ber_bvchr( &sid, '#' );
3596 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3597 return LDAP_INVALID_SYNTAX;
3600 sid.bv_len = ptr - sid.bv_val;
3601 assert( sid.bv_len == STRLENOF( "00" ) );
3603 mod.bv_val = ptr + 1;
3604 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3605 assert( mod.bv_len == STRLENOF( "000000" ) );
3607 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3608 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3610 ptr = normalized->bv_val;
3611 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3612 ptr = lutil_strcopy( ptr, ".000000Z#" );
3613 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3616 for ( i = 0; i < sid.bv_len; i++ ) {
3617 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3620 for ( i = 0; i < mod.bv_len; i++ ) {
3621 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3625 assert( ptr - normalized->bv_val == normalized->bv_len );
3627 return LDAP_SUCCESS;
3630 /* Normalize a CSN */
3637 struct berval *normalized,
3640 struct berval cnt, sid, mod;
3644 assert( val != NULL );
3645 assert( normalized != NULL );
3647 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3649 if ( BER_BVISEMPTY( val ) ) {
3650 return LDAP_INVALID_SYNTAX;
3653 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3654 /* Openldap <= 2.3 */
3656 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3659 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3661 ptr = ber_bvchr( val, '#' );
3662 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3663 return LDAP_INVALID_SYNTAX;
3666 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3668 cnt.bv_val = ptr + 1;
3669 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3671 ptr = ber_bvchr( &cnt, '#' );
3672 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3673 return LDAP_INVALID_SYNTAX;
3676 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3678 sid.bv_val = ptr + 1;
3679 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3681 ptr = ber_bvchr( &sid, '#' );
3682 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3683 return LDAP_INVALID_SYNTAX;
3686 sid.bv_len = ptr - sid.bv_val;
3687 assert( sid.bv_len == STRLENOF( "000" ) );
3689 mod.bv_val = ptr + 1;
3690 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3692 assert( mod.bv_len == STRLENOF( "000000" ) );
3694 ber_dupbv_x( normalized, val, ctx );
3696 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3697 i < normalized->bv_len; i++ )
3699 /* assume it's already validated that's all hex digits */
3700 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3703 return LDAP_SUCCESS;
3713 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3716 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3717 /* slight optimization - does not need the start parameter */
3718 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3723 check_time_syntax (struct berval *val,
3726 struct berval *fraction)
3729 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3730 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3731 * GeneralizedTime supports leap seconds, UTCTime does not.
3733 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3734 static const int mdays[2][12] = {
3735 /* non-leap years */
3736 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3738 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3741 int part, c, c1, c2, tzoffset, leapyear = 0;
3744 e = p + val->bv_len;
3746 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3747 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3749 for (part = start; part < 7 && p < e; part++) {
3751 if (!ASCII_DIGIT(c1)) {
3756 return LDAP_INVALID_SYNTAX;
3759 if (!ASCII_DIGIT(c)) {
3760 return LDAP_INVALID_SYNTAX;
3762 c += c1 * 10 - '0' * 11;
3763 if ((part | 1) == 3) {
3766 return LDAP_INVALID_SYNTAX;
3769 if (c >= ceiling[part]) {
3770 if (! (c == 60 && part == 6 && start == 0))
3771 return LDAP_INVALID_SYNTAX;
3775 if (part < 5 + start) {
3776 return LDAP_INVALID_SYNTAX;
3778 for (; part < 9; part++) {
3782 /* leapyear check for the Gregorian calendar (year>1581) */
3783 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3787 if (parts[3] >= mdays[leapyear][parts[2]]) {
3788 return LDAP_INVALID_SYNTAX;
3792 fraction->bv_val = p;
3793 fraction->bv_len = 0;
3794 if (p < e && (*p == '.' || *p == ',')) {
3796 while (++p < e && ASCII_DIGIT(*p)) {
3799 if (p - fraction->bv_val == 1) {
3800 return LDAP_INVALID_SYNTAX;
3802 for (end_num = p; end_num[-1] == '0'; --end_num) {
3805 c = end_num - fraction->bv_val;
3806 if (c != 1) fraction->bv_len = c;
3812 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3818 return LDAP_INVALID_SYNTAX;
3824 for (part = 7; part < 9 && p < e; part++) {
3826 if (!ASCII_DIGIT(c1)) {
3831 return LDAP_INVALID_SYNTAX;
3834 if (!ASCII_DIGIT(c2)) {
3835 return LDAP_INVALID_SYNTAX;
3837 parts[part] = c1 * 10 + c2 - '0' * 11;
3838 if (parts[part] >= ceiling[part]) {
3839 return LDAP_INVALID_SYNTAX;
3842 if (part < 8 + start) {
3843 return LDAP_INVALID_SYNTAX;
3846 if (tzoffset == '-') {
3847 /* negative offset to UTC, ie west of Greenwich */
3848 parts[4] += parts[7];
3849 parts[5] += parts[8];
3850 /* offset is just hhmm, no seconds */
3851 for (part = 6; --part >= 0; ) {
3855 c = mdays[leapyear][parts[2]];
3857 if (parts[part] >= c) {
3859 return LDAP_INVALID_SYNTAX;
3864 } else if (part != 5) {
3869 /* positive offset to UTC, ie east of Greenwich */
3870 parts[4] -= parts[7];
3871 parts[5] -= parts[8];
3872 for (part = 6; --part >= 0; ) {
3873 if (parts[part] < 0) {
3875 return LDAP_INVALID_SYNTAX;
3880 /* make first arg to % non-negative */
3881 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3886 } else if (part != 5) {
3893 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3896 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3903 struct berval *normalized )
3907 rc = check_time_syntax(val, 1, parts, NULL);
3908 if (rc != LDAP_SUCCESS) {
3912 normalized->bv_val = ch_malloc( 14 );
3913 if ( normalized->bv_val == NULL ) {
3914 return LBER_ERROR_MEMORY;
3917 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3918 parts[1], parts[2] + 1, parts[3] + 1,
3919 parts[4], parts[5], parts[6] );
3920 normalized->bv_len = 13;
3922 return LDAP_SUCCESS;
3932 return check_time_syntax(in, 1, parts, NULL);
3935 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3938 generalizedTimeValidate(
3943 struct berval fraction;
3944 return check_time_syntax(in, 0, parts, &fraction);
3948 generalizedTimeNormalize(
3953 struct berval *normalized,
3958 struct berval fraction;
3960 rc = check_time_syntax(val, 0, parts, &fraction);
3961 if (rc != LDAP_SUCCESS) {
3965 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3966 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3967 if ( BER_BVISNULL( normalized ) ) {
3968 return LBER_ERROR_MEMORY;
3971 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3972 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3973 parts[4], parts[5], parts[6] );
3974 if ( !BER_BVISEMPTY( &fraction ) ) {
3975 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3976 fraction.bv_val, fraction.bv_len );
3977 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3979 strcpy( normalized->bv_val + len-1, "Z" );
3980 normalized->bv_len = len;
3982 return LDAP_SUCCESS;
3986 generalizedTimeOrderingMatch(
3991 struct berval *value,
3992 void *assertedValue )
3994 struct berval *asserted = (struct berval *) assertedValue;
3995 ber_len_t v_len = value->bv_len;
3996 ber_len_t av_len = asserted->bv_len;
3998 /* ignore trailing 'Z' when comparing */
3999 int match = memcmp( value->bv_val, asserted->bv_val,
4000 (v_len < av_len ? v_len : av_len) - 1 );
4001 if ( match == 0 ) match = v_len - av_len;
4004 return LDAP_SUCCESS;
4007 /* Index generation function */
4008 int generalizedTimeIndexer(
4013 struct berval *prefix,
4021 BerValue bvtmp; /* 40 bit index */
4023 struct lutil_timet tt;
4025 bvtmp.bv_len = sizeof(tmp);
4027 for( i=0; values[i].bv_val != NULL; i++ ) {
4028 /* just count them */
4031 /* we should have at least one value at this point */
4034 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4036 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4037 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4038 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4039 /* Use 40 bits of time for key */
4040 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4041 lutil_tm2time( &tm, &tt );
4042 tmp[0] = tt.tt_gsec & 0xff;
4043 tmp[4] = tt.tt_sec & 0xff;
4045 tmp[3] = tt.tt_sec & 0xff;
4047 tmp[2] = tt.tt_sec & 0xff;
4049 tmp[1] = tt.tt_sec & 0xff;
4051 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4055 keys[j].bv_val = NULL;
4060 return LDAP_SUCCESS;
4063 /* Index generation function */
4064 int generalizedTimeFilter(
4069 struct berval *prefix,
4070 void * assertedValue,
4076 BerValue bvtmp; /* 40 bit index */
4077 BerValue *value = (BerValue *) assertedValue;
4079 struct lutil_timet tt;
4081 bvtmp.bv_len = sizeof(tmp);
4083 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4084 /* Use 40 bits of time for key */
4085 if ( value->bv_val && value->bv_len >= 10 &&
4086 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4088 lutil_tm2time( &tm, &tt );
4089 tmp[0] = tt.tt_gsec & 0xff;
4090 tmp[4] = tt.tt_sec & 0xff;
4092 tmp[3] = tt.tt_sec & 0xff;
4094 tmp[2] = tt.tt_sec & 0xff;
4096 tmp[1] = tt.tt_sec & 0xff;
4098 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4099 ber_dupbv_x(keys, &bvtmp, ctx );
4100 keys[1].bv_val = NULL;
4108 return LDAP_SUCCESS;
4112 deliveryMethodValidate(
4114 struct berval *val )
4117 #define LENOF(s) (sizeof(s)-1)
4118 struct berval tmp = *val;
4120 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4121 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4122 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4125 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4127 switch( tmp.bv_val[0] ) {
4130 if(( tmp.bv_len >= LENOF("any") ) &&
4131 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4133 tmp.bv_len -= LENOF("any");
4134 tmp.bv_val += LENOF("any");
4137 return LDAP_INVALID_SYNTAX;
4141 if(( tmp.bv_len >= LENOF("mhs") ) &&
4142 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4144 tmp.bv_len -= LENOF("mhs");
4145 tmp.bv_val += LENOF("mhs");
4148 return LDAP_INVALID_SYNTAX;
4152 if(( tmp.bv_len >= LENOF("physical") ) &&
4153 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4155 tmp.bv_len -= LENOF("physical");
4156 tmp.bv_val += LENOF("physical");
4159 return LDAP_INVALID_SYNTAX;
4162 case 'T': /* telex or teletex or telephone */
4163 if(( tmp.bv_len >= LENOF("telex") ) &&
4164 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4166 tmp.bv_len -= LENOF("telex");
4167 tmp.bv_val += LENOF("telex");
4170 if(( tmp.bv_len >= LENOF("teletex") ) &&
4171 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4173 tmp.bv_len -= LENOF("teletex");
4174 tmp.bv_val += LENOF("teletex");
4177 if(( tmp.bv_len >= LENOF("telephone") ) &&
4178 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4180 tmp.bv_len -= LENOF("telephone");
4181 tmp.bv_val += LENOF("telephone");
4184 return LDAP_INVALID_SYNTAX;
4187 case 'G': /* g3fax or g4fax */
4188 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4189 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4190 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4192 tmp.bv_len -= LENOF("g3fax");
4193 tmp.bv_val += LENOF("g3fax");
4196 return LDAP_INVALID_SYNTAX;
4200 if(( tmp.bv_len >= LENOF("ia5") ) &&
4201 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4203 tmp.bv_len -= LENOF("ia5");
4204 tmp.bv_val += LENOF("ia5");
4207 return LDAP_INVALID_SYNTAX;
4211 if(( tmp.bv_len >= LENOF("videotex") ) &&
4212 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4214 tmp.bv_len -= LENOF("videotex");
4215 tmp.bv_val += LENOF("videotex");
4218 return LDAP_INVALID_SYNTAX;
4221 return LDAP_INVALID_SYNTAX;
4224 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4226 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4230 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4234 return LDAP_INVALID_SYNTAX;
4236 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4245 nisNetgroupTripleValidate(
4247 struct berval *val )
4252 if ( BER_BVISEMPTY( val ) ) {
4253 return LDAP_INVALID_SYNTAX;
4256 p = (char *)val->bv_val;
4257 e = p + val->bv_len;
4259 if ( *p != '(' /*')'*/ ) {
4260 return LDAP_INVALID_SYNTAX;
4263 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4267 return LDAP_INVALID_SYNTAX;
4270 } else if ( !AD_CHAR( *p ) ) {
4271 return LDAP_INVALID_SYNTAX;
4275 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4276 return LDAP_INVALID_SYNTAX;
4282 return LDAP_INVALID_SYNTAX;
4285 return LDAP_SUCCESS;
4289 bootParameterValidate(
4291 struct berval *val )
4295 if ( BER_BVISEMPTY( val ) ) {
4296 return LDAP_INVALID_SYNTAX;
4299 p = (char *)val->bv_val;
4300 e = p + val->bv_len;
4303 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4304 if ( !AD_CHAR( *p ) ) {
4305 return LDAP_INVALID_SYNTAX;
4310 return LDAP_INVALID_SYNTAX;
4314 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4315 if ( !AD_CHAR( *p ) ) {
4316 return LDAP_INVALID_SYNTAX;
4321 return LDAP_INVALID_SYNTAX;
4325 for ( p++; p < e; p++ ) {
4326 if ( !SLAP_PRINTABLE( *p ) ) {
4327 return LDAP_INVALID_SYNTAX;
4331 return LDAP_SUCCESS;
4335 firstComponentNormalize(
4340 struct berval *normalized,
4347 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4348 ber_dupbv_x( normalized, val, ctx );
4349 return LDAP_SUCCESS;
4352 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4354 if( val->bv_val[0] != '(' /*')'*/ &&
4355 val->bv_val[0] != '{' /*'}'*/ )
4357 return LDAP_INVALID_SYNTAX;
4360 /* trim leading white space */
4362 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4368 /* grab next word */
4369 comp.bv_val = &val->bv_val[len];
4370 len = val->bv_len - len;
4371 for( comp.bv_len = 0;
4372 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4378 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4379 rc = numericoidValidate( NULL, &comp );
4380 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4381 rc = integerValidate( NULL, &comp );
4383 rc = LDAP_INVALID_SYNTAX;
4387 if( rc == LDAP_SUCCESS ) {
4388 ber_dupbv_x( normalized, &comp, ctx );
4394 static char *country_gen_syn[] = {
4395 "1.3.6.1.4.1.1466.115.121.1.15",
4396 "1.3.6.1.4.1.1466.115.121.1.26",
4397 "1.3.6.1.4.1.1466.115.121.1.44",
4401 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4402 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4404 static slap_syntax_defs_rec syntax_defs[] = {
4405 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4406 X_BINARY X_NOT_H_R ")",
4407 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4408 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4409 0, NULL, NULL, NULL},
4410 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4411 0, NULL, NULL, NULL},
4412 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4414 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4415 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4417 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4418 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4419 0, NULL, bitStringValidate, NULL },
4420 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4421 0, NULL, booleanValidate, NULL},
4422 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4423 X_BINARY X_NOT_H_R ")",
4424 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4425 NULL, certificateValidate, NULL},
4426 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4427 X_BINARY X_NOT_H_R ")",
4428 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4429 NULL, certificateListValidate, NULL},
4430 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4431 X_BINARY X_NOT_H_R ")",
4432 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4433 NULL, sequenceValidate, NULL},
4434 #if 0 /* need to go __after__ printableString */
4435 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4436 0, "1.3.6.1.4.1.1466.115.121.1.44",
4437 countryStringValidate, NULL},
4439 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4440 0, NULL, dnValidate, dnPretty},
4441 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4442 0, NULL, rdnValidate, rdnPretty},
4443 #ifdef LDAP_COMP_MATCH
4444 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4445 0, NULL, allComponentsValidate, NULL},
4446 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4447 0, NULL, componentFilterValidate, NULL},
4449 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4450 0, NULL, NULL, NULL},
4451 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4452 0, NULL, deliveryMethodValidate, NULL},
4453 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4454 0, NULL, UTF8StringValidate, NULL},
4455 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4456 0, NULL, NULL, NULL},
4457 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4458 0, NULL, NULL, NULL},
4459 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4460 0, NULL, NULL, NULL},
4461 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4462 0, NULL, NULL, NULL},
4463 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4464 0, NULL, NULL, NULL},
4465 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4466 0, NULL, printablesStringValidate, NULL},
4467 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4468 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4469 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4470 0, NULL, generalizedTimeValidate, NULL},
4471 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4472 0, NULL, NULL, NULL},
4473 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4474 0, NULL, IA5StringValidate, NULL},
4475 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4476 0, NULL, integerValidate, NULL},
4477 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4478 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4479 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4480 0, NULL, NULL, NULL},
4481 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4482 0, NULL, NULL, NULL},
4483 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4484 0, NULL, NULL, NULL},
4485 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4486 0, NULL, NULL, NULL},
4487 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4488 0, NULL, NULL, NULL},
4489 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4490 0, NULL, nameUIDValidate, nameUIDPretty },
4491 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4492 0, NULL, NULL, NULL},
4493 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4494 0, NULL, numericStringValidate, NULL},
4495 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4496 0, NULL, NULL, NULL},
4497 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4498 0, NULL, numericoidValidate, NULL},
4499 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4500 0, NULL, IA5StringValidate, NULL},
4501 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4502 0, NULL, blobValidate, NULL},
4503 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4504 0, NULL, UTF8StringValidate, NULL},
4505 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4506 0, NULL, NULL, NULL},
4507 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4508 0, NULL, NULL, NULL},
4509 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4510 0, NULL, printableStringValidate, NULL},
4511 /* moved here because now depends on Directory String, IA5 String
4512 * and Printable String */
4513 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4514 0, country_gen_syn, countryStringValidate, NULL},
4515 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4516 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4517 0, NULL, subtreeSpecificationValidate, NULL},
4518 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4519 X_BINARY X_NOT_H_R ")",
4520 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4521 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4522 0, NULL, printableStringValidate, NULL},
4523 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4524 0, NULL, NULL, NULL},
4525 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4526 0, NULL, printablesStringValidate, NULL},
4527 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4528 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4529 0, NULL, utcTimeValidate, NULL},
4531 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4532 0, NULL, NULL, NULL},
4533 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4534 0, NULL, NULL, NULL},
4535 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4536 0, NULL, NULL, NULL},
4537 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4538 0, NULL, NULL, NULL},
4539 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4540 0, NULL, NULL, NULL},
4542 /* RFC 2307 NIS Syntaxes */
4543 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4544 0, NULL, nisNetgroupTripleValidate, NULL},
4545 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4546 0, NULL, bootParameterValidate, NULL},
4548 /* draft-zeilenga-ldap-x509 */
4549 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4550 SLAP_SYNTAX_HIDE, NULL,
4551 serialNumberAndIssuerValidate,
4552 serialNumberAndIssuerPretty},
4553 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4554 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4555 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4556 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4557 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4558 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4559 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4560 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4561 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4562 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4563 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4564 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4566 #ifdef SLAPD_AUTHPASSWD
4567 /* needs updating */
4568 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4569 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4572 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4573 0, NULL, UUIDValidate, UUIDPretty},
4575 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4576 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4578 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4579 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4581 /* OpenLDAP Void Syntax */
4582 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4583 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4585 /* FIXME: OID is unused, but not registered yet */
4586 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4587 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4589 {NULL, 0, NULL, NULL, NULL}
4592 char *csnSIDMatchSyntaxes[] = {
4593 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4596 char *certificateExactMatchSyntaxes[] = {
4597 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4600 #ifdef LDAP_COMP_MATCH
4601 char *componentFilterMatchSyntaxes[] = {
4602 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4606 char *directoryStringSyntaxes[] = {
4607 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4610 char *integerFirstComponentMatchSyntaxes[] = {
4611 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4612 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4615 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4616 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4617 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4618 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4619 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4620 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4621 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4622 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4623 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4628 * Other matching rules in X.520 that we do not use (yet):
4630 * 2.5.13.25 uTCTimeMatch
4631 * 2.5.13.26 uTCTimeOrderingMatch
4632 * 2.5.13.31* directoryStringFirstComponentMatch
4633 * 2.5.13.32* wordMatch
4634 * 2.5.13.33* keywordMatch
4635 * 2.5.13.36+ certificatePairExactMatch
4636 * 2.5.13.37+ certificatePairMatch
4637 * 2.5.13.38+ certificateListExactMatch
4638 * 2.5.13.39+ certificateListMatch
4639 * 2.5.13.40+ algorithmIdentifierMatch
4640 * 2.5.13.41* storedPrefixMatch
4641 * 2.5.13.42 attributeCertificateMatch
4642 * 2.5.13.43 readerAndKeyIDMatch
4643 * 2.5.13.44 attributeIntegrityMatch
4645 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4646 * (+) described in draft-zeilenga-ldap-x509
4648 static slap_mrule_defs_rec mrule_defs[] = {
4650 * EQUALITY matching rules must be listed after associated APPROX
4651 * matching rules. So, we list all APPROX matching rules first.
4653 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4654 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4655 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4656 NULL, NULL, directoryStringApproxMatch,
4657 directoryStringApproxIndexer, directoryStringApproxFilter,
4660 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4661 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4662 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4663 NULL, NULL, IA5StringApproxMatch,
4664 IA5StringApproxIndexer, IA5StringApproxFilter,
4668 * Other matching rules
4671 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4672 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4673 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4674 NULL, NULL, octetStringMatch,
4675 octetStringIndexer, octetStringFilter,
4678 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4679 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4680 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4681 NULL, dnNormalize, dnMatch,
4682 octetStringIndexer, octetStringFilter,
4685 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4686 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4687 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4688 NULL, dnNormalize, dnRelativeMatch,
4692 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4693 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4694 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4695 NULL, dnNormalize, dnRelativeMatch,
4699 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4700 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4701 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4702 NULL, dnNormalize, dnRelativeMatch,
4706 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4707 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4708 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4709 NULL, dnNormalize, dnRelativeMatch,
4713 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4714 "SYNTAX 1.2.36.79672281.1.5.0 )",
4715 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4716 NULL, rdnNormalize, rdnMatch,
4717 octetStringIndexer, octetStringFilter,
4720 #ifdef LDAP_COMP_MATCH
4721 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4722 "SYNTAX 1.2.36.79672281.1.5.2 )",
4723 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4724 NULL, NULL , componentFilterMatch,
4725 octetStringIndexer, octetStringFilter,
4728 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4729 "SYNTAX 1.2.36.79672281.1.5.3 )",
4730 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4731 NULL, NULL , allComponentsMatch,
4732 octetStringIndexer, octetStringFilter,
4735 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4736 "SYNTAX 1.2.36.79672281.1.5.3 )",
4737 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4738 NULL, NULL , directoryComponentsMatch,
4739 octetStringIndexer, octetStringFilter,
4743 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4745 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4746 NULL, UTF8StringNormalize, octetStringMatch,
4747 octetStringIndexer, octetStringFilter,
4748 directoryStringApproxMatchOID },
4750 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4751 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4752 SLAP_MR_ORDERING, directoryStringSyntaxes,
4753 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4755 "caseIgnoreMatch" },
4757 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4758 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4759 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4760 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4761 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4762 "caseIgnoreMatch" },
4764 {"( 2.5.13.5 NAME 'caseExactMatch' "
4765 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4766 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4767 NULL, UTF8StringNormalize, octetStringMatch,
4768 octetStringIndexer, octetStringFilter,
4769 directoryStringApproxMatchOID },
4771 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4772 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4773 SLAP_MR_ORDERING, directoryStringSyntaxes,
4774 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4778 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4779 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4780 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4781 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4782 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4785 {"( 2.5.13.8 NAME 'numericStringMatch' "
4786 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4787 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4788 NULL, numericStringNormalize, octetStringMatch,
4789 octetStringIndexer, octetStringFilter,
4792 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4793 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4794 SLAP_MR_ORDERING, NULL,
4795 NULL, numericStringNormalize, octetStringOrderingMatch,
4797 "numericStringMatch" },
4799 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4800 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4801 SLAP_MR_SUBSTR, NULL,
4802 NULL, numericStringNormalize, octetStringSubstringsMatch,
4803 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4804 "numericStringMatch" },
4806 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4807 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4808 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4809 NULL, NULL, NULL, NULL, NULL, NULL },
4811 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4812 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4813 SLAP_MR_SUBSTR, NULL,
4814 NULL, NULL, NULL, NULL, NULL,
4815 "caseIgnoreListMatch" },
4817 {"( 2.5.13.13 NAME 'booleanMatch' "
4818 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4819 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4820 NULL, NULL, booleanMatch,
4821 octetStringIndexer, octetStringFilter,
4824 {"( 2.5.13.14 NAME 'integerMatch' "
4825 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4826 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4827 NULL, NULL, integerMatch,
4828 integerIndexer, integerFilter,
4831 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4832 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4833 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4834 NULL, NULL, integerMatch,
4838 {"( 2.5.13.16 NAME 'bitStringMatch' "
4839 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4840 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4841 NULL, NULL, octetStringMatch,
4842 octetStringIndexer, octetStringFilter,
4845 {"( 2.5.13.17 NAME 'octetStringMatch' "
4846 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4847 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4848 NULL, NULL, octetStringMatch,
4849 octetStringIndexer, octetStringFilter,
4852 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4853 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4854 SLAP_MR_ORDERING, NULL,
4855 NULL, NULL, octetStringOrderingMatch,
4857 "octetStringMatch" },
4859 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4860 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4861 SLAP_MR_SUBSTR, NULL,
4862 NULL, NULL, octetStringSubstringsMatch,
4863 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4864 "octetStringMatch" },
4866 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4867 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4868 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4870 telephoneNumberNormalize, octetStringMatch,
4871 octetStringIndexer, octetStringFilter,
4874 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4876 SLAP_MR_SUBSTR, NULL,
4877 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4878 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4879 "telephoneNumberMatch" },
4881 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4882 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4883 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4884 NULL, NULL, NULL, NULL, NULL, NULL },
4886 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4887 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4888 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4889 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4890 uniqueMemberIndexer, uniqueMemberFilter,
4893 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4894 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4895 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4896 NULL, NULL, NULL, NULL, NULL, NULL },
4898 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4899 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4900 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4901 NULL, generalizedTimeNormalize, octetStringMatch,
4902 generalizedTimeIndexer, generalizedTimeFilter,
4905 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4906 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4907 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4908 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4910 "generalizedTimeMatch" },
4912 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4913 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4914 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4915 integerFirstComponentMatchSyntaxes,
4916 NULL, firstComponentNormalize, integerMatch,
4917 octetStringIndexer, octetStringFilter,
4920 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4922 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4923 objectIdentifierFirstComponentMatchSyntaxes,
4924 NULL, firstComponentNormalize, octetStringMatch,
4925 octetStringIndexer, octetStringFilter,
4928 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4929 "SYNTAX 1.3.6.1.1.15.1 )",
4930 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4931 NULL, certificateExactNormalize, octetStringMatch,
4932 octetStringIndexer, octetStringFilter,
4935 {"( 2.5.13.35 NAME 'certificateMatch' "
4936 "SYNTAX 1.3.6.1.1.15.2 )",
4937 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4938 NULL, NULL, NULL, NULL, NULL,
4941 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4942 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4943 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4944 NULL, IA5StringNormalize, octetStringMatch,
4945 octetStringIndexer, octetStringFilter,
4946 IA5StringApproxMatchOID },
4948 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4949 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4950 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4951 NULL, IA5StringNormalize, octetStringMatch,
4952 octetStringIndexer, octetStringFilter,
4953 IA5StringApproxMatchOID },
4955 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4957 SLAP_MR_SUBSTR, NULL,
4958 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4959 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4960 "caseIgnoreIA5Match" },
4962 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4963 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4964 SLAP_MR_SUBSTR, NULL,
4965 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4966 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4967 "caseExactIA5Match" },
4969 #ifdef SLAPD_AUTHPASSWD
4970 /* needs updating */
4971 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4973 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4974 NULL, NULL, authPasswordMatch,
4979 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4980 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4982 NULL, NULL, integerBitAndMatch,
4986 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4987 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4989 NULL, NULL, integerBitOrMatch,
4993 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
4994 "SYNTAX 1.3.6.1.1.16.1 )",
4995 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
4996 NULL, UUIDNormalize, octetStringMatch,
4997 octetStringIndexer, octetStringFilter,
5000 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5001 "SYNTAX 1.3.6.1.1.16.1 )",
5002 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5003 NULL, UUIDNormalize, octetStringOrderingMatch,
5004 octetStringIndexer, octetStringFilter,
5007 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5008 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5009 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5010 NULL, csnNormalize, csnMatch,
5011 csnIndexer, csnFilter,
5014 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5015 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5016 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5017 NULL, NULL, csnOrderingMatch,
5021 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5022 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5023 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5024 NULL, csnSidNormalize, octetStringMatch,
5025 octetStringIndexer, octetStringFilter,
5028 /* FIXME: OID is unused, but not registered yet */
5029 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5030 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5031 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5032 NULL, authzNormalize, authzMatch,
5036 {NULL, SLAP_MR_NONE, NULL,
5037 NULL, NULL, NULL, NULL, NULL,
5042 slap_schema_init( void )
5047 /* we should only be called once (from main) */
5048 assert( schema_init_done == 0 );
5050 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5051 res = register_syntax( &syntax_defs[i] );
5054 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5055 syntax_defs[i].sd_desc );
5060 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5061 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5062 mrule_defs[i].mrd_compat_syntaxes == NULL )
5065 "slap_schema_init: Ignoring unusable matching rule %s\n",
5066 mrule_defs[i].mrd_desc );
5070 res = register_matching_rule( &mrule_defs[i] );
5074 "slap_schema_init: Error registering matching rule %s\n",
5075 mrule_defs[i].mrd_desc );
5080 res = slap_schema_load();
5081 schema_init_done = 1;
5086 schema_destroy( void )
5095 if( schema_init_done ) {
5096 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5097 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );