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 keys[1].bv_val = NULL;
2279 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2280 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2281 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2282 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2285 iv.bv_len = sizeof(ibuf);
2288 rc = integerVal2Key( value, keys, &iv, ctx );
2292 if ( iv.bv_val != ibuf ) {
2293 slap_sl_free( iv.bv_val, ctx );
2299 countryStringValidate(
2301 struct berval *val )
2303 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2305 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2306 return LDAP_INVALID_SYNTAX;
2308 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2309 return LDAP_INVALID_SYNTAX;
2312 return LDAP_SUCCESS;
2316 printableStringValidate(
2318 struct berval *val )
2322 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2324 for(i=0; i < val->bv_len; i++) {
2325 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2326 return LDAP_INVALID_SYNTAX;
2330 return LDAP_SUCCESS;
2334 printablesStringValidate(
2336 struct berval *val )
2340 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2342 for(i=0,len=0; i < val->bv_len; i++) {
2343 int c = val->bv_val[i];
2347 return LDAP_INVALID_SYNTAX;
2351 } else if ( SLAP_PRINTABLE(c) ) {
2354 return LDAP_INVALID_SYNTAX;
2359 return LDAP_INVALID_SYNTAX;
2362 return LDAP_SUCCESS;
2368 struct berval *val )
2372 for(i=0; i < val->bv_len; i++) {
2373 if( !LDAP_ASCII(val->bv_val[i]) ) {
2374 return LDAP_INVALID_SYNTAX;
2378 return LDAP_SUCCESS;
2387 struct berval *normalized,
2391 int casefold = !SLAP_MR_ASSOCIATED( mr,
2392 slap_schema.si_mr_caseExactIA5Match );
2394 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2398 /* Ignore initial whitespace */
2399 while ( ASCII_SPACE( *p ) ) p++;
2401 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2402 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2403 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2404 normalized->bv_val[normalized->bv_len] = '\0';
2406 p = q = normalized->bv_val;
2409 if ( ASCII_SPACE( *p ) ) {
2412 /* Ignore the extra whitespace */
2413 while ( ASCII_SPACE( *p ) ) {
2417 } else if ( casefold ) {
2418 /* Most IA5 rules require casefolding */
2419 *q++ = TOLOWER(*p); p++;
2426 assert( normalized->bv_val <= p );
2430 * If the string ended in space, backup the pointer one
2431 * position. One is enough because the above loop collapsed
2432 * all whitespace to a single space.
2434 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2436 /* null terminate */
2439 normalized->bv_len = q - normalized->bv_val;
2441 return LDAP_SUCCESS;
2450 if( in->bv_len != 36 ) {
2451 return LDAP_INVALID_SYNTAX;
2454 for( i=0; i<36; i++ ) {
2460 if( in->bv_val[i] != '-' ) {
2461 return LDAP_INVALID_SYNTAX;
2465 if( !ASCII_HEX( in->bv_val[i]) ) {
2466 return LDAP_INVALID_SYNTAX;
2471 return LDAP_SUCCESS;
2482 int rc=LDAP_INVALID_SYNTAX;
2484 assert( in != NULL );
2485 assert( out != NULL );
2487 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2490 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2492 for( i=0; i<36; i++ ) {
2498 if( in->bv_val[i] != '-' ) {
2501 out->bv_val[i] = '-';
2505 if( !ASCII_HEX( in->bv_val[i]) ) {
2508 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2513 out->bv_val[ out->bv_len ] = '\0';
2517 slap_sl_free( out->bv_val, ctx );
2530 struct berval *normalized,
2533 unsigned char octet = '\0';
2537 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2538 /* NOTE: must be a normalized UUID */
2539 assert( val->bv_len == 16 );
2541 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2542 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2543 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2544 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2546 return LDAP_SUCCESS;
2549 normalized->bv_len = 16;
2550 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2552 for( i=0, j=0; i<36; i++ ) {
2553 unsigned char nibble;
2554 if( val->bv_val[i] == '-' ) {
2557 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2558 nibble = val->bv_val[i] - '0';
2560 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2561 nibble = val->bv_val[i] - ('a'-10);
2563 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2564 nibble = val->bv_val[i] - ('A'-10);
2567 slap_sl_free( normalized->bv_val, ctx );
2568 return LDAP_INVALID_SYNTAX;
2573 normalized->bv_val[j>>1] = octet;
2575 octet = nibble << 4;
2580 normalized->bv_val[normalized->bv_len] = 0;
2581 return LDAP_SUCCESS;
2587 numericStringValidate(
2593 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2595 for(i=0; i < in->bv_len; i++) {
2596 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2597 return LDAP_INVALID_SYNTAX;
2601 return LDAP_SUCCESS;
2605 numericStringNormalize(
2610 struct berval *normalized,
2613 /* removal all spaces */
2616 assert( !BER_BVISEMPTY( val ) );
2618 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2621 q = normalized->bv_val;
2624 if ( ASCII_SPACE( *p ) ) {
2625 /* Ignore whitespace */
2632 /* we should have copied no more than is in val */
2633 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2635 /* null terminate */
2638 normalized->bv_len = q - normalized->bv_val;
2640 if( BER_BVISEMPTY( normalized ) ) {
2641 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2642 normalized->bv_val[0] = ' ';
2643 normalized->bv_val[1] = '\0';
2644 normalized->bv_len = 1;
2647 return LDAP_SUCCESS;
2651 * Integer conversion macros that will use the largest available
2654 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2655 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2656 # define SLAP_LONG long long
2658 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2659 # define SLAP_LONG long
2660 #endif /* HAVE_STRTOLL ... */
2668 struct berval *value,
2669 void *assertedValue )
2671 SLAP_LONG lValue, lAssertedValue;
2674 /* safe to assume integers are NUL terminated? */
2675 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2676 if( errno == ERANGE )
2678 return LDAP_CONSTRAINT_VIOLATION;
2681 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2683 if( errno == ERANGE )
2685 return LDAP_CONSTRAINT_VIOLATION;
2688 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2689 return LDAP_SUCCESS;
2698 struct berval *value,
2699 void *assertedValue )
2701 SLAP_LONG lValue, lAssertedValue;
2704 /* safe to assume integers are NUL terminated? */
2705 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2706 if( errno == ERANGE )
2708 return LDAP_CONSTRAINT_VIOLATION;
2711 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2713 if( errno == ERANGE )
2715 return LDAP_CONSTRAINT_VIOLATION;
2718 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2719 return LDAP_SUCCESS;
2723 serialNumberAndIssuerCheck(
2732 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2734 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2735 /* Parse old format */
2736 is->bv_val = ber_bvchr( in, '$' );
2737 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2739 sn->bv_val = in->bv_val;
2740 sn->bv_len = is->bv_val - in->bv_val;
2743 is->bv_len = in->bv_len - (sn->bv_len + 1);
2745 /* eat leading zeros */
2746 for( n=0; n < (sn->bv_len-1); n++ ) {
2747 if( sn->bv_val[n] != '0' ) break;
2752 for( n=0; n < sn->bv_len; n++ ) {
2753 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2757 /* Parse GSER format */
2758 int havesn=0,haveissuer=0;
2759 struct berval x = *in;
2764 /* eat leading spaces */
2765 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2769 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2770 return LDAP_INVALID_SYNTAX;
2773 /* should be at issuer or serialNumber NamedValue */
2774 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2776 x.bv_val += STRLENOF("issuer");
2777 x.bv_len -= STRLENOF("issuer");
2779 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2780 x.bv_val++; x.bv_len--;
2782 /* eat leading spaces */
2783 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2787 /* For backward compatibility, this part is optional */
2788 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2789 x.bv_val += STRLENOF("rdnSequence:");
2790 x.bv_len -= STRLENOF("rdnSequence:");
2793 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2794 x.bv_val++; x.bv_len--;
2796 is->bv_val = x.bv_val;
2799 for( ; is->bv_len < x.bv_len; ) {
2800 if ( is->bv_val[is->bv_len] != '"' ) {
2804 if ( is->bv_val[is->bv_len+1] == '"' ) {
2811 x.bv_val += is->bv_len+1;
2812 x.bv_len -= is->bv_len+1;
2814 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2815 return LDAP_INVALID_SYNTAX;
2820 } else if( strncasecmp( x.bv_val, "serialNumber",
2821 STRLENOF("serialNumber")) == 0 )
2823 /* parse serialNumber */
2825 x.bv_val += STRLENOF("serialNumber");
2826 x.bv_len -= STRLENOF("serialNumber");
2828 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2829 x.bv_val++; x.bv_len--;
2831 /* eat leading spaces */
2832 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2836 sn->bv_val = x.bv_val;
2839 if( sn->bv_val[0] == '-' ) {
2844 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2845 sn->bv_val[1] == 'X' )) {
2847 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2848 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2850 } else if ( sn->bv_val[0] == '\'' ) {
2851 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2852 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2854 if ( sn->bv_val[sn->bv_len] == '\'' &&
2855 sn->bv_val[sn->bv_len+1] == 'H' )
2858 return LDAP_INVALID_SYNTAX;
2861 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2862 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2866 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2867 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2868 return LDAP_INVALID_SYNTAX;
2871 x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len;
2873 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2874 return LDAP_INVALID_SYNTAX;
2879 } else return LDAP_INVALID_SYNTAX;
2881 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2882 x.bv_val++; x.bv_len--;
2885 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2889 /* should be at remaining NamedValue */
2890 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2891 STRLENOF("issuer" )) == 0 ))
2894 x.bv_val += STRLENOF("issuer");
2895 x.bv_len -= STRLENOF("issuer");
2897 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2898 x.bv_val++; x.bv_len--;
2900 /* eat leading spaces */
2901 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2905 /* For backward compatibility, this part is optional */
2906 if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2907 x.bv_val += STRLENOF("rdnSequence:");
2908 x.bv_len -= STRLENOF("rdnSequence:");
2911 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2912 x.bv_val++; x.bv_len--;
2914 is->bv_val = x.bv_val;
2917 for( ; is->bv_len < x.bv_len; ) {
2918 if ( is->bv_val[is->bv_len] != '"' ) {
2922 if ( is->bv_val[is->bv_len+1] == '"' ) {
2929 x.bv_val += is->bv_len+1;
2930 x.bv_len -= is->bv_len+1;
2932 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2933 STRLENOF("serialNumber")) == 0 ))
2935 /* parse serialNumber */
2937 x.bv_val += STRLENOF("serialNumber");
2938 x.bv_len -= STRLENOF("serialNumber");
2940 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2941 x.bv_val++; x.bv_len--;
2943 /* eat leading spaces */
2944 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2948 sn->bv_val = x.bv_val;
2951 if( sn->bv_val[0] == '-' ) {
2956 if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' ||
2957 sn->bv_val[1] == 'X' )) {
2959 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2960 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2962 } else if ( sn->bv_val[0] == '\'' ) {
2963 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2964 if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break;
2966 if ( sn->bv_val[sn->bv_len] == '\'' &&
2967 sn->bv_val[sn->bv_len+1] == 'H' )
2970 return LDAP_INVALID_SYNTAX;
2973 for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) {
2974 if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break;
2978 if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX;
2979 if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) {
2980 return LDAP_INVALID_SYNTAX;
2983 x.bv_val += sn->bv_len;
2984 x.bv_len -= sn->bv_len;
2986 } else return LDAP_INVALID_SYNTAX;
2988 /* eat trailing spaces */
2989 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2993 /* should have no characters left... */
2994 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2996 ber_dupbv_x( &ni, is, ctx );
2999 /* need to handle double dquotes here */
3005 serialNumberAndIssuerValidate(
3010 struct berval sn, i;
3012 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3015 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3019 /* validate DN -- doesn't handle double dquote */
3020 rc = dnValidate( NULL, &i );
3022 rc = LDAP_INVALID_SYNTAX;
3024 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3025 slap_sl_free( i.bv_val, NULL );
3028 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
3034 serialNumberAndIssuerPretty(
3041 struct berval sn, i, ni;
3043 assert( in != NULL );
3044 assert( out != NULL );
3046 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3049 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3053 rc = dnPretty( syntax, &i, &ni, ctx );
3055 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3056 slap_sl_free( i.bv_val, ctx );
3059 if( rc ) return LDAP_INVALID_SYNTAX;
3061 /* make room from sn + "$" */
3062 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3063 + sn.bv_len + ni.bv_len;
3064 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3066 if( out->bv_val == NULL ) {
3068 slap_sl_free( ni.bv_val, ctx );
3073 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3074 STRLENOF("{ serialNumber "));
3075 n = STRLENOF("{ serialNumber ");
3077 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3080 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3081 n += STRLENOF(", issuer rdnSequence:\"");
3083 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3086 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3087 n += STRLENOF("\" }");
3089 out->bv_val[n] = '\0';
3091 assert( n == out->bv_len );
3093 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3094 out->bv_val, 0, 0 );
3096 slap_sl_free( ni.bv_val, ctx );
3098 return LDAP_SUCCESS;
3102 * This routine is called by certificateExactNormalize when
3103 * certificateExactNormalize receives a search string instead of
3104 * a certificate. This routine checks if the search value is valid
3105 * and then returns the normalized value
3108 serialNumberAndIssuerNormalize(
3116 struct berval sn, sn2, i, ni;
3117 char sbuf[64], *stmp = sbuf;
3121 assert( in != NULL );
3122 assert( out != NULL );
3124 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3127 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3131 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3133 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3134 slap_sl_free( i.bv_val, ctx );
3137 if( rc ) return LDAP_INVALID_SYNTAX;
3139 /* Convert sn to canonical hex */
3140 if ( sn.bv_len > sizeof( sbuf )) {
3141 stmp = slap_sl_malloc( sn.bv_len, ctx );
3144 sn2.bv_len = sn.bv_len;
3145 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3146 rc = LDAP_INVALID_SYNTAX;
3150 /* make room for sn + "$" */
3151 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3152 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3153 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3155 if( out->bv_val == NULL ) {
3157 slap_sl_free( ni.bv_val, ctx );
3163 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3164 STRLENOF( "{ serialNumber " ));
3165 n = STRLENOF( "{ serialNumber " );
3167 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3170 unsigned char *v = (unsigned char *)sn2.bv_val;
3171 out->bv_val[n++] = '\'';
3172 for ( j = 0; j < sn2.bv_len; j++ ) {
3173 snprintf( &out->bv_val[n], out->bv_len - n + 1,
3177 out->bv_val[n++] = '\'';
3178 out->bv_val[n++] = 'H';
3181 AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3182 n += STRLENOF( ", issuer rdnSequence:\"" );
3184 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3187 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3188 n += STRLENOF( "\" }" );
3190 out->bv_val[n] = '\0';
3192 assert( n == out->bv_len );
3194 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3195 out->bv_val, 0, 0 );
3199 slap_sl_free( stmp, ctx );
3200 slap_sl_free( ni.bv_val, ctx );
3206 certificateExactNormalize(
3211 struct berval *normalized,
3214 BerElementBuffer berbuf;
3215 BerElement *ber = (BerElement *)&berbuf;
3219 char serialbuf[64], *serial = serialbuf;
3220 ber_len_t seriallen;
3221 struct berval issuer_dn = BER_BVNULL, bvdn;
3223 int rc = LDAP_INVALID_SYNTAX;
3225 if( BER_BVISEMPTY( val ) ) goto done;
3227 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3228 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3231 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3233 ber_init2( ber, val, LBER_USE_DER );
3234 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3235 tag = ber_skip_tag( ber, &len ); /* Sequence */
3236 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3237 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3238 tag = ber_skip_tag( ber, &len );
3239 tag = ber_get_int( ber, &i ); /* version */
3242 /* NOTE: move the test here from certificateValidate,
3243 * so that we can validate certs with serial longer
3244 * than sizeof(ber_int_t) */
3245 tag = ber_peek_tag( ber, &len ); /* serial */
3247 /* Use hex format. '123456789abcdef'H
3253 tag = ber_skip_tag( ber, &len );
3254 ptr = (unsigned char *)ber->ber_ptr;
3255 ber_skip_data( ber, len );
3257 /* Check for minimal encodings */
3259 if ( ptr[0] & 0x80 ) {
3260 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3261 return LDAP_INVALID_SYNTAX;
3262 } else if ( ptr[0] == 0 ) {
3263 if (!( ptr[1] & 0x80 ))
3264 return LDAP_INVALID_SYNTAX;
3268 seriallen = len * 2 + 4; /* quotes, H, NUL */
3269 if ( seriallen > sizeof( serialbuf ))
3270 serial = slap_sl_malloc( seriallen, ctx );
3273 for ( i = 0; i<len; i++ ) {
3274 sprintf( sptr, "%02X", ptr[i] );
3281 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3282 ber_skip_data( ber, len );
3283 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3284 len = ber_ptrlen( ber );
3285 bvdn.bv_val = val->bv_val + len;
3286 bvdn.bv_len = val->bv_len - len;
3288 rc = dnX509normalize( &bvdn, &issuer_dn );
3289 if( rc != LDAP_SUCCESS ) goto done;
3291 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3292 + seriallen + issuer_dn.bv_len;
3293 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3295 p = (unsigned char *)normalized->bv_val;
3297 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3298 p += STRLENOF( "{ serialNumber " );
3300 AC_MEMCPY(p, serial, seriallen);
3303 AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3304 p += STRLENOF( ", issuer rdnSequence:\"" );
3306 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3307 p += issuer_dn.bv_len;
3309 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3310 p += STRLENOF( "\" }" );
3314 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3315 normalized->bv_val, NULL, NULL );
3320 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3321 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3333 assert( in != NULL );
3334 assert( !BER_BVISNULL( in ) );
3336 for ( i = 0; i < in->bv_len; i++ ) {
3337 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3338 return LDAP_INVALID_SYNTAX;
3342 return LDAP_SUCCESS;
3345 /* Normalize a SID as used inside a CSN:
3346 * three-digit numeric string */
3353 struct berval *normalized,
3358 assert( val != NULL );
3359 assert( normalized != NULL );
3361 ber_dupbv_x( normalized, val, ctx );
3363 for ( i = 0; i < normalized->bv_len; i++ ) {
3364 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3365 ber_memfree_x( normalized->bv_val, ctx );
3366 BER_BVZERO( normalized );
3367 return LDAP_INVALID_SYNTAX;
3370 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3373 return LDAP_SUCCESS;
3381 assert( in != NULL );
3382 assert( !BER_BVISNULL( in ) );
3384 if ( in->bv_len != 3 ) {
3385 return LDAP_INVALID_SYNTAX;
3388 return hexValidate( NULL, in );
3391 /* Normalize a SID as used inside a CSN:
3392 * three-digit numeric string */
3399 struct berval *normalized,
3402 if ( val->bv_len != 3 ) {
3403 return LDAP_INVALID_SYNTAX;
3406 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3416 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3419 /* Normalize a SID as used inside a CSN, either as-is
3420 * (assertion value) or extracted from the CSN
3421 * (attribute value) */
3428 struct berval *normalized,
3436 if ( BER_BVISEMPTY( val ) ) {
3437 return LDAP_INVALID_SYNTAX;
3440 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3441 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3444 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3446 ptr = ber_bvchr( val, '#' );
3447 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3448 return LDAP_INVALID_SYNTAX;
3451 bv.bv_val = ptr + 1;
3452 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3454 ptr = ber_bvchr( &bv, '#' );
3455 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3456 return LDAP_INVALID_SYNTAX;
3459 bv.bv_val = ptr + 1;
3460 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3462 ptr = ber_bvchr( &bv, '#' );
3463 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3464 return LDAP_INVALID_SYNTAX;
3467 bv.bv_len = ptr - bv.bv_val;
3469 if ( bv.bv_len == 2 ) {
3470 /* OpenLDAP 2.3 SID */
3472 buf[ 1 ] = bv.bv_val[ 0 ];
3473 buf[ 2 ] = bv.bv_val[ 1 ];
3480 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3492 assert( in != NULL );
3493 assert( !BER_BVISNULL( in ) );
3495 if ( BER_BVISEMPTY( in ) ) {
3496 return LDAP_INVALID_SYNTAX;
3501 ptr = ber_bvchr( &bv, '#' );
3502 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3503 return LDAP_INVALID_SYNTAX;
3506 bv.bv_len = ptr - bv.bv_val;
3507 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3508 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3510 return LDAP_INVALID_SYNTAX;
3513 rc = generalizedTimeValidate( NULL, &bv );
3514 if ( rc != LDAP_SUCCESS ) {
3518 bv.bv_val = ptr + 1;
3519 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3521 ptr = ber_bvchr( &bv, '#' );
3522 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3523 return LDAP_INVALID_SYNTAX;
3526 bv.bv_len = ptr - bv.bv_val;
3527 if ( bv.bv_len != 6 ) {
3528 return LDAP_INVALID_SYNTAX;
3531 rc = hexValidate( NULL, &bv );
3532 if ( rc != LDAP_SUCCESS ) {
3536 bv.bv_val = ptr + 1;
3537 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3539 ptr = ber_bvchr( &bv, '#' );
3540 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3541 return LDAP_INVALID_SYNTAX;
3544 bv.bv_len = ptr - bv.bv_val;
3545 if ( bv.bv_len == 2 ) {
3546 /* tolerate old 2-digit replica-id */
3547 rc = hexValidate( NULL, &bv );
3550 rc = sidValidate( NULL, &bv );
3552 if ( rc != LDAP_SUCCESS ) {
3556 bv.bv_val = ptr + 1;
3557 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3559 if ( bv.bv_len != 6 ) {
3560 return LDAP_INVALID_SYNTAX;
3563 return hexValidate( NULL, &bv );
3566 /* Normalize a CSN in OpenLDAP 2.1 format */
3573 struct berval *normalized,
3576 struct berval gt, cnt, sid, mod;
3578 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3582 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3583 assert( !BER_BVISEMPTY( val ) );
3587 ptr = ber_bvchr( >, '#' );
3588 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3589 return LDAP_INVALID_SYNTAX;
3592 gt.bv_len = ptr - gt.bv_val;
3593 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
3594 return LDAP_INVALID_SYNTAX;
3597 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
3598 return LDAP_INVALID_SYNTAX;
3601 cnt.bv_val = ptr + 1;
3602 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3604 ptr = ber_bvchr( &cnt, '#' );
3605 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3606 return LDAP_INVALID_SYNTAX;
3609 cnt.bv_len = ptr - cnt.bv_val;
3610 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
3611 return LDAP_INVALID_SYNTAX;
3614 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
3615 return LDAP_INVALID_SYNTAX;
3618 cnt.bv_val += STRLENOF( "0x" );
3619 cnt.bv_len -= STRLENOF( "0x" );
3621 sid.bv_val = ptr + 1;
3622 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3624 ptr = ber_bvchr( &sid, '#' );
3625 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3626 return LDAP_INVALID_SYNTAX;
3629 sid.bv_len = ptr - sid.bv_val;
3630 if ( sid.bv_len != STRLENOF( "0" ) ) {
3631 return LDAP_INVALID_SYNTAX;
3634 mod.bv_val = ptr + 1;
3635 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3636 if ( mod.bv_len != STRLENOF( "0000" ) ) {
3637 return LDAP_INVALID_SYNTAX;
3640 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3644 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
3645 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
3647 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
3649 ptr = lutil_strcopy( ptr, ".000000Z#00" );
3650 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3654 *ptr++ = sid.bv_val[ 0 ];
3658 for ( i = 0; i < mod.bv_len; i++ ) {
3659 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3663 assert( ptr - bv.bv_val == bv.bv_len );
3665 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3666 return LDAP_INVALID_SYNTAX;
3669 ber_dupbv_x( normalized, &bv, ctx );
3671 return LDAP_SUCCESS;
3674 /* Normalize a CSN in OpenLDAP 2.3 format */
3681 struct berval *normalized,
3684 struct berval gt, cnt, sid, mod;
3686 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3690 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3691 assert( !BER_BVISEMPTY( val ) );
3695 ptr = ber_bvchr( >, '#' );
3696 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3697 return LDAP_INVALID_SYNTAX;
3700 gt.bv_len = ptr - gt.bv_val;
3701 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3702 return LDAP_INVALID_SYNTAX;
3705 cnt.bv_val = ptr + 1;
3706 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3708 ptr = ber_bvchr( &cnt, '#' );
3709 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3710 return LDAP_INVALID_SYNTAX;
3713 cnt.bv_len = ptr - cnt.bv_val;
3714 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
3715 return LDAP_INVALID_SYNTAX;
3718 sid.bv_val = ptr + 1;
3719 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3721 ptr = ber_bvchr( &sid, '#' );
3722 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3723 return LDAP_INVALID_SYNTAX;
3726 sid.bv_len = ptr - sid.bv_val;
3727 if ( sid.bv_len != STRLENOF( "00" ) ) {
3728 return LDAP_INVALID_SYNTAX;
3731 mod.bv_val = ptr + 1;
3732 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3733 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3734 return LDAP_INVALID_SYNTAX;
3737 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3741 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3742 ptr = lutil_strcopy( ptr, ".000000Z#" );
3743 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3746 for ( i = 0; i < sid.bv_len; i++ ) {
3747 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3750 for ( i = 0; i < mod.bv_len; i++ ) {
3751 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3755 assert( ptr - bv.bv_val == bv.bv_len );
3756 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3757 return LDAP_INVALID_SYNTAX;
3760 ber_dupbv_x( normalized, &bv, ctx );
3762 return LDAP_SUCCESS;
3765 /* Normalize a CSN */
3772 struct berval *normalized,
3775 struct berval cnt, sid, mod;
3779 assert( val != NULL );
3780 assert( normalized != NULL );
3782 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3784 if ( BER_BVISEMPTY( val ) ) {
3785 return LDAP_INVALID_SYNTAX;
3788 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3789 /* Openldap <= 2.3 */
3791 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3794 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
3797 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
3800 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
3801 return LDAP_INVALID_SYNTAX;
3804 ptr = ber_bvchr( val, '#' );
3805 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3806 return LDAP_INVALID_SYNTAX;
3809 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
3810 return LDAP_INVALID_SYNTAX;
3813 cnt.bv_val = ptr + 1;
3814 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3816 ptr = ber_bvchr( &cnt, '#' );
3817 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3818 return LDAP_INVALID_SYNTAX;
3821 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
3822 return LDAP_INVALID_SYNTAX;
3825 sid.bv_val = ptr + 1;
3826 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3828 ptr = ber_bvchr( &sid, '#' );
3829 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3830 return LDAP_INVALID_SYNTAX;
3833 sid.bv_len = ptr - sid.bv_val;
3834 if ( sid.bv_len != STRLENOF( "000" ) ) {
3835 return LDAP_INVALID_SYNTAX;
3838 mod.bv_val = ptr + 1;
3839 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3841 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3842 return LDAP_INVALID_SYNTAX;
3845 ber_dupbv_x( normalized, val, ctx );
3847 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3848 i < normalized->bv_len; i++ )
3850 /* assume it's already validated that's all hex digits */
3851 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3854 return LDAP_SUCCESS;
3864 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3867 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3868 /* slight optimization - does not need the start parameter */
3869 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3874 check_time_syntax (struct berval *val,
3877 struct berval *fraction)
3880 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3881 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3882 * GeneralizedTime supports leap seconds, UTCTime does not.
3884 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3885 static const int mdays[2][12] = {
3886 /* non-leap years */
3887 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3889 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3892 int part, c, c1, c2, tzoffset, leapyear = 0;
3895 e = p + val->bv_len;
3897 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3898 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3900 for (part = start; part < 7 && p < e; part++) {
3902 if (!ASCII_DIGIT(c1)) {
3907 return LDAP_INVALID_SYNTAX;
3910 if (!ASCII_DIGIT(c)) {
3911 return LDAP_INVALID_SYNTAX;
3913 c += c1 * 10 - '0' * 11;
3914 if ((part | 1) == 3) {
3917 return LDAP_INVALID_SYNTAX;
3920 if (c >= ceiling[part]) {
3921 if (! (c == 60 && part == 6 && start == 0))
3922 return LDAP_INVALID_SYNTAX;
3926 if (part < 5 + start) {
3927 return LDAP_INVALID_SYNTAX;
3929 for (; part < 9; part++) {
3933 /* leapyear check for the Gregorian calendar (year>1581) */
3934 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3938 if (parts[3] >= mdays[leapyear][parts[2]]) {
3939 return LDAP_INVALID_SYNTAX;
3943 fraction->bv_val = p;
3944 fraction->bv_len = 0;
3945 if (p < e && (*p == '.' || *p == ',')) {
3947 while (++p < e && ASCII_DIGIT(*p)) {
3950 if (p - fraction->bv_val == 1) {
3951 return LDAP_INVALID_SYNTAX;
3953 for (end_num = p; end_num[-1] == '0'; --end_num) {
3956 c = end_num - fraction->bv_val;
3957 if (c != 1) fraction->bv_len = c;
3963 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3969 return LDAP_INVALID_SYNTAX;
3975 for (part = 7; part < 9 && p < e; part++) {
3977 if (!ASCII_DIGIT(c1)) {
3982 return LDAP_INVALID_SYNTAX;
3985 if (!ASCII_DIGIT(c2)) {
3986 return LDAP_INVALID_SYNTAX;
3988 parts[part] = c1 * 10 + c2 - '0' * 11;
3989 if (parts[part] >= ceiling[part]) {
3990 return LDAP_INVALID_SYNTAX;
3993 if (part < 8 + start) {
3994 return LDAP_INVALID_SYNTAX;
3997 if (tzoffset == '-') {
3998 /* negative offset to UTC, ie west of Greenwich */
3999 parts[4] += parts[7];
4000 parts[5] += parts[8];
4001 /* offset is just hhmm, no seconds */
4002 for (part = 6; --part >= 0; ) {
4006 c = mdays[leapyear][parts[2]];
4008 if (parts[part] >= c) {
4010 return LDAP_INVALID_SYNTAX;
4015 } else if (part != 5) {
4020 /* positive offset to UTC, ie east of Greenwich */
4021 parts[4] -= parts[7];
4022 parts[5] -= parts[8];
4023 for (part = 6; --part >= 0; ) {
4024 if (parts[part] < 0) {
4026 return LDAP_INVALID_SYNTAX;
4031 /* make first arg to % non-negative */
4032 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4037 } else if (part != 5) {
4044 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4047 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4054 struct berval *normalized )
4058 rc = check_time_syntax(val, 1, parts, NULL);
4059 if (rc != LDAP_SUCCESS) {
4063 normalized->bv_val = ch_malloc( 14 );
4064 if ( normalized->bv_val == NULL ) {
4065 return LBER_ERROR_MEMORY;
4068 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4069 parts[1], parts[2] + 1, parts[3] + 1,
4070 parts[4], parts[5], parts[6] );
4071 normalized->bv_len = 13;
4073 return LDAP_SUCCESS;
4083 return check_time_syntax(in, 1, parts, NULL);
4086 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4089 generalizedTimeValidate(
4094 struct berval fraction;
4095 return check_time_syntax(in, 0, parts, &fraction);
4099 generalizedTimeNormalize(
4104 struct berval *normalized,
4109 struct berval fraction;
4111 rc = check_time_syntax(val, 0, parts, &fraction);
4112 if (rc != LDAP_SUCCESS) {
4116 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4117 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4118 if ( BER_BVISNULL( normalized ) ) {
4119 return LBER_ERROR_MEMORY;
4122 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4123 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4124 parts[4], parts[5], parts[6] );
4125 if ( !BER_BVISEMPTY( &fraction ) ) {
4126 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4127 fraction.bv_val, fraction.bv_len );
4128 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4130 strcpy( normalized->bv_val + len-1, "Z" );
4131 normalized->bv_len = len;
4133 return LDAP_SUCCESS;
4137 generalizedTimeOrderingMatch(
4142 struct berval *value,
4143 void *assertedValue )
4145 struct berval *asserted = (struct berval *) assertedValue;
4146 ber_len_t v_len = value->bv_len;
4147 ber_len_t av_len = asserted->bv_len;
4149 /* ignore trailing 'Z' when comparing */
4150 int match = memcmp( value->bv_val, asserted->bv_val,
4151 (v_len < av_len ? v_len : av_len) - 1 );
4152 if ( match == 0 ) match = v_len - av_len;
4155 return LDAP_SUCCESS;
4158 /* Index generation function */
4159 int generalizedTimeIndexer(
4164 struct berval *prefix,
4172 BerValue bvtmp; /* 40 bit index */
4174 struct lutil_timet tt;
4176 bvtmp.bv_len = sizeof(tmp);
4178 for( i=0; values[i].bv_val != NULL; i++ ) {
4179 /* just count them */
4182 /* we should have at least one value at this point */
4185 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4187 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4188 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4189 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4190 /* Use 40 bits of time for key */
4191 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4192 lutil_tm2time( &tm, &tt );
4193 tmp[0] = tt.tt_gsec & 0xff;
4194 tmp[4] = tt.tt_sec & 0xff;
4196 tmp[3] = tt.tt_sec & 0xff;
4198 tmp[2] = tt.tt_sec & 0xff;
4200 tmp[1] = tt.tt_sec & 0xff;
4202 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4206 keys[j].bv_val = NULL;
4211 return LDAP_SUCCESS;
4214 /* Index generation function */
4215 int generalizedTimeFilter(
4220 struct berval *prefix,
4221 void * assertedValue,
4227 BerValue bvtmp; /* 40 bit index */
4228 BerValue *value = (BerValue *) assertedValue;
4230 struct lutil_timet tt;
4232 bvtmp.bv_len = sizeof(tmp);
4234 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4235 /* Use 40 bits of time for key */
4236 if ( value->bv_val && value->bv_len >= 10 &&
4237 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4239 lutil_tm2time( &tm, &tt );
4240 tmp[0] = tt.tt_gsec & 0xff;
4241 tmp[4] = tt.tt_sec & 0xff;
4243 tmp[3] = tt.tt_sec & 0xff;
4245 tmp[2] = tt.tt_sec & 0xff;
4247 tmp[1] = tt.tt_sec & 0xff;
4249 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4250 ber_dupbv_x(keys, &bvtmp, ctx );
4251 keys[1].bv_val = NULL;
4259 return LDAP_SUCCESS;
4263 deliveryMethodValidate(
4265 struct berval *val )
4268 #define LENOF(s) (sizeof(s)-1)
4269 struct berval tmp = *val;
4271 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4272 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4273 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4276 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4278 switch( tmp.bv_val[0] ) {
4281 if(( tmp.bv_len >= LENOF("any") ) &&
4282 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4284 tmp.bv_len -= LENOF("any");
4285 tmp.bv_val += LENOF("any");
4288 return LDAP_INVALID_SYNTAX;
4292 if(( tmp.bv_len >= LENOF("mhs") ) &&
4293 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4295 tmp.bv_len -= LENOF("mhs");
4296 tmp.bv_val += LENOF("mhs");
4299 return LDAP_INVALID_SYNTAX;
4303 if(( tmp.bv_len >= LENOF("physical") ) &&
4304 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4306 tmp.bv_len -= LENOF("physical");
4307 tmp.bv_val += LENOF("physical");
4310 return LDAP_INVALID_SYNTAX;
4313 case 'T': /* telex or teletex or telephone */
4314 if(( tmp.bv_len >= LENOF("telex") ) &&
4315 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4317 tmp.bv_len -= LENOF("telex");
4318 tmp.bv_val += LENOF("telex");
4321 if(( tmp.bv_len >= LENOF("teletex") ) &&
4322 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4324 tmp.bv_len -= LENOF("teletex");
4325 tmp.bv_val += LENOF("teletex");
4328 if(( tmp.bv_len >= LENOF("telephone") ) &&
4329 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4331 tmp.bv_len -= LENOF("telephone");
4332 tmp.bv_val += LENOF("telephone");
4335 return LDAP_INVALID_SYNTAX;
4338 case 'G': /* g3fax or g4fax */
4339 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4340 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4341 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4343 tmp.bv_len -= LENOF("g3fax");
4344 tmp.bv_val += LENOF("g3fax");
4347 return LDAP_INVALID_SYNTAX;
4351 if(( tmp.bv_len >= LENOF("ia5") ) &&
4352 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4354 tmp.bv_len -= LENOF("ia5");
4355 tmp.bv_val += LENOF("ia5");
4358 return LDAP_INVALID_SYNTAX;
4362 if(( tmp.bv_len >= LENOF("videotex") ) &&
4363 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4365 tmp.bv_len -= LENOF("videotex");
4366 tmp.bv_val += LENOF("videotex");
4369 return LDAP_INVALID_SYNTAX;
4372 return LDAP_INVALID_SYNTAX;
4375 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4377 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4381 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4385 return LDAP_INVALID_SYNTAX;
4387 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4396 nisNetgroupTripleValidate(
4398 struct berval *val )
4403 if ( BER_BVISEMPTY( val ) ) {
4404 return LDAP_INVALID_SYNTAX;
4407 p = (char *)val->bv_val;
4408 e = p + val->bv_len;
4410 if ( *p != '(' /*')'*/ ) {
4411 return LDAP_INVALID_SYNTAX;
4414 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4418 return LDAP_INVALID_SYNTAX;
4421 } else if ( !AD_CHAR( *p ) ) {
4422 return LDAP_INVALID_SYNTAX;
4426 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4427 return LDAP_INVALID_SYNTAX;
4433 return LDAP_INVALID_SYNTAX;
4436 return LDAP_SUCCESS;
4440 bootParameterValidate(
4442 struct berval *val )
4446 if ( BER_BVISEMPTY( val ) ) {
4447 return LDAP_INVALID_SYNTAX;
4450 p = (char *)val->bv_val;
4451 e = p + val->bv_len;
4454 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4455 if ( !AD_CHAR( *p ) ) {
4456 return LDAP_INVALID_SYNTAX;
4461 return LDAP_INVALID_SYNTAX;
4465 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4466 if ( !AD_CHAR( *p ) ) {
4467 return LDAP_INVALID_SYNTAX;
4472 return LDAP_INVALID_SYNTAX;
4476 for ( p++; p < e; p++ ) {
4477 if ( !SLAP_PRINTABLE( *p ) ) {
4478 return LDAP_INVALID_SYNTAX;
4482 return LDAP_SUCCESS;
4486 firstComponentNormalize(
4491 struct berval *normalized,
4498 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4499 ber_dupbv_x( normalized, val, ctx );
4500 return LDAP_SUCCESS;
4503 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4505 if( val->bv_val[0] != '(' /*')'*/ &&
4506 val->bv_val[0] != '{' /*'}'*/ )
4508 return LDAP_INVALID_SYNTAX;
4511 /* trim leading white space */
4513 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4519 /* grab next word */
4520 comp.bv_val = &val->bv_val[len];
4521 len = val->bv_len - len;
4522 for( comp.bv_len = 0;
4523 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4529 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4530 rc = numericoidValidate( NULL, &comp );
4531 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4532 rc = integerValidate( NULL, &comp );
4534 rc = LDAP_INVALID_SYNTAX;
4538 if( rc == LDAP_SUCCESS ) {
4539 ber_dupbv_x( normalized, &comp, ctx );
4545 static char *country_gen_syn[] = {
4546 "1.3.6.1.4.1.1466.115.121.1.15",
4547 "1.3.6.1.4.1.1466.115.121.1.26",
4548 "1.3.6.1.4.1.1466.115.121.1.44",
4552 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4553 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4555 static slap_syntax_defs_rec syntax_defs[] = {
4556 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4557 X_BINARY X_NOT_H_R ")",
4558 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4559 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4560 0, NULL, NULL, NULL},
4561 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4562 0, NULL, NULL, NULL},
4563 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4565 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4566 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4568 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4569 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4570 0, NULL, bitStringValidate, NULL },
4571 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4572 0, NULL, booleanValidate, NULL},
4573 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4574 X_BINARY X_NOT_H_R ")",
4575 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4576 NULL, certificateValidate, NULL},
4577 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4578 X_BINARY X_NOT_H_R ")",
4579 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4580 NULL, certificateListValidate, NULL},
4581 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4582 X_BINARY X_NOT_H_R ")",
4583 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4584 NULL, sequenceValidate, NULL},
4585 #if 0 /* need to go __after__ printableString */
4586 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4587 0, "1.3.6.1.4.1.1466.115.121.1.44",
4588 countryStringValidate, NULL},
4590 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4591 0, NULL, dnValidate, dnPretty},
4592 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4593 0, NULL, rdnValidate, rdnPretty},
4594 #ifdef LDAP_COMP_MATCH
4595 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4596 0, NULL, allComponentsValidate, NULL},
4597 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4598 0, NULL, componentFilterValidate, NULL},
4600 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4601 0, NULL, NULL, NULL},
4602 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4603 0, NULL, deliveryMethodValidate, NULL},
4604 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4605 0, NULL, UTF8StringValidate, NULL},
4606 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4607 0, NULL, NULL, NULL},
4608 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4609 0, NULL, NULL, NULL},
4610 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4611 0, NULL, NULL, NULL},
4612 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4613 0, NULL, NULL, NULL},
4614 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4615 0, NULL, NULL, NULL},
4616 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4617 0, NULL, printablesStringValidate, NULL},
4618 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4619 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4620 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4621 0, NULL, generalizedTimeValidate, NULL},
4622 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4623 0, NULL, NULL, NULL},
4624 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4625 0, NULL, IA5StringValidate, NULL},
4626 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4627 0, NULL, integerValidate, NULL},
4628 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4629 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4630 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4631 0, NULL, NULL, NULL},
4632 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4633 0, NULL, NULL, NULL},
4634 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4635 0, NULL, NULL, NULL},
4636 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4637 0, NULL, NULL, NULL},
4638 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4639 0, NULL, NULL, NULL},
4640 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4641 0, NULL, nameUIDValidate, nameUIDPretty },
4642 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4643 0, NULL, NULL, NULL},
4644 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4645 0, NULL, numericStringValidate, NULL},
4646 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4647 0, NULL, NULL, NULL},
4648 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4649 0, NULL, numericoidValidate, NULL},
4650 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4651 0, NULL, IA5StringValidate, NULL},
4652 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4653 0, NULL, blobValidate, NULL},
4654 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4655 0, NULL, UTF8StringValidate, NULL},
4656 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4657 0, NULL, NULL, NULL},
4658 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4659 0, NULL, NULL, NULL},
4660 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4661 0, NULL, printableStringValidate, NULL},
4662 /* moved here because now depends on Directory String, IA5 String
4663 * and Printable String */
4664 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4665 0, country_gen_syn, countryStringValidate, NULL},
4666 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4667 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4668 0, NULL, subtreeSpecificationValidate, NULL},
4669 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4670 X_BINARY X_NOT_H_R ")",
4671 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4672 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4673 0, NULL, printableStringValidate, NULL},
4674 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4675 0, NULL, NULL, NULL},
4676 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4677 0, NULL, printablesStringValidate, NULL},
4678 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4679 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4680 0, NULL, utcTimeValidate, NULL},
4682 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4683 0, NULL, NULL, NULL},
4684 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4685 0, NULL, NULL, NULL},
4686 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4687 0, NULL, NULL, NULL},
4688 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4689 0, NULL, NULL, NULL},
4690 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4691 0, NULL, NULL, NULL},
4693 /* RFC 2307 NIS Syntaxes */
4694 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4695 0, NULL, nisNetgroupTripleValidate, NULL},
4696 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4697 0, NULL, bootParameterValidate, NULL},
4699 /* draft-zeilenga-ldap-x509 */
4700 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4701 SLAP_SYNTAX_HIDE, NULL,
4702 serialNumberAndIssuerValidate,
4703 serialNumberAndIssuerPretty},
4704 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4705 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4706 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4707 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4708 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4709 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4710 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4711 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4712 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4713 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4714 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4715 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4717 #ifdef SLAPD_AUTHPASSWD
4718 /* needs updating */
4719 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4720 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4723 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4724 0, NULL, UUIDValidate, UUIDPretty},
4726 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4727 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4729 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4730 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4732 /* OpenLDAP Void Syntax */
4733 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4734 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4736 /* FIXME: OID is unused, but not registered yet */
4737 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4738 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4740 {NULL, 0, NULL, NULL, NULL}
4743 char *csnSIDMatchSyntaxes[] = {
4744 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4747 char *certificateExactMatchSyntaxes[] = {
4748 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4751 #ifdef LDAP_COMP_MATCH
4752 char *componentFilterMatchSyntaxes[] = {
4753 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4757 char *directoryStringSyntaxes[] = {
4758 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4761 char *integerFirstComponentMatchSyntaxes[] = {
4762 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4763 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4766 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4767 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4768 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4769 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4770 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4771 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4772 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4773 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4774 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4779 * Other matching rules in X.520 that we do not use (yet):
4781 * 2.5.13.25 uTCTimeMatch
4782 * 2.5.13.26 uTCTimeOrderingMatch
4783 * 2.5.13.31* directoryStringFirstComponentMatch
4784 * 2.5.13.32* wordMatch
4785 * 2.5.13.33* keywordMatch
4786 * 2.5.13.36+ certificatePairExactMatch
4787 * 2.5.13.37+ certificatePairMatch
4788 * 2.5.13.38+ certificateListExactMatch
4789 * 2.5.13.39+ certificateListMatch
4790 * 2.5.13.40+ algorithmIdentifierMatch
4791 * 2.5.13.41* storedPrefixMatch
4792 * 2.5.13.42 attributeCertificateMatch
4793 * 2.5.13.43 readerAndKeyIDMatch
4794 * 2.5.13.44 attributeIntegrityMatch
4796 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4797 * (+) described in draft-zeilenga-ldap-x509
4799 static slap_mrule_defs_rec mrule_defs[] = {
4801 * EQUALITY matching rules must be listed after associated APPROX
4802 * matching rules. So, we list all APPROX matching rules first.
4804 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4805 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4806 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4807 NULL, NULL, directoryStringApproxMatch,
4808 directoryStringApproxIndexer, directoryStringApproxFilter,
4811 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4812 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4813 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4814 NULL, NULL, IA5StringApproxMatch,
4815 IA5StringApproxIndexer, IA5StringApproxFilter,
4819 * Other matching rules
4822 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4823 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4824 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4825 NULL, NULL, octetStringMatch,
4826 octetStringIndexer, octetStringFilter,
4829 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4830 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4831 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4832 NULL, dnNormalize, dnMatch,
4833 octetStringIndexer, octetStringFilter,
4836 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4837 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4838 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4839 NULL, dnNormalize, dnRelativeMatch,
4843 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4844 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4845 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4846 NULL, dnNormalize, dnRelativeMatch,
4850 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4851 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4852 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4853 NULL, dnNormalize, dnRelativeMatch,
4857 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4858 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4859 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4860 NULL, dnNormalize, dnRelativeMatch,
4864 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4865 "SYNTAX 1.2.36.79672281.1.5.0 )",
4866 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4867 NULL, rdnNormalize, rdnMatch,
4868 octetStringIndexer, octetStringFilter,
4871 #ifdef LDAP_COMP_MATCH
4872 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4873 "SYNTAX 1.2.36.79672281.1.5.2 )",
4874 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4875 NULL, NULL , componentFilterMatch,
4876 octetStringIndexer, octetStringFilter,
4879 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4880 "SYNTAX 1.2.36.79672281.1.5.3 )",
4881 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4882 NULL, NULL , allComponentsMatch,
4883 octetStringIndexer, octetStringFilter,
4886 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4887 "SYNTAX 1.2.36.79672281.1.5.3 )",
4888 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4889 NULL, NULL , directoryComponentsMatch,
4890 octetStringIndexer, octetStringFilter,
4894 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4895 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4896 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4897 NULL, UTF8StringNormalize, octetStringMatch,
4898 octetStringIndexer, octetStringFilter,
4899 directoryStringApproxMatchOID },
4901 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4902 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4903 SLAP_MR_ORDERING, directoryStringSyntaxes,
4904 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4906 "caseIgnoreMatch" },
4908 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4909 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4910 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4911 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4912 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4913 "caseIgnoreMatch" },
4915 {"( 2.5.13.5 NAME 'caseExactMatch' "
4916 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4917 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4918 NULL, UTF8StringNormalize, octetStringMatch,
4919 octetStringIndexer, octetStringFilter,
4920 directoryStringApproxMatchOID },
4922 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4923 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4924 SLAP_MR_ORDERING, directoryStringSyntaxes,
4925 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4929 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4930 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4931 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4932 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4933 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4936 {"( 2.5.13.8 NAME 'numericStringMatch' "
4937 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4938 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4939 NULL, numericStringNormalize, octetStringMatch,
4940 octetStringIndexer, octetStringFilter,
4943 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4944 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4945 SLAP_MR_ORDERING, NULL,
4946 NULL, numericStringNormalize, octetStringOrderingMatch,
4948 "numericStringMatch" },
4950 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4951 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4952 SLAP_MR_SUBSTR, NULL,
4953 NULL, numericStringNormalize, octetStringSubstringsMatch,
4954 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4955 "numericStringMatch" },
4957 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4958 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4959 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4960 NULL, NULL, NULL, NULL, NULL, NULL },
4962 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4963 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4964 SLAP_MR_SUBSTR, NULL,
4965 NULL, NULL, NULL, NULL, NULL,
4966 "caseIgnoreListMatch" },
4968 {"( 2.5.13.13 NAME 'booleanMatch' "
4969 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4970 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4971 NULL, NULL, booleanMatch,
4972 octetStringIndexer, octetStringFilter,
4975 {"( 2.5.13.14 NAME 'integerMatch' "
4976 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4977 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
4978 NULL, NULL, integerMatch,
4979 integerIndexer, integerFilter,
4982 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4983 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4984 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
4985 NULL, NULL, integerMatch,
4989 {"( 2.5.13.16 NAME 'bitStringMatch' "
4990 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4991 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4992 NULL, NULL, octetStringMatch,
4993 octetStringIndexer, octetStringFilter,
4996 {"( 2.5.13.17 NAME 'octetStringMatch' "
4997 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4998 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4999 NULL, NULL, octetStringMatch,
5000 octetStringIndexer, octetStringFilter,
5003 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5004 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5005 SLAP_MR_ORDERING, NULL,
5006 NULL, NULL, octetStringOrderingMatch,
5008 "octetStringMatch" },
5010 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5011 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5012 SLAP_MR_SUBSTR, NULL,
5013 NULL, NULL, octetStringSubstringsMatch,
5014 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5015 "octetStringMatch" },
5017 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5018 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5019 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5021 telephoneNumberNormalize, octetStringMatch,
5022 octetStringIndexer, octetStringFilter,
5025 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5026 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5027 SLAP_MR_SUBSTR, NULL,
5028 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5029 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5030 "telephoneNumberMatch" },
5032 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5033 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5034 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5035 NULL, NULL, NULL, NULL, NULL, NULL },
5037 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5038 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5039 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5040 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5041 uniqueMemberIndexer, uniqueMemberFilter,
5044 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5045 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5046 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5047 NULL, NULL, NULL, NULL, NULL, NULL },
5049 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5050 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5051 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5052 NULL, generalizedTimeNormalize, octetStringMatch,
5053 generalizedTimeIndexer, generalizedTimeFilter,
5056 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5057 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5058 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5059 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5061 "generalizedTimeMatch" },
5063 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5064 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5065 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5066 integerFirstComponentMatchSyntaxes,
5067 NULL, firstComponentNormalize, integerMatch,
5068 octetStringIndexer, octetStringFilter,
5071 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5072 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5073 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5074 objectIdentifierFirstComponentMatchSyntaxes,
5075 NULL, firstComponentNormalize, octetStringMatch,
5076 octetStringIndexer, octetStringFilter,
5079 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5080 "SYNTAX 1.3.6.1.1.15.1 )",
5081 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5082 NULL, certificateExactNormalize, octetStringMatch,
5083 octetStringIndexer, octetStringFilter,
5086 {"( 2.5.13.35 NAME 'certificateMatch' "
5087 "SYNTAX 1.3.6.1.1.15.2 )",
5088 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5089 NULL, NULL, NULL, NULL, NULL,
5092 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5094 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5095 NULL, IA5StringNormalize, octetStringMatch,
5096 octetStringIndexer, octetStringFilter,
5097 IA5StringApproxMatchOID },
5099 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5101 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5102 NULL, IA5StringNormalize, octetStringMatch,
5103 octetStringIndexer, octetStringFilter,
5104 IA5StringApproxMatchOID },
5106 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5108 SLAP_MR_SUBSTR, NULL,
5109 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5110 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5111 "caseIgnoreIA5Match" },
5113 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5115 SLAP_MR_SUBSTR, NULL,
5116 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5117 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5118 "caseExactIA5Match" },
5120 #ifdef SLAPD_AUTHPASSWD
5121 /* needs updating */
5122 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5123 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5124 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5125 NULL, NULL, authPasswordMatch,
5130 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5131 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5133 NULL, NULL, integerBitAndMatch,
5137 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5138 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5140 NULL, NULL, integerBitOrMatch,
5144 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5145 "SYNTAX 1.3.6.1.1.16.1 )",
5146 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5147 NULL, UUIDNormalize, octetStringMatch,
5148 octetStringIndexer, octetStringFilter,
5151 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5152 "SYNTAX 1.3.6.1.1.16.1 )",
5153 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5154 NULL, UUIDNormalize, octetStringOrderingMatch,
5155 octetStringIndexer, octetStringFilter,
5158 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5159 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5160 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5161 NULL, csnNormalize, csnMatch,
5162 csnIndexer, csnFilter,
5165 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5166 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5167 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5168 NULL, NULL, csnOrderingMatch,
5172 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5173 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5174 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5175 NULL, csnSidNormalize, octetStringMatch,
5176 octetStringIndexer, octetStringFilter,
5179 /* FIXME: OID is unused, but not registered yet */
5180 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5181 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5182 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5183 NULL, authzNormalize, authzMatch,
5187 {NULL, SLAP_MR_NONE, NULL,
5188 NULL, NULL, NULL, NULL, NULL,
5193 slap_schema_init( void )
5198 /* we should only be called once (from main) */
5199 assert( schema_init_done == 0 );
5201 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5202 res = register_syntax( &syntax_defs[i] );
5205 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5206 syntax_defs[i].sd_desc );
5211 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5212 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5213 mrule_defs[i].mrd_compat_syntaxes == NULL )
5216 "slap_schema_init: Ignoring unusable matching rule %s\n",
5217 mrule_defs[i].mrd_desc );
5221 res = register_matching_rule( &mrule_defs[i] );
5225 "slap_schema_init: Error registering matching rule %s\n",
5226 mrule_defs[i].mrd_desc );
5231 res = slap_schema_load();
5232 schema_init_done = 1;
5237 schema_destroy( void )
5246 if( schema_init_done ) {
5247 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5248 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );