1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 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 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3590 return LDAP_INVALID_SYNTAX;
3593 cnt.bv_val = ptr + 1;
3594 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3596 ptr = ber_bvchr( &cnt, '#' );
3597 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3598 return LDAP_INVALID_SYNTAX;
3601 cnt.bv_len = ptr - cnt.bv_val;
3602 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
3603 return LDAP_INVALID_SYNTAX;
3606 sid.bv_val = ptr + 1;
3607 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3609 ptr = ber_bvchr( &sid, '#' );
3610 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3611 return LDAP_INVALID_SYNTAX;
3614 sid.bv_len = ptr - sid.bv_val;
3615 if ( sid.bv_len != STRLENOF( "00" ) ) {
3616 return LDAP_INVALID_SYNTAX;
3619 mod.bv_val = ptr + 1;
3620 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3621 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3622 return LDAP_INVALID_SYNTAX;
3625 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3626 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3628 ptr = normalized->bv_val;
3629 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3630 ptr = lutil_strcopy( ptr, ".000000Z#" );
3631 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3634 for ( i = 0; i < sid.bv_len; i++ ) {
3635 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3638 for ( i = 0; i < mod.bv_len; i++ ) {
3639 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3643 if ( ptr - normalized->bv_val != normalized->bv_len ) {
3644 ber_memfree_x( normalized->bv_val, ctx );
3645 return LDAP_INVALID_SYNTAX;
3648 return LDAP_SUCCESS;
3651 /* Normalize a CSN */
3658 struct berval *normalized,
3661 struct berval cnt, sid, mod;
3665 assert( val != NULL );
3666 assert( normalized != NULL );
3668 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3670 if ( BER_BVISEMPTY( val ) ) {
3671 return LDAP_INVALID_SYNTAX;
3674 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3675 /* Openldap <= 2.3 */
3677 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3680 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
3681 return LDAP_INVALID_SYNTAX;
3684 ptr = ber_bvchr( val, '#' );
3685 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3686 return LDAP_INVALID_SYNTAX;
3689 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
3690 return LDAP_INVALID_SYNTAX;
3693 cnt.bv_val = ptr + 1;
3694 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3696 ptr = ber_bvchr( &cnt, '#' );
3697 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3698 return LDAP_INVALID_SYNTAX;
3701 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
3702 return LDAP_INVALID_SYNTAX;
3705 sid.bv_val = ptr + 1;
3706 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3708 ptr = ber_bvchr( &sid, '#' );
3709 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3710 return LDAP_INVALID_SYNTAX;
3713 sid.bv_len = ptr - sid.bv_val;
3714 if ( sid.bv_len != STRLENOF( "000" ) ) {
3715 return LDAP_INVALID_SYNTAX;
3718 mod.bv_val = ptr + 1;
3719 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3721 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3722 return LDAP_INVALID_SYNTAX;
3725 ber_dupbv_x( normalized, val, ctx );
3727 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3728 i < normalized->bv_len; i++ )
3730 /* assume it's already validated that's all hex digits */
3731 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3734 return LDAP_SUCCESS;
3744 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3747 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3748 /* slight optimization - does not need the start parameter */
3749 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3754 check_time_syntax (struct berval *val,
3757 struct berval *fraction)
3760 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3761 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3762 * GeneralizedTime supports leap seconds, UTCTime does not.
3764 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3765 static const int mdays[2][12] = {
3766 /* non-leap years */
3767 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3769 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3772 int part, c, c1, c2, tzoffset, leapyear = 0;
3775 e = p + val->bv_len;
3777 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3778 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3780 for (part = start; part < 7 && p < e; part++) {
3782 if (!ASCII_DIGIT(c1)) {
3787 return LDAP_INVALID_SYNTAX;
3790 if (!ASCII_DIGIT(c)) {
3791 return LDAP_INVALID_SYNTAX;
3793 c += c1 * 10 - '0' * 11;
3794 if ((part | 1) == 3) {
3797 return LDAP_INVALID_SYNTAX;
3800 if (c >= ceiling[part]) {
3801 if (! (c == 60 && part == 6 && start == 0))
3802 return LDAP_INVALID_SYNTAX;
3806 if (part < 5 + start) {
3807 return LDAP_INVALID_SYNTAX;
3809 for (; part < 9; part++) {
3813 /* leapyear check for the Gregorian calendar (year>1581) */
3814 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3818 if (parts[3] >= mdays[leapyear][parts[2]]) {
3819 return LDAP_INVALID_SYNTAX;
3823 fraction->bv_val = p;
3824 fraction->bv_len = 0;
3825 if (p < e && (*p == '.' || *p == ',')) {
3827 while (++p < e && ASCII_DIGIT(*p)) {
3830 if (p - fraction->bv_val == 1) {
3831 return LDAP_INVALID_SYNTAX;
3833 for (end_num = p; end_num[-1] == '0'; --end_num) {
3836 c = end_num - fraction->bv_val;
3837 if (c != 1) fraction->bv_len = c;
3843 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3849 return LDAP_INVALID_SYNTAX;
3855 for (part = 7; part < 9 && p < e; part++) {
3857 if (!ASCII_DIGIT(c1)) {
3862 return LDAP_INVALID_SYNTAX;
3865 if (!ASCII_DIGIT(c2)) {
3866 return LDAP_INVALID_SYNTAX;
3868 parts[part] = c1 * 10 + c2 - '0' * 11;
3869 if (parts[part] >= ceiling[part]) {
3870 return LDAP_INVALID_SYNTAX;
3873 if (part < 8 + start) {
3874 return LDAP_INVALID_SYNTAX;
3877 if (tzoffset == '-') {
3878 /* negative offset to UTC, ie west of Greenwich */
3879 parts[4] += parts[7];
3880 parts[5] += parts[8];
3881 /* offset is just hhmm, no seconds */
3882 for (part = 6; --part >= 0; ) {
3886 c = mdays[leapyear][parts[2]];
3888 if (parts[part] >= c) {
3890 return LDAP_INVALID_SYNTAX;
3895 } else if (part != 5) {
3900 /* positive offset to UTC, ie east of Greenwich */
3901 parts[4] -= parts[7];
3902 parts[5] -= parts[8];
3903 for (part = 6; --part >= 0; ) {
3904 if (parts[part] < 0) {
3906 return LDAP_INVALID_SYNTAX;
3911 /* make first arg to % non-negative */
3912 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3917 } else if (part != 5) {
3924 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3927 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3934 struct berval *normalized )
3938 rc = check_time_syntax(val, 1, parts, NULL);
3939 if (rc != LDAP_SUCCESS) {
3943 normalized->bv_val = ch_malloc( 14 );
3944 if ( normalized->bv_val == NULL ) {
3945 return LBER_ERROR_MEMORY;
3948 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3949 parts[1], parts[2] + 1, parts[3] + 1,
3950 parts[4], parts[5], parts[6] );
3951 normalized->bv_len = 13;
3953 return LDAP_SUCCESS;
3963 return check_time_syntax(in, 1, parts, NULL);
3966 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
3969 generalizedTimeValidate(
3974 struct berval fraction;
3975 return check_time_syntax(in, 0, parts, &fraction);
3979 generalizedTimeNormalize(
3984 struct berval *normalized,
3989 struct berval fraction;
3991 rc = check_time_syntax(val, 0, parts, &fraction);
3992 if (rc != LDAP_SUCCESS) {
3996 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
3997 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
3998 if ( BER_BVISNULL( normalized ) ) {
3999 return LBER_ERROR_MEMORY;
4002 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4003 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4004 parts[4], parts[5], parts[6] );
4005 if ( !BER_BVISEMPTY( &fraction ) ) {
4006 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4007 fraction.bv_val, fraction.bv_len );
4008 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4010 strcpy( normalized->bv_val + len-1, "Z" );
4011 normalized->bv_len = len;
4013 return LDAP_SUCCESS;
4017 generalizedTimeOrderingMatch(
4022 struct berval *value,
4023 void *assertedValue )
4025 struct berval *asserted = (struct berval *) assertedValue;
4026 ber_len_t v_len = value->bv_len;
4027 ber_len_t av_len = asserted->bv_len;
4029 /* ignore trailing 'Z' when comparing */
4030 int match = memcmp( value->bv_val, asserted->bv_val,
4031 (v_len < av_len ? v_len : av_len) - 1 );
4032 if ( match == 0 ) match = v_len - av_len;
4035 return LDAP_SUCCESS;
4038 /* Index generation function */
4039 int generalizedTimeIndexer(
4044 struct berval *prefix,
4052 BerValue bvtmp; /* 40 bit index */
4054 struct lutil_timet tt;
4056 bvtmp.bv_len = sizeof(tmp);
4058 for( i=0; values[i].bv_val != NULL; i++ ) {
4059 /* just count them */
4062 /* we should have at least one value at this point */
4065 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4067 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4068 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4069 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4070 /* Use 40 bits of time for key */
4071 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4072 lutil_tm2time( &tm, &tt );
4073 tmp[0] = tt.tt_gsec & 0xff;
4074 tmp[4] = tt.tt_sec & 0xff;
4076 tmp[3] = tt.tt_sec & 0xff;
4078 tmp[2] = tt.tt_sec & 0xff;
4080 tmp[1] = tt.tt_sec & 0xff;
4082 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4086 keys[j].bv_val = NULL;
4091 return LDAP_SUCCESS;
4094 /* Index generation function */
4095 int generalizedTimeFilter(
4100 struct berval *prefix,
4101 void * assertedValue,
4107 BerValue bvtmp; /* 40 bit index */
4108 BerValue *value = (BerValue *) assertedValue;
4110 struct lutil_timet tt;
4112 bvtmp.bv_len = sizeof(tmp);
4114 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4115 /* Use 40 bits of time for key */
4116 if ( value->bv_val && value->bv_len >= 10 &&
4117 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4119 lutil_tm2time( &tm, &tt );
4120 tmp[0] = tt.tt_gsec & 0xff;
4121 tmp[4] = tt.tt_sec & 0xff;
4123 tmp[3] = tt.tt_sec & 0xff;
4125 tmp[2] = tt.tt_sec & 0xff;
4127 tmp[1] = tt.tt_sec & 0xff;
4129 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4130 ber_dupbv_x(keys, &bvtmp, ctx );
4131 keys[1].bv_val = NULL;
4139 return LDAP_SUCCESS;
4143 deliveryMethodValidate(
4145 struct berval *val )
4148 #define LENOF(s) (sizeof(s)-1)
4149 struct berval tmp = *val;
4151 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4152 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4153 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4156 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4158 switch( tmp.bv_val[0] ) {
4161 if(( tmp.bv_len >= LENOF("any") ) &&
4162 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4164 tmp.bv_len -= LENOF("any");
4165 tmp.bv_val += LENOF("any");
4168 return LDAP_INVALID_SYNTAX;
4172 if(( tmp.bv_len >= LENOF("mhs") ) &&
4173 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4175 tmp.bv_len -= LENOF("mhs");
4176 tmp.bv_val += LENOF("mhs");
4179 return LDAP_INVALID_SYNTAX;
4183 if(( tmp.bv_len >= LENOF("physical") ) &&
4184 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4186 tmp.bv_len -= LENOF("physical");
4187 tmp.bv_val += LENOF("physical");
4190 return LDAP_INVALID_SYNTAX;
4193 case 'T': /* telex or teletex or telephone */
4194 if(( tmp.bv_len >= LENOF("telex") ) &&
4195 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4197 tmp.bv_len -= LENOF("telex");
4198 tmp.bv_val += LENOF("telex");
4201 if(( tmp.bv_len >= LENOF("teletex") ) &&
4202 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4204 tmp.bv_len -= LENOF("teletex");
4205 tmp.bv_val += LENOF("teletex");
4208 if(( tmp.bv_len >= LENOF("telephone") ) &&
4209 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4211 tmp.bv_len -= LENOF("telephone");
4212 tmp.bv_val += LENOF("telephone");
4215 return LDAP_INVALID_SYNTAX;
4218 case 'G': /* g3fax or g4fax */
4219 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4220 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4221 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4223 tmp.bv_len -= LENOF("g3fax");
4224 tmp.bv_val += LENOF("g3fax");
4227 return LDAP_INVALID_SYNTAX;
4231 if(( tmp.bv_len >= LENOF("ia5") ) &&
4232 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4234 tmp.bv_len -= LENOF("ia5");
4235 tmp.bv_val += LENOF("ia5");
4238 return LDAP_INVALID_SYNTAX;
4242 if(( tmp.bv_len >= LENOF("videotex") ) &&
4243 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4245 tmp.bv_len -= LENOF("videotex");
4246 tmp.bv_val += LENOF("videotex");
4249 return LDAP_INVALID_SYNTAX;
4252 return LDAP_INVALID_SYNTAX;
4255 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4257 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4261 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4265 return LDAP_INVALID_SYNTAX;
4267 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4276 nisNetgroupTripleValidate(
4278 struct berval *val )
4283 if ( BER_BVISEMPTY( val ) ) {
4284 return LDAP_INVALID_SYNTAX;
4287 p = (char *)val->bv_val;
4288 e = p + val->bv_len;
4290 if ( *p != '(' /*')'*/ ) {
4291 return LDAP_INVALID_SYNTAX;
4294 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4298 return LDAP_INVALID_SYNTAX;
4301 } else if ( !AD_CHAR( *p ) ) {
4302 return LDAP_INVALID_SYNTAX;
4306 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4307 return LDAP_INVALID_SYNTAX;
4313 return LDAP_INVALID_SYNTAX;
4316 return LDAP_SUCCESS;
4320 bootParameterValidate(
4322 struct berval *val )
4326 if ( BER_BVISEMPTY( val ) ) {
4327 return LDAP_INVALID_SYNTAX;
4330 p = (char *)val->bv_val;
4331 e = p + val->bv_len;
4334 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4335 if ( !AD_CHAR( *p ) ) {
4336 return LDAP_INVALID_SYNTAX;
4341 return LDAP_INVALID_SYNTAX;
4345 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4346 if ( !AD_CHAR( *p ) ) {
4347 return LDAP_INVALID_SYNTAX;
4352 return LDAP_INVALID_SYNTAX;
4356 for ( p++; p < e; p++ ) {
4357 if ( !SLAP_PRINTABLE( *p ) ) {
4358 return LDAP_INVALID_SYNTAX;
4362 return LDAP_SUCCESS;
4366 firstComponentNormalize(
4371 struct berval *normalized,
4378 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4379 ber_dupbv_x( normalized, val, ctx );
4380 return LDAP_SUCCESS;
4383 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4385 if( val->bv_val[0] != '(' /*')'*/ &&
4386 val->bv_val[0] != '{' /*'}'*/ )
4388 return LDAP_INVALID_SYNTAX;
4391 /* trim leading white space */
4393 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4399 /* grab next word */
4400 comp.bv_val = &val->bv_val[len];
4401 len = val->bv_len - len;
4402 for( comp.bv_len = 0;
4403 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4409 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4410 rc = numericoidValidate( NULL, &comp );
4411 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4412 rc = integerValidate( NULL, &comp );
4414 rc = LDAP_INVALID_SYNTAX;
4418 if( rc == LDAP_SUCCESS ) {
4419 ber_dupbv_x( normalized, &comp, ctx );
4425 static char *country_gen_syn[] = {
4426 "1.3.6.1.4.1.1466.115.121.1.15",
4427 "1.3.6.1.4.1.1466.115.121.1.26",
4428 "1.3.6.1.4.1.1466.115.121.1.44",
4432 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4433 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4435 static slap_syntax_defs_rec syntax_defs[] = {
4436 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4437 X_BINARY X_NOT_H_R ")",
4438 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4439 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4440 0, NULL, NULL, NULL},
4441 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4442 0, NULL, NULL, NULL},
4443 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4445 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4446 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4448 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4449 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4450 0, NULL, bitStringValidate, NULL },
4451 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4452 0, NULL, booleanValidate, NULL},
4453 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4454 X_BINARY X_NOT_H_R ")",
4455 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4456 NULL, certificateValidate, NULL},
4457 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4458 X_BINARY X_NOT_H_R ")",
4459 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4460 NULL, certificateListValidate, NULL},
4461 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4462 X_BINARY X_NOT_H_R ")",
4463 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4464 NULL, sequenceValidate, NULL},
4465 #if 0 /* need to go __after__ printableString */
4466 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4467 0, "1.3.6.1.4.1.1466.115.121.1.44",
4468 countryStringValidate, NULL},
4470 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4471 0, NULL, dnValidate, dnPretty},
4472 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4473 0, NULL, rdnValidate, rdnPretty},
4474 #ifdef LDAP_COMP_MATCH
4475 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4476 0, NULL, allComponentsValidate, NULL},
4477 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4478 0, NULL, componentFilterValidate, NULL},
4480 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4481 0, NULL, NULL, NULL},
4482 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4483 0, NULL, deliveryMethodValidate, NULL},
4484 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4485 0, NULL, UTF8StringValidate, NULL},
4486 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4487 0, NULL, NULL, NULL},
4488 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4489 0, NULL, NULL, NULL},
4490 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4491 0, NULL, NULL, NULL},
4492 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4493 0, NULL, NULL, NULL},
4494 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4495 0, NULL, NULL, NULL},
4496 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4497 0, NULL, printablesStringValidate, NULL},
4498 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4499 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4500 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4501 0, NULL, generalizedTimeValidate, NULL},
4502 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4503 0, NULL, NULL, NULL},
4504 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4505 0, NULL, IA5StringValidate, NULL},
4506 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4507 0, NULL, integerValidate, NULL},
4508 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4509 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4510 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4511 0, NULL, NULL, NULL},
4512 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4513 0, NULL, NULL, NULL},
4514 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4515 0, NULL, NULL, NULL},
4516 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4517 0, NULL, NULL, NULL},
4518 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4519 0, NULL, NULL, NULL},
4520 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4521 0, NULL, nameUIDValidate, nameUIDPretty },
4522 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4523 0, NULL, NULL, NULL},
4524 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4525 0, NULL, numericStringValidate, NULL},
4526 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4527 0, NULL, NULL, NULL},
4528 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4529 0, NULL, numericoidValidate, NULL},
4530 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4531 0, NULL, IA5StringValidate, NULL},
4532 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4533 0, NULL, blobValidate, NULL},
4534 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4535 0, NULL, UTF8StringValidate, NULL},
4536 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4537 0, NULL, NULL, NULL},
4538 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4539 0, NULL, NULL, NULL},
4540 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4541 0, NULL, printableStringValidate, NULL},
4542 /* moved here because now depends on Directory String, IA5 String
4543 * and Printable String */
4544 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4545 0, country_gen_syn, countryStringValidate, NULL},
4546 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4547 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4548 0, NULL, subtreeSpecificationValidate, NULL},
4549 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4550 X_BINARY X_NOT_H_R ")",
4551 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4552 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4553 0, NULL, printableStringValidate, NULL},
4554 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4555 0, NULL, NULL, NULL},
4556 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4557 0, NULL, printablesStringValidate, NULL},
4558 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4559 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4560 0, NULL, utcTimeValidate, NULL},
4562 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4563 0, NULL, NULL, NULL},
4564 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4565 0, NULL, NULL, NULL},
4566 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4567 0, NULL, NULL, NULL},
4568 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4569 0, NULL, NULL, NULL},
4570 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4571 0, NULL, NULL, NULL},
4573 /* RFC 2307 NIS Syntaxes */
4574 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4575 0, NULL, nisNetgroupTripleValidate, NULL},
4576 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4577 0, NULL, bootParameterValidate, NULL},
4579 /* draft-zeilenga-ldap-x509 */
4580 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4581 SLAP_SYNTAX_HIDE, NULL,
4582 serialNumberAndIssuerValidate,
4583 serialNumberAndIssuerPretty},
4584 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4585 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4586 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4587 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4588 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4589 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4590 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4591 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4592 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4593 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4594 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4595 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4597 #ifdef SLAPD_AUTHPASSWD
4598 /* needs updating */
4599 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4600 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4603 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4604 0, NULL, UUIDValidate, UUIDPretty},
4606 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4607 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4609 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4610 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4612 /* OpenLDAP Void Syntax */
4613 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4614 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4616 /* FIXME: OID is unused, but not registered yet */
4617 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4618 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4620 {NULL, 0, NULL, NULL, NULL}
4623 char *csnSIDMatchSyntaxes[] = {
4624 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4627 char *certificateExactMatchSyntaxes[] = {
4628 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4631 #ifdef LDAP_COMP_MATCH
4632 char *componentFilterMatchSyntaxes[] = {
4633 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4637 char *directoryStringSyntaxes[] = {
4638 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4641 char *integerFirstComponentMatchSyntaxes[] = {
4642 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4643 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4646 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4647 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4648 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4649 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4650 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4651 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4652 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4653 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4654 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4659 * Other matching rules in X.520 that we do not use (yet):
4661 * 2.5.13.25 uTCTimeMatch
4662 * 2.5.13.26 uTCTimeOrderingMatch
4663 * 2.5.13.31* directoryStringFirstComponentMatch
4664 * 2.5.13.32* wordMatch
4665 * 2.5.13.33* keywordMatch
4666 * 2.5.13.36+ certificatePairExactMatch
4667 * 2.5.13.37+ certificatePairMatch
4668 * 2.5.13.38+ certificateListExactMatch
4669 * 2.5.13.39+ certificateListMatch
4670 * 2.5.13.40+ algorithmIdentifierMatch
4671 * 2.5.13.41* storedPrefixMatch
4672 * 2.5.13.42 attributeCertificateMatch
4673 * 2.5.13.43 readerAndKeyIDMatch
4674 * 2.5.13.44 attributeIntegrityMatch
4676 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4677 * (+) described in draft-zeilenga-ldap-x509
4679 static slap_mrule_defs_rec mrule_defs[] = {
4681 * EQUALITY matching rules must be listed after associated APPROX
4682 * matching rules. So, we list all APPROX matching rules first.
4684 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4685 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4686 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4687 NULL, NULL, directoryStringApproxMatch,
4688 directoryStringApproxIndexer, directoryStringApproxFilter,
4691 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4692 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4693 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4694 NULL, NULL, IA5StringApproxMatch,
4695 IA5StringApproxIndexer, IA5StringApproxFilter,
4699 * Other matching rules
4702 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4703 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4704 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4705 NULL, NULL, octetStringMatch,
4706 octetStringIndexer, octetStringFilter,
4709 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4710 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4711 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4712 NULL, dnNormalize, dnMatch,
4713 octetStringIndexer, octetStringFilter,
4716 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
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.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4724 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4725 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4726 NULL, dnNormalize, dnRelativeMatch,
4730 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4731 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4732 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4733 NULL, dnNormalize, dnRelativeMatch,
4737 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4738 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4739 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4740 NULL, dnNormalize, dnRelativeMatch,
4744 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4745 "SYNTAX 1.2.36.79672281.1.5.0 )",
4746 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4747 NULL, rdnNormalize, rdnMatch,
4748 octetStringIndexer, octetStringFilter,
4751 #ifdef LDAP_COMP_MATCH
4752 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4753 "SYNTAX 1.2.36.79672281.1.5.2 )",
4754 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4755 NULL, NULL , componentFilterMatch,
4756 octetStringIndexer, octetStringFilter,
4759 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4760 "SYNTAX 1.2.36.79672281.1.5.3 )",
4761 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4762 NULL, NULL , allComponentsMatch,
4763 octetStringIndexer, octetStringFilter,
4766 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4767 "SYNTAX 1.2.36.79672281.1.5.3 )",
4768 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4769 NULL, NULL , directoryComponentsMatch,
4770 octetStringIndexer, octetStringFilter,
4774 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
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.3 NAME 'caseIgnoreOrderingMatch' "
4782 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4783 SLAP_MR_ORDERING, directoryStringSyntaxes,
4784 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4786 "caseIgnoreMatch" },
4788 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
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,
4793 "caseIgnoreMatch" },
4795 {"( 2.5.13.5 NAME 'caseExactMatch' "
4796 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4797 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4798 NULL, UTF8StringNormalize, octetStringMatch,
4799 octetStringIndexer, octetStringFilter,
4800 directoryStringApproxMatchOID },
4802 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4803 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4804 SLAP_MR_ORDERING, directoryStringSyntaxes,
4805 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4809 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4810 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4811 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4812 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4813 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4816 {"( 2.5.13.8 NAME 'numericStringMatch' "
4817 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4818 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4819 NULL, numericStringNormalize, octetStringMatch,
4820 octetStringIndexer, octetStringFilter,
4823 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4824 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4825 SLAP_MR_ORDERING, NULL,
4826 NULL, numericStringNormalize, octetStringOrderingMatch,
4828 "numericStringMatch" },
4830 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4831 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4832 SLAP_MR_SUBSTR, NULL,
4833 NULL, numericStringNormalize, octetStringSubstringsMatch,
4834 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4835 "numericStringMatch" },
4837 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4838 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4839 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4840 NULL, NULL, NULL, NULL, NULL, NULL },
4842 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4843 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4844 SLAP_MR_SUBSTR, NULL,
4845 NULL, NULL, NULL, NULL, NULL,
4846 "caseIgnoreListMatch" },
4848 {"( 2.5.13.13 NAME 'booleanMatch' "
4849 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4850 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4851 NULL, NULL, booleanMatch,
4852 octetStringIndexer, octetStringFilter,
4855 {"( 2.5.13.14 NAME 'integerMatch' "
4856 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4857 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4858 NULL, NULL, integerMatch,
4859 integerIndexer, integerFilter,
4862 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4864 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4865 NULL, NULL, integerMatch,
4869 {"( 2.5.13.16 NAME 'bitStringMatch' "
4870 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4871 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4872 NULL, NULL, octetStringMatch,
4873 octetStringIndexer, octetStringFilter,
4876 {"( 2.5.13.17 NAME 'octetStringMatch' "
4877 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4878 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4879 NULL, NULL, octetStringMatch,
4880 octetStringIndexer, octetStringFilter,
4883 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4884 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4885 SLAP_MR_ORDERING, NULL,
4886 NULL, NULL, octetStringOrderingMatch,
4888 "octetStringMatch" },
4890 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
4891 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4892 SLAP_MR_SUBSTR, NULL,
4893 NULL, NULL, octetStringSubstringsMatch,
4894 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4895 "octetStringMatch" },
4897 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4898 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4899 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4901 telephoneNumberNormalize, octetStringMatch,
4902 octetStringIndexer, octetStringFilter,
4905 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4906 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4907 SLAP_MR_SUBSTR, NULL,
4908 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
4909 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4910 "telephoneNumberMatch" },
4912 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4913 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4914 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4915 NULL, NULL, NULL, NULL, NULL, NULL },
4917 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4919 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4920 NULL, uniqueMemberNormalize, uniqueMemberMatch,
4921 uniqueMemberIndexer, uniqueMemberFilter,
4924 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4926 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4927 NULL, NULL, NULL, NULL, NULL, NULL },
4929 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4930 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4931 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4932 NULL, generalizedTimeNormalize, octetStringMatch,
4933 generalizedTimeIndexer, generalizedTimeFilter,
4936 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4937 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4938 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4939 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
4941 "generalizedTimeMatch" },
4943 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4944 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4945 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4946 integerFirstComponentMatchSyntaxes,
4947 NULL, firstComponentNormalize, integerMatch,
4948 octetStringIndexer, octetStringFilter,
4951 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4952 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4953 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4954 objectIdentifierFirstComponentMatchSyntaxes,
4955 NULL, firstComponentNormalize, octetStringMatch,
4956 octetStringIndexer, octetStringFilter,
4959 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4960 "SYNTAX 1.3.6.1.1.15.1 )",
4961 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4962 NULL, certificateExactNormalize, octetStringMatch,
4963 octetStringIndexer, octetStringFilter,
4966 {"( 2.5.13.35 NAME 'certificateMatch' "
4967 "SYNTAX 1.3.6.1.1.15.2 )",
4968 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4969 NULL, NULL, NULL, NULL, NULL,
4972 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4973 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4974 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4975 NULL, IA5StringNormalize, octetStringMatch,
4976 octetStringIndexer, octetStringFilter,
4977 IA5StringApproxMatchOID },
4979 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4980 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4981 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4982 NULL, IA5StringNormalize, octetStringMatch,
4983 octetStringIndexer, octetStringFilter,
4984 IA5StringApproxMatchOID },
4986 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4987 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4988 SLAP_MR_SUBSTR, NULL,
4989 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4990 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4991 "caseIgnoreIA5Match" },
4993 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4994 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4995 SLAP_MR_SUBSTR, NULL,
4996 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
4997 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4998 "caseExactIA5Match" },
5000 #ifdef SLAPD_AUTHPASSWD
5001 /* needs updating */
5002 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5004 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5005 NULL, NULL, authPasswordMatch,
5010 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5011 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5013 NULL, NULL, integerBitAndMatch,
5017 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5018 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5020 NULL, NULL, integerBitOrMatch,
5024 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5025 "SYNTAX 1.3.6.1.1.16.1 )",
5026 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5027 NULL, UUIDNormalize, octetStringMatch,
5028 octetStringIndexer, octetStringFilter,
5031 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5032 "SYNTAX 1.3.6.1.1.16.1 )",
5033 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5034 NULL, UUIDNormalize, octetStringOrderingMatch,
5035 octetStringIndexer, octetStringFilter,
5038 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5039 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5040 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5041 NULL, csnNormalize, csnMatch,
5042 csnIndexer, csnFilter,
5045 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5046 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5047 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5048 NULL, NULL, csnOrderingMatch,
5052 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5053 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5054 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5055 NULL, csnSidNormalize, octetStringMatch,
5056 octetStringIndexer, octetStringFilter,
5059 /* FIXME: OID is unused, but not registered yet */
5060 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5061 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5062 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5063 NULL, authzNormalize, authzMatch,
5067 {NULL, SLAP_MR_NONE, NULL,
5068 NULL, NULL, NULL, NULL, NULL,
5073 slap_schema_init( void )
5078 /* we should only be called once (from main) */
5079 assert( schema_init_done == 0 );
5081 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5082 res = register_syntax( &syntax_defs[i] );
5085 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5086 syntax_defs[i].sd_desc );
5091 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5092 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5093 mrule_defs[i].mrd_compat_syntaxes == NULL )
5096 "slap_schema_init: Ignoring unusable matching rule %s\n",
5097 mrule_defs[i].mrd_desc );
5101 res = register_matching_rule( &mrule_defs[i] );
5105 "slap_schema_init: Error registering matching rule %s\n",
5106 mrule_defs[i].mrd_desc );
5111 res = slap_schema_load();
5112 schema_init_done = 1;
5117 schema_destroy( void )
5126 if( schema_init_done ) {
5127 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5128 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );