1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
66 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
67 SLAP_INDEX_INTLEN_DEFAULT );
69 ldap_pvt_thread_mutex_t ad_undef_mutex;
70 ldap_pvt_thread_mutex_t oc_undef_mutex;
73 generalizedTimeValidate(
82 /* no value allowed */
83 return LDAP_INVALID_SYNTAX;
91 /* any value allowed */
95 #define berValidate blobValidate
102 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
103 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
108 /* X.509 related stuff */
116 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
119 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
120 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
121 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
122 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
126 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
129 /* X.509 certificate validation */
130 static int certificateValidate( Syntax *syntax, struct berval *in )
132 BerElementBuffer berbuf;
133 BerElement *ber = (BerElement *)&berbuf;
136 ber_int_t version = SLAP_X509_V1;
138 ber_init2( ber, in, LBER_USE_DER );
139 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
140 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 tag = ber_skip_tag( ber, &len ); /* Sequence */
142 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
143 tag = ber_peek_tag( ber, &len );
144 /* Optional version */
145 if ( tag == SLAP_X509_OPT_C_VERSION ) {
146 tag = ber_skip_tag( ber, &len );
147 tag = ber_get_int( ber, &version );
148 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
150 /* NOTE: don't try to parse Serial, because it might be longer
151 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
152 tag = ber_skip_tag( ber, &len ); /* Serial */
153 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
154 ber_skip_data( ber, len );
155 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
157 ber_skip_data( ber, len );
158 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
159 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
160 ber_skip_data( ber, len );
161 tag = ber_skip_tag( ber, &len ); /* Validity */
162 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
163 ber_skip_data( ber, len );
164 tag = ber_skip_tag( ber, &len ); /* Subject DN */
165 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
166 ber_skip_data( ber, len );
167 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
168 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
169 ber_skip_data( ber, len );
170 tag = ber_skip_tag( ber, &len );
171 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
172 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
173 ber_skip_data( ber, len );
174 tag = ber_skip_tag( ber, &len );
176 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
177 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
178 ber_skip_data( ber, len );
179 tag = ber_skip_tag( ber, &len );
181 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
182 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
183 tag = ber_skip_tag( ber, &len );
184 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
185 ber_skip_data( ber, len );
186 tag = ber_skip_tag( ber, &len );
188 /* signatureAlgorithm */
189 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
190 ber_skip_data( ber, len );
191 tag = ber_skip_tag( ber, &len );
193 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
194 ber_skip_data( ber, len );
195 tag = ber_skip_tag( ber, &len );
196 /* Must be at end now */
197 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
201 /* X.509 certificate list validation */
202 static int certificateListValidate( Syntax *syntax, struct berval *in )
204 BerElementBuffer berbuf;
205 BerElement *ber = (BerElement *)&berbuf;
208 ber_int_t version = SLAP_X509_V1;
210 ber_init2( ber, in, LBER_USE_DER );
211 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
212 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
213 tag = ber_skip_tag( ber, &len ); /* Sequence */
214 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
215 tag = ber_peek_tag( ber, &len );
216 /* Optional version */
217 if ( tag == LBER_INTEGER ) {
218 tag = ber_get_int( ber, &version );
219 assert( tag == LBER_INTEGER );
220 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
222 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
223 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
224 ber_skip_data( ber, len );
225 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
226 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
227 ber_skip_data( ber, len );
228 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
229 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
230 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
231 ber_skip_data( ber, len );
232 /* Optional nextUpdate */
233 tag = ber_skip_tag( ber, &len );
234 if ( tag == 0x17U || tag == 0x18U ) {
235 ber_skip_data( ber, len );
236 tag = ber_skip_tag( ber, &len );
238 /* revokedCertificates - Sequence of Sequence, Optional */
239 if ( tag == LBER_SEQUENCE ) {
241 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
242 /* Should NOT be empty */
243 ber_skip_data( ber, len );
244 tag = ber_skip_tag( ber, &len );
247 /* Optional Extensions */
248 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
249 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
250 tag = ber_skip_tag( ber, &len );
251 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
252 ber_skip_data( ber, len );
253 tag = ber_skip_tag( ber, &len );
255 /* signatureAlgorithm */
256 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
257 ber_skip_data( ber, len );
258 tag = ber_skip_tag( ber, &len );
260 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
261 ber_skip_data( ber, len );
262 tag = ber_skip_tag( ber, &len );
263 /* Must be at end now */
264 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
274 struct berval *value,
275 void *assertedValue )
277 struct berval *asserted = (struct berval *) assertedValue;
278 int match = value->bv_len - asserted->bv_len;
281 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
289 octetStringOrderingMatch(
294 struct berval *value,
295 void *assertedValue )
297 struct berval *asserted = (struct berval *) assertedValue;
298 ber_len_t v_len = value->bv_len;
299 ber_len_t av_len = asserted->bv_len;
301 int match = memcmp( value->bv_val, asserted->bv_val,
302 (v_len < av_len ? v_len : av_len) );
304 if( match == 0 ) match = v_len - av_len;
312 HASH_CONTEXT *HASHcontext,
313 struct berval *prefix,
318 HASH_Init(HASHcontext);
319 if(prefix && prefix->bv_len > 0) {
320 HASH_Update(HASHcontext,
321 (unsigned char *)prefix->bv_val, prefix->bv_len);
323 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
324 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
325 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
331 HASH_CONTEXT *HASHcontext,
332 unsigned char *HASHdigest,
333 unsigned char *value,
336 HASH_CONTEXT ctx = *HASHcontext;
337 HASH_Update( &ctx, value, len );
338 HASH_Final( HASHdigest, &ctx );
341 /* Index generation function */
342 int octetStringIndexer(
347 struct berval *prefix,
355 HASH_CONTEXT HASHcontext;
356 unsigned char HASHdigest[HASH_BYTES];
357 struct berval digest;
358 digest.bv_val = (char *)HASHdigest;
359 digest.bv_len = sizeof(HASHdigest);
361 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
362 /* just count them */
365 /* we should have at least one value at this point */
368 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
370 slen = syntax->ssyn_oidlen;
371 mlen = mr->smr_oidlen;
373 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
374 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
375 hashIter( &HASHcontext, HASHdigest,
376 (unsigned char *)values[i].bv_val, values[i].bv_len );
377 ber_dupbv_x( &keys[i], &digest, ctx );
380 BER_BVZERO( &keys[i] );
387 /* Index generation function */
388 int octetStringFilter(
393 struct berval *prefix,
394 void * assertedValue,
400 HASH_CONTEXT HASHcontext;
401 unsigned char HASHdigest[HASH_BYTES];
402 struct berval *value = (struct berval *) assertedValue;
403 struct berval digest;
404 digest.bv_val = (char *)HASHdigest;
405 digest.bv_len = sizeof(HASHdigest);
407 slen = syntax->ssyn_oidlen;
408 mlen = mr->smr_oidlen;
410 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
412 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
413 hashIter( &HASHcontext, HASHdigest,
414 (unsigned char *)value->bv_val, value->bv_len );
416 ber_dupbv_x( keys, &digest, ctx );
417 BER_BVZERO( &keys[1] );
425 octetStringSubstringsMatch(
430 struct berval *value,
431 void *assertedValue )
434 SubstringsAssertion *sub = assertedValue;
435 struct berval left = *value;
439 /* Add up asserted input length */
440 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
441 inlen += sub->sa_initial.bv_len;
444 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
445 inlen += sub->sa_any[i].bv_len;
448 if ( !BER_BVISNULL( &sub->sa_final ) ) {
449 inlen += sub->sa_final.bv_len;
452 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
453 if ( inlen > left.bv_len ) {
458 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
459 sub->sa_initial.bv_len );
465 left.bv_val += sub->sa_initial.bv_len;
466 left.bv_len -= sub->sa_initial.bv_len;
467 inlen -= sub->sa_initial.bv_len;
470 if ( !BER_BVISNULL( &sub->sa_final ) ) {
471 if ( inlen > left.bv_len ) {
476 match = memcmp( sub->sa_final.bv_val,
477 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
478 sub->sa_final.bv_len );
484 left.bv_len -= sub->sa_final.bv_len;
485 inlen -= sub->sa_final.bv_len;
489 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
494 if ( inlen > left.bv_len ) {
495 /* not enough length */
500 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
504 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
511 idx = p - left.bv_val;
513 if ( idx >= left.bv_len ) {
514 /* this shouldn't happen */
521 if ( sub->sa_any[i].bv_len > left.bv_len ) {
522 /* not enough left */
527 match = memcmp( left.bv_val,
528 sub->sa_any[i].bv_val,
529 sub->sa_any[i].bv_len );
537 left.bv_val += sub->sa_any[i].bv_len;
538 left.bv_len -= sub->sa_any[i].bv_len;
539 inlen -= sub->sa_any[i].bv_len;
548 /* Substrings Index generation function */
550 octetStringSubstringsIndexer(
555 struct berval *prefix,
564 HASH_CONTEXT HCany, HCini, HCfin;
565 unsigned char HASHdigest[HASH_BYTES];
566 struct berval digest;
567 digest.bv_val = (char *)HASHdigest;
568 digest.bv_len = sizeof(HASHdigest);
572 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
573 /* count number of indices to generate */
574 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
575 if( values[i].bv_len >= index_substr_if_maxlen ) {
576 nkeys += index_substr_if_maxlen -
577 (index_substr_if_minlen - 1);
578 } else if( values[i].bv_len >= index_substr_if_minlen ) {
579 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
583 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
584 if( values[i].bv_len >= index_substr_any_len ) {
585 nkeys += values[i].bv_len - (index_substr_any_len - 1);
589 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
590 if( values[i].bv_len >= index_substr_if_maxlen ) {
591 nkeys += index_substr_if_maxlen -
592 (index_substr_if_minlen - 1);
593 } else if( values[i].bv_len >= index_substr_if_minlen ) {
594 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
600 /* no keys to generate */
605 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
607 slen = syntax->ssyn_oidlen;
608 mlen = mr->smr_oidlen;
610 if ( flags & SLAP_INDEX_SUBSTR_ANY )
611 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
612 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
613 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
614 if( flags & SLAP_INDEX_SUBSTR_FINAL )
615 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
618 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
621 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
622 ( values[i].bv_len >= index_substr_any_len ) )
624 max = values[i].bv_len - (index_substr_any_len - 1);
626 for( j=0; j<max; j++ ) {
627 hashIter( &HCany, HASHdigest,
628 (unsigned char *)&values[i].bv_val[j],
629 index_substr_any_len );
630 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
634 /* skip if too short */
635 if( values[i].bv_len < index_substr_if_minlen ) continue;
637 max = index_substr_if_maxlen < values[i].bv_len
638 ? index_substr_if_maxlen : values[i].bv_len;
640 for( j=index_substr_if_minlen; j<=max; j++ ) {
642 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
643 hashIter( &HCini, HASHdigest,
644 (unsigned char *)values[i].bv_val, j );
645 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
648 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
649 hashIter( &HCfin, HASHdigest,
650 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
651 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
658 BER_BVZERO( &keys[nkeys] );
669 octetStringSubstringsFilter (
674 struct berval *prefix,
675 void * assertedValue,
679 SubstringsAssertion *sa;
682 size_t slen, mlen, klen;
684 HASH_CONTEXT HASHcontext;
685 unsigned char HASHdigest[HASH_BYTES];
686 struct berval *value;
687 struct berval digest;
689 sa = (SubstringsAssertion *) assertedValue;
691 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
692 !BER_BVISNULL( &sa->sa_initial ) &&
693 sa->sa_initial.bv_len >= index_substr_if_minlen )
696 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
697 ( flags & SLAP_INDEX_SUBSTR_ANY ))
699 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
703 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
705 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
706 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
707 /* don't bother accounting with stepping */
708 nkeys += sa->sa_any[i].bv_len -
709 ( index_substr_any_len - 1 );
714 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
715 !BER_BVISNULL( &sa->sa_final ) &&
716 sa->sa_final.bv_len >= index_substr_if_minlen )
719 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
720 ( flags & SLAP_INDEX_SUBSTR_ANY ))
722 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
731 digest.bv_val = (char *)HASHdigest;
732 digest.bv_len = sizeof(HASHdigest);
734 slen = syntax->ssyn_oidlen;
735 mlen = mr->smr_oidlen;
737 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
740 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
741 !BER_BVISNULL( &sa->sa_initial ) &&
742 sa->sa_initial.bv_len >= index_substr_if_minlen )
744 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
745 value = &sa->sa_initial;
747 klen = index_substr_if_maxlen < value->bv_len
748 ? index_substr_if_maxlen : value->bv_len;
750 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
751 hashIter( &HASHcontext, HASHdigest,
752 (unsigned char *)value->bv_val, klen );
753 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
755 /* If initial is too long and we have subany indexed, use it
756 * to match the excess...
758 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
761 pre = SLAP_INDEX_SUBSTR_PREFIX;
762 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
763 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
765 hashIter( &HASHcontext, HASHdigest,
766 (unsigned char *)&value->bv_val[j], index_substr_any_len );
767 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
772 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
774 pre = SLAP_INDEX_SUBSTR_PREFIX;
775 klen = index_substr_any_len;
777 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
778 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
782 value = &sa->sa_any[i];
784 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
786 j <= value->bv_len - index_substr_any_len;
787 j += index_substr_any_step )
789 hashIter( &HASHcontext, HASHdigest,
790 (unsigned char *)&value->bv_val[j], klen );
791 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
796 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
797 !BER_BVISNULL( &sa->sa_final ) &&
798 sa->sa_final.bv_len >= index_substr_if_minlen )
800 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
801 value = &sa->sa_final;
803 klen = index_substr_if_maxlen < value->bv_len
804 ? index_substr_if_maxlen : value->bv_len;
806 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
807 hashIter( &HASHcontext, HASHdigest,
808 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
809 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
811 /* If final is too long and we have subany indexed, use it
812 * to match the excess...
814 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
817 pre = SLAP_INDEX_SUBSTR_PREFIX;
818 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
819 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
821 hashIter( &HASHcontext, HASHdigest,
822 (unsigned char *)&value->bv_val[j], index_substr_any_len );
823 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
829 BER_BVZERO( &keys[nkeys] );
846 /* very unforgiving validation, requires no normalization
847 * before simplistic matching
849 if( in->bv_len < 3 ) {
850 return LDAP_INVALID_SYNTAX;
853 /* RFC 4517 Section 3.3.2 Bit String:
854 * BitString = SQUOTE *binary-digit SQUOTE "B"
855 * binary-digit = "0" / "1"
857 * where SQUOTE [RFC4512] is
858 * SQUOTE = %x27 ; single quote ("'")
860 * Example: '0101111101'B
863 if( in->bv_val[0] != '\'' ||
864 in->bv_val[in->bv_len - 2] != '\'' ||
865 in->bv_val[in->bv_len - 1] != 'B' )
867 return LDAP_INVALID_SYNTAX;
870 for( i = in->bv_len - 3; i > 0; i-- ) {
871 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
872 return LDAP_INVALID_SYNTAX;
880 * Syntaxes from RFC 4517
885 A value of the Bit String syntax is a sequence of binary digits. The
886 LDAP-specific encoding of a value of this syntax is defined by the
889 BitString = SQUOTE *binary-digit SQUOTE "B"
891 binary-digit = "0" / "1"
893 The <SQUOTE> rule is defined in [MODELS].
898 The LDAP definition for the Bit String syntax is:
900 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
902 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
906 3.3.21. Name and Optional UID
908 A value of the Name and Optional UID syntax is the distinguished name
909 [MODELS] of an entity optionally accompanied by a unique identifier
910 that serves to differentiate the entity from others with an identical
913 The LDAP-specific encoding of a value of this syntax is defined by
916 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
918 The <BitString> rule is defined in Section 3.3.2. The
919 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
922 Note that although the '#' character may occur in the string
923 representation of a distinguished name, no additional escaping of
924 this character is performed when a <distinguishedName> is encoded in
925 a <NameAndOptionalUID>.
928 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
930 The LDAP definition for the Name and Optional UID syntax is:
932 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
934 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
941 1.4. Common ABNF Productions
944 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
946 SQUOTE = %x27 ; single quote ("'")
950 * Note: normalization strips any leading "0"s, unless the
951 * bit string is exactly "'0'B", so the normalized example,
952 * in slapd, would result in
954 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
956 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
957 * be escaped except when at the beginning of a value, the
958 * definition of Name and Optional UID appears to be flawed,
959 * because there is no clear means to determine whether the
960 * UID part is present or not.
964 * cn=Someone,dc=example,dc=com#'1'B
966 * could be either a NameAndOptionalUID with trailing UID, i.e.
968 * DN = "cn=Someone,dc=example,dc=com"
971 * or a NameAndOptionalUID with no trailing UID, and the AVA
972 * in the last RDN made of
975 * attributeValue = com#'1'B
977 * in fact "com#'1'B" is a valid IA5 string.
979 * As a consequence, current slapd code assumes that the
980 * presence of portions of a BitString at the end of the string
981 * representation of a NameAndOptionalUID means a BitString
982 * is expected, and cause an error otherwise. This is quite
983 * arbitrary, and might change in the future.
993 struct berval dn, uid;
995 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
997 ber_dupbv( &dn, in );
998 if( !dn.bv_val ) return LDAP_OTHER;
1000 /* if there's a "#", try bitStringValidate()... */
1001 uid.bv_val = strrchr( dn.bv_val, '#' );
1002 if ( !BER_BVISNULL( &uid ) ) {
1004 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1006 rc = bitStringValidate( NULL, &uid );
1007 if ( rc == LDAP_SUCCESS ) {
1008 /* in case of success, trim the UID,
1009 * otherwise treat it as part of the DN */
1010 dn.bv_len -= uid.bv_len + 1;
1011 uid.bv_val[-1] = '\0';
1015 rc = dnValidate( NULL, &dn );
1017 ber_memfree( dn.bv_val );
1028 assert( val != NULL );
1029 assert( out != NULL );
1032 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1034 if( BER_BVISEMPTY( val ) ) {
1035 ber_dupbv_x( out, val, ctx );
1037 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1038 return LDAP_INVALID_SYNTAX;
1042 struct berval dnval = *val;
1043 struct berval uidval = BER_BVNULL;
1045 uidval.bv_val = strrchr( val->bv_val, '#' );
1046 if ( !BER_BVISNULL( &uidval ) ) {
1048 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1050 rc = bitStringValidate( NULL, &uidval );
1052 if ( rc == LDAP_SUCCESS ) {
1053 ber_dupbv_x( &dnval, val, ctx );
1054 dnval.bv_len -= uidval.bv_len + 1;
1055 dnval.bv_val[dnval.bv_len] = '\0';
1058 BER_BVZERO( &uidval );
1062 rc = dnPretty( syntax, &dnval, out, ctx );
1063 if ( dnval.bv_val != val->bv_val ) {
1064 slap_sl_free( dnval.bv_val, ctx );
1066 if( rc != LDAP_SUCCESS ) {
1070 if( !BER_BVISNULL( &uidval ) ) {
1074 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1075 + STRLENOF( "#" ) + uidval.bv_len + 1,
1078 ber_memfree_x( out->bv_val, ctx );
1082 out->bv_val[out->bv_len++] = '#';
1083 out->bv_val[out->bv_len++] = '\'';
1085 got1 = uidval.bv_len < sizeof("'0'B");
1086 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1087 c = uidval.bv_val[i];
1090 if( got1 ) out->bv_val[out->bv_len++] = c;
1094 out->bv_val[out->bv_len++] = c;
1099 out->bv_val[out->bv_len++] = '\'';
1100 out->bv_val[out->bv_len++] = 'B';
1101 out->bv_val[out->bv_len] = '\0';
1105 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1107 return LDAP_SUCCESS;
1111 uniqueMemberNormalize(
1116 struct berval *normalized,
1122 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1124 ber_dupbv_x( &out, val, ctx );
1125 if ( BER_BVISEMPTY( &out ) ) {
1129 struct berval uid = BER_BVNULL;
1131 uid.bv_val = strrchr( out.bv_val, '#' );
1132 if ( !BER_BVISNULL( &uid ) ) {
1134 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1136 rc = bitStringValidate( NULL, &uid );
1137 if ( rc == LDAP_SUCCESS ) {
1138 uid.bv_val[-1] = '\0';
1139 out.bv_len -= uid.bv_len + 1;
1145 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1147 if( rc != LDAP_SUCCESS ) {
1148 slap_sl_free( out.bv_val, ctx );
1149 return LDAP_INVALID_SYNTAX;
1152 if( !BER_BVISNULL( &uid ) ) {
1155 tmp = ch_realloc( normalized->bv_val,
1156 normalized->bv_len + uid.bv_len
1157 + STRLENOF("#") + 1 );
1158 if ( tmp == NULL ) {
1159 ber_memfree_x( normalized->bv_val, ctx );
1163 normalized->bv_val = tmp;
1165 /* insert the separator */
1166 normalized->bv_val[normalized->bv_len++] = '#';
1168 /* append the UID */
1169 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1170 uid.bv_val, uid.bv_len );
1171 normalized->bv_len += uid.bv_len;
1174 normalized->bv_val[normalized->bv_len] = '\0';
1177 slap_sl_free( out.bv_val, ctx );
1180 return LDAP_SUCCESS;
1189 struct berval *value,
1190 void *assertedValue )
1193 struct berval *asserted = (struct berval *) assertedValue;
1194 struct berval assertedDN = *asserted;
1195 struct berval assertedUID = BER_BVNULL;
1196 struct berval valueDN = *value;
1197 struct berval valueUID = BER_BVNULL;
1198 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1200 if ( !BER_BVISEMPTY( asserted ) ) {
1201 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1202 if ( !BER_BVISNULL( &assertedUID ) ) {
1203 assertedUID.bv_val++;
1204 assertedUID.bv_len = assertedDN.bv_len
1205 - ( assertedUID.bv_val - assertedDN.bv_val );
1207 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1208 assertedDN.bv_len -= assertedUID.bv_len + 1;
1211 BER_BVZERO( &assertedUID );
1216 if ( !BER_BVISEMPTY( value ) ) {
1218 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1219 if ( !BER_BVISNULL( &valueUID ) ) {
1221 valueUID.bv_len = valueDN.bv_len
1222 - ( valueUID.bv_val - valueDN.bv_val );
1224 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1225 valueDN.bv_len -= valueUID.bv_len + 1;
1228 BER_BVZERO( &valueUID );
1233 if( valueUID.bv_len && assertedUID.bv_len ) {
1234 match = valueUID.bv_len - assertedUID.bv_len;
1237 return LDAP_SUCCESS;
1240 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1243 return LDAP_SUCCESS;
1246 } else if ( !approx && valueUID.bv_len ) {
1249 return LDAP_SUCCESS;
1251 } else if ( !approx && assertedUID.bv_len ) {
1254 return LDAP_SUCCESS;
1257 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1261 uniqueMemberIndexer(
1266 struct berval *prefix,
1274 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1275 /* just count them */
1279 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1281 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1282 struct berval assertedDN = values[i];
1283 struct berval assertedUID = BER_BVNULL;
1285 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1286 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1287 if ( !BER_BVISNULL( &assertedUID ) ) {
1288 assertedUID.bv_val++;
1289 assertedUID.bv_len = assertedDN.bv_len
1290 - ( assertedUID.bv_val - assertedDN.bv_val );
1292 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1293 assertedDN.bv_len -= assertedUID.bv_len + 1;
1296 BER_BVZERO( &assertedUID );
1301 dnvalues[i] = assertedDN;
1303 BER_BVZERO( &dnvalues[i] );
1305 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1306 dnvalues, keysp, ctx );
1308 slap_sl_free( dnvalues, ctx );
1318 struct berval *prefix,
1319 void * assertedValue,
1323 struct berval *asserted = (struct berval *) assertedValue;
1324 struct berval assertedDN = *asserted;
1325 struct berval assertedUID = BER_BVNULL;
1327 if ( !BER_BVISEMPTY( asserted ) ) {
1328 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1329 if ( !BER_BVISNULL( &assertedUID ) ) {
1330 assertedUID.bv_val++;
1331 assertedUID.bv_len = assertedDN.bv_len
1332 - ( assertedUID.bv_val - assertedDN.bv_val );
1334 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1335 assertedDN.bv_len -= assertedUID.bv_len + 1;
1338 BER_BVZERO( &assertedUID );
1343 return octetStringFilter( use, flags, syntax, mr, prefix,
1344 &assertedDN, keysp, ctx );
1349 * Handling boolean syntax and matching is quite rigid.
1350 * A more flexible approach would be to allow a variety
1351 * of strings to be normalized and prettied into TRUE
1359 /* very unforgiving validation, requires no normalization
1360 * before simplistic matching
1363 if( in->bv_len == 4 ) {
1364 if( bvmatch( in, &slap_true_bv ) ) {
1365 return LDAP_SUCCESS;
1367 } else if( in->bv_len == 5 ) {
1368 if( bvmatch( in, &slap_false_bv ) ) {
1369 return LDAP_SUCCESS;
1373 return LDAP_INVALID_SYNTAX;
1382 struct berval *value,
1383 void *assertedValue )
1385 /* simplistic matching allowed by rigid validation */
1386 struct berval *asserted = (struct berval *) assertedValue;
1387 *matchp = value->bv_len != asserted->bv_len;
1388 return LDAP_SUCCESS;
1391 /*-------------------------------------------------------------------
1392 LDAP/X.500 string syntax / matching rules have a few oddities. This
1393 comment attempts to detail how slapd(8) treats them.
1396 StringSyntax X.500 LDAP Matching/Comments
1397 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1398 PrintableString subset subset i/e + ignore insignificant spaces
1399 PrintableString subset subset i/e + ignore insignificant spaces
1400 NumericString subset subset ignore all spaces
1401 IA5String ASCII ASCII i/e + ignore insignificant spaces
1402 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1404 TelephoneNumber subset subset i + ignore all spaces and "-"
1406 See RFC 4518 for details.
1410 In X.500(93), a directory string can be either a PrintableString,
1411 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1412 In later versions, more CHOICEs were added. In all cases the string
1415 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1416 A directory string cannot be zero length.
1418 For matching, there are both case ignore and exact rules. Both
1419 also require that "insignificant" spaces be ignored.
1420 spaces before the first non-space are ignored;
1421 spaces after the last non-space are ignored;
1422 spaces after a space are ignored.
1423 Note: by these rules (and as clarified in X.520), a string of only
1424 spaces is to be treated as if held one space, not empty (which
1425 would be a syntax error).
1428 In ASN.1, numeric string is just a string of digits and spaces
1429 and could be empty. However, in X.500, all attribute values of
1430 numeric string carry a non-empty constraint. For example:
1432 internationalISDNNumber ATTRIBUTE ::= {
1433 WITH SYNTAX InternationalISDNNumber
1434 EQUALITY MATCHING RULE numericStringMatch
1435 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1436 ID id-at-internationalISDNNumber }
1437 InternationalISDNNumber ::=
1438 NumericString (SIZE(1..ub-international-isdn-number))
1440 Unforunately, some assertion values are don't carry the same
1441 constraint (but its unclear how such an assertion could ever
1442 be true). In LDAP, there is one syntax (numericString) not two
1443 (numericString with constraint, numericString without constraint).
1444 This should be treated as numericString with non-empty constraint.
1445 Note that while someone may have no ISDN number, there are no ISDN
1446 numbers which are zero length.
1448 In matching, spaces are ignored.
1451 In ASN.1, Printable string is just a string of printable characters
1452 and can be empty. In X.500, semantics much like NumericString (see
1453 serialNumber for a like example) excepting uses insignificant space
1454 handling instead of ignore all spaces. They must be non-empty.
1457 Basically same as PrintableString. There are no examples in X.500,
1458 but same logic applies. Empty strings are allowed.
1460 -------------------------------------------------------------------*/
1469 unsigned char *u = (unsigned char *)in->bv_val;
1471 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1472 /* directory strings cannot be empty */
1473 return LDAP_INVALID_SYNTAX;
1476 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1477 /* get the length indicated by the first byte */
1478 len = LDAP_UTF8_CHARLEN2( u, len );
1480 /* very basic checks */
1483 if( (u[5] & 0xC0) != 0x80 ) {
1484 return LDAP_INVALID_SYNTAX;
1487 if( (u[4] & 0xC0) != 0x80 ) {
1488 return LDAP_INVALID_SYNTAX;
1491 if( (u[3] & 0xC0) != 0x80 ) {
1492 return LDAP_INVALID_SYNTAX;
1495 if( (u[2] & 0xC0 )!= 0x80 ) {
1496 return LDAP_INVALID_SYNTAX;
1499 if( (u[1] & 0xC0) != 0x80 ) {
1500 return LDAP_INVALID_SYNTAX;
1503 /* CHARLEN already validated it */
1506 return LDAP_INVALID_SYNTAX;
1509 /* make sure len corresponds with the offset
1510 to the next character */
1511 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1515 return LDAP_INVALID_SYNTAX;
1518 return LDAP_SUCCESS;
1522 UTF8StringNormalize(
1527 struct berval *normalized,
1530 struct berval tmp, nvalue;
1534 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1536 if( BER_BVISNULL( val ) ) {
1537 /* assume we're dealing with a syntax (e.g., UTF8String)
1538 * which allows empty strings
1540 BER_BVZERO( normalized );
1541 return LDAP_SUCCESS;
1544 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1545 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1546 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1547 ? LDAP_UTF8_APPROX : 0;
1549 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1554 /* collapse spaces (in place) */
1556 nvalue.bv_val = tmp.bv_val;
1558 /* trim leading spaces? */
1559 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1560 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1562 for( i = 0; i < tmp.bv_len; i++) {
1563 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1564 if( wasspace++ == 0 ) {
1565 /* trim repeated spaces */
1566 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1570 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1574 if( !BER_BVISEMPTY( &nvalue ) ) {
1575 /* trim trailing space? */
1577 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1578 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1582 nvalue.bv_val[nvalue.bv_len] = '\0';
1585 /* string of all spaces is treated as one space */
1586 nvalue.bv_val[0] = ' ';
1587 nvalue.bv_val[1] = '\0';
1591 *normalized = nvalue;
1592 return LDAP_SUCCESS;
1596 directoryStringSubstringsMatch(
1601 struct berval *value,
1602 void *assertedValue )
1605 SubstringsAssertion *sub = assertedValue;
1606 struct berval left = *value;
1610 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1611 if ( sub->sa_initial.bv_len > left.bv_len ) {
1612 /* not enough left */
1617 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1618 sub->sa_initial.bv_len );
1624 left.bv_val += sub->sa_initial.bv_len;
1625 left.bv_len -= sub->sa_initial.bv_len;
1627 priorspace = ASCII_SPACE(
1628 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1631 if ( sub->sa_any ) {
1632 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1636 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1637 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1639 /* allow next space to match */
1646 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1650 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1651 /* not enough left */
1656 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1663 idx = p - left.bv_val;
1665 if ( idx >= left.bv_len ) {
1666 /* this shouldn't happen */
1673 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1674 /* not enough left */
1679 match = memcmp( left.bv_val,
1680 sub->sa_any[i].bv_val,
1681 sub->sa_any[i].bv_len );
1689 left.bv_val += sub->sa_any[i].bv_len;
1690 left.bv_len -= sub->sa_any[i].bv_len;
1692 priorspace = ASCII_SPACE(
1693 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1697 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1698 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1699 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1701 /* allow next space to match */
1706 if ( sub->sa_final.bv_len > left.bv_len ) {
1707 /* not enough left */
1712 match = memcmp( sub->sa_final.bv_val,
1713 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1714 sub->sa_final.bv_len );
1723 return LDAP_SUCCESS;
1726 #if defined(SLAPD_APPROX_INITIALS)
1727 # define SLAPD_APPROX_DELIMITER "._ "
1728 # define SLAPD_APPROX_WORDLEN 2
1730 # define SLAPD_APPROX_DELIMITER " "
1731 # define SLAPD_APPROX_WORDLEN 1
1740 struct berval *value,
1741 void *assertedValue )
1743 struct berval *nval, *assertv;
1744 char *val, **values, **words, *c;
1745 int i, count, len, nextchunk=0, nextavail=0;
1747 /* Yes, this is necessary */
1748 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1749 if( nval == NULL ) {
1751 return LDAP_SUCCESS;
1754 /* Yes, this is necessary */
1755 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1756 NULL, LDAP_UTF8_APPROX, NULL );
1757 if( assertv == NULL ) {
1760 return LDAP_SUCCESS;
1763 /* Isolate how many words there are */
1764 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1765 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1766 if ( c == NULL ) break;
1771 /* Get a phonetic copy of each word */
1772 words = (char **)ch_malloc( count * sizeof(char *) );
1773 values = (char **)ch_malloc( count * sizeof(char *) );
1774 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1776 values[i] = phonetic(c);
1779 /* Work through the asserted value's words, to see if at least some
1780 of the words are there, in the same order. */
1782 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1783 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1788 #if defined(SLAPD_APPROX_INITIALS)
1789 else if( len == 1 ) {
1790 /* Single letter words need to at least match one word's initial */
1791 for( i=nextavail; i<count; i++ )
1792 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1799 /* Isolate the next word in the asserted value and phonetic it */
1800 assertv->bv_val[nextchunk+len] = '\0';
1801 val = phonetic( assertv->bv_val + nextchunk );
1803 /* See if this phonetic chunk is in the remaining words of *value */
1804 for( i=nextavail; i<count; i++ ){
1805 if( !strcmp( val, values[i] ) ){
1813 /* This chunk in the asserted value was NOT within the *value. */
1819 /* Go on to the next word in the asserted value */
1823 /* If some of the words were seen, call it a match */
1824 if( nextavail > 0 ) {
1831 /* Cleanup allocs */
1832 ber_bvfree( assertv );
1833 for( i=0; i<count; i++ ) {
1834 ch_free( values[i] );
1840 return LDAP_SUCCESS;
1849 struct berval *prefix,
1855 int i,j, len, wordcount, keycount=0;
1856 struct berval *newkeys;
1857 BerVarray keys=NULL;
1859 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1860 struct berval val = BER_BVNULL;
1861 /* Yes, this is necessary */
1862 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1863 assert( !BER_BVISNULL( &val ) );
1865 /* Isolate how many words there are. There will be a key for each */
1866 for( wordcount = 0, c = val.bv_val; *c; c++) {
1867 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1868 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1870 if (*c == '\0') break;
1874 /* Allocate/increase storage to account for new keys */
1875 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1876 * sizeof(struct berval) );
1877 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1878 if( keys ) ch_free( keys );
1881 /* Get a phonetic copy of each word */
1882 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1884 if( len < SLAPD_APPROX_WORDLEN ) continue;
1885 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1890 ber_memfree( val.bv_val );
1892 BER_BVZERO( &keys[keycount] );
1895 return LDAP_SUCCESS;
1904 struct berval *prefix,
1905 void * assertedValue,
1914 /* Yes, this is necessary */
1915 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1916 NULL, LDAP_UTF8_APPROX, NULL );
1917 if( val == NULL || BER_BVISNULL( val ) ) {
1918 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1919 BER_BVZERO( &keys[0] );
1922 return LDAP_SUCCESS;
1925 /* Isolate how many words there are. There will be a key for each */
1926 for( count = 0,c = val->bv_val; *c; c++) {
1927 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1928 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1930 if (*c == '\0') break;
1934 /* Allocate storage for new keys */
1935 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1937 /* Get a phonetic copy of each word */
1938 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1940 if( len < SLAPD_APPROX_WORDLEN ) continue;
1941 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1947 BER_BVZERO( &keys[count] );
1950 return LDAP_SUCCESS;
1953 /* Remove all spaces and '-' characters */
1955 telephoneNumberNormalize(
1960 struct berval *normalized,
1965 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1967 /* validator should have refused an empty string */
1968 assert( !BER_BVISEMPTY( val ) );
1970 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1972 for( p = val->bv_val; *p; p++ ) {
1973 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1979 normalized->bv_len = q - normalized->bv_val;
1981 if( BER_BVISEMPTY( normalized ) ) {
1982 slap_sl_free( normalized->bv_val, ctx );
1983 BER_BVZERO( normalized );
1984 return LDAP_INVALID_SYNTAX;
1987 return LDAP_SUCCESS;
1995 struct berval val = *in;
1997 if( BER_BVISEMPTY( &val ) ) {
1998 /* disallow empty strings */
1999 return LDAP_INVALID_SYNTAX;
2002 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2003 if ( val.bv_len == 1 ) {
2004 return LDAP_SUCCESS;
2007 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2014 while ( OID_LEADCHAR( val.bv_val[0] )) {
2018 if ( val.bv_len == 0 ) {
2019 return LDAP_SUCCESS;
2023 if( !OID_SEPARATOR( val.bv_val[0] )) {
2031 return LDAP_INVALID_SYNTAX;
2040 struct berval val = *in;
2042 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2044 if ( val.bv_val[0] == '-' ) {
2048 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2049 return LDAP_INVALID_SYNTAX;
2052 if( val.bv_val[0] == '0' ) { /* "-0" */
2053 return LDAP_INVALID_SYNTAX;
2056 } else if ( val.bv_val[0] == '0' ) {
2057 if( val.bv_len > 1 ) { /* "0<more>" */
2058 return LDAP_INVALID_SYNTAX;
2061 return LDAP_SUCCESS;
2064 for( i=0; i < val.bv_len; i++ ) {
2065 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2066 return LDAP_INVALID_SYNTAX;
2070 return LDAP_SUCCESS;
2079 struct berval *value,
2080 void *assertedValue )
2082 struct berval *asserted = (struct berval *) assertedValue;
2083 int vsign = 1, asign = 1; /* default sign = '+' */
2088 if( v.bv_val[0] == '-' ) {
2094 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2097 if( a.bv_val[0] == '-' ) {
2103 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2105 match = vsign - asign;
2107 match = ( v.bv_len != a.bv_len
2108 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2109 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2110 if( vsign < 0 ) match = -match;
2114 return LDAP_SUCCESS;
2117 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2118 #define INDEX_INTLEN_CHOP 7
2119 #define INDEX_INTLEN_CHOPBYTES 3
2129 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2130 * two's complement value (sign-extended or chopped as needed),
2131 * however the top <number of exponent-bytes + 1> bits of first byte
2132 * above is the inverse sign. The next bit is the sign as delimiter.
2134 ber_slen_t k = index_intlen_strlen;
2136 unsigned signmask = ~0x7fU;
2137 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2138 struct berval val = *in, itmp = *tmp;
2140 if ( val.bv_val[0] != '-' ) {
2145 /* Chop least significant digits, increase length instead */
2146 if ( val.bv_len > (ber_len_t) k ) {
2147 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2148 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2149 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2152 if ( lutil_str2bin( &val, &itmp, ctx )) {
2153 return LDAP_INVALID_SYNTAX;
2156 /* Omit leading sign byte */
2157 if ( itmp.bv_val[0] == neg ) {
2162 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2164 assert( chop == 0 );
2165 memset( key->bv_val, neg, k ); /* sign-extend */
2166 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2167 lenp = lenbuf + sizeof(lenbuf);
2168 chop = - (ber_len_t) k;
2170 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2172 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2173 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2174 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2175 k = (lenbuf + sizeof(lenbuf)) - lenp;
2176 if ( k > (ber_slen_t) index_intlen )
2178 memcpy( key->bv_val, lenp, k );
2179 itmp.bv_len = index_intlen - k;
2181 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2182 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2186 /* Index generation function */
2193 struct berval *prefix,
2203 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2205 /* count the values and find max needed length */
2207 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2208 if ( vlen < values[i].bv_len )
2209 vlen = values[i].bv_len;
2211 if ( vlen > maxstrlen )
2214 /* we should have at least one value at this point */
2217 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2218 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2219 keys[i].bv_len = index_intlen;
2220 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2223 keys[i].bv_val = NULL;
2225 if ( vlen > sizeof(ibuf) ) {
2226 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2230 itmp.bv_len = sizeof(ibuf);
2232 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2233 if ( itmp.bv_val != ibuf ) {
2234 itmp.bv_len = values[i].bv_len;
2235 if ( itmp.bv_len <= sizeof(ibuf) )
2236 itmp.bv_len = sizeof(ibuf);
2237 else if ( itmp.bv_len > maxstrlen )
2238 itmp.bv_len = maxstrlen;
2240 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2246 if ( itmp.bv_val != ibuf ) {
2247 slap_sl_free( itmp.bv_val, ctx );
2252 /* Index generation function */
2259 struct berval *prefix,
2260 void * assertedValue,
2267 struct berval *value;
2270 value = (struct berval *) assertedValue;
2272 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2274 keys[0].bv_len = index_intlen;
2275 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2277 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2278 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2279 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2280 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2283 iv.bv_len = sizeof(ibuf);
2286 rc = integerVal2Key( value, keys, &iv, ctx );
2290 if ( iv.bv_val != ibuf ) {
2291 slap_sl_free( iv.bv_val, ctx );
2297 countryStringValidate(
2299 struct berval *val )
2301 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2303 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2304 return LDAP_INVALID_SYNTAX;
2306 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2307 return LDAP_INVALID_SYNTAX;
2310 return LDAP_SUCCESS;
2314 printableStringValidate(
2316 struct berval *val )
2320 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2322 for(i=0; i < val->bv_len; i++) {
2323 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2324 return LDAP_INVALID_SYNTAX;
2328 return LDAP_SUCCESS;
2332 printablesStringValidate(
2334 struct berval *val )
2338 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2340 for(i=0,len=0; i < val->bv_len; i++) {
2341 int c = val->bv_val[i];
2345 return LDAP_INVALID_SYNTAX;
2349 } else if ( SLAP_PRINTABLE(c) ) {
2352 return LDAP_INVALID_SYNTAX;
2357 return LDAP_INVALID_SYNTAX;
2360 return LDAP_SUCCESS;
2366 struct berval *val )
2370 for(i=0; i < val->bv_len; i++) {
2371 if( !LDAP_ASCII(val->bv_val[i]) ) {
2372 return LDAP_INVALID_SYNTAX;
2376 return LDAP_SUCCESS;
2385 struct berval *normalized,
2389 int casefold = !SLAP_MR_ASSOCIATED( mr,
2390 slap_schema.si_mr_caseExactIA5Match );
2392 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2396 /* Ignore initial whitespace */
2397 while ( ASCII_SPACE( *p ) ) p++;
2399 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2400 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2401 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2402 normalized->bv_val[normalized->bv_len] = '\0';
2404 p = q = normalized->bv_val;
2407 if ( ASCII_SPACE( *p ) ) {
2410 /* Ignore the extra whitespace */
2411 while ( ASCII_SPACE( *p ) ) {
2415 } else if ( casefold ) {
2416 /* Most IA5 rules require casefolding */
2417 *q++ = TOLOWER(*p); p++;
2424 assert( normalized->bv_val <= p );
2428 * If the string ended in space, backup the pointer one
2429 * position. One is enough because the above loop collapsed
2430 * all whitespace to a single space.
2432 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2434 /* null terminate */
2437 normalized->bv_len = q - normalized->bv_val;
2439 return LDAP_SUCCESS;
2448 if( in->bv_len != 36 ) {
2449 return LDAP_INVALID_SYNTAX;
2452 for( i=0; i<36; i++ ) {
2458 if( in->bv_val[i] != '-' ) {
2459 return LDAP_INVALID_SYNTAX;
2463 if( !ASCII_HEX( in->bv_val[i]) ) {
2464 return LDAP_INVALID_SYNTAX;
2469 return LDAP_SUCCESS;
2480 int rc=LDAP_INVALID_SYNTAX;
2482 assert( in != NULL );
2483 assert( out != NULL );
2485 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2488 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2490 for( i=0; i<36; i++ ) {
2496 if( in->bv_val[i] != '-' ) {
2499 out->bv_val[i] = '-';
2503 if( !ASCII_HEX( in->bv_val[i]) ) {
2506 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2511 out->bv_val[ out->bv_len ] = '\0';
2515 slap_sl_free( out->bv_val, ctx );
2528 struct berval *normalized,
2531 unsigned char octet = '\0';
2535 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2536 /* NOTE: must be a normalized UUID */
2537 assert( val->bv_len == 16 );
2539 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2540 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2541 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2542 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2544 return LDAP_SUCCESS;
2547 normalized->bv_len = 16;
2548 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2550 for( i=0, j=0; i<36; i++ ) {
2551 unsigned char nibble;
2552 if( val->bv_val[i] == '-' ) {
2555 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2556 nibble = val->bv_val[i] - '0';
2558 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2559 nibble = val->bv_val[i] - ('a'-10);
2561 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2562 nibble = val->bv_val[i] - ('A'-10);
2565 slap_sl_free( normalized->bv_val, ctx );
2566 return LDAP_INVALID_SYNTAX;
2571 normalized->bv_val[j>>1] = octet;
2573 octet = nibble << 4;
2578 normalized->bv_val[normalized->bv_len] = 0;
2579 return LDAP_SUCCESS;
2585 numericStringValidate(
2591 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2593 for(i=0; i < in->bv_len; i++) {
2594 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2595 return LDAP_INVALID_SYNTAX;
2599 return LDAP_SUCCESS;
2603 numericStringNormalize(
2608 struct berval *normalized,
2611 /* removal all spaces */
2614 assert( !BER_BVISEMPTY( val ) );
2616 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2619 q = normalized->bv_val;
2622 if ( ASCII_SPACE( *p ) ) {
2623 /* Ignore whitespace */
2630 /* we should have copied no more than is in val */
2631 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2633 /* null terminate */
2636 normalized->bv_len = q - normalized->bv_val;
2638 if( BER_BVISEMPTY( normalized ) ) {
2639 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2640 normalized->bv_val[0] = ' ';
2641 normalized->bv_val[1] = '\0';
2642 normalized->bv_len = 1;
2645 return LDAP_SUCCESS;
2649 * Integer conversion macros that will use the largest available
2652 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2653 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2654 # define SLAP_LONG long long
2656 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2657 # define SLAP_LONG long
2658 #endif /* HAVE_STRTOLL ... */
2666 struct berval *value,
2667 void *assertedValue )
2669 SLAP_LONG lValue, lAssertedValue;
2672 /* safe to assume integers are NUL terminated? */
2673 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2674 if( errno == ERANGE )
2676 return LDAP_CONSTRAINT_VIOLATION;
2679 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2681 if( errno == ERANGE )
2683 return LDAP_CONSTRAINT_VIOLATION;
2686 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2687 return LDAP_SUCCESS;
2696 struct berval *value,
2697 void *assertedValue )
2699 SLAP_LONG lValue, lAssertedValue;
2702 /* safe to assume integers are NUL terminated? */
2703 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2704 if( errno == ERANGE )
2706 return LDAP_CONSTRAINT_VIOLATION;
2709 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2711 if( errno == ERANGE )
2713 return LDAP_CONSTRAINT_VIOLATION;
2716 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2717 return LDAP_SUCCESS;
2721 serialNumberAndIssuerCheck(
2730 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2732 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2733 /* Parse old format */
2734 is->bv_val = ber_bvchr( in, '$' );
2735 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2737 sn->bv_val = in->bv_val;
2738 sn->bv_len = is->bv_val - in->bv_val;
2741 is->bv_len = in->bv_len - (sn->bv_len + 1);
2743 /* eat leading zeros */
2744 for( n=0; n < (sn->bv_len-1); n++ ) {
2745 if( sn->bv_val[n] != '0' ) break;
2750 for( n=0; n < sn->bv_len; n++ ) {
2751 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2755 /* Parse GSER format */
2756 int havesn=0,haveissuer=0;
2757 struct berval x = *in;
2762 /* eat leading spaces */
2763 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2767 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2768 return LDAP_INVALID_SYNTAX;
2771 /* should be at issuer or serialNumber NamedValue */
2772 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2774 x.bv_val += STRLENOF("issuer");
2775 x.bv_len -= STRLENOF("issuer");
2777 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2778 x.bv_val++; x.bv_len--;
2780 /* eat leading spaces */
2781 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2785 /* For backward compatibility, this part is optional */
2786 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2787 x.bv_val += STRLENOF("rdnSequence:");
2788 x.bv_len -= STRLENOF("rdnSequence:");
2791 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2792 x.bv_val++; x.bv_len--;
2794 is->bv_val = x.bv_val;
2797 for( ; is->bv_len < x.bv_len; ) {
2798 if ( is->bv_val[is->bv_len] != '"' ) {
2802 if ( is->bv_val[is->bv_len+1] == '"' ) {
2809 x.bv_val += is->bv_len+1;
2810 x.bv_len -= is->bv_len+1;
2812 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2813 return LDAP_INVALID_SYNTAX;
2818 } else if( strncasecmp( x.bv_val, "serialNumber",
2819 STRLENOF("serialNumber")) == 0 )
2821 /* parse serialNumber */
2823 x.bv_val += STRLENOF("serialNumber");
2824 x.bv_len -= STRLENOF("serialNumber");
2826 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2827 x.bv_val++; x.bv_len--;
2829 /* eat leading spaces */
2830 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2834 sn->bv_val = x.bv_val;
2837 if( sn->bv_val[0] == '-' ) {
2842 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2843 sn->bv_val[1] == 'X' )) {
2845 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2846 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2848 } else if ( sn->bv_val[0] == '\'' ) {
2849 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2850 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2852 if ( sn->bv_val[sn->bv_len] == '\'' &&
2853 sn->bv_val[sn->bv_len+1] == 'H' )
2856 return LDAP_INVALID_SYNTAX;
2859 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2860 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2864 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2865 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2866 return LDAP_INVALID_SYNTAX;
2869 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2871 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2872 return LDAP_INVALID_SYNTAX;
2877 } else return LDAP_INVALID_SYNTAX;
2879 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2880 x.bv_val++; x.bv_len--;
2883 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2887 /* should be at remaining NamedValue */
2888 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2889 STRLENOF("issuer" )) == 0 ))
2892 x.bv_val += STRLENOF("issuer");
2893 x.bv_len -= STRLENOF("issuer");
2895 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2896 x.bv_val++; x.bv_len--;
2898 /* eat leading spaces */
2899 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2903 /* For backward compatibility, this part is optional */
2904 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2905 x.bv_val += STRLENOF("rdnSequence:");
2906 x.bv_len -= STRLENOF("rdnSequence:");
2909 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2910 x.bv_val++; x.bv_len--;
2912 is->bv_val = x.bv_val;
2915 for( ; is->bv_len < x.bv_len; ) {
2916 if ( is->bv_val[is->bv_len] != '"' ) {
2920 if ( is->bv_val[is->bv_len+1] == '"' ) {
2927 x.bv_val += is->bv_len+1;
2928 x.bv_len -= is->bv_len+1;
2930 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2931 STRLENOF("serialNumber")) == 0 ))
2933 /* parse serialNumber */
2935 x.bv_val += STRLENOF("serialNumber");
2936 x.bv_len -= STRLENOF("serialNumber");
2938 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2939 x.bv_val++; x.bv_len--;
2941 /* eat leading spaces */
2942 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2946 sn->bv_val = x.bv_val;
2949 if( sn->bv_val[0] == '-' ) {
2954 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2955 sn->bv_val[1] == 'X' )) {
2957 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2958 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2960 } else if ( sn->bv_val[0] == '\'' ) {
2961 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2962 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2964 if ( sn->bv_val[sn->bv_len] == '\'' &&
2965 sn->bv_val[sn->bv_len+1] == 'H' )
2968 return LDAP_INVALID_SYNTAX;
2971 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2972 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2976 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2977 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2978 return LDAP_INVALID_SYNTAX;
2981 x.bv_val += sn->bv_len;
2982 x.bv_len -= sn->bv_len;
2984 } else return LDAP_INVALID_SYNTAX;
2986 /* eat trailing spaces */
2987 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2991 /* should have no characters left... */
2992 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2994 ber_dupbv_x( &ni, is, ctx );
2997 /* need to handle double dquotes here */
3003 serialNumberAndIssuerValidate(
3008 struct berval sn, i;
3010 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3013 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3017 /* validate DN -- doesn't handle double dquote */
3018 rc = dnValidate( NULL, &i );
3020 rc = LDAP_INVALID_SYNTAX;
3022 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3023 slap_sl_free( i.bv_val, NULL );
3026 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3032 serialNumberAndIssuerPretty(
3039 struct berval sn, i, ni;
3041 assert( in != NULL );
3042 assert( out != NULL );
3044 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3047 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3051 rc = dnPretty( syntax, &i, &ni, ctx );
3053 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3054 slap_sl_free( i.bv_val, ctx );
3057 if( rc ) return LDAP_INVALID_SYNTAX;
3059 /* make room from sn + "$" */
3060 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3061 + sn.bv_len + ni.bv_len;
3062 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3064 if( out->bv_val == NULL ) {
3066 slap_sl_free( ni.bv_val, ctx );
3071 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3072 STRLENOF("{ serialNumber "));
3073 n = STRLENOF("{ serialNumber ");
3075 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3078 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3079 n += STRLENOF(", issuer rdnSequence:\"");
3081 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3084 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3085 n += STRLENOF("\" }");
3087 out->bv_val[n] = '\0';
3089 assert( n == out->bv_len );
3091 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3092 out->bv_val, 0, 0 );
3094 slap_sl_free( ni.bv_val, ctx );
3096 return LDAP_SUCCESS;
3100 * This routine is called by certificateExactNormalize when
3101 * certificateExactNormalize receives a search string instead of
3102 * a certificate. This routine checks if the search value is valid
3103 * and then returns the normalized value
3106 serialNumberAndIssuerNormalize(
3114 struct berval sn, sn2, i, ni;
3115 char sbuf[64], *stmp = sbuf;
3119 assert( in != NULL );
3120 assert( out != NULL );
3122 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3125 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3129 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3131 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3132 slap_sl_free( i.bv_val, ctx );
3135 if( rc ) return LDAP_INVALID_SYNTAX;
3137 /* Convert sn to canonical hex */
3138 if ( sn.bv_len > sizeof( sbuf )) {
3139 stmp = slap_sl_malloc( sn.bv_len, ctx );
3142 sn2.bv_len = sn.bv_len;
3143 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3144 rc = LDAP_INVALID_SYNTAX;
3148 /* make room for sn + "$" */
3149 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3150 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3151 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3153 if( out->bv_val == NULL ) {
3155 slap_sl_free( ni.bv_val, ctx );
3161 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3162 STRLENOF( "{ serialNumber " ));
3163 n = STRLENOF( "{ serialNumber " );
3165 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3168 unsigned char *v = (unsigned char *)sn2.bv_val;
3169 out->bv_val[n++] = '\'';
3170 for ( j = 0; j < sn2.bv_len; j++ ) {
3171 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3175 out->bv_val[n++] = '\'';
3176 out->bv_val[n++] = 'H';
3179 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3180 n += STRLENOF( ", issuer rdnSequence:\"" );
3182 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3185 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3186 n += STRLENOF( "\" }" );
3188 out->bv_val[n] = '\0';
3190 assert( n == out->bv_len );
3192 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3193 out->bv_val, 0, 0 );
3197 slap_sl_free( stmp, ctx );
3198 slap_sl_free( ni.bv_val, ctx );
3204 certificateExactNormalize(
3209 struct berval *normalized,
3212 BerElementBuffer berbuf;
3213 BerElement *ber = (BerElement *)&berbuf;
3217 char serialbuf[64], *serial = serialbuf;
3218 ber_len_t seriallen;
3219 struct berval issuer_dn = BER_BVNULL, bvdn;
3221 int rc = LDAP_INVALID_SYNTAX;
3223 if( BER_BVISEMPTY( val ) ) goto done;
3225 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3226 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3229 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3231 ber_init2( ber, val, LBER_USE_DER );
3232 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3233 tag = ber_skip_tag( ber, &len ); /* Sequence */
3234 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3235 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3236 tag = ber_skip_tag( ber, &len );
3237 tag = ber_get_int( ber, &i ); /* version */
3240 /* NOTE: move the test here from certificateValidate,
3241 * so that we can validate certs with serial longer
3242 * than sizeof(ber_int_t) */
3243 tag = ber_peek_tag( ber, &len ); /* serial */
3245 /* Use hex format. '123456789abcdef'H
3251 tag = ber_skip_tag( ber, &len );
3252 ptr = (unsigned char *)ber->ber_ptr;
3253 ber_skip_data( ber, len );
3255 /* Check for minimal encodings */
3257 if ( ptr[0] & 0x80 ) {
3258 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3259 return LDAP_INVALID_SYNTAX;
3260 } else if ( ptr[0] == 0 ) {
3261 if (!( ptr[1] & 0x80 ))
3262 return LDAP_INVALID_SYNTAX;
3266 seriallen = len * 2 + 4; /* quotes, H, NUL */
3267 if ( seriallen > sizeof( serialbuf ))
3268 serial = slap_sl_malloc( seriallen, ctx );
3271 for ( i = 0; i<len; i++ ) {
3272 sprintf( sptr, "%02X", ptr[i] );
3279 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3280 ber_skip_data( ber, len );
3281 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3282 len = ber_ptrlen( ber );
3283 bvdn.bv_val = val->bv_val + len;
3284 bvdn.bv_len = val->bv_len - len;
3286 rc = dnX509normalize( &bvdn, &issuer_dn );
3287 if( rc != LDAP_SUCCESS ) goto done;
3289 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3290 + seriallen + issuer_dn.bv_len;
3291 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3293 p = (unsigned char *)normalized->bv_val;
3295 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3296 p += STRLENOF( "{ serialNumber " );
3298 AC_MEMCPY(p, serial, seriallen);
3301 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3302 p += STRLENOF( ", issuer rdnSequence:\"" );
3304 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3305 p += issuer_dn.bv_len;
3307 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3308 p += STRLENOF( "\" }" );
3312 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3313 normalized->bv_val, NULL, NULL );
3318 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3319 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3331 assert( in != NULL );
3332 assert( !BER_BVISNULL( in ) );
3334 for ( i = 0; i < in->bv_len; i++ ) {
3335 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3336 return LDAP_INVALID_SYNTAX;
3340 return LDAP_SUCCESS;
3343 /* Normalize a SID as used inside a CSN:
3344 * three-digit numeric string */
3351 struct berval *normalized,
3356 assert( val != NULL );
3357 assert( normalized != NULL );
3359 ber_dupbv_x( normalized, val, ctx );
3361 for ( i = 0; i < normalized->bv_len; i++ ) {
3362 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3363 ber_memfree_x( normalized->bv_val, ctx );
3364 BER_BVZERO( normalized );
3365 return LDAP_INVALID_SYNTAX;
3368 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3371 return LDAP_SUCCESS;
3379 assert( in != NULL );
3380 assert( !BER_BVISNULL( in ) );
3382 if ( in->bv_len != 3 ) {
3383 return LDAP_INVALID_SYNTAX;
3386 return hexValidate( NULL, in );
3389 /* Normalize a SID as used inside a CSN:
3390 * three-digit numeric string */
3397 struct berval *normalized,
3400 if ( val->bv_len != 3 ) {
3401 return LDAP_INVALID_SYNTAX;
3404 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3414 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3417 /* Normalize a SID as used inside a CSN, either as-is
3418 * (assertion value) or extracted from the CSN
3419 * (attribute value) */
3426 struct berval *normalized,
3434 if ( BER_BVISEMPTY( val ) ) {
3435 return LDAP_INVALID_SYNTAX;
3438 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3439 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3442 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3444 ptr = ber_bvchr( val, '#' );
3445 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3446 return LDAP_INVALID_SYNTAX;
3449 bv.bv_val = ptr + 1;
3450 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3452 ptr = ber_bvchr( &bv, '#' );
3453 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3454 return LDAP_INVALID_SYNTAX;
3457 bv.bv_val = ptr + 1;
3458 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3460 ptr = ber_bvchr( &bv, '#' );
3461 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3462 return LDAP_INVALID_SYNTAX;
3465 bv.bv_len = ptr - bv.bv_val;
3467 if ( bv.bv_len == 2 ) {
3468 /* OpenLDAP 2.3 SID */
3470 buf[ 1 ] = bv.bv_val[ 0 ];
3471 buf[ 2 ] = bv.bv_val[ 1 ];
3478 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3490 assert( in != NULL );
3491 assert( !BER_BVISNULL( in ) );
3493 if ( BER_BVISEMPTY( in ) ) {
3494 return LDAP_INVALID_SYNTAX;
3499 ptr = ber_bvchr( &bv, '#' );
3500 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3501 return LDAP_INVALID_SYNTAX;
3504 bv.bv_len = ptr - bv.bv_val;
3505 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3506 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3508 return LDAP_INVALID_SYNTAX;
3511 rc = generalizedTimeValidate( NULL, &bv );
3512 if ( rc != LDAP_SUCCESS ) {
3516 bv.bv_val = ptr + 1;
3517 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3519 ptr = ber_bvchr( &bv, '#' );
3520 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3521 return LDAP_INVALID_SYNTAX;
3524 bv.bv_len = ptr - bv.bv_val;
3525 if ( bv.bv_len != 6 ) {
3526 return LDAP_INVALID_SYNTAX;
3529 rc = hexValidate( NULL, &bv );
3530 if ( rc != LDAP_SUCCESS ) {
3534 bv.bv_val = ptr + 1;
3535 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3537 ptr = ber_bvchr( &bv, '#' );
3538 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3539 return LDAP_INVALID_SYNTAX;
3542 bv.bv_len = ptr - bv.bv_val;
3543 if ( bv.bv_len == 2 ) {
3544 /* tolerate old 2-digit replica-id */
3545 rc = hexValidate( NULL, &bv );
3548 rc = sidValidate( NULL, &bv );
3550 if ( rc != LDAP_SUCCESS ) {
3554 bv.bv_val = ptr + 1;
3555 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3557 if ( bv.bv_len != 6 ) {
3558 return LDAP_INVALID_SYNTAX;
3561 return hexValidate( NULL, &bv );
3564 /* Normalize a CSN in OpenLDAP 2.3 format */
3571 struct berval *normalized,
3574 struct berval gt, cnt, sid, mod;
3578 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3579 assert( !BER_BVISEMPTY( val ) );
3583 ptr = ber_bvchr( >, '#' );
3584 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3585 return LDAP_INVALID_SYNTAX;
3588 gt.bv_len = ptr - gt.bv_val;
3589 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3591 cnt.bv_val = ptr + 1;
3592 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3594 ptr = ber_bvchr( &cnt, '#' );
3595 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3596 return LDAP_INVALID_SYNTAX;
3599 cnt.bv_len = ptr - cnt.bv_val;
3600 assert( cnt.bv_len == STRLENOF( "000000" ) );
3602 sid.bv_val = ptr + 1;
3603 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3605 ptr = ber_bvchr( &sid, '#' );
3606 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3607 return LDAP_INVALID_SYNTAX;
3610 sid.bv_len = ptr - sid.bv_val;
3611 assert( sid.bv_len == STRLENOF( "00" ) );
3613 mod.bv_val = ptr + 1;
3614 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3615 assert( mod.bv_len == STRLENOF( "000000" ) );
3617 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3618 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3620 ptr = normalized->bv_val;
3621 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3622 ptr = lutil_strcopy( ptr, ".000000Z#" );
3623 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3626 for ( i = 0; i < sid.bv_len; i++ ) {
3627 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3630 for ( i = 0; i < mod.bv_len; i++ ) {
3631 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3635 assert( ptr - normalized->bv_val == normalized->bv_len );
3637 return LDAP_SUCCESS;
3640 /* Normalize a CSN */
3647 struct berval *normalized,
3650 struct berval cnt, sid, mod;
3654 assert( val != NULL );
3655 assert( normalized != NULL );
3657 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3659 if ( BER_BVISEMPTY( val ) ) {
3660 return LDAP_INVALID_SYNTAX;
3663 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3664 /* Openldap <= 2.3 */
3666 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3669 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3671 ptr = ber_bvchr( val, '#' );
3672 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3673 return LDAP_INVALID_SYNTAX;
3676 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3678 cnt.bv_val = ptr + 1;
3679 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3681 ptr = ber_bvchr( &cnt, '#' );
3682 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3683 return LDAP_INVALID_SYNTAX;
3686 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3688 sid.bv_val = ptr + 1;
3689 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3691 ptr = ber_bvchr( &sid, '#' );
3692 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3693 return LDAP_INVALID_SYNTAX;
3696 sid.bv_len = ptr - sid.bv_val;
3697 assert( sid.bv_len == STRLENOF( "000" ) );
3699 mod.bv_val = ptr + 1;
3700 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3702 assert( mod.bv_len == STRLENOF( "000000" ) );
3704 ber_dupbv_x( normalized, val, ctx );
3706 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3707 i < normalized->bv_len; i++ )
3709 /* assume it's already validated that's all hex digits */
3710 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3713 return LDAP_SUCCESS;
3723 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3726 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3727 /* slight optimization - does not need the start parameter */
3728 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3733 check_time_syntax (struct berval *val,
3736 struct berval *fraction)
3739 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3740 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3741 * GeneralizedTime supports leap seconds, UTCTime does not.
3743 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3744 static const int mdays[2][12] = {
3745 /* non-leap years */
3746 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3748 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3751 int part, c, c1, c2, tzoffset, leapyear = 0;
3754 e = p + val->bv_len;
3756 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3757 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3759 for (part = start; part < 7 && p < e; part++) {
3761 if (!ASCII_DIGIT(c1)) {
3766 return LDAP_INVALID_SYNTAX;
3769 if (!ASCII_DIGIT(c)) {
3770 return LDAP_INVALID_SYNTAX;
3772 c += c1 * 10 - '0' * 11;
3773 if ((part | 1) == 3) {
3776 return LDAP_INVALID_SYNTAX;
3779 if (c >= ceiling[part]) {
3780 if (! (c == 60 && part == 6 && start == 0))
3781 return LDAP_INVALID_SYNTAX;
3785 if (part < 5 + start) {
3786 return LDAP_INVALID_SYNTAX;
3788 for (; part < 9; part++) {
3792 /* leapyear check for the Gregorian calendar (year>1581) */
3793 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3797 if (parts[3] >= mdays[leapyear][parts[2]]) {
3798 return LDAP_INVALID_SYNTAX;
3802 fraction->bv_val = p;
3803 fraction->bv_len = 0;
3804 if (p < e && (*p == '.' || *p == ',')) {
3806 while (++p < e && ASCII_DIGIT(*p)) {
3809 if (p - fraction->bv_val == 1) {
3810 return LDAP_INVALID_SYNTAX;
3812 for (end_num = p; end_num[-1] == '0'; --end_num) {
3815 c = end_num - fraction->bv_val;
3816 if (c != 1) fraction->bv_len = c;
3822 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3828 return LDAP_INVALID_SYNTAX;
3834 for (part = 7; part < 9 && p < e; part++) {
3836 if (!ASCII_DIGIT(c1)) {
3841 return LDAP_INVALID_SYNTAX;
3844 if (!ASCII_DIGIT(c2)) {
3845 return LDAP_INVALID_SYNTAX;
3847 parts[part] = c1 * 10 + c2 - '0' * 11;
3848 if (parts[part] >= ceiling[part]) {
3849 return LDAP_INVALID_SYNTAX;
3852 if (part < 8 + start) {
3853 return LDAP_INVALID_SYNTAX;
3856 if (tzoffset == '-') {
3857 /* negative offset to UTC, ie west of Greenwich */
3858 parts[4] += parts[7];
3859 parts[5] += parts[8];
3860 /* offset is just hhmm, no seconds */
3861 for (part = 6; --part >= 0; ) {
3865 c = mdays[leapyear][parts[2]];
3867 if (parts[part] >= c) {
3869 return LDAP_INVALID_SYNTAX;
3874 } else if (part != 5) {
3879 /* positive offset to UTC, ie east of Greenwich */
3880 parts[4] -= parts[7];
3881 parts[5] -= parts[8];
3882 for (part = 6; --part >= 0; ) {
3883 if (parts[part] < 0) {
3885 return LDAP_INVALID_SYNTAX;
3890 /* make first arg to % non-negative */
3891 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3896 } else if (part != 5) {
3903 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3906 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3913 struct berval *normalized )
3917 rc = check_time_syntax(val, 1, parts, NULL);
3918 if (rc != LDAP_SUCCESS) {
3922 normalized->bv_val = ch_malloc( 14 );
3923 if ( normalized->bv_val == NULL ) {
3924 return LBER_ERROR_MEMORY;
3927 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3928 parts[1], parts[2] + 1, parts[3] + 1,
3929 parts[4], parts[5], parts[6] );
3930 normalized->bv_len = 13;
3932 return LDAP_SUCCESS;
3942 return check_time_syntax(in, 1, parts, NULL);
3945 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3948 generalizedTimeValidate(
3953 struct berval fraction;
3954 return check_time_syntax(in, 0, parts, &fraction);
3958 generalizedTimeNormalize(
3963 struct berval *normalized,
3968 struct berval fraction;
3970 rc = check_time_syntax(val, 0, parts, &fraction);
3971 if (rc != LDAP_SUCCESS) {
3975 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3976 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3977 if ( BER_BVISNULL( normalized ) ) {
3978 return LBER_ERROR_MEMORY;
3981 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
3982 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3983 parts[4], parts[5], parts[6] );
3984 if ( !BER_BVISEMPTY( &fraction ) ) {
3985 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
3986 fraction.bv_val, fraction.bv_len );
3987 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
3989 strcpy( normalized->bv_val + len-1, "Z" );
3990 normalized->bv_len = len;
3992 return LDAP_SUCCESS;
3996 generalizedTimeOrderingMatch(
4001 struct berval *value,
4002 void *assertedValue )
4004 struct berval *asserted = (struct berval *) assertedValue;
4005 ber_len_t v_len = value->bv_len;
4006 ber_len_t av_len = asserted->bv_len;
4008 /* ignore trailing 'Z' when comparing */
4009 int match = memcmp( value->bv_val, asserted->bv_val,
4010 (v_len < av_len ? v_len : av_len) - 1 );
4011 if ( match == 0 ) match = v_len - av_len;
4014 return LDAP_SUCCESS;
4017 /* Index generation function */
4018 int generalizedTimeIndexer(
4023 struct berval *prefix,
4031 BerValue bvtmp; /* 40 bit index */
4033 struct lutil_timet tt;
4035 bvtmp.bv_len = sizeof(tmp);
4037 for( i=0; values[i].bv_val != NULL; i++ ) {
4038 /* just count them */
4041 /* we should have at least one value at this point */
4044 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4046 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4047 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4048 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4049 /* Use 40 bits of time for key */
4050 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4051 lutil_tm2time( &tm, &tt );
4052 tmp[0] = tt.tt_gsec & 0xff;
4053 tmp[4] = tt.tt_sec & 0xff;
4055 tmp[3] = tt.tt_sec & 0xff;
4057 tmp[2] = tt.tt_sec & 0xff;
4059 tmp[1] = tt.tt_sec & 0xff;
4061 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4065 keys[j].bv_val = NULL;
4070 return LDAP_SUCCESS;
4073 /* Index generation function */
4074 int generalizedTimeFilter(
4079 struct berval *prefix,
4080 void * assertedValue,
4086 BerValue bvtmp; /* 40 bit index */
4087 BerValue *value = (BerValue *) assertedValue;
4089 struct lutil_timet tt;
4091 bvtmp.bv_len = sizeof(tmp);
4093 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4094 /* Use 40 bits of time for key */
4095 if ( value->bv_val && value->bv_len >= 10 &&
4096 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4098 lutil_tm2time( &tm, &tt );
4099 tmp[0] = tt.tt_gsec & 0xff;
4100 tmp[4] = tt.tt_sec & 0xff;
4102 tmp[3] = tt.tt_sec & 0xff;
4104 tmp[2] = tt.tt_sec & 0xff;
4106 tmp[1] = tt.tt_sec & 0xff;
4108 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4109 ber_dupbv_x(keys, &bvtmp, ctx );
4110 keys[1].bv_val = NULL;
4118 return LDAP_SUCCESS;
4122 deliveryMethodValidate(
4124 struct berval *val )
4127 #define LENOF(s) (sizeof(s)-1)
4128 struct berval tmp = *val;
4130 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4131 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4132 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4135 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4137 switch( tmp.bv_val[0] ) {
4140 if(( tmp.bv_len >= LENOF("any") ) &&
4141 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4143 tmp.bv_len -= LENOF("any");
4144 tmp.bv_val += LENOF("any");
4147 return LDAP_INVALID_SYNTAX;
4151 if(( tmp.bv_len >= LENOF("mhs") ) &&
4152 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4154 tmp.bv_len -= LENOF("mhs");
4155 tmp.bv_val += LENOF("mhs");
4158 return LDAP_INVALID_SYNTAX;
4162 if(( tmp.bv_len >= LENOF("physical") ) &&
4163 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4165 tmp.bv_len -= LENOF("physical");
4166 tmp.bv_val += LENOF("physical");
4169 return LDAP_INVALID_SYNTAX;
4172 case 'T': /* telex or teletex or telephone */
4173 if(( tmp.bv_len >= LENOF("telex") ) &&
4174 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4176 tmp.bv_len -= LENOF("telex");
4177 tmp.bv_val += LENOF("telex");
4180 if(( tmp.bv_len >= LENOF("teletex") ) &&
4181 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4183 tmp.bv_len -= LENOF("teletex");
4184 tmp.bv_val += LENOF("teletex");
4187 if(( tmp.bv_len >= LENOF("telephone") ) &&
4188 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4190 tmp.bv_len -= LENOF("telephone");
4191 tmp.bv_val += LENOF("telephone");
4194 return LDAP_INVALID_SYNTAX;
4197 case 'G': /* g3fax or g4fax */
4198 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4199 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4200 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4202 tmp.bv_len -= LENOF("g3fax");
4203 tmp.bv_val += LENOF("g3fax");
4206 return LDAP_INVALID_SYNTAX;
4210 if(( tmp.bv_len >= LENOF("ia5") ) &&
4211 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4213 tmp.bv_len -= LENOF("ia5");
4214 tmp.bv_val += LENOF("ia5");
4217 return LDAP_INVALID_SYNTAX;
4221 if(( tmp.bv_len >= LENOF("videotex") ) &&
4222 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4224 tmp.bv_len -= LENOF("videotex");
4225 tmp.bv_val += LENOF("videotex");
4228 return LDAP_INVALID_SYNTAX;
4231 return LDAP_INVALID_SYNTAX;
4234 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4236 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4240 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4244 return LDAP_INVALID_SYNTAX;
4246 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4255 nisNetgroupTripleValidate(
4257 struct berval *val )
4262 if ( BER_BVISEMPTY( val ) ) {
4263 return LDAP_INVALID_SYNTAX;
4266 p = (char *)val->bv_val;
4267 e = p + val->bv_len;
4269 if ( *p != '(' /*')'*/ ) {
4270 return LDAP_INVALID_SYNTAX;
4273 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4277 return LDAP_INVALID_SYNTAX;
4280 } else if ( !AD_CHAR( *p ) ) {
4281 return LDAP_INVALID_SYNTAX;
4285 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4286 return LDAP_INVALID_SYNTAX;
4292 return LDAP_INVALID_SYNTAX;
4295 return LDAP_SUCCESS;
4299 bootParameterValidate(
4301 struct berval *val )
4305 if ( BER_BVISEMPTY( val ) ) {
4306 return LDAP_INVALID_SYNTAX;
4309 p = (char *)val->bv_val;
4310 e = p + val->bv_len;
4313 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4314 if ( !AD_CHAR( *p ) ) {
4315 return LDAP_INVALID_SYNTAX;
4320 return LDAP_INVALID_SYNTAX;
4324 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4325 if ( !AD_CHAR( *p ) ) {
4326 return LDAP_INVALID_SYNTAX;
4331 return LDAP_INVALID_SYNTAX;
4335 for ( p++; p < e; p++ ) {
4336 if ( !SLAP_PRINTABLE( *p ) ) {
4337 return LDAP_INVALID_SYNTAX;
4341 return LDAP_SUCCESS;
4345 firstComponentNormalize(
4350 struct berval *normalized,
4357 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4358 ber_dupbv_x( normalized, val, ctx );
4359 return LDAP_SUCCESS;
4362 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4364 if( val->bv_val[0] != '(' /*')'*/ &&
4365 val->bv_val[0] != '{' /*'}'*/ )
4367 return LDAP_INVALID_SYNTAX;
4370 /* trim leading white space */
4372 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4378 /* grab next word */
4379 comp.bv_val = &val->bv_val[len];
4380 len = val->bv_len - len;
4381 for( comp.bv_len = 0;
4382 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4388 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4389 rc = numericoidValidate( NULL, &comp );
4390 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4391 rc = integerValidate( NULL, &comp );
4393 rc = LDAP_INVALID_SYNTAX;
4397 if( rc == LDAP_SUCCESS ) {
4398 ber_dupbv_x( normalized, &comp, ctx );
4404 static char *country_gen_syn[] = {
4405 "1.3.6.1.4.1.1466.115.121.1.15",
4406 "1.3.6.1.4.1.1466.115.121.1.26",
4407 "1.3.6.1.4.1.1466.115.121.1.44",
4411 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4412 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4414 static slap_syntax_defs_rec syntax_defs[] = {
4415 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4416 X_BINARY X_NOT_H_R ")",
4417 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4418 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4419 0, NULL, NULL, NULL},
4420 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4421 0, NULL, NULL, NULL},
4422 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4424 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4425 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4427 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4428 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4429 0, NULL, bitStringValidate, NULL },
4430 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4431 0, NULL, booleanValidate, NULL},
4432 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4433 X_BINARY X_NOT_H_R ")",
4434 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4435 NULL, certificateValidate, NULL},
4436 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4437 X_BINARY X_NOT_H_R ")",
4438 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4439 NULL, certificateListValidate, NULL},
4440 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4441 X_BINARY X_NOT_H_R ")",
4442 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4443 NULL, sequenceValidate, NULL},
4444 #if 0 /* need to go __after__ printableString */
4445 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4446 0, "1.3.6.1.4.1.1466.115.121.1.44",
4447 countryStringValidate, NULL},
4449 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4450 0, NULL, dnValidate, dnPretty},
4451 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4452 0, NULL, rdnValidate, rdnPretty},
4453 #ifdef LDAP_COMP_MATCH
4454 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4455 0, NULL, allComponentsValidate, NULL},
4456 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4457 0, NULL, componentFilterValidate, NULL},
4459 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4460 0, NULL, NULL, NULL},
4461 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4462 0, NULL, deliveryMethodValidate, NULL},
4463 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4464 0, NULL, UTF8StringValidate, NULL},
4465 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4466 0, NULL, NULL, NULL},
4467 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4468 0, NULL, NULL, NULL},
4469 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4470 0, NULL, NULL, NULL},
4471 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4472 0, NULL, NULL, NULL},
4473 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4474 0, NULL, NULL, NULL},
4475 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4476 0, NULL, printablesStringValidate, NULL},
4477 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4478 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4479 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4480 0, NULL, generalizedTimeValidate, NULL},
4481 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4482 0, NULL, NULL, NULL},
4483 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4484 0, NULL, IA5StringValidate, NULL},
4485 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4486 0, NULL, integerValidate, NULL},
4487 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4488 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4489 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4490 0, NULL, NULL, NULL},
4491 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4492 0, NULL, NULL, NULL},
4493 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4494 0, NULL, NULL, NULL},
4495 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4496 0, NULL, NULL, NULL},
4497 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4498 0, NULL, NULL, NULL},
4499 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4500 0, NULL, nameUIDValidate, nameUIDPretty },
4501 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4502 0, NULL, NULL, NULL},
4503 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4504 0, NULL, numericStringValidate, NULL},
4505 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4506 0, NULL, NULL, NULL},
4507 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4508 0, NULL, numericoidValidate, NULL},
4509 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4510 0, NULL, IA5StringValidate, NULL},
4511 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4512 0, NULL, blobValidate, NULL},
4513 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4514 0, NULL, UTF8StringValidate, NULL},
4515 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4516 0, NULL, NULL, NULL},
4517 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4518 0, NULL, NULL, NULL},
4519 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4520 0, NULL, printableStringValidate, NULL},
4521 /* moved here because now depends on Directory String, IA5 String
4522 * and Printable String */
4523 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4524 0, country_gen_syn, countryStringValidate, NULL},
4525 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4526 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4527 0, NULL, subtreeSpecificationValidate, NULL},
4528 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4529 X_BINARY X_NOT_H_R ")",
4530 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4531 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4532 0, NULL, printableStringValidate, NULL},
4533 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4534 0, NULL, NULL, NULL},
4535 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4536 0, NULL, printablesStringValidate, NULL},
4537 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4538 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4539 0, NULL, utcTimeValidate, NULL},
4541 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4542 0, NULL, NULL, NULL},
4543 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4544 0, NULL, NULL, NULL},
4545 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4546 0, NULL, NULL, NULL},
4547 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4548 0, NULL, NULL, NULL},
4549 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4550 0, NULL, NULL, NULL},
4552 /* RFC 2307 NIS Syntaxes */
4553 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4554 0, NULL, nisNetgroupTripleValidate, NULL},
4555 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4556 0, NULL, bootParameterValidate, NULL},
4558 /* draft-zeilenga-ldap-x509 */
4559 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4560 SLAP_SYNTAX_HIDE, NULL,
4561 serialNumberAndIssuerValidate,
4562 serialNumberAndIssuerPretty},
4563 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4564 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4565 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4566 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4567 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4568 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4569 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4570 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4571 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4572 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4573 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4574 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4576 #ifdef SLAPD_AUTHPASSWD
4577 /* needs updating */
4578 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4579 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4582 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4583 0, NULL, UUIDValidate, UUIDPretty},
4585 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4586 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4588 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4589 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4591 /* OpenLDAP Void Syntax */
4592 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4593 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4595 /* FIXME: OID is unused, but not registered yet */
4596 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4597 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4599 {NULL, 0, NULL, NULL, NULL}
4602 char *csnSIDMatchSyntaxes[] = {
4603 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4606 char *certificateExactMatchSyntaxes[] = {
4607 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4610 #ifdef LDAP_COMP_MATCH
4611 char *componentFilterMatchSyntaxes[] = {
4612 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4616 char *directoryStringSyntaxes[] = {
4617 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4620 char *integerFirstComponentMatchSyntaxes[] = {
4621 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4622 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4625 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4626 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4627 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4628 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4629 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4630 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4631 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4632 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4633 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4638 * Other matching rules in X.520 that we do not use (yet):
4640 * 2.5.13.25 uTCTimeMatch
4641 * 2.5.13.26 uTCTimeOrderingMatch
4642 * 2.5.13.31* directoryStringFirstComponentMatch
4643 * 2.5.13.32* wordMatch
4644 * 2.5.13.33* keywordMatch
4645 * 2.5.13.36+ certificatePairExactMatch
4646 * 2.5.13.37+ certificatePairMatch
4647 * 2.5.13.38+ certificateListExactMatch
4648 * 2.5.13.39+ certificateListMatch
4649 * 2.5.13.40+ algorithmIdentifierMatch
4650 * 2.5.13.41* storedPrefixMatch
4651 * 2.5.13.42 attributeCertificateMatch
4652 * 2.5.13.43 readerAndKeyIDMatch
4653 * 2.5.13.44 attributeIntegrityMatch
4655 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4656 * (+) described in draft-zeilenga-ldap-x509
4658 static slap_mrule_defs_rec mrule_defs[] = {
4660 * EQUALITY matching rules must be listed after associated APPROX
4661 * matching rules. So, we list all APPROX matching rules first.
4663 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4664 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4665 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4666 NULL, NULL, directoryStringApproxMatch,
4667 directoryStringApproxIndexer, directoryStringApproxFilter,
4670 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4671 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4672 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4673 NULL, NULL, IA5StringApproxMatch,
4674 IA5StringApproxIndexer, IA5StringApproxFilter,
4678 * Other matching rules
4681 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4682 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4683 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4684 NULL, NULL, octetStringMatch,
4685 octetStringIndexer, octetStringFilter,
4688 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4689 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4690 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4691 NULL, dnNormalize, dnMatch,
4692 octetStringIndexer, octetStringFilter,
4695 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4696 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4697 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4698 NULL, dnNormalize, dnRelativeMatch,
4702 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4703 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4704 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4705 NULL, dnNormalize, dnRelativeMatch,
4709 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4710 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4711 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4712 NULL, dnNormalize, dnRelativeMatch,
4716 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4717 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4718 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4719 NULL, dnNormalize, dnRelativeMatch,
4723 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4724 "SYNTAX 1.2.36.79672281.1.5.0 )",
4725 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4726 NULL, rdnNormalize, rdnMatch,
4727 octetStringIndexer, octetStringFilter,
4730 #ifdef LDAP_COMP_MATCH
4731 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4732 "SYNTAX 1.2.36.79672281.1.5.2 )",
4733 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4734 NULL, NULL , componentFilterMatch,
4735 octetStringIndexer, octetStringFilter,
4738 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4739 "SYNTAX 1.2.36.79672281.1.5.3 )",
4740 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4741 NULL, NULL , allComponentsMatch,
4742 octetStringIndexer, octetStringFilter,
4745 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4746 "SYNTAX 1.2.36.79672281.1.5.3 )",
4747 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4748 NULL, NULL , directoryComponentsMatch,
4749 octetStringIndexer, octetStringFilter,
4753 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4754 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4755 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4756 NULL, UTF8StringNormalize, octetStringMatch,
4757 octetStringIndexer, octetStringFilter,
4758 directoryStringApproxMatchOID },
4760 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4762 SLAP_MR_ORDERING, directoryStringSyntaxes,
4763 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4765 "caseIgnoreMatch" },
4767 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4768 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4769 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4770 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4771 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4772 "caseIgnoreMatch" },
4774 {"( 2.5.13.5 NAME 'caseExactMatch' "
4775 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4776 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4777 NULL, UTF8StringNormalize, octetStringMatch,
4778 octetStringIndexer, octetStringFilter,
4779 directoryStringApproxMatchOID },
4781 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4782 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4783 SLAP_MR_ORDERING, directoryStringSyntaxes,
4784 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4788 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4789 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4790 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4791 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4792 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4795 {"( 2.5.13.8 NAME 'numericStringMatch' "
4796 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4797 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4798 NULL, numericStringNormalize, octetStringMatch,
4799 octetStringIndexer, octetStringFilter,
4802 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4803 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4804 SLAP_MR_ORDERING, NULL,
4805 NULL, numericStringNormalize, octetStringOrderingMatch,
4807 "numericStringMatch" },
4809 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4810 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4811 SLAP_MR_SUBSTR, NULL,
4812 NULL, numericStringNormalize, octetStringSubstringsMatch,
4813 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4814 "numericStringMatch" },
4816 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4817 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4818 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4819 NULL, NULL, NULL, NULL, NULL, NULL },
4821 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4823 SLAP_MR_SUBSTR, NULL,
4824 NULL, NULL, NULL, NULL, NULL,
4825 "caseIgnoreListMatch" },
4827 {"( 2.5.13.13 NAME 'booleanMatch' "
4828 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4829 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4830 NULL, NULL, booleanMatch,
4831 octetStringIndexer, octetStringFilter,
4834 {"( 2.5.13.14 NAME 'integerMatch' "
4835 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4836 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4837 NULL, NULL, integerMatch,
4838 integerIndexer, integerFilter,
4841 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4842 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4843 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4844 NULL, NULL, integerMatch,
4848 {"( 2.5.13.16 NAME 'bitStringMatch' "
4849 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4850 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4851 NULL, NULL, octetStringMatch,
4852 octetStringIndexer, octetStringFilter,
4855 {"( 2.5.13.17 NAME 'octetStringMatch' "
4856 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4857 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4858 NULL, NULL, octetStringMatch,
4859 octetStringIndexer, octetStringFilter,
4862 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4864 SLAP_MR_ORDERING, NULL,
4865 NULL, NULL, octetStringOrderingMatch,
4867 "octetStringMatch" },
4869 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4870 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4871 SLAP_MR_SUBSTR, NULL,
4872 NULL, NULL, octetStringSubstringsMatch,
4873 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4874 "octetStringMatch" },
4876 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4877 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4878 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4880 telephoneNumberNormalize, octetStringMatch,
4881 octetStringIndexer, octetStringFilter,
4884 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4885 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4886 SLAP_MR_SUBSTR, NULL,
4887 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4888 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4889 "telephoneNumberMatch" },
4891 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4893 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4894 NULL, NULL, NULL, NULL, NULL, NULL },
4896 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4897 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4898 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4899 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4900 uniqueMemberIndexer, uniqueMemberFilter,
4903 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4904 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4905 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4906 NULL, NULL, NULL, NULL, NULL, NULL },
4908 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4909 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4910 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4911 NULL, generalizedTimeNormalize, octetStringMatch,
4912 generalizedTimeIndexer, generalizedTimeFilter,
4915 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4916 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4917 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4918 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4920 "generalizedTimeMatch" },
4922 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4923 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4924 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4925 integerFirstComponentMatchSyntaxes,
4926 NULL, firstComponentNormalize, integerMatch,
4927 octetStringIndexer, octetStringFilter,
4930 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4931 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4932 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4933 objectIdentifierFirstComponentMatchSyntaxes,
4934 NULL, firstComponentNormalize, octetStringMatch,
4935 octetStringIndexer, octetStringFilter,
4938 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4939 "SYNTAX 1.3.6.1.1.15.1 )",
4940 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4941 NULL, certificateExactNormalize, octetStringMatch,
4942 octetStringIndexer, octetStringFilter,
4945 {"( 2.5.13.35 NAME 'certificateMatch' "
4946 "SYNTAX 1.3.6.1.1.15.2 )",
4947 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4948 NULL, NULL, NULL, NULL, NULL,
4951 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4952 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4953 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4954 NULL, IA5StringNormalize, octetStringMatch,
4955 octetStringIndexer, octetStringFilter,
4956 IA5StringApproxMatchOID },
4958 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4959 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4960 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4961 NULL, IA5StringNormalize, octetStringMatch,
4962 octetStringIndexer, octetStringFilter,
4963 IA5StringApproxMatchOID },
4965 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4966 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4967 SLAP_MR_SUBSTR, NULL,
4968 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4969 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4970 "caseIgnoreIA5Match" },
4972 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4973 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4974 SLAP_MR_SUBSTR, NULL,
4975 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4976 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4977 "caseExactIA5Match" },
4979 #ifdef SLAPD_AUTHPASSWD
4980 /* needs updating */
4981 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4982 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4983 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
4984 NULL, NULL, authPasswordMatch,
4989 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4990 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4992 NULL, NULL, integerBitAndMatch,
4996 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4997 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4999 NULL, NULL, integerBitOrMatch,
5003 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5004 "SYNTAX 1.3.6.1.1.16.1 )",
5005 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5006 NULL, UUIDNormalize, octetStringMatch,
5007 octetStringIndexer, octetStringFilter,
5010 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5011 "SYNTAX 1.3.6.1.1.16.1 )",
5012 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5013 NULL, UUIDNormalize, octetStringOrderingMatch,
5014 octetStringIndexer, octetStringFilter,
5017 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5018 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5019 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5020 NULL, csnNormalize, csnMatch,
5021 csnIndexer, csnFilter,
5024 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5025 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5026 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5027 NULL, NULL, csnOrderingMatch,
5031 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5032 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5033 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5034 NULL, csnSidNormalize, octetStringMatch,
5035 octetStringIndexer, octetStringFilter,
5038 /* FIXME: OID is unused, but not registered yet */
5039 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5040 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5041 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5042 NULL, authzNormalize, authzMatch,
5046 {NULL, SLAP_MR_NONE, NULL,
5047 NULL, NULL, NULL, NULL, NULL,
5052 slap_schema_init( void )
5057 /* we should only be called once (from main) */
5058 assert( schema_init_done == 0 );
5060 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5061 res = register_syntax( &syntax_defs[i] );
5064 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5065 syntax_defs[i].sd_desc );
5070 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5071 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5072 mrule_defs[i].mrd_compat_syntaxes == NULL )
5075 "slap_schema_init: Ignoring unusable matching rule %s\n",
5076 mrule_defs[i].mrd_desc );
5080 res = register_matching_rule( &mrule_defs[i] );
5084 "slap_schema_init: Error registering matching rule %s\n",
5085 mrule_defs[i].mrd_desc );
5090 res = slap_schema_load();
5091 schema_init_done = 1;
5096 schema_destroy( void )
5105 if( schema_init_done ) {
5106 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5107 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );