1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 /* FIXME: temporary */
59 #define authzMatch octetStringMatch
61 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
62 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
63 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
64 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
66 ldap_pvt_thread_mutex_t ad_undef_mutex;
67 ldap_pvt_thread_mutex_t oc_undef_mutex;
70 generalizedTimeValidate(
79 /* no value allowed */
80 return LDAP_INVALID_SYNTAX;
88 /* any value allowed */
92 #define berValidate blobValidate
99 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
100 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
105 /* X.509 related stuff */
113 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
116 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
117 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
118 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
119 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
123 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
126 /* X.509 certificate validation */
127 static int certificateValidate( Syntax *syntax, struct berval *in )
129 BerElementBuffer berbuf;
130 BerElement *ber = (BerElement *)&berbuf;
133 ber_int_t version = SLAP_X509_V1;
135 ber_init2( ber, in, LBER_USE_DER );
136 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
137 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
138 tag = ber_skip_tag( ber, &len ); /* Sequence */
139 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
140 tag = ber_peek_tag( ber, &len );
141 /* Optional version */
142 if ( tag == SLAP_X509_OPT_C_VERSION ) {
143 tag = ber_skip_tag( ber, &len );
144 tag = ber_get_int( ber, &version );
145 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
147 /* NOTE: don't try to parse Serial, because it might be longer
148 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
149 tag = ber_skip_tag( ber, &len ); /* Serial */
150 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
151 ber_skip_data( ber, len );
152 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
153 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
154 ber_skip_data( ber, len );
155 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
156 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
157 ber_skip_data( ber, len );
158 tag = ber_skip_tag( ber, &len ); /* Validity */
159 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
160 ber_skip_data( ber, len );
161 tag = ber_skip_tag( ber, &len ); /* Subject DN */
162 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
163 ber_skip_data( ber, len );
164 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
165 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
166 ber_skip_data( ber, len );
167 tag = ber_skip_tag( ber, &len );
168 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
169 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
170 ber_skip_data( ber, len );
171 tag = ber_skip_tag( ber, &len );
173 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
174 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
175 ber_skip_data( ber, len );
176 tag = ber_skip_tag( ber, &len );
178 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
179 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
180 tag = ber_skip_tag( ber, &len );
181 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
182 ber_skip_data( ber, len );
183 tag = ber_skip_tag( ber, &len );
185 /* signatureAlgorithm */
186 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
187 ber_skip_data( ber, len );
188 tag = ber_skip_tag( ber, &len );
190 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
191 ber_skip_data( ber, len );
192 tag = ber_skip_tag( ber, &len );
193 /* Must be at end now */
194 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
198 /* X.509 certificate list validation */
199 static int certificateListValidate( Syntax *syntax, struct berval *in )
201 BerElementBuffer berbuf;
202 BerElement *ber = (BerElement *)&berbuf;
205 ber_int_t version = SLAP_X509_V1;
207 ber_init2( ber, in, LBER_USE_DER );
208 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
209 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
210 tag = ber_skip_tag( ber, &len ); /* Sequence */
211 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
212 tag = ber_peek_tag( ber, &len );
213 /* Optional version */
214 if ( tag == LBER_INTEGER ) {
215 tag = ber_get_int( ber, &version );
216 assert( tag == LBER_INTEGER );
217 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
219 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
220 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
221 ber_skip_data( ber, len );
222 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
223 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
224 ber_skip_data( ber, len );
225 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
226 /* NOTE: in the certificates I'm playing with, the time is UTC.
227 * maybe the tag is different from 0x17U for generalizedTime? */
228 if ( tag != 0x17U ) return LDAP_INVALID_SYNTAX;
229 ber_skip_data( ber, len );
230 /* Optional nextUpdate */
231 tag = ber_skip_tag( ber, &len );
232 if ( tag == 0x17U ) {
233 ber_skip_data( ber, len );
234 tag = ber_skip_tag( ber, &len );
236 /* Optional revokedCertificates */
237 if ( tag == LBER_SEQUENCE ) {
238 /* Should NOT be empty */
239 ber_skip_data( ber, len );
240 tag = ber_skip_tag( ber, &len );
242 /* Optional Extensions */
243 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
244 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
245 tag = ber_skip_tag( ber, &len );
246 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
247 ber_skip_data( ber, len );
248 tag = ber_skip_tag( ber, &len );
250 /* signatureAlgorithm */
251 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
252 ber_skip_data( ber, len );
253 tag = ber_skip_tag( ber, &len );
255 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
256 ber_skip_data( ber, len );
257 tag = ber_skip_tag( ber, &len );
258 /* Must be at end now */
259 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
269 struct berval *value,
270 void *assertedValue )
272 struct berval *asserted = (struct berval *) assertedValue;
273 int match = value->bv_len - asserted->bv_len;
276 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
284 octetStringOrderingMatch(
289 struct berval *value,
290 void *assertedValue )
292 struct berval *asserted = (struct berval *) assertedValue;
293 ber_len_t v_len = value->bv_len;
294 ber_len_t av_len = asserted->bv_len;
296 int match = memcmp( value->bv_val, asserted->bv_val,
297 (v_len < av_len ? v_len : av_len) );
299 if( match == 0 ) match = v_len - av_len;
307 HASH_CONTEXT *HASHcontext,
308 struct berval *prefix,
313 HASH_Init(HASHcontext);
314 if(prefix && prefix->bv_len > 0) {
315 HASH_Update(HASHcontext,
316 (unsigned char *)prefix->bv_val, prefix->bv_len);
318 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
319 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
320 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
326 HASH_CONTEXT *HASHcontext,
327 unsigned char *HASHdigest,
328 unsigned char *value,
331 HASH_CONTEXT ctx = *HASHcontext;
332 HASH_Update( &ctx, value, len );
333 HASH_Final( HASHdigest, &ctx );
336 /* Index generation function */
337 int octetStringIndexer(
342 struct berval *prefix,
350 HASH_CONTEXT HASHcontext;
351 unsigned char HASHdigest[HASH_BYTES];
352 struct berval digest;
353 digest.bv_val = (char *)HASHdigest;
354 digest.bv_len = sizeof(HASHdigest);
356 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
357 /* just count them */
360 /* we should have at least one value at this point */
363 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
365 slen = syntax->ssyn_oidlen;
366 mlen = mr->smr_oidlen;
368 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
369 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
370 hashIter( &HASHcontext, HASHdigest,
371 (unsigned char *)values[i].bv_val, values[i].bv_len );
372 ber_dupbv_x( &keys[i], &digest, ctx );
375 BER_BVZERO( &keys[i] );
382 /* Index generation function */
383 int octetStringFilter(
388 struct berval *prefix,
389 void * assertedValue,
395 HASH_CONTEXT HASHcontext;
396 unsigned char HASHdigest[HASH_BYTES];
397 struct berval *value = (struct berval *) assertedValue;
398 struct berval digest;
399 digest.bv_val = (char *)HASHdigest;
400 digest.bv_len = sizeof(HASHdigest);
402 slen = syntax->ssyn_oidlen;
403 mlen = mr->smr_oidlen;
405 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
407 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
408 hashIter( &HASHcontext, HASHdigest,
409 (unsigned char *)value->bv_val, value->bv_len );
411 ber_dupbv_x( keys, &digest, ctx );
412 BER_BVZERO( &keys[1] );
420 octetStringSubstringsMatch(
425 struct berval *value,
426 void *assertedValue )
429 SubstringsAssertion *sub = assertedValue;
430 struct berval left = *value;
434 /* Add up asserted input length */
435 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
436 inlen += sub->sa_initial.bv_len;
439 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
440 inlen += sub->sa_any[i].bv_len;
443 if ( !BER_BVISNULL( &sub->sa_final ) ) {
444 inlen += sub->sa_final.bv_len;
447 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
448 if ( inlen > left.bv_len ) {
453 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
454 sub->sa_initial.bv_len );
460 left.bv_val += sub->sa_initial.bv_len;
461 left.bv_len -= sub->sa_initial.bv_len;
462 inlen -= sub->sa_initial.bv_len;
465 if ( !BER_BVISNULL( &sub->sa_final ) ) {
466 if ( inlen > left.bv_len ) {
471 match = memcmp( sub->sa_final.bv_val,
472 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
473 sub->sa_final.bv_len );
479 left.bv_len -= sub->sa_final.bv_len;
480 inlen -= sub->sa_final.bv_len;
484 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
489 if ( inlen > left.bv_len ) {
490 /* not enough length */
495 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
499 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
506 idx = p - left.bv_val;
508 if ( idx >= left.bv_len ) {
509 /* this shouldn't happen */
516 if ( sub->sa_any[i].bv_len > left.bv_len ) {
517 /* not enough left */
522 match = memcmp( left.bv_val,
523 sub->sa_any[i].bv_val,
524 sub->sa_any[i].bv_len );
532 left.bv_val += sub->sa_any[i].bv_len;
533 left.bv_len -= sub->sa_any[i].bv_len;
534 inlen -= sub->sa_any[i].bv_len;
543 /* Substrings Index generation function */
545 octetStringSubstringsIndexer(
550 struct berval *prefix,
559 HASH_CONTEXT HCany, HCini, HCfin;
560 unsigned char HASHdigest[HASH_BYTES];
561 struct berval digest;
562 digest.bv_val = (char *)HASHdigest;
563 digest.bv_len = sizeof(HASHdigest);
567 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
568 /* count number of indices to generate */
569 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
570 if( values[i].bv_len >= index_substr_if_maxlen ) {
571 nkeys += index_substr_if_maxlen -
572 (index_substr_if_minlen - 1);
573 } else if( values[i].bv_len >= index_substr_if_minlen ) {
574 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
578 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
579 if( values[i].bv_len >= index_substr_any_len ) {
580 nkeys += values[i].bv_len - (index_substr_any_len - 1);
584 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
585 if( values[i].bv_len >= index_substr_if_maxlen ) {
586 nkeys += index_substr_if_maxlen -
587 (index_substr_if_minlen - 1);
588 } else if( values[i].bv_len >= index_substr_if_minlen ) {
589 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
595 /* no keys to generate */
600 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
602 slen = syntax->ssyn_oidlen;
603 mlen = mr->smr_oidlen;
605 if ( flags & SLAP_INDEX_SUBSTR_ANY )
606 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
607 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
608 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
609 if( flags & SLAP_INDEX_SUBSTR_FINAL )
610 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
613 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
616 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
617 ( values[i].bv_len >= index_substr_any_len ) )
619 max = values[i].bv_len - (index_substr_any_len - 1);
621 for( j=0; j<max; j++ ) {
622 hashIter( &HCany, HASHdigest,
623 (unsigned char *)&values[i].bv_val[j],
624 index_substr_any_len );
625 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
629 /* skip if too short */
630 if( values[i].bv_len < index_substr_if_minlen ) continue;
632 max = index_substr_if_maxlen < values[i].bv_len
633 ? index_substr_if_maxlen : values[i].bv_len;
635 for( j=index_substr_if_minlen; j<=max; j++ ) {
637 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
638 hashIter( &HCini, HASHdigest,
639 (unsigned char *)values[i].bv_val, j );
640 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
643 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
644 hashIter( &HCfin, HASHdigest,
645 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
646 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
653 BER_BVZERO( &keys[nkeys] );
664 octetStringSubstringsFilter (
669 struct berval *prefix,
670 void * assertedValue,
674 SubstringsAssertion *sa;
677 size_t slen, mlen, klen;
679 HASH_CONTEXT HASHcontext;
680 unsigned char HASHdigest[HASH_BYTES];
681 struct berval *value;
682 struct berval digest;
684 sa = (SubstringsAssertion *) assertedValue;
686 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
687 !BER_BVISNULL( &sa->sa_initial ) &&
688 sa->sa_initial.bv_len >= index_substr_if_minlen )
691 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
692 ( flags & SLAP_INDEX_SUBSTR_ANY ))
694 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
698 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
700 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
701 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
702 /* don't bother accounting with stepping */
703 nkeys += sa->sa_any[i].bv_len -
704 ( index_substr_any_len - 1 );
709 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
710 !BER_BVISNULL( &sa->sa_final ) &&
711 sa->sa_final.bv_len >= index_substr_if_minlen )
714 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
715 ( flags & SLAP_INDEX_SUBSTR_ANY ))
717 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
726 digest.bv_val = (char *)HASHdigest;
727 digest.bv_len = sizeof(HASHdigest);
729 slen = syntax->ssyn_oidlen;
730 mlen = mr->smr_oidlen;
732 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
735 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
736 !BER_BVISNULL( &sa->sa_initial ) &&
737 sa->sa_initial.bv_len >= index_substr_if_minlen )
739 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
740 value = &sa->sa_initial;
742 klen = index_substr_if_maxlen < value->bv_len
743 ? index_substr_if_maxlen : value->bv_len;
745 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
746 hashIter( &HASHcontext, HASHdigest,
747 (unsigned char *)value->bv_val, klen );
748 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
750 /* If initial is too long and we have subany indexed, use it
751 * to match the excess...
753 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
756 pre = SLAP_INDEX_SUBSTR_PREFIX;
757 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
758 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
760 hashIter( &HASHcontext, HASHdigest,
761 (unsigned char *)&value->bv_val[j], index_substr_any_len );
762 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
767 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
769 pre = SLAP_INDEX_SUBSTR_PREFIX;
770 klen = index_substr_any_len;
772 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
773 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
777 value = &sa->sa_any[i];
779 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
781 j <= value->bv_len - index_substr_any_len;
782 j += index_substr_any_step )
784 hashIter( &HASHcontext, HASHdigest,
785 (unsigned char *)&value->bv_val[j], klen );
786 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
791 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
792 !BER_BVISNULL( &sa->sa_final ) &&
793 sa->sa_final.bv_len >= index_substr_if_minlen )
795 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
796 value = &sa->sa_final;
798 klen = index_substr_if_maxlen < value->bv_len
799 ? index_substr_if_maxlen : value->bv_len;
801 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
802 hashIter( &HASHcontext, HASHdigest,
803 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
804 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
806 /* If final is too long and we have subany indexed, use it
807 * to match the excess...
809 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
812 pre = SLAP_INDEX_SUBSTR_PREFIX;
813 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
814 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
816 hashIter( &HASHcontext, HASHdigest,
817 (unsigned char *)&value->bv_val[j], index_substr_any_len );
818 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
824 BER_BVZERO( &keys[nkeys] );
841 /* very unforgiving validation, requires no normalization
842 * before simplistic matching
844 if( in->bv_len < 3 ) {
845 return LDAP_INVALID_SYNTAX;
848 /* RFC 4517 Section 3.3.2 Bit String:
849 * BitString = SQUOTE *binary-digit SQUOTE "B"
850 * binary-digit = "0" / "1"
852 * where SQUOTE [RFC4512] is
853 * SQUOTE = %x27 ; single quote ("'")
855 * Example: '0101111101'B
858 if( in->bv_val[0] != '\'' ||
859 in->bv_val[in->bv_len - 2] != '\'' ||
860 in->bv_val[in->bv_len - 1] != 'B' )
862 return LDAP_INVALID_SYNTAX;
865 for( i = in->bv_len - 3; i > 0; i-- ) {
866 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
867 return LDAP_INVALID_SYNTAX;
875 * Syntaxes from RFC 4517
880 A value of the Bit String syntax is a sequence of binary digits. The
881 LDAP-specific encoding of a value of this syntax is defined by the
884 BitString = SQUOTE *binary-digit SQUOTE "B"
886 binary-digit = "0" / "1"
888 The <SQUOTE> rule is defined in [MODELS].
893 The LDAP definition for the Bit String syntax is:
895 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
897 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
901 3.3.21. Name and Optional UID
903 A value of the Name and Optional UID syntax is the distinguished name
904 [MODELS] of an entity optionally accompanied by a unique identifier
905 that serves to differentiate the entity from others with an identical
908 The LDAP-specific encoding of a value of this syntax is defined by
911 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
913 The <BitString> rule is defined in Section 3.3.2. The
914 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
917 Note that although the '#' character may occur in the string
918 representation of a distinguished name, no additional escaping of
919 this character is performed when a <distinguishedName> is encoded in
920 a <NameAndOptionalUID>.
923 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
925 The LDAP definition for the Name and Optional UID syntax is:
927 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
929 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
936 1.4. Common ABNF Productions
939 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
941 SQUOTE = %x27 ; single quote ("'")
945 * Note: normalization strips any leading "0"s, unless the
946 * bit string is exactly "'0'B", so the normalized example,
947 * in slapd, would result in
949 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
951 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
952 * be escaped except when at the beginning of a value, the
953 * definition of Name and Optional UID appears to be flawed,
954 * because there is no clear means to determine whether the
955 * UID part is present or not.
959 * cn=Someone,dc=example,dc=com#'1'B
961 * could be either a NameAndOptionalUID with trailing UID, i.e.
963 * DN = "cn=Someone,dc=example,dc=com"
966 * or a NameAndOptionalUID with no trailing UID, and the AVA
967 * in the last RDN made of
970 * attributeValue = com#'1'B
972 * in fact "com#'1'B" is a valid IA5 string.
974 * As a consequence, current slapd code assumes that the
975 * presence of portions of a BitString at the end of the string
976 * representation of a NameAndOptionalUID means a BitString
977 * is expected, and cause an error otherwise. This is quite
978 * arbitrary, and might change in the future.
988 struct berval dn, uid;
990 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
992 ber_dupbv( &dn, in );
993 if( !dn.bv_val ) return LDAP_OTHER;
995 /* if there's a "#", try bitStringValidate()... */
996 uid.bv_val = strrchr( dn.bv_val, '#' );
997 if ( !BER_BVISNULL( &uid ) ) {
999 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1001 rc = bitStringValidate( NULL, &uid );
1002 if ( rc == LDAP_SUCCESS ) {
1003 /* in case of success, trim the UID,
1004 * otherwise treat it as part of the DN */
1005 dn.bv_len -= uid.bv_len + 1;
1006 uid.bv_val[-1] = '\0';
1010 rc = dnValidate( NULL, &dn );
1012 ber_memfree( dn.bv_val );
1023 assert( val != NULL );
1024 assert( out != NULL );
1027 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1029 if( BER_BVISEMPTY( val ) ) {
1030 ber_dupbv_x( out, val, ctx );
1032 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1033 return LDAP_INVALID_SYNTAX;
1037 struct berval dnval = *val;
1038 struct berval uidval = BER_BVNULL;
1040 uidval.bv_val = strrchr( val->bv_val, '#' );
1041 if ( !BER_BVISNULL( &uidval ) ) {
1043 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1045 rc = bitStringValidate( NULL, &uidval );
1047 if ( rc == LDAP_SUCCESS ) {
1048 ber_dupbv_x( &dnval, val, ctx );
1049 dnval.bv_len -= uidval.bv_len + 1;
1050 dnval.bv_val[dnval.bv_len] = '\0';
1053 BER_BVZERO( &uidval );
1057 rc = dnPretty( syntax, &dnval, out, ctx );
1058 if ( dnval.bv_val != val->bv_val ) {
1059 slap_sl_free( dnval.bv_val, ctx );
1061 if( rc != LDAP_SUCCESS ) {
1065 if( !BER_BVISNULL( &uidval ) ) {
1069 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1070 + STRLENOF( "#" ) + uidval.bv_len + 1,
1073 ber_memfree_x( out->bv_val, ctx );
1077 out->bv_val[out->bv_len++] = '#';
1078 out->bv_val[out->bv_len++] = '\'';
1080 got1 = uidval.bv_len < sizeof("'0'B");
1081 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1082 c = uidval.bv_val[i];
1085 if( got1 ) out->bv_val[out->bv_len++] = c;
1089 out->bv_val[out->bv_len++] = c;
1094 out->bv_val[out->bv_len++] = '\'';
1095 out->bv_val[out->bv_len++] = 'B';
1096 out->bv_val[out->bv_len] = '\0';
1100 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1102 return LDAP_SUCCESS;
1106 uniqueMemberNormalize(
1111 struct berval *normalized,
1117 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1119 ber_dupbv_x( &out, val, ctx );
1120 if ( BER_BVISEMPTY( &out ) ) {
1124 struct berval uid = BER_BVNULL;
1126 uid.bv_val = strrchr( out.bv_val, '#' );
1127 if ( !BER_BVISNULL( &uid ) ) {
1129 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1131 rc = bitStringValidate( NULL, &uid );
1132 if ( rc == LDAP_SUCCESS ) {
1133 uid.bv_val[-1] = '\0';
1134 out.bv_len -= uid.bv_len + 1;
1140 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1142 if( rc != LDAP_SUCCESS ) {
1143 slap_sl_free( out.bv_val, ctx );
1144 return LDAP_INVALID_SYNTAX;
1147 if( !BER_BVISNULL( &uid ) ) {
1150 tmp = ch_realloc( normalized->bv_val,
1151 normalized->bv_len + uid.bv_len
1152 + STRLENOF("#") + 1 );
1153 if ( tmp == NULL ) {
1154 ber_memfree_x( normalized->bv_val, ctx );
1158 normalized->bv_val = tmp;
1160 /* insert the separator */
1161 normalized->bv_val[normalized->bv_len++] = '#';
1163 /* append the UID */
1164 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1165 uid.bv_val, uid.bv_len );
1166 normalized->bv_len += uid.bv_len;
1169 normalized->bv_val[normalized->bv_len] = '\0';
1172 slap_sl_free( out.bv_val, ctx );
1175 return LDAP_SUCCESS;
1184 struct berval *value,
1185 void *assertedValue )
1188 struct berval *asserted = (struct berval *) assertedValue;
1189 struct berval assertedDN = *asserted;
1190 struct berval assertedUID = BER_BVNULL;
1191 struct berval valueDN = *value;
1192 struct berval valueUID = BER_BVNULL;
1193 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1195 if ( !BER_BVISEMPTY( asserted ) ) {
1196 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1197 if ( !BER_BVISNULL( &assertedUID ) ) {
1198 assertedUID.bv_val++;
1199 assertedUID.bv_len = assertedDN.bv_len
1200 - ( assertedUID.bv_val - assertedDN.bv_val );
1202 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1203 assertedDN.bv_len -= assertedUID.bv_len + 1;
1206 BER_BVZERO( &assertedUID );
1211 if ( !BER_BVISEMPTY( value ) ) {
1213 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1214 if ( !BER_BVISNULL( &valueUID ) ) {
1216 valueUID.bv_len = valueDN.bv_len
1217 - ( valueUID.bv_val - valueDN.bv_val );
1219 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1220 valueDN.bv_len -= valueUID.bv_len + 1;
1223 BER_BVZERO( &valueUID );
1228 if( valueUID.bv_len && assertedUID.bv_len ) {
1229 match = valueUID.bv_len - assertedUID.bv_len;
1232 return LDAP_SUCCESS;
1235 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1238 return LDAP_SUCCESS;
1241 } else if ( !approx && valueUID.bv_len ) {
1244 return LDAP_SUCCESS;
1246 } else if ( !approx && assertedUID.bv_len ) {
1249 return LDAP_SUCCESS;
1252 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1256 uniqueMemberIndexer(
1261 struct berval *prefix,
1269 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1270 /* just count them */
1274 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1276 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1277 struct berval assertedDN = values[i];
1278 struct berval assertedUID = BER_BVNULL;
1280 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1281 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1282 if ( !BER_BVISNULL( &assertedUID ) ) {
1283 assertedUID.bv_val++;
1284 assertedUID.bv_len = assertedDN.bv_len
1285 - ( assertedUID.bv_val - assertedDN.bv_val );
1287 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1288 assertedDN.bv_len -= assertedUID.bv_len + 1;
1291 BER_BVZERO( &assertedUID );
1296 dnvalues[i] = assertedDN;
1298 BER_BVZERO( &dnvalues[i] );
1300 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1301 dnvalues, keysp, ctx );
1303 slap_sl_free( dnvalues, ctx );
1313 struct berval *prefix,
1314 void * assertedValue,
1318 struct berval *asserted = (struct berval *) assertedValue;
1319 struct berval assertedDN = *asserted;
1320 struct berval assertedUID = BER_BVNULL;
1322 if ( !BER_BVISEMPTY( asserted ) ) {
1323 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1324 if ( !BER_BVISNULL( &assertedUID ) ) {
1325 assertedUID.bv_val++;
1326 assertedUID.bv_len = assertedDN.bv_len
1327 - ( assertedUID.bv_val - assertedDN.bv_val );
1329 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1330 assertedDN.bv_len -= assertedUID.bv_len + 1;
1333 BER_BVZERO( &assertedUID );
1338 return octetStringFilter( use, flags, syntax, mr, prefix,
1339 &assertedDN, keysp, ctx );
1344 * Handling boolean syntax and matching is quite rigid.
1345 * A more flexible approach would be to allow a variety
1346 * of strings to be normalized and prettied into TRUE
1354 /* very unforgiving validation, requires no normalization
1355 * before simplistic matching
1358 if( in->bv_len == 4 ) {
1359 if( bvmatch( in, &slap_true_bv ) ) {
1360 return LDAP_SUCCESS;
1362 } else if( in->bv_len == 5 ) {
1363 if( bvmatch( in, &slap_false_bv ) ) {
1364 return LDAP_SUCCESS;
1368 return LDAP_INVALID_SYNTAX;
1377 struct berval *value,
1378 void *assertedValue )
1380 /* simplistic matching allowed by rigid validation */
1381 struct berval *asserted = (struct berval *) assertedValue;
1382 *matchp = value->bv_len != asserted->bv_len;
1383 return LDAP_SUCCESS;
1386 /*-------------------------------------------------------------------
1387 LDAP/X.500 string syntax / matching rules have a few oddities. This
1388 comment attempts to detail how slapd(8) treats them.
1391 StringSyntax X.500 LDAP Matching/Comments
1392 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1393 PrintableString subset subset i/e + ignore insignificant spaces
1394 PrintableString subset subset i/e + ignore insignificant spaces
1395 NumericString subset subset ignore all spaces
1396 IA5String ASCII ASCII i/e + ignore insignificant spaces
1397 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1399 TelephoneNumber subset subset i + ignore all spaces and "-"
1401 See RFC 4518 for details.
1405 In X.500(93), a directory string can be either a PrintableString,
1406 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1407 In later versions, more CHOICEs were added. In all cases the string
1410 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1411 A directory string cannot be zero length.
1413 For matching, there are both case ignore and exact rules. Both
1414 also require that "insignificant" spaces be ignored.
1415 spaces before the first non-space are ignored;
1416 spaces after the last non-space are ignored;
1417 spaces after a space are ignored.
1418 Note: by these rules (and as clarified in X.520), a string of only
1419 spaces is to be treated as if held one space, not empty (which
1420 would be a syntax error).
1423 In ASN.1, numeric string is just a string of digits and spaces
1424 and could be empty. However, in X.500, all attribute values of
1425 numeric string carry a non-empty constraint. For example:
1427 internationalISDNNumber ATTRIBUTE ::= {
1428 WITH SYNTAX InternationalISDNNumber
1429 EQUALITY MATCHING RULE numericStringMatch
1430 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1431 ID id-at-internationalISDNNumber }
1432 InternationalISDNNumber ::=
1433 NumericString (SIZE(1..ub-international-isdn-number))
1435 Unforunately, some assertion values are don't carry the same
1436 constraint (but its unclear how such an assertion could ever
1437 be true). In LDAP, there is one syntax (numericString) not two
1438 (numericString with constraint, numericString without constraint).
1439 This should be treated as numericString with non-empty constraint.
1440 Note that while someone may have no ISDN number, there are no ISDN
1441 numbers which are zero length.
1443 In matching, spaces are ignored.
1446 In ASN.1, Printable string is just a string of printable characters
1447 and can be empty. In X.500, semantics much like NumericString (see
1448 serialNumber for a like example) excepting uses insignificant space
1449 handling instead of ignore all spaces.
1452 Basically same as PrintableString. There are no examples in X.500,
1453 but same logic applies. So we require them to be non-empty as
1456 -------------------------------------------------------------------*/
1465 unsigned char *u = (unsigned char *)in->bv_val;
1467 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1468 /* directory strings cannot be empty */
1469 return LDAP_INVALID_SYNTAX;
1472 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1473 /* get the length indicated by the first byte */
1474 len = LDAP_UTF8_CHARLEN2( u, len );
1476 /* very basic checks */
1479 if( (u[5] & 0xC0) != 0x80 ) {
1480 return LDAP_INVALID_SYNTAX;
1483 if( (u[4] & 0xC0) != 0x80 ) {
1484 return LDAP_INVALID_SYNTAX;
1487 if( (u[3] & 0xC0) != 0x80 ) {
1488 return LDAP_INVALID_SYNTAX;
1491 if( (u[2] & 0xC0 )!= 0x80 ) {
1492 return LDAP_INVALID_SYNTAX;
1495 if( (u[1] & 0xC0) != 0x80 ) {
1496 return LDAP_INVALID_SYNTAX;
1499 /* CHARLEN already validated it */
1502 return LDAP_INVALID_SYNTAX;
1505 /* make sure len corresponds with the offset
1506 to the next character */
1507 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1511 return LDAP_INVALID_SYNTAX;
1514 return LDAP_SUCCESS;
1518 UTF8StringNormalize(
1523 struct berval *normalized,
1526 struct berval tmp, nvalue;
1530 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1532 if( BER_BVISNULL( val ) ) {
1533 /* assume we're dealing with a syntax (e.g., UTF8String)
1534 * which allows empty strings
1536 BER_BVZERO( normalized );
1537 return LDAP_SUCCESS;
1540 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1541 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1542 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1543 ? LDAP_UTF8_APPROX : 0;
1545 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1550 /* collapse spaces (in place) */
1552 nvalue.bv_val = tmp.bv_val;
1554 /* trim leading spaces? */
1555 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1556 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1558 for( i = 0; i < tmp.bv_len; i++) {
1559 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1560 if( wasspace++ == 0 ) {
1561 /* trim repeated spaces */
1562 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1566 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1570 if( !BER_BVISEMPTY( &nvalue ) ) {
1571 /* trim trailing space? */
1573 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1574 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1578 nvalue.bv_val[nvalue.bv_len] = '\0';
1581 /* string of all spaces is treated as one space */
1582 nvalue.bv_val[0] = ' ';
1583 nvalue.bv_val[1] = '\0';
1587 *normalized = nvalue;
1588 return LDAP_SUCCESS;
1592 directoryStringSubstringsMatch(
1597 struct berval *value,
1598 void *assertedValue )
1601 SubstringsAssertion *sub = assertedValue;
1602 struct berval left = *value;
1606 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1607 if ( sub->sa_initial.bv_len > left.bv_len ) {
1608 /* not enough left */
1613 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1614 sub->sa_initial.bv_len );
1620 left.bv_val += sub->sa_initial.bv_len;
1621 left.bv_len -= sub->sa_initial.bv_len;
1623 priorspace = ASCII_SPACE(
1624 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1627 if ( sub->sa_any ) {
1628 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1632 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1633 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1635 /* allow next space to match */
1642 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1646 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1647 /* not enough left */
1652 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1659 idx = p - left.bv_val;
1661 if ( idx >= left.bv_len ) {
1662 /* this shouldn't happen */
1669 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1670 /* not enough left */
1675 match = memcmp( left.bv_val,
1676 sub->sa_any[i].bv_val,
1677 sub->sa_any[i].bv_len );
1685 left.bv_val += sub->sa_any[i].bv_len;
1686 left.bv_len -= sub->sa_any[i].bv_len;
1688 priorspace = ASCII_SPACE(
1689 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1693 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1694 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1695 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1697 /* allow next space to match */
1702 if ( sub->sa_final.bv_len > left.bv_len ) {
1703 /* not enough left */
1708 match = memcmp( sub->sa_final.bv_val,
1709 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1710 sub->sa_final.bv_len );
1719 return LDAP_SUCCESS;
1722 #if defined(SLAPD_APPROX_INITIALS)
1723 # define SLAPD_APPROX_DELIMITER "._ "
1724 # define SLAPD_APPROX_WORDLEN 2
1726 # define SLAPD_APPROX_DELIMITER " "
1727 # define SLAPD_APPROX_WORDLEN 1
1736 struct berval *value,
1737 void *assertedValue )
1739 struct berval *nval, *assertv;
1740 char *val, **values, **words, *c;
1741 int i, count, len, nextchunk=0, nextavail=0;
1743 /* Yes, this is necessary */
1744 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1745 if( nval == NULL ) {
1747 return LDAP_SUCCESS;
1750 /* Yes, this is necessary */
1751 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1752 NULL, LDAP_UTF8_APPROX, NULL );
1753 if( assertv == NULL ) {
1756 return LDAP_SUCCESS;
1759 /* Isolate how many words there are */
1760 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1761 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1762 if ( c == NULL ) break;
1767 /* Get a phonetic copy of each word */
1768 words = (char **)ch_malloc( count * sizeof(char *) );
1769 values = (char **)ch_malloc( count * sizeof(char *) );
1770 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1772 values[i] = phonetic(c);
1775 /* Work through the asserted value's words, to see if at least some
1776 of the words are there, in the same order. */
1778 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1779 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1784 #if defined(SLAPD_APPROX_INITIALS)
1785 else if( len == 1 ) {
1786 /* Single letter words need to at least match one word's initial */
1787 for( i=nextavail; i<count; i++ )
1788 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1795 /* Isolate the next word in the asserted value and phonetic it */
1796 assertv->bv_val[nextchunk+len] = '\0';
1797 val = phonetic( assertv->bv_val + nextchunk );
1799 /* See if this phonetic chunk is in the remaining words of *value */
1800 for( i=nextavail; i<count; i++ ){
1801 if( !strcmp( val, values[i] ) ){
1809 /* This chunk in the asserted value was NOT within the *value. */
1815 /* Go on to the next word in the asserted value */
1819 /* If some of the words were seen, call it a match */
1820 if( nextavail > 0 ) {
1827 /* Cleanup allocs */
1828 ber_bvfree( assertv );
1829 for( i=0; i<count; i++ ) {
1830 ch_free( values[i] );
1836 return LDAP_SUCCESS;
1845 struct berval *prefix,
1851 int i,j, len, wordcount, keycount=0;
1852 struct berval *newkeys;
1853 BerVarray keys=NULL;
1855 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1856 struct berval val = BER_BVNULL;
1857 /* Yes, this is necessary */
1858 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1859 assert( !BER_BVISNULL( &val ) );
1861 /* Isolate how many words there are. There will be a key for each */
1862 for( wordcount = 0, c = val.bv_val; *c; c++) {
1863 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1864 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1866 if (*c == '\0') break;
1870 /* Allocate/increase storage to account for new keys */
1871 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1872 * sizeof(struct berval) );
1873 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1874 if( keys ) ch_free( keys );
1877 /* Get a phonetic copy of each word */
1878 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1880 if( len < SLAPD_APPROX_WORDLEN ) continue;
1881 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1886 ber_memfree( val.bv_val );
1888 BER_BVZERO( &keys[keycount] );
1891 return LDAP_SUCCESS;
1900 struct berval *prefix,
1901 void * assertedValue,
1910 /* Yes, this is necessary */
1911 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1912 NULL, LDAP_UTF8_APPROX, NULL );
1913 if( val == NULL || BER_BVISNULL( val ) ) {
1914 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1915 BER_BVZERO( &keys[0] );
1918 return LDAP_SUCCESS;
1921 /* Isolate how many words there are. There will be a key for each */
1922 for( count = 0,c = val->bv_val; *c; c++) {
1923 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1924 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1926 if (*c == '\0') break;
1930 /* Allocate storage for new keys */
1931 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1933 /* Get a phonetic copy of each word */
1934 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1936 if( len < SLAPD_APPROX_WORDLEN ) continue;
1937 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1943 BER_BVZERO( &keys[count] );
1946 return LDAP_SUCCESS;
1949 /* Remove all spaces and '-' characters */
1951 telephoneNumberNormalize(
1956 struct berval *normalized,
1961 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1963 /* validator should have refused an empty string */
1964 assert( !BER_BVISEMPTY( val ) );
1966 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1968 for( p = val->bv_val; *p; p++ ) {
1969 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1975 normalized->bv_len = q - normalized->bv_val;
1977 if( BER_BVISEMPTY( normalized ) ) {
1978 slap_sl_free( normalized->bv_val, ctx );
1979 BER_BVZERO( normalized );
1980 return LDAP_INVALID_SYNTAX;
1983 return LDAP_SUCCESS;
1991 struct berval val = *in;
1993 if( BER_BVISEMPTY( &val ) ) {
1994 /* disallow empty strings */
1995 return LDAP_INVALID_SYNTAX;
1998 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1999 if ( val.bv_len == 1 ) {
2000 return LDAP_SUCCESS;
2003 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2010 while ( OID_LEADCHAR( val.bv_val[0] )) {
2014 if ( val.bv_len == 0 ) {
2015 return LDAP_SUCCESS;
2019 if( !OID_SEPARATOR( val.bv_val[0] )) {
2027 return LDAP_INVALID_SYNTAX;
2036 struct berval val = *in;
2038 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2040 if ( val.bv_val[0] == '-' ) {
2044 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2045 return LDAP_INVALID_SYNTAX;
2048 if( val.bv_val[0] == '0' ) { /* "-0" */
2049 return LDAP_INVALID_SYNTAX;
2052 } else if ( val.bv_val[0] == '0' ) {
2053 if( val.bv_len > 1 ) { /* "0<more>" */
2054 return LDAP_INVALID_SYNTAX;
2057 return LDAP_SUCCESS;
2060 for( i=0; i < val.bv_len; i++ ) {
2061 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2062 return LDAP_INVALID_SYNTAX;
2066 return LDAP_SUCCESS;
2075 struct berval *value,
2076 void *assertedValue )
2078 struct berval *asserted = (struct berval *) assertedValue;
2079 int vsign = 1, asign = 1; /* default sign = '+' */
2084 if( v.bv_val[0] == '-' ) {
2090 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2093 if( a.bv_val[0] == '-' ) {
2099 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2101 match = vsign - asign;
2103 match = ( v.bv_len != a.bv_len
2104 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2105 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2106 if( vsign < 0 ) match = -match;
2110 return LDAP_SUCCESS;
2114 countryStringValidate(
2116 struct berval *val )
2118 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2120 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2121 return LDAP_INVALID_SYNTAX;
2123 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2124 return LDAP_INVALID_SYNTAX;
2127 return LDAP_SUCCESS;
2131 printableStringValidate(
2133 struct berval *val )
2137 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2139 for(i=0; i < val->bv_len; i++) {
2140 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2141 return LDAP_INVALID_SYNTAX;
2145 return LDAP_SUCCESS;
2149 printablesStringValidate(
2151 struct berval *val )
2155 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2157 for(i=0,len=0; i < val->bv_len; i++) {
2158 int c = val->bv_val[i];
2162 return LDAP_INVALID_SYNTAX;
2166 } else if ( SLAP_PRINTABLE(c) ) {
2169 return LDAP_INVALID_SYNTAX;
2174 return LDAP_INVALID_SYNTAX;
2177 return LDAP_SUCCESS;
2183 struct berval *val )
2187 for(i=0; i < val->bv_len; i++) {
2188 if( !LDAP_ASCII(val->bv_val[i]) ) {
2189 return LDAP_INVALID_SYNTAX;
2193 return LDAP_SUCCESS;
2202 struct berval *normalized,
2206 int casefold = !SLAP_MR_ASSOCIATED( mr,
2207 slap_schema.si_mr_caseExactIA5Match );
2209 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2213 /* Ignore initial whitespace */
2214 while ( ASCII_SPACE( *p ) ) p++;
2216 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2217 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2218 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2219 normalized->bv_val[normalized->bv_len] = '\0';
2221 p = q = normalized->bv_val;
2224 if ( ASCII_SPACE( *p ) ) {
2227 /* Ignore the extra whitespace */
2228 while ( ASCII_SPACE( *p ) ) {
2232 } else if ( casefold ) {
2233 /* Most IA5 rules require casefolding */
2234 *q++ = TOLOWER(*p); p++;
2241 assert( normalized->bv_val <= p );
2245 * If the string ended in space, backup the pointer one
2246 * position. One is enough because the above loop collapsed
2247 * all whitespace to a single space.
2249 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2251 /* null terminate */
2254 normalized->bv_len = q - normalized->bv_val;
2256 return LDAP_SUCCESS;
2265 if( in->bv_len != 36 ) {
2266 return LDAP_INVALID_SYNTAX;
2269 for( i=0; i<36; i++ ) {
2275 if( in->bv_val[i] != '-' ) {
2276 return LDAP_INVALID_SYNTAX;
2280 if( !ASCII_HEX( in->bv_val[i]) ) {
2281 return LDAP_INVALID_SYNTAX;
2286 return LDAP_SUCCESS;
2297 int rc=LDAP_INVALID_SYNTAX;
2299 assert( in != NULL );
2300 assert( out != NULL );
2302 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2305 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2307 for( i=0; i<36; i++ ) {
2313 if( in->bv_val[i] != '-' ) {
2316 out->bv_val[i] = '-';
2320 if( !ASCII_HEX( in->bv_val[i]) ) {
2323 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2328 out->bv_val[ out->bv_len ] = '\0';
2332 slap_sl_free( out->bv_val, ctx );
2345 struct berval *normalized,
2348 unsigned char octet = '\0';
2351 normalized->bv_len = 16;
2352 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2354 for( i=0, j=0; i<36; i++ ) {
2355 unsigned char nibble;
2356 if( val->bv_val[i] == '-' ) {
2359 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2360 nibble = val->bv_val[i] - '0';
2362 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2363 nibble = val->bv_val[i] - ('a'-10);
2365 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2366 nibble = val->bv_val[i] - ('A'-10);
2369 slap_sl_free( normalized->bv_val, ctx );
2370 return LDAP_INVALID_SYNTAX;
2375 normalized->bv_val[j>>1] = octet;
2377 octet = nibble << 4;
2382 normalized->bv_val[normalized->bv_len] = 0;
2383 return LDAP_SUCCESS;
2389 numericStringValidate(
2395 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2397 for(i=0; i < in->bv_len; i++) {
2398 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2399 return LDAP_INVALID_SYNTAX;
2403 return LDAP_SUCCESS;
2407 numericStringNormalize(
2412 struct berval *normalized,
2415 /* removal all spaces */
2418 assert( !BER_BVISEMPTY( val ) );
2420 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2423 q = normalized->bv_val;
2426 if ( ASCII_SPACE( *p ) ) {
2427 /* Ignore whitespace */
2434 /* we should have copied no more than is in val */
2435 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2437 /* null terminate */
2440 normalized->bv_len = q - normalized->bv_val;
2442 if( BER_BVISEMPTY( normalized ) ) {
2443 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2444 normalized->bv_val[0] = ' ';
2445 normalized->bv_val[1] = '\0';
2446 normalized->bv_len = 1;
2449 return LDAP_SUCCESS;
2453 * Integer conversion macros that will use the largest available
2456 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2457 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2458 # define SLAP_LONG long long
2460 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2461 # define SLAP_LONG long
2462 #endif /* HAVE_STRTOLL ... */
2470 struct berval *value,
2471 void *assertedValue )
2473 SLAP_LONG lValue, lAssertedValue;
2476 /* safe to assume integers are NUL terminated? */
2477 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2478 if( errno == ERANGE )
2480 return LDAP_CONSTRAINT_VIOLATION;
2483 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2485 if( errno == ERANGE )
2487 return LDAP_CONSTRAINT_VIOLATION;
2490 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2491 return LDAP_SUCCESS;
2500 struct berval *value,
2501 void *assertedValue )
2503 SLAP_LONG lValue, lAssertedValue;
2506 /* safe to assume integers are NUL terminated? */
2507 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2508 if( errno == ERANGE )
2510 return LDAP_CONSTRAINT_VIOLATION;
2513 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2515 if( errno == ERANGE )
2517 return LDAP_CONSTRAINT_VIOLATION;
2520 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2521 return LDAP_SUCCESS;
2525 serialNumberAndIssuerValidate(
2531 struct berval sn, i;
2533 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
2536 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2538 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2539 /* Parse old format */
2540 i.bv_val = ber_bvchr( in, '$' );
2541 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2543 sn.bv_val = in->bv_val;
2544 sn.bv_len = i.bv_val - in->bv_val;
2547 i.bv_len = in->bv_len - (sn.bv_len + 1);
2549 /* eat leading zeros */
2550 for( n=0; n < (sn.bv_len-1); n++ ) {
2551 if( sn.bv_val[n] != '0' ) break;
2556 for( n=0; n < sn.bv_len; n++ ) {
2557 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2561 /* Parse GSER format */
2562 int havesn=0,haveissuer=0;
2563 struct berval x = *in;
2567 /* eat leading spaces */
2568 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2572 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2573 return LDAP_INVALID_SYNTAX;
2576 /* should be at issuer or serialNumber NamedValue */
2577 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2579 x.bv_val += STRLENOF("issuer");
2580 x.bv_len -= STRLENOF("issuer");
2582 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2583 x.bv_val++; x.bv_len--;
2585 /* eat leading spaces */
2586 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2590 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2591 x.bv_val++; x.bv_len--;
2593 i.bv_val = x.bv_val;
2596 for( ; i.bv_len < x.bv_len; ) {
2597 if ( i.bv_val[i.bv_len] != '"' ) {
2601 if ( i.bv_val[i.bv_len+1] == '"' ) {
2608 x.bv_val += i.bv_len+1;
2609 x.bv_len -= i.bv_len+1;
2611 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2612 return LDAP_INVALID_SYNTAX;
2617 } else if( strncasecmp( x.bv_val, "serialNumber",
2618 STRLENOF("serialNumber")) == 0 )
2620 /* parse serialNumber */
2622 x.bv_val += STRLENOF("serialNumber");
2623 x.bv_len -= STRLENOF("serialNumber");
2625 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2626 x.bv_val++; x.bv_len--;
2628 /* eat leading spaces */
2629 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2633 sn.bv_val = x.bv_val;
2636 if( sn.bv_val[0] == '-' ) {
2641 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2642 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2645 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2646 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2647 return LDAP_INVALID_SYNTAX;
2650 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2652 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2653 return LDAP_INVALID_SYNTAX;
2658 } else return LDAP_INVALID_SYNTAX;
2660 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2661 x.bv_val++; x.bv_len--;
2664 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2668 /* should be at remaining NamedValue */
2669 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2670 STRLENOF("issuer" )) == 0 ))
2673 x.bv_val += STRLENOF("issuer");
2674 x.bv_len -= STRLENOF("issuer");
2676 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2677 x.bv_val++; x.bv_len--;
2679 /* eat leading spaces */
2680 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2684 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2685 x.bv_val++; x.bv_len--;
2687 i.bv_val = x.bv_val;
2690 for( ; i.bv_len < x.bv_len; ) {
2691 if ( i.bv_val[i.bv_len] != '"' ) {
2695 if ( i.bv_val[i.bv_len+1] == '"' ) {
2702 x.bv_val += i.bv_len+1;
2703 x.bv_len -= i.bv_len+1;
2705 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2706 STRLENOF("serialNumber")) == 0 ))
2708 /* parse serialNumber */
2710 x.bv_val += STRLENOF("serialNumber");
2711 x.bv_len -= STRLENOF("serialNumber");
2713 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2714 x.bv_val++; x.bv_len--;
2716 /* eat leading spaces */
2717 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2721 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2722 x.bv_val++; x.bv_len--;
2724 sn.bv_val = x.bv_val;
2727 if( sn.bv_val[0] == '-' ) {
2732 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2733 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2736 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2737 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2738 return LDAP_INVALID_SYNTAX;
2741 x.bv_val += sn.bv_len;
2742 x.bv_len -= sn.bv_len;
2744 } else return LDAP_INVALID_SYNTAX;
2746 /* eat trailing spaces */
2747 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2751 /* should have no characters left... */
2752 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
2755 /* validate DN -- doesn't handle double dquote */
2756 rc = dnValidate( NULL, &i );
2757 if( rc ) return LDAP_INVALID_SYNTAX;
2759 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: OKAY\n",
2761 return LDAP_SUCCESS;
2765 serialNumberAndIssuerPretty(
2773 struct berval sn, i, ni;
2775 assert( in != NULL );
2776 assert( out != NULL );
2778 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2781 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2783 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2784 /* Parse old format */
2785 i.bv_val = ber_bvchr( in, '$' );
2786 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2788 sn.bv_val = in->bv_val;
2789 sn.bv_len = i.bv_val - in->bv_val;
2792 i.bv_len = in->bv_len - (sn.bv_len + 1);
2794 /* eat leading zeros */
2795 for( n=0; n < (sn.bv_len-1); n++ ) {
2796 if( sn.bv_val[n] != '0' ) break;
2801 for( n=0; n < sn.bv_len; n++ ) {
2802 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2806 /* Parse GSER format */
2807 int havesn=0,haveissuer=0;
2808 struct berval x = *in;
2812 /* eat leading spaces */
2813 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2817 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
2818 return LDAP_INVALID_SYNTAX;
2821 /* should be at issuer or serialNumber NamedValue */
2822 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
2824 x.bv_val += STRLENOF("issuer");
2825 x.bv_len -= STRLENOF("issuer");
2827 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2828 x.bv_val++; x.bv_len--;
2830 /* eat leading spaces */
2831 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2835 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2836 x.bv_val++; x.bv_len--;
2838 i.bv_val = x.bv_val;
2841 for( ; i.bv_len < x.bv_len; ) {
2842 if ( i.bv_val[i.bv_len] != '"' ) {
2846 if ( i.bv_val[i.bv_len+1] == '"' ) {
2853 x.bv_val += i.bv_len+1;
2854 x.bv_len -= i.bv_len+1;
2856 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
2857 return LDAP_INVALID_SYNTAX;
2862 } else if( strncasecmp( x.bv_val, "serialNumber",
2863 STRLENOF("serialNumber")) == 0 )
2865 /* parse serialNumber */
2867 x.bv_val += STRLENOF("serialNumber");
2868 x.bv_len -= STRLENOF("serialNumber");
2870 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2871 x.bv_val++; x.bv_len--;
2873 /* eat leading spaces */
2874 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2878 sn.bv_val = x.bv_val;
2881 if( sn.bv_val[0] == '-' ) {
2886 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2887 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
2890 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
2891 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
2892 return LDAP_INVALID_SYNTAX;
2895 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
2897 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
2898 return LDAP_INVALID_SYNTAX;
2903 } else return LDAP_INVALID_SYNTAX;
2905 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
2906 x.bv_val++; x.bv_len--;
2909 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2913 /* should be at remaining NamedValue */
2914 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
2915 STRLENOF("issuer" )) == 0 ))
2918 x.bv_val += STRLENOF("issuer");
2919 x.bv_len -= STRLENOF("issuer");
2921 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2922 x.bv_val++; x.bv_len--;
2924 /* eat leading spaces */
2925 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
2929 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2930 x.bv_val++; x.bv_len--;
2932 i.bv_val = x.bv_val;
2935 for( ; i.bv_len < x.bv_len; ) {
2936 if ( i.bv_val[i.bv_len] != '"' ) {
2940 if ( i.bv_val[i.bv_len+1] == '"' ) {
2947 x.bv_val += i.bv_len+1;
2948 x.bv_len -= i.bv_len+1;
2950 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
2951 STRLENOF("serialNumber")) == 0 ))
2953 /* parse serialNumber */
2955 x.bv_val += STRLENOF("serialNumber");
2956 x.bv_len -= STRLENOF("serialNumber");
2958 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2959 x.bv_val++; x.bv_len--;
2961 /* eat leading spaces */
2962 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
2966 sn.bv_val = x.bv_val;
2969 if( sn.bv_val[0] == '-' ) {
2974 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
2975 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, &i, ctx );
2999 /* need to handle double dquotes here */
3002 rc = dnPretty( syntax, &i, &ni, ctx );
3004 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3005 slap_sl_free( i.bv_val, ctx );
3008 if( rc ) return LDAP_INVALID_SYNTAX;
3010 /* make room from sn + "$" */
3011 out->bv_len = STRLENOF("{ serialNumber , issuer \"\" }")
3012 + sn.bv_len + ni.bv_len;
3013 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3015 if( out->bv_val == NULL ) {
3017 slap_sl_free( ni.bv_val, ctx );
3022 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3023 STRLENOF("{ serialNumber "));
3024 n = STRLENOF("{ serialNumber ");
3026 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3029 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF(", issuer \""));
3030 n += STRLENOF(", issuer \"");
3032 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3035 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }"));
3036 n += STRLENOF("\" }");
3038 out->bv_val[n] = '\0';
3040 assert( n == out->bv_len );
3042 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
3043 out->bv_val, 0, 0 );
3045 slap_sl_free( ni.bv_val, ctx );
3047 return LDAP_SUCCESS;
3051 * This routine is called by certificateExactNormalize when
3052 * certificateExactNormalize receives a search string instead of
3053 * a certificate. This routine checks if the search value is valid
3054 * and then returns the normalized value
3057 serialNumberAndIssuerNormalize(
3067 struct berval sn, i, ni;
3069 assert( in != NULL );
3070 assert( out != NULL );
3072 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3075 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3077 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3078 /* Parse old format */
3079 i.bv_val = ber_bvchr( in, '$' );
3080 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
3082 sn.bv_val = in->bv_val;
3083 sn.bv_len = i.bv_val - in->bv_val;
3086 i.bv_len = in->bv_len - (sn.bv_len + 1);
3088 /* eat leading zeros */
3089 for( n=0; n < (sn.bv_len-1); n++ ) {
3090 if( sn.bv_val[n] != '0' ) break;
3095 for( n=0; n < sn.bv_len; n++ ) {
3096 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3100 /* Parse GSER format */
3101 int havesn=0,haveissuer=0;
3102 struct berval x = *in;
3106 /* eat leading spaces */
3107 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3111 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3112 return LDAP_INVALID_SYNTAX;
3115 /* should be at issuer or serialNumber NamedValue */
3116 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3118 x.bv_val += STRLENOF("issuer");
3119 x.bv_len -= STRLENOF("issuer");
3121 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3122 x.bv_val++; x.bv_len--;
3124 /* eat leading spaces */
3125 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3129 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3130 x.bv_val++; x.bv_len--;
3132 i.bv_val = x.bv_val;
3135 for( ; i.bv_len < x.bv_len; ) {
3136 if ( i.bv_val[i.bv_len] != '"' ) {
3140 if ( i.bv_val[i.bv_len+1] == '"' ) {
3147 x.bv_val += i.bv_len+1;
3148 x.bv_len -= i.bv_len+1;
3150 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3151 return LDAP_INVALID_SYNTAX;
3156 } else if( strncasecmp( x.bv_val, "serialNumber",
3157 STRLENOF("serialNumber")) == 0 )
3159 /* parse serialNumber */
3161 x.bv_val += STRLENOF("serialNumber");
3162 x.bv_len -= STRLENOF("serialNumber");
3164 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3165 x.bv_val++; x.bv_len--;
3167 /* eat leading spaces */
3168 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3172 sn.bv_val = x.bv_val;
3175 if( sn.bv_val[0] == '-' ) {
3180 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3181 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3184 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3185 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3186 return LDAP_INVALID_SYNTAX;
3189 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3191 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3192 return LDAP_INVALID_SYNTAX;
3197 } else return LDAP_INVALID_SYNTAX;
3199 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3200 x.bv_val++; x.bv_len--;
3203 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3207 /* should be at remaining NamedValue */
3208 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3209 STRLENOF("issuer" )) == 0 ))
3212 x.bv_val += STRLENOF("issuer");
3213 x.bv_len -= STRLENOF("issuer");
3215 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3216 x.bv_val++; x.bv_len--;
3218 /* eat leading spaces */
3219 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3223 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3224 x.bv_val++; x.bv_len--;
3226 i.bv_val = x.bv_val;
3229 for( ; i.bv_len < x.bv_len; ) {
3230 if ( i.bv_val[i.bv_len] != '"' ) {
3234 if ( i.bv_val[i.bv_len+1] == '"' ) {
3241 x.bv_val += i.bv_len+1;
3242 x.bv_len -= i.bv_len+1;
3244 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3245 STRLENOF("serialNumber")) == 0 ))
3247 /* parse serialNumber */
3249 x.bv_val += STRLENOF("serialNumber");
3250 x.bv_len -= STRLENOF("serialNumber");
3252 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3253 x.bv_val++; x.bv_len--;
3255 /* eat leading spaces */
3256 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3260 sn.bv_val = x.bv_val;
3263 if( sn.bv_val[0] == '-' ) {
3268 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3269 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3272 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3273 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3274 return LDAP_INVALID_SYNTAX;
3277 x.bv_val += sn.bv_len;
3278 x.bv_len -= sn.bv_len;
3280 } else return LDAP_INVALID_SYNTAX;
3282 /* eat trailing spaces */
3283 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3287 /* should have no characters left... */
3288 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3290 ber_dupbv_x( &ni, &i, ctx );
3293 /* need to handle double dquotes here */
3296 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3298 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3299 slap_sl_free( i.bv_val, ctx );
3302 if( rc ) return LDAP_INVALID_SYNTAX;
3304 /* make room from sn + "$" */
3305 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3306 + sn.bv_len + ni.bv_len;
3307 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3309 if( out->bv_val == NULL ) {
3311 slap_sl_free( ni.bv_val, ctx );
3316 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3317 STRLENOF( "{ serialNumber " ));
3318 n = STRLENOF( "{ serialNumber " );
3320 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3323 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3324 n += STRLENOF( ", issuer \"" );
3326 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3329 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3330 n += STRLENOF( "\" }" );
3332 out->bv_val[n] = '\0';
3334 assert( n == out->bv_len );
3336 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3337 out->bv_val, 0, 0 );
3339 slap_sl_free( ni.bv_val, ctx );
3341 return LDAP_SUCCESS;
3345 certificateExactNormalize(
3350 struct berval *normalized,
3353 BerElementBuffer berbuf;
3354 BerElement *ber = (BerElement *)&berbuf;
3358 char serialbuf[64], *serial = serialbuf;
3359 ber_len_t seriallen;
3360 struct berval issuer_dn = BER_BVNULL, bvdn;
3362 int rc = LDAP_INVALID_SYNTAX;
3364 if( BER_BVISEMPTY( val ) ) goto done;
3366 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3367 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3370 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3372 ber_init2( ber, val, LBER_USE_DER );
3373 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3374 tag = ber_skip_tag( ber, &len ); /* Sequence */
3375 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3376 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3377 tag = ber_skip_tag( ber, &len );
3378 tag = ber_get_int( ber, &i ); /* version */
3381 /* NOTE: move the test here from certificateNormalize,
3382 * so that we can validate certs with serial longer
3383 * than sizeof(ber_int_t) */
3384 tag = ber_peek_tag( ber, &len ); /* serial */
3385 if ( len > sizeof(ber_int_t) ) {
3388 tag = ber_skip_tag( ber, &len );
3389 ptr = (unsigned char *)ber->ber_ptr;
3390 ber_skip_data( ber, len );
3392 while ( ptr[0] == '\0' && len > 0 ) {
3397 #if defined(USE_MP_BIGNUM)
3400 #elif defined(USE_MP_GMP)
3402 /* hint: use mpz_import(), mpz_get_str() */
3404 #elif defined(USE_MP_LONG_LONG)
3405 if ( len <= sizeof( unsigned long long ) ) {
3406 unsigned long long sn = 0;
3411 for ( i = 1; i < len; i++ ) {
3416 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%llu", sn );
3419 /* do not accept serialNumber that requires
3420 * more than long long */
3421 rc = LDAP_INVALID_SYNTAX;
3426 /* do not accept serialNumber that requires
3428 rc = LDAP_INVALID_SYNTAX;
3433 tag = ber_get_int( ber, &i ); /* serial */
3434 seriallen = snprintf( serialbuf, sizeof(serialbuf), "%d", i );
3436 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3437 ber_skip_data( ber, len );
3438 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3439 len = ber_ptrlen( ber );
3440 bvdn.bv_val = val->bv_val + len;
3441 bvdn.bv_len = val->bv_len - len;
3443 rc = dnX509normalize( &bvdn, &issuer_dn );
3444 if( rc != LDAP_SUCCESS ) goto done;
3446 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3447 + seriallen + issuer_dn.bv_len;
3448 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3450 p = (unsigned char *)normalized->bv_val;
3452 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3453 p += STRLENOF( "{ serialNumber " );
3455 AC_MEMCPY(p, serial, seriallen);
3458 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3459 p += STRLENOF( ", issuer \"" );
3461 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3462 p += issuer_dn.bv_len;
3464 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3465 p += STRLENOF( "\" }" );
3469 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3470 normalized->bv_val, NULL, NULL );
3475 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3476 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3488 assert( in != NULL );
3489 assert( !BER_BVISNULL( in ) );
3491 for ( i = 0; i < in->bv_len; i++ ) {
3492 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3493 return LDAP_INVALID_SYNTAX;
3497 return LDAP_SUCCESS;
3500 /* Normalize a SID as used inside a CSN:
3501 * three-digit numeric string */
3508 struct berval *normalized,
3513 ber_dupbv_x( normalized, val, ctx );
3515 for ( i = 0; i < normalized->bv_len; i++ ) {
3516 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3517 ber_memfree_x( normalized->bv_val, ctx );
3518 BER_BVZERO( normalized );
3519 return LDAP_INVALID_SYNTAX;
3522 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3525 return LDAP_SUCCESS;
3533 assert( in != NULL );
3534 assert( !BER_BVISNULL( in ) );
3536 if ( in->bv_len != 3 ) {
3537 return LDAP_INVALID_SYNTAX;
3540 return hexValidate( NULL, in );
3543 /* Normalize a SID as used inside a CSN:
3544 * three-digit numeric string */
3551 struct berval *normalized,
3554 if ( val->bv_len != 3 ) {
3555 return LDAP_INVALID_SYNTAX;
3558 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3568 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3571 /* Normalize a SID as used inside a CSN, either as-is
3572 * (assertion value) or extracted from the CSN
3573 * (attribute value) */
3580 struct berval *normalized,
3588 if ( BER_BVISEMPTY( val ) ) {
3589 return LDAP_INVALID_SYNTAX;
3592 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3593 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3596 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3598 ptr = ber_bvchr( val, '#' );
3599 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3600 return LDAP_INVALID_SYNTAX;
3603 bv.bv_val = ptr + 1;
3604 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3606 ptr = ber_bvchr( &bv, '#' );
3607 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3608 return LDAP_INVALID_SYNTAX;
3611 bv.bv_val = ptr + 1;
3612 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3614 ptr = ber_bvchr( &bv, '#' );
3615 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3616 return LDAP_INVALID_SYNTAX;
3619 bv.bv_len = ptr - bv.bv_val;
3621 if ( bv.bv_len == 2 ) {
3622 /* OpenLDAP 2.3 SID */
3624 buf[ 1 ] = bv.bv_val[ 0 ];
3625 buf[ 2 ] = bv.bv_val[ 1 ];
3632 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3644 assert( in != NULL );
3645 assert( !BER_BVISNULL( in ) );
3647 if ( BER_BVISEMPTY( in ) ) {
3648 return LDAP_INVALID_SYNTAX;
3653 ptr = ber_bvchr( &bv, '#' );
3654 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3655 return LDAP_INVALID_SYNTAX;
3658 bv.bv_len = ptr - bv.bv_val;
3659 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3660 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3662 return LDAP_INVALID_SYNTAX;
3665 rc = generalizedTimeValidate( NULL, &bv );
3666 if ( rc != LDAP_SUCCESS ) {
3670 bv.bv_val = ptr + 1;
3671 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3673 ptr = ber_bvchr( &bv, '#' );
3674 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3675 return LDAP_INVALID_SYNTAX;
3678 bv.bv_len = ptr - bv.bv_val;
3679 if ( bv.bv_len != 6 ) {
3680 return LDAP_INVALID_SYNTAX;
3683 rc = hexValidate( NULL, &bv );
3684 if ( rc != LDAP_SUCCESS ) {
3688 bv.bv_val = ptr + 1;
3689 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3691 ptr = ber_bvchr( &bv, '#' );
3692 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3693 return LDAP_INVALID_SYNTAX;
3696 bv.bv_len = ptr - bv.bv_val;
3697 if ( bv.bv_len == 2 ) {
3698 /* tolerate old 2-digit replica-id */
3699 rc = hexValidate( NULL, &bv );
3702 rc = sidValidate( NULL, &bv );
3704 if ( rc != LDAP_SUCCESS ) {
3708 bv.bv_val = ptr + 1;
3709 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3711 if ( bv.bv_len != 6 ) {
3712 return LDAP_INVALID_SYNTAX;
3715 return hexValidate( NULL, &bv );
3718 /* Normalize a CSN in OpenLDAP 2.3 format */
3725 struct berval *normalized,
3728 struct berval gt, cnt, sid, mod;
3732 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3733 assert( !BER_BVISEMPTY( val ) );
3737 ptr = ber_bvchr( >, '#' );
3738 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3739 return LDAP_INVALID_SYNTAX;
3742 gt.bv_len = ptr - gt.bv_val;
3743 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3745 cnt.bv_val = ptr + 1;
3746 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3748 ptr = ber_bvchr( &cnt, '#' );
3749 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3750 return LDAP_INVALID_SYNTAX;
3753 cnt.bv_len = ptr - cnt.bv_val;
3754 assert( cnt.bv_len == STRLENOF( "000000" ) );
3756 sid.bv_val = ptr + 1;
3757 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3759 ptr = ber_bvchr( &sid, '#' );
3760 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3761 return LDAP_INVALID_SYNTAX;
3764 sid.bv_len = ptr - sid.bv_val;
3765 assert( sid.bv_len == STRLENOF( "00" ) );
3767 mod.bv_val = ptr + 1;
3768 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3769 assert( mod.bv_len == STRLENOF( "000000" ) );
3771 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3772 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3774 ptr = normalized->bv_val;
3775 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3776 ptr = lutil_strcopy( ptr, ".000000Z#" );
3777 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3780 for ( i = 0; i < sid.bv_len; i++ ) {
3781 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3784 for ( i = 0; i < mod.bv_len; i++ ) {
3785 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3789 assert( ptr - normalized->bv_val == normalized->bv_len );
3791 return LDAP_SUCCESS;
3794 /* Normalize a CSN */
3801 struct berval *normalized,
3804 struct berval cnt, sid, mod;
3808 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3810 if ( BER_BVISEMPTY( val ) ) {
3811 return LDAP_INVALID_SYNTAX;
3814 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3815 /* Openldap <= 2.3 */
3817 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3820 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3822 ptr = ber_bvchr( val, '#' );
3823 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3824 return LDAP_INVALID_SYNTAX;
3827 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3829 cnt.bv_val = ptr + 1;
3830 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3832 ptr = ber_bvchr( &cnt, '#' );
3833 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3834 return LDAP_INVALID_SYNTAX;
3837 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3839 sid.bv_val = ptr + 1;
3840 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3842 ptr = ber_bvchr( &sid, '#' );
3843 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3844 return LDAP_INVALID_SYNTAX;
3847 sid.bv_len = ptr - sid.bv_val;
3848 assert( sid.bv_len == STRLENOF( "000" ) );
3850 mod.bv_val = ptr + 1;
3851 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3853 assert( mod.bv_len == STRLENOF( "000000" ) );
3855 ber_dupbv_x( normalized, val, ctx );
3857 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3858 i < normalized->bv_len; i++ )
3860 /* assume it's already validated that's all hex digits */
3861 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3864 return LDAP_SUCCESS;
3874 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3877 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3878 /* slight optimization - does not need the start parameter */
3879 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3884 check_time_syntax (struct berval *val,
3887 struct berval *fraction)
3890 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3891 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3892 * GeneralizedTime supports leap seconds, UTCTime does not.
3894 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3895 static const int mdays[2][12] = {
3896 /* non-leap years */
3897 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3899 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3902 int part, c, c1, c2, tzoffset, leapyear = 0;
3905 e = p + val->bv_len;
3907 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3908 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3910 for (part = start; part < 7 && p < e; part++) {
3912 if (!ASCII_DIGIT(c1)) {
3917 return LDAP_INVALID_SYNTAX;
3920 if (!ASCII_DIGIT(c)) {
3921 return LDAP_INVALID_SYNTAX;
3923 c += c1 * 10 - '0' * 11;
3924 if ((part | 1) == 3) {
3927 return LDAP_INVALID_SYNTAX;
3930 if (c >= ceiling[part]) {
3931 if (! (c == 60 && part == 6 && start == 0))
3932 return LDAP_INVALID_SYNTAX;
3936 if (part < 5 + start) {
3937 return LDAP_INVALID_SYNTAX;
3939 for (; part < 9; part++) {
3943 /* leapyear check for the Gregorian calendar (year>1581) */
3944 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
3948 if (parts[3] >= mdays[leapyear][parts[2]]) {
3949 return LDAP_INVALID_SYNTAX;
3953 fraction->bv_val = p;
3954 fraction->bv_len = 0;
3955 if (p < e && (*p == '.' || *p == ',')) {
3957 while (++p < e && ASCII_DIGIT(*p)) {
3960 if (p - fraction->bv_val == 1) {
3961 return LDAP_INVALID_SYNTAX;
3963 for (end_num = p; end_num[-1] == '0'; --end_num) {
3966 c = end_num - fraction->bv_val;
3967 if (c != 1) fraction->bv_len = c;
3973 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
3979 return LDAP_INVALID_SYNTAX;
3985 for (part = 7; part < 9 && p < e; part++) {
3987 if (!ASCII_DIGIT(c1)) {
3992 return LDAP_INVALID_SYNTAX;
3995 if (!ASCII_DIGIT(c2)) {
3996 return LDAP_INVALID_SYNTAX;
3998 parts[part] = c1 * 10 + c2 - '0' * 11;
3999 if (parts[part] >= ceiling[part]) {
4000 return LDAP_INVALID_SYNTAX;
4003 if (part < 8 + start) {
4004 return LDAP_INVALID_SYNTAX;
4007 if (tzoffset == '-') {
4008 /* negative offset to UTC, ie west of Greenwich */
4009 parts[4] += parts[7];
4010 parts[5] += parts[8];
4011 /* offset is just hhmm, no seconds */
4012 for (part = 6; --part >= 0; ) {
4016 c = mdays[leapyear][parts[2]];
4018 if (parts[part] >= c) {
4020 return LDAP_INVALID_SYNTAX;
4025 } else if (part != 5) {
4030 /* positive offset to UTC, ie east of Greenwich */
4031 parts[4] -= parts[7];
4032 parts[5] -= parts[8];
4033 for (part = 6; --part >= 0; ) {
4034 if (parts[part] < 0) {
4036 return LDAP_INVALID_SYNTAX;
4041 /* make first arg to % non-negative */
4042 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4047 } else if (part != 5) {
4054 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4057 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4064 struct berval *normalized )
4068 rc = check_time_syntax(val, 1, parts, NULL);
4069 if (rc != LDAP_SUCCESS) {
4073 normalized->bv_val = ch_malloc( 14 );
4074 if ( normalized->bv_val == NULL ) {
4075 return LBER_ERROR_MEMORY;
4078 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4079 parts[1], parts[2] + 1, parts[3] + 1,
4080 parts[4], parts[5], parts[6] );
4081 normalized->bv_len = 13;
4083 return LDAP_SUCCESS;
4093 return check_time_syntax(in, 1, parts, NULL);
4096 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4099 generalizedTimeValidate(
4104 struct berval fraction;
4105 return check_time_syntax(in, 0, parts, &fraction);
4109 generalizedTimeNormalize(
4114 struct berval *normalized,
4119 struct berval fraction;
4121 rc = check_time_syntax(val, 0, parts, &fraction);
4122 if (rc != LDAP_SUCCESS) {
4126 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4127 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4128 if ( BER_BVISNULL( normalized ) ) {
4129 return LBER_ERROR_MEMORY;
4132 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4133 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4134 parts[4], parts[5], parts[6] );
4135 if ( !BER_BVISEMPTY( &fraction ) ) {
4136 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4137 fraction.bv_val, fraction.bv_len );
4138 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4140 strcpy( normalized->bv_val + len-1, "Z" );
4141 normalized->bv_len = len;
4143 return LDAP_SUCCESS;
4147 generalizedTimeOrderingMatch(
4152 struct berval *value,
4153 void *assertedValue )
4155 struct berval *asserted = (struct berval *) assertedValue;
4156 ber_len_t v_len = value->bv_len;
4157 ber_len_t av_len = asserted->bv_len;
4159 /* ignore trailing 'Z' when comparing */
4160 int match = memcmp( value->bv_val, asserted->bv_val,
4161 (v_len < av_len ? v_len : av_len) - 1 );
4162 if ( match == 0 ) match = v_len - av_len;
4165 return LDAP_SUCCESS;
4168 /* Index generation function */
4169 int generalizedTimeIndexer(
4174 struct berval *prefix,
4182 BerValue bvtmp; /* 40 bit index */
4184 struct lutil_timet tt;
4186 bvtmp.bv_len = sizeof(tmp);
4188 for( i=0; values[i].bv_val != NULL; i++ ) {
4189 /* just count them */
4192 /* we should have at least one value at this point */
4195 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4197 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4198 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4199 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4200 /* Use 40 bits of time for key */
4201 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4202 lutil_tm2time( &tm, &tt );
4203 tmp[0] = tt.tt_gsec & 0xff;
4204 tmp[4] = tt.tt_sec & 0xff;
4206 tmp[3] = tt.tt_sec & 0xff;
4208 tmp[2] = tt.tt_sec & 0xff;
4210 tmp[1] = tt.tt_sec & 0xff;
4212 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4216 keys[j].bv_val = NULL;
4221 return LDAP_SUCCESS;
4224 /* Index generation function */
4225 int generalizedTimeFilter(
4230 struct berval *prefix,
4231 void * assertedValue,
4237 BerValue bvtmp; /* 40 bit index */
4238 BerValue *value = (BerValue *) assertedValue;
4240 struct lutil_timet tt;
4242 bvtmp.bv_len = sizeof(tmp);
4244 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4245 /* Use 40 bits of time for key */
4246 if ( value->bv_val && value->bv_len >= 10 &&
4247 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4249 lutil_tm2time( &tm, &tt );
4250 tmp[0] = tt.tt_gsec & 0xff;
4251 tmp[4] = tt.tt_sec & 0xff;
4253 tmp[3] = tt.tt_sec & 0xff;
4255 tmp[2] = tt.tt_sec & 0xff;
4257 tmp[1] = tt.tt_sec & 0xff;
4259 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4260 ber_dupbv_x(keys, &bvtmp, ctx );
4261 keys[1].bv_val = NULL;
4269 return LDAP_SUCCESS;
4273 deliveryMethodValidate(
4275 struct berval *val )
4278 #define LENOF(s) (sizeof(s)-1)
4279 struct berval tmp = *val;
4281 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4282 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4283 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4286 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4288 switch( tmp.bv_val[0] ) {
4291 if(( tmp.bv_len >= LENOF("any") ) &&
4292 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4294 tmp.bv_len -= LENOF("any");
4295 tmp.bv_val += LENOF("any");
4298 return LDAP_INVALID_SYNTAX;
4302 if(( tmp.bv_len >= LENOF("mhs") ) &&
4303 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4305 tmp.bv_len -= LENOF("mhs");
4306 tmp.bv_val += LENOF("mhs");
4309 return LDAP_INVALID_SYNTAX;
4313 if(( tmp.bv_len >= LENOF("physical") ) &&
4314 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4316 tmp.bv_len -= LENOF("physical");
4317 tmp.bv_val += LENOF("physical");
4320 return LDAP_INVALID_SYNTAX;
4323 case 'T': /* telex or teletex or telephone */
4324 if(( tmp.bv_len >= LENOF("telex") ) &&
4325 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4327 tmp.bv_len -= LENOF("telex");
4328 tmp.bv_val += LENOF("telex");
4331 if(( tmp.bv_len >= LENOF("teletex") ) &&
4332 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4334 tmp.bv_len -= LENOF("teletex");
4335 tmp.bv_val += LENOF("teletex");
4338 if(( tmp.bv_len >= LENOF("telephone") ) &&
4339 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4341 tmp.bv_len -= LENOF("telephone");
4342 tmp.bv_val += LENOF("telephone");
4345 return LDAP_INVALID_SYNTAX;
4348 case 'G': /* g3fax or g4fax */
4349 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4350 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4351 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4353 tmp.bv_len -= LENOF("g3fax");
4354 tmp.bv_val += LENOF("g3fax");
4357 return LDAP_INVALID_SYNTAX;
4361 if(( tmp.bv_len >= LENOF("ia5") ) &&
4362 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4364 tmp.bv_len -= LENOF("ia5");
4365 tmp.bv_val += LENOF("ia5");
4368 return LDAP_INVALID_SYNTAX;
4372 if(( tmp.bv_len >= LENOF("videotex") ) &&
4373 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4375 tmp.bv_len -= LENOF("videotex");
4376 tmp.bv_val += LENOF("videotex");
4379 return LDAP_INVALID_SYNTAX;
4382 return LDAP_INVALID_SYNTAX;
4385 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4387 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4391 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4395 return LDAP_INVALID_SYNTAX;
4397 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4406 nisNetgroupTripleValidate(
4408 struct berval *val )
4413 if ( BER_BVISEMPTY( val ) ) {
4414 return LDAP_INVALID_SYNTAX;
4417 p = (char *)val->bv_val;
4418 e = p + val->bv_len;
4420 if ( *p != '(' /*')'*/ ) {
4421 return LDAP_INVALID_SYNTAX;
4424 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4428 return LDAP_INVALID_SYNTAX;
4431 } else if ( !AD_CHAR( *p ) ) {
4432 return LDAP_INVALID_SYNTAX;
4436 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4437 return LDAP_INVALID_SYNTAX;
4443 return LDAP_INVALID_SYNTAX;
4446 return LDAP_SUCCESS;
4450 bootParameterValidate(
4452 struct berval *val )
4456 if ( BER_BVISEMPTY( val ) ) {
4457 return LDAP_INVALID_SYNTAX;
4460 p = (char *)val->bv_val;
4461 e = p + val->bv_len;
4464 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4465 if ( !AD_CHAR( *p ) ) {
4466 return LDAP_INVALID_SYNTAX;
4471 return LDAP_INVALID_SYNTAX;
4475 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4476 if ( !AD_CHAR( *p ) ) {
4477 return LDAP_INVALID_SYNTAX;
4482 return LDAP_INVALID_SYNTAX;
4486 for ( p++; p < e; p++ ) {
4487 if ( !SLAP_PRINTABLE( *p ) ) {
4488 return LDAP_INVALID_SYNTAX;
4492 return LDAP_SUCCESS;
4496 firstComponentNormalize(
4501 struct berval *normalized,
4508 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4509 ber_dupbv_x( normalized, val, ctx );
4510 return LDAP_SUCCESS;
4513 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4515 if( val->bv_val[0] != '(' /*')'*/ &&
4516 val->bv_val[0] != '{' /*'}'*/ )
4518 return LDAP_INVALID_SYNTAX;
4521 /* trim leading white space */
4523 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4529 /* grab next word */
4530 comp.bv_val = &val->bv_val[len];
4531 len = val->bv_len - len;
4532 for( comp.bv_len = 0;
4533 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4539 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4540 rc = numericoidValidate( NULL, &comp );
4541 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4542 rc = integerValidate( NULL, &comp );
4544 rc = LDAP_INVALID_SYNTAX;
4548 if( rc == LDAP_SUCCESS ) {
4549 ber_dupbv_x( normalized, &comp, ctx );
4555 static char *country_gen_syn[] = {
4556 "1.3.6.1.4.1.1466.115.121.1.15",
4557 "1.3.6.1.4.1.1466.115.121.1.26",
4558 "1.3.6.1.4.1.1466.115.121.1.44",
4562 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4563 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4565 static slap_syntax_defs_rec syntax_defs[] = {
4566 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4567 X_BINARY X_NOT_H_R ")",
4568 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4569 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4570 0, NULL, NULL, NULL},
4571 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4572 0, NULL, NULL, NULL},
4573 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4575 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4576 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4578 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4579 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4580 0, NULL, bitStringValidate, NULL },
4581 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4582 0, NULL, booleanValidate, NULL},
4583 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4584 X_BINARY X_NOT_H_R ")",
4585 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4586 NULL, certificateValidate, NULL},
4587 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4588 X_BINARY X_NOT_H_R ")",
4589 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4590 NULL, certificateListValidate, NULL},
4591 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4592 X_BINARY X_NOT_H_R ")",
4593 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4594 NULL, sequenceValidate, NULL},
4595 #if 0 /* need to go __after__ printableString */
4596 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4597 0, "1.3.6.1.4.1.1466.115.121.1.44",
4598 countryStringValidate, NULL},
4600 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4601 0, NULL, dnValidate, dnPretty},
4602 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4603 0, NULL, rdnValidate, rdnPretty},
4604 #ifdef LDAP_COMP_MATCH
4605 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4606 0, NULL, allComponentsValidate, NULL},
4607 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4608 0, NULL, componentFilterValidate, NULL},
4610 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4611 0, NULL, NULL, NULL},
4612 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4613 0, NULL, deliveryMethodValidate, NULL},
4614 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4615 0, NULL, UTF8StringValidate, NULL},
4616 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4617 0, NULL, NULL, NULL},
4618 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4619 0, NULL, NULL, NULL},
4620 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4621 0, NULL, NULL, NULL},
4622 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4623 0, NULL, NULL, NULL},
4624 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4625 0, NULL, NULL, NULL},
4626 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4627 0, NULL, printablesStringValidate, NULL},
4628 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4629 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4630 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4631 0, NULL, generalizedTimeValidate, NULL},
4632 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4633 0, NULL, NULL, NULL},
4634 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4635 0, NULL, IA5StringValidate, NULL},
4636 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4637 0, NULL, integerValidate, NULL},
4638 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4639 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4640 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4641 0, NULL, NULL, NULL},
4642 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4643 0, NULL, NULL, NULL},
4644 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4645 0, NULL, NULL, NULL},
4646 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4647 0, NULL, NULL, NULL},
4648 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4649 0, NULL, NULL, NULL},
4650 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4651 0, NULL, nameUIDValidate, nameUIDPretty },
4652 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4653 0, NULL, NULL, NULL},
4654 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4655 0, NULL, numericStringValidate, NULL},
4656 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4657 0, NULL, NULL, NULL},
4658 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4659 0, NULL, numericoidValidate, NULL},
4660 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4661 0, NULL, IA5StringValidate, NULL},
4662 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4663 0, NULL, blobValidate, NULL},
4664 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4665 0, NULL, UTF8StringValidate, NULL},
4666 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4667 0, NULL, NULL, NULL},
4668 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4669 0, NULL, NULL, NULL},
4670 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4671 0, NULL, printableStringValidate, NULL},
4672 /* moved here because now depends on Directory String, IA5 String
4673 * and Printable String */
4674 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4675 0, country_gen_syn, countryStringValidate, NULL},
4676 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4677 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4678 0, NULL, subtreeSpecificationValidate, NULL},
4679 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4680 X_BINARY X_NOT_H_R ")",
4681 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4682 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4683 0, NULL, printableStringValidate, NULL},
4684 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4685 0, NULL, NULL, NULL},
4686 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4687 0, NULL, printablesStringValidate, NULL},
4688 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4689 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4690 0, NULL, utcTimeValidate, NULL},
4692 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4693 0, NULL, NULL, NULL},
4694 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4695 0, NULL, NULL, NULL},
4696 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4697 0, NULL, NULL, NULL},
4698 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4699 0, NULL, NULL, NULL},
4700 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4701 0, NULL, NULL, NULL},
4703 /* RFC 2307 NIS Syntaxes */
4704 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4705 0, NULL, nisNetgroupTripleValidate, NULL},
4706 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4707 0, NULL, bootParameterValidate, NULL},
4709 /* draft-zeilenga-ldap-x509 */
4710 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4711 SLAP_SYNTAX_HIDE, NULL,
4712 serialNumberAndIssuerValidate,
4713 serialNumberAndIssuerPretty},
4714 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4715 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4716 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4717 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4718 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4719 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4720 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4721 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4722 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4723 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4724 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4725 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4727 #ifdef SLAPD_AUTHPASSWD
4728 /* needs updating */
4729 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4730 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4733 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4734 0, NULL, UUIDValidate, UUIDPretty},
4736 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4737 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4739 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4740 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4742 /* OpenLDAP Void Syntax */
4743 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4744 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4746 /* FIXME: OID is unused, but not registered yet */
4747 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4748 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4750 {NULL, 0, NULL, NULL, NULL}
4753 char *csnSIDMatchSyntaxes[] = {
4754 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4757 char *certificateExactMatchSyntaxes[] = {
4758 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4761 #ifdef LDAP_COMP_MATCH
4762 char *componentFilterMatchSyntaxes[] = {
4763 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4767 char *directoryStringSyntaxes[] = {
4768 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4771 char *integerFirstComponentMatchSyntaxes[] = {
4772 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4773 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4776 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4777 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4778 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4779 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4780 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4781 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4782 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4783 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4784 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4789 * Other matching rules in X.520 that we do not use (yet):
4791 * 2.5.13.25 uTCTimeMatch
4792 * 2.5.13.26 uTCTimeOrderingMatch
4793 * 2.5.13.31* directoryStringFirstComponentMatch
4794 * 2.5.13.32* wordMatch
4795 * 2.5.13.33* keywordMatch
4796 * 2.5.13.36+ certificatePairExactMatch
4797 * 2.5.13.37+ certificatePairMatch
4798 * 2.5.13.38+ certificateListExactMatch
4799 * 2.5.13.39+ certificateListMatch
4800 * 2.5.13.40+ algorithmIdentifierMatch
4801 * 2.5.13.41* storedPrefixMatch
4802 * 2.5.13.42 attributeCertificateMatch
4803 * 2.5.13.43 readerAndKeyIDMatch
4804 * 2.5.13.44 attributeIntegrityMatch
4806 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4807 * (+) described in draft-zeilenga-ldap-x509
4809 static slap_mrule_defs_rec mrule_defs[] = {
4811 * EQUALITY matching rules must be listed after associated APPROX
4812 * matching rules. So, we list all APPROX matching rules first.
4814 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4816 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4817 NULL, NULL, directoryStringApproxMatch,
4818 directoryStringApproxIndexer, directoryStringApproxFilter,
4821 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4823 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4824 NULL, NULL, IA5StringApproxMatch,
4825 IA5StringApproxIndexer, IA5StringApproxFilter,
4829 * Other matching rules
4832 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4833 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4834 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4835 NULL, NULL, octetStringMatch,
4836 octetStringIndexer, octetStringFilter,
4839 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4840 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4841 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4842 NULL, dnNormalize, dnMatch,
4843 octetStringIndexer, octetStringFilter,
4846 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4847 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4848 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4849 NULL, dnNormalize, dnRelativeMatch,
4853 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4854 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4855 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4856 NULL, dnNormalize, dnRelativeMatch,
4860 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4861 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4862 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4863 NULL, dnNormalize, dnRelativeMatch,
4867 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4868 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4869 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4870 NULL, dnNormalize, dnRelativeMatch,
4874 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4875 "SYNTAX 1.2.36.79672281.1.5.0 )",
4876 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4877 NULL, rdnNormalize, rdnMatch,
4878 octetStringIndexer, octetStringFilter,
4881 #ifdef LDAP_COMP_MATCH
4882 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4883 "SYNTAX 1.2.36.79672281.1.5.2 )",
4884 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4885 NULL, NULL , componentFilterMatch,
4886 octetStringIndexer, octetStringFilter,
4889 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4890 "SYNTAX 1.2.36.79672281.1.5.3 )",
4891 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4892 NULL, NULL , allComponentsMatch,
4893 octetStringIndexer, octetStringFilter,
4896 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4897 "SYNTAX 1.2.36.79672281.1.5.3 )",
4898 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4899 NULL, NULL , directoryComponentsMatch,
4900 octetStringIndexer, octetStringFilter,
4904 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4905 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4906 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4907 NULL, UTF8StringNormalize, octetStringMatch,
4908 octetStringIndexer, octetStringFilter,
4909 directoryStringApproxMatchOID },
4911 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4912 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4913 SLAP_MR_ORDERING, directoryStringSyntaxes,
4914 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4916 "caseIgnoreMatch" },
4918 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4919 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4920 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4921 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4922 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4923 "caseIgnoreMatch" },
4925 {"( 2.5.13.5 NAME 'caseExactMatch' "
4926 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4927 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4928 NULL, UTF8StringNormalize, octetStringMatch,
4929 octetStringIndexer, octetStringFilter,
4930 directoryStringApproxMatchOID },
4932 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4933 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4934 SLAP_MR_ORDERING, directoryStringSyntaxes,
4935 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4939 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4940 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4941 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4942 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4943 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4946 {"( 2.5.13.8 NAME 'numericStringMatch' "
4947 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4948 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4949 NULL, numericStringNormalize, octetStringMatch,
4950 octetStringIndexer, octetStringFilter,
4953 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4954 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4955 SLAP_MR_ORDERING, NULL,
4956 NULL, numericStringNormalize, octetStringOrderingMatch,
4958 "numericStringMatch" },
4960 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4962 SLAP_MR_SUBSTR, NULL,
4963 NULL, numericStringNormalize, octetStringSubstringsMatch,
4964 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4965 "numericStringMatch" },
4967 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4968 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4969 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4970 NULL, NULL, NULL, NULL, NULL, NULL },
4972 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4973 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4974 SLAP_MR_SUBSTR, NULL,
4975 NULL, NULL, NULL, NULL, NULL,
4976 "caseIgnoreListMatch" },
4978 {"( 2.5.13.13 NAME 'booleanMatch' "
4979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4980 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4981 NULL, NULL, booleanMatch,
4982 octetStringIndexer, octetStringFilter,
4985 {"( 2.5.13.14 NAME 'integerMatch' "
4986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4987 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4988 NULL, NULL, integerMatch,
4989 octetStringIndexer, octetStringFilter,
4992 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4994 SLAP_MR_ORDERING, NULL,
4995 NULL, NULL, integerMatch,
4999 {"( 2.5.13.16 NAME 'bitStringMatch' "
5000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5001 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5002 NULL, NULL, octetStringMatch,
5003 octetStringIndexer, octetStringFilter,
5006 {"( 2.5.13.17 NAME 'octetStringMatch' "
5007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5008 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5009 NULL, NULL, octetStringMatch,
5010 octetStringIndexer, octetStringFilter,
5013 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5015 SLAP_MR_ORDERING, NULL,
5016 NULL, NULL, octetStringOrderingMatch,
5018 "octetStringMatch" },
5020 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5021 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5022 SLAP_MR_SUBSTR, NULL,
5023 NULL, NULL, octetStringSubstringsMatch,
5024 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5025 "octetStringMatch" },
5027 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5028 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5029 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5031 telephoneNumberNormalize, octetStringMatch,
5032 octetStringIndexer, octetStringFilter,
5035 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5036 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5037 SLAP_MR_SUBSTR, NULL,
5038 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5039 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5040 "telephoneNumberMatch" },
5042 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5043 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5044 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5045 NULL, NULL, NULL, NULL, NULL, NULL },
5047 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5049 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5050 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5051 uniqueMemberIndexer, uniqueMemberFilter,
5054 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5055 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5056 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5057 NULL, NULL, NULL, NULL, NULL, NULL },
5059 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5061 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5062 NULL, generalizedTimeNormalize, octetStringMatch,
5063 generalizedTimeIndexer, generalizedTimeFilter,
5066 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5068 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5069 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5071 "generalizedTimeMatch" },
5073 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5074 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5075 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5076 integerFirstComponentMatchSyntaxes,
5077 NULL, firstComponentNormalize, integerMatch,
5078 octetStringIndexer, octetStringFilter,
5081 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5082 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5083 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5084 objectIdentifierFirstComponentMatchSyntaxes,
5085 NULL, firstComponentNormalize, octetStringMatch,
5086 octetStringIndexer, octetStringFilter,
5089 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5090 "SYNTAX 1.3.6.1.1.15.1 )",
5091 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5092 NULL, certificateExactNormalize, octetStringMatch,
5093 octetStringIndexer, octetStringFilter,
5096 {"( 2.5.13.35 NAME 'certificateMatch' "
5097 "SYNTAX 1.3.6.1.1.15.2 )",
5098 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5099 NULL, NULL, NULL, NULL, NULL,
5102 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5103 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5104 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5105 NULL, IA5StringNormalize, octetStringMatch,
5106 octetStringIndexer, octetStringFilter,
5107 IA5StringApproxMatchOID },
5109 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5110 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5111 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5112 NULL, IA5StringNormalize, octetStringMatch,
5113 octetStringIndexer, octetStringFilter,
5114 IA5StringApproxMatchOID },
5116 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5117 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5118 SLAP_MR_SUBSTR, NULL,
5119 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5120 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5121 "caseIgnoreIA5Match" },
5123 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5124 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5125 SLAP_MR_SUBSTR, NULL,
5126 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5127 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5128 "caseExactIA5Match" },
5130 #ifdef SLAPD_AUTHPASSWD
5131 /* needs updating */
5132 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5133 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5134 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5135 NULL, NULL, authPasswordMatch,
5140 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5141 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5143 NULL, NULL, integerBitAndMatch,
5147 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5148 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5150 NULL, NULL, integerBitOrMatch,
5154 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5155 "SYNTAX 1.3.6.1.1.16.1 )",
5156 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5157 NULL, UUIDNormalize, octetStringMatch,
5158 octetStringIndexer, octetStringFilter,
5161 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5162 "SYNTAX 1.3.6.1.1.16.1 )",
5163 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5164 NULL, UUIDNormalize, octetStringOrderingMatch,
5165 octetStringIndexer, octetStringFilter,
5168 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5169 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5170 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5171 NULL, csnNormalize, csnMatch,
5172 csnIndexer, csnFilter,
5175 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5176 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5177 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5178 NULL, NULL, csnOrderingMatch,
5182 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5183 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5184 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5185 NULL, csnSidNormalize, octetStringMatch,
5186 octetStringIndexer, octetStringFilter,
5189 /* FIXME: OID is unused, but not registered yet */
5190 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5191 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5192 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5193 NULL, authzNormalize, authzMatch,
5197 {NULL, SLAP_MR_NONE, NULL,
5198 NULL, NULL, NULL, NULL, NULL,
5203 slap_schema_init( void )
5208 /* we should only be called once (from main) */
5209 assert( schema_init_done == 0 );
5211 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5212 res = register_syntax( &syntax_defs[i] );
5215 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5216 syntax_defs[i].sd_desc );
5221 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5222 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5223 mrule_defs[i].mrd_compat_syntaxes == NULL )
5226 "slap_schema_init: Ignoring unusable matching rule %s\n",
5227 mrule_defs[i].mrd_desc );
5231 res = register_matching_rule( &mrule_defs[i] );
5235 "slap_schema_init: Error registering matching rule %s\n",
5236 mrule_defs[i].mrd_desc );
5241 res = slap_schema_load();
5242 schema_init_done = 1;
5247 schema_destroy( void )
5256 if( schema_init_done ) {
5257 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5258 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );