1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2007 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 ldap_pvt_thread_mutex_t ad_undef_mutex;
66 ldap_pvt_thread_mutex_t oc_undef_mutex;
69 generalizedTimeValidate(
78 /* no value allowed */
79 return LDAP_INVALID_SYNTAX;
87 /* any value allowed */
91 #define berValidate blobValidate
98 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
99 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
104 /* X.509 related stuff */
112 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
115 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
116 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
117 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
118 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
122 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
125 /* X.509 certificate validation */
126 static int certificateValidate( Syntax *syntax, struct berval *in )
128 BerElementBuffer berbuf;
129 BerElement *ber = (BerElement *)&berbuf;
132 ber_int_t version = SLAP_X509_V1;
134 ber_init2( ber, in, LBER_USE_DER );
135 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
136 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
137 tag = ber_skip_tag( ber, &len ); /* Sequence */
138 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
139 tag = ber_peek_tag( ber, &len );
140 /* Optional version */
141 if ( tag == SLAP_X509_OPT_C_VERSION ) {
142 tag = ber_skip_tag( ber, &len );
143 tag = ber_get_int( ber, &version );
144 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
146 /* NOTE: don't try to parse Serial, because it might be longer
147 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
148 tag = ber_skip_tag( ber, &len ); /* Serial */
149 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
150 ber_skip_data( ber, len );
151 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
152 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
153 ber_skip_data( ber, len );
154 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
155 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
156 ber_skip_data( ber, len );
157 tag = ber_skip_tag( ber, &len ); /* Validity */
158 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
159 ber_skip_data( ber, len );
160 tag = ber_skip_tag( ber, &len ); /* Subject DN */
161 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
162 ber_skip_data( ber, len );
163 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
164 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
165 ber_skip_data( ber, len );
166 tag = ber_skip_tag( ber, &len );
167 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
168 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
169 ber_skip_data( ber, len );
170 tag = ber_skip_tag( ber, &len );
172 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
173 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
174 ber_skip_data( ber, len );
175 tag = ber_skip_tag( ber, &len );
177 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
178 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
179 tag = ber_skip_tag( ber, &len );
180 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
181 ber_skip_data( ber, len );
182 tag = ber_skip_tag( ber, &len );
184 /* signatureAlgorithm */
185 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
186 ber_skip_data( ber, len );
187 tag = ber_skip_tag( ber, &len );
189 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
190 ber_skip_data( ber, len );
191 tag = ber_skip_tag( ber, &len );
192 /* Must be at end now */
193 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
197 /* X.509 certificate list validation */
198 static int certificateListValidate( Syntax *syntax, struct berval *in )
200 BerElementBuffer berbuf;
201 BerElement *ber = (BerElement *)&berbuf;
204 ber_int_t version = SLAP_X509_V1;
206 ber_init2( ber, in, LBER_USE_DER );
207 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
208 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
209 tag = ber_skip_tag( ber, &len ); /* Sequence */
210 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
211 tag = ber_peek_tag( ber, &len );
212 /* Optional version */
213 if ( tag == LBER_INTEGER ) {
214 tag = ber_get_int( ber, &version );
215 assert( tag == LBER_INTEGER );
216 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
218 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
219 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
220 ber_skip_data( ber, len );
221 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
222 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
223 ber_skip_data( ber, len );
224 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
225 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
226 if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX;
227 ber_skip_data( ber, len );
228 /* Optional nextUpdate */
229 tag = ber_skip_tag( ber, &len );
230 if ( tag == 0x17U || tag == 0x18U ) {
231 ber_skip_data( ber, len );
232 tag = ber_skip_tag( ber, &len );
234 /* revokedCertificates - Sequence of Sequence, Optional */
235 if ( tag == LBER_SEQUENCE ) {
237 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
238 /* Should NOT be empty */
239 ber_skip_data( ber, len );
240 tag = ber_skip_tag( ber, &len );
243 /* Optional Extensions */
244 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
245 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
246 tag = ber_skip_tag( ber, &len );
247 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
248 ber_skip_data( ber, len );
249 tag = ber_skip_tag( ber, &len );
251 /* signatureAlgorithm */
252 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
253 ber_skip_data( ber, len );
254 tag = ber_skip_tag( ber, &len );
256 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
257 ber_skip_data( ber, len );
258 tag = ber_skip_tag( ber, &len );
259 /* Must be at end now */
260 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
270 struct berval *value,
271 void *assertedValue )
273 struct berval *asserted = (struct berval *) assertedValue;
274 int match = value->bv_len - asserted->bv_len;
277 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
285 octetStringOrderingMatch(
290 struct berval *value,
291 void *assertedValue )
293 struct berval *asserted = (struct berval *) assertedValue;
294 ber_len_t v_len = value->bv_len;
295 ber_len_t av_len = asserted->bv_len;
297 int match = memcmp( value->bv_val, asserted->bv_val,
298 (v_len < av_len ? v_len : av_len) );
300 if( match == 0 ) match = v_len - av_len;
308 HASH_CONTEXT *HASHcontext,
309 struct berval *prefix,
314 HASH_Init(HASHcontext);
315 if(prefix && prefix->bv_len > 0) {
316 HASH_Update(HASHcontext,
317 (unsigned char *)prefix->bv_val, prefix->bv_len);
319 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
320 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
321 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
327 HASH_CONTEXT *HASHcontext,
328 unsigned char *HASHdigest,
329 unsigned char *value,
332 HASH_CONTEXT ctx = *HASHcontext;
333 HASH_Update( &ctx, value, len );
334 HASH_Final( HASHdigest, &ctx );
337 /* Index generation function */
338 int octetStringIndexer(
343 struct berval *prefix,
351 HASH_CONTEXT HASHcontext;
352 unsigned char HASHdigest[HASH_BYTES];
353 struct berval digest;
354 digest.bv_val = (char *)HASHdigest;
355 digest.bv_len = sizeof(HASHdigest);
357 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
358 /* just count them */
361 /* we should have at least one value at this point */
364 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
366 slen = syntax->ssyn_oidlen;
367 mlen = mr->smr_oidlen;
369 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
370 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
371 hashIter( &HASHcontext, HASHdigest,
372 (unsigned char *)values[i].bv_val, values[i].bv_len );
373 ber_dupbv_x( &keys[i], &digest, ctx );
376 BER_BVZERO( &keys[i] );
383 /* Index generation function */
384 int octetStringFilter(
389 struct berval *prefix,
390 void * assertedValue,
396 HASH_CONTEXT HASHcontext;
397 unsigned char HASHdigest[HASH_BYTES];
398 struct berval *value = (struct berval *) assertedValue;
399 struct berval digest;
400 digest.bv_val = (char *)HASHdigest;
401 digest.bv_len = sizeof(HASHdigest);
403 slen = syntax->ssyn_oidlen;
404 mlen = mr->smr_oidlen;
406 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
408 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
409 hashIter( &HASHcontext, HASHdigest,
410 (unsigned char *)value->bv_val, value->bv_len );
412 ber_dupbv_x( keys, &digest, ctx );
413 BER_BVZERO( &keys[1] );
421 octetStringSubstringsMatch(
426 struct berval *value,
427 void *assertedValue )
430 SubstringsAssertion *sub = assertedValue;
431 struct berval left = *value;
435 /* Add up asserted input length */
436 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
437 inlen += sub->sa_initial.bv_len;
440 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
441 inlen += sub->sa_any[i].bv_len;
444 if ( !BER_BVISNULL( &sub->sa_final ) ) {
445 inlen += sub->sa_final.bv_len;
448 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
449 if ( inlen > left.bv_len ) {
454 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
455 sub->sa_initial.bv_len );
461 left.bv_val += sub->sa_initial.bv_len;
462 left.bv_len -= sub->sa_initial.bv_len;
463 inlen -= sub->sa_initial.bv_len;
466 if ( !BER_BVISNULL( &sub->sa_final ) ) {
467 if ( inlen > left.bv_len ) {
472 match = memcmp( sub->sa_final.bv_val,
473 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
474 sub->sa_final.bv_len );
480 left.bv_len -= sub->sa_final.bv_len;
481 inlen -= sub->sa_final.bv_len;
485 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
490 if ( inlen > left.bv_len ) {
491 /* not enough length */
496 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
500 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
507 idx = p - left.bv_val;
509 if ( idx >= left.bv_len ) {
510 /* this shouldn't happen */
517 if ( sub->sa_any[i].bv_len > left.bv_len ) {
518 /* not enough left */
523 match = memcmp( left.bv_val,
524 sub->sa_any[i].bv_val,
525 sub->sa_any[i].bv_len );
533 left.bv_val += sub->sa_any[i].bv_len;
534 left.bv_len -= sub->sa_any[i].bv_len;
535 inlen -= sub->sa_any[i].bv_len;
544 /* Substrings Index generation function */
546 octetStringSubstringsIndexer(
551 struct berval *prefix,
560 HASH_CONTEXT HCany, HCini, HCfin;
561 unsigned char HASHdigest[HASH_BYTES];
562 struct berval digest;
563 digest.bv_val = (char *)HASHdigest;
564 digest.bv_len = sizeof(HASHdigest);
568 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
569 /* count number of indices to generate */
570 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
571 if( values[i].bv_len >= index_substr_if_maxlen ) {
572 nkeys += index_substr_if_maxlen -
573 (index_substr_if_minlen - 1);
574 } else if( values[i].bv_len >= index_substr_if_minlen ) {
575 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
579 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
580 if( values[i].bv_len >= index_substr_any_len ) {
581 nkeys += values[i].bv_len - (index_substr_any_len - 1);
585 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
586 if( values[i].bv_len >= index_substr_if_maxlen ) {
587 nkeys += index_substr_if_maxlen -
588 (index_substr_if_minlen - 1);
589 } else if( values[i].bv_len >= index_substr_if_minlen ) {
590 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
596 /* no keys to generate */
601 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
603 slen = syntax->ssyn_oidlen;
604 mlen = mr->smr_oidlen;
606 if ( flags & SLAP_INDEX_SUBSTR_ANY )
607 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
608 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
609 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
610 if( flags & SLAP_INDEX_SUBSTR_FINAL )
611 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
614 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
617 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
618 ( values[i].bv_len >= index_substr_any_len ) )
620 max = values[i].bv_len - (index_substr_any_len - 1);
622 for( j=0; j<max; j++ ) {
623 hashIter( &HCany, HASHdigest,
624 (unsigned char *)&values[i].bv_val[j],
625 index_substr_any_len );
626 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
630 /* skip if too short */
631 if( values[i].bv_len < index_substr_if_minlen ) continue;
633 max = index_substr_if_maxlen < values[i].bv_len
634 ? index_substr_if_maxlen : values[i].bv_len;
636 for( j=index_substr_if_minlen; j<=max; j++ ) {
638 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
639 hashIter( &HCini, HASHdigest,
640 (unsigned char *)values[i].bv_val, j );
641 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
644 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
645 hashIter( &HCfin, HASHdigest,
646 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
647 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
654 BER_BVZERO( &keys[nkeys] );
665 octetStringSubstringsFilter (
670 struct berval *prefix,
671 void * assertedValue,
675 SubstringsAssertion *sa;
678 size_t slen, mlen, klen;
680 HASH_CONTEXT HASHcontext;
681 unsigned char HASHdigest[HASH_BYTES];
682 struct berval *value;
683 struct berval digest;
685 sa = (SubstringsAssertion *) assertedValue;
687 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
688 !BER_BVISNULL( &sa->sa_initial ) &&
689 sa->sa_initial.bv_len >= index_substr_if_minlen )
692 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
693 ( flags & SLAP_INDEX_SUBSTR_ANY ))
695 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
699 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
701 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
702 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
703 /* don't bother accounting with stepping */
704 nkeys += sa->sa_any[i].bv_len -
705 ( index_substr_any_len - 1 );
710 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
711 !BER_BVISNULL( &sa->sa_final ) &&
712 sa->sa_final.bv_len >= index_substr_if_minlen )
715 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
716 ( flags & SLAP_INDEX_SUBSTR_ANY ))
718 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
727 digest.bv_val = (char *)HASHdigest;
728 digest.bv_len = sizeof(HASHdigest);
730 slen = syntax->ssyn_oidlen;
731 mlen = mr->smr_oidlen;
733 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
736 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
737 !BER_BVISNULL( &sa->sa_initial ) &&
738 sa->sa_initial.bv_len >= index_substr_if_minlen )
740 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
741 value = &sa->sa_initial;
743 klen = index_substr_if_maxlen < value->bv_len
744 ? index_substr_if_maxlen : value->bv_len;
746 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
747 hashIter( &HASHcontext, HASHdigest,
748 (unsigned char *)value->bv_val, klen );
749 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
751 /* If initial is too long and we have subany indexed, use it
752 * to match the excess...
754 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
757 pre = SLAP_INDEX_SUBSTR_PREFIX;
758 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
759 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
761 hashIter( &HASHcontext, HASHdigest,
762 (unsigned char *)&value->bv_val[j], index_substr_any_len );
763 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
768 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
770 pre = SLAP_INDEX_SUBSTR_PREFIX;
771 klen = index_substr_any_len;
773 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
774 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
778 value = &sa->sa_any[i];
780 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
782 j <= value->bv_len - index_substr_any_len;
783 j += index_substr_any_step )
785 hashIter( &HASHcontext, HASHdigest,
786 (unsigned char *)&value->bv_val[j], klen );
787 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
792 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
793 !BER_BVISNULL( &sa->sa_final ) &&
794 sa->sa_final.bv_len >= index_substr_if_minlen )
796 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
797 value = &sa->sa_final;
799 klen = index_substr_if_maxlen < value->bv_len
800 ? index_substr_if_maxlen : value->bv_len;
802 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
803 hashIter( &HASHcontext, HASHdigest,
804 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
805 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
807 /* If final is too long and we have subany indexed, use it
808 * to match the excess...
810 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
813 pre = SLAP_INDEX_SUBSTR_PREFIX;
814 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
815 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
817 hashIter( &HASHcontext, HASHdigest,
818 (unsigned char *)&value->bv_val[j], index_substr_any_len );
819 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
825 BER_BVZERO( &keys[nkeys] );
842 /* very unforgiving validation, requires no normalization
843 * before simplistic matching
845 if( in->bv_len < 3 ) {
846 return LDAP_INVALID_SYNTAX;
849 /* RFC 4517 Section 3.3.2 Bit String:
850 * BitString = SQUOTE *binary-digit SQUOTE "B"
851 * binary-digit = "0" / "1"
853 * where SQUOTE [RFC4512] is
854 * SQUOTE = %x27 ; single quote ("'")
856 * Example: '0101111101'B
859 if( in->bv_val[0] != '\'' ||
860 in->bv_val[in->bv_len - 2] != '\'' ||
861 in->bv_val[in->bv_len - 1] != 'B' )
863 return LDAP_INVALID_SYNTAX;
866 for( i = in->bv_len - 3; i > 0; i-- ) {
867 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
868 return LDAP_INVALID_SYNTAX;
876 * Syntaxes from RFC 4517
881 A value of the Bit String syntax is a sequence of binary digits. The
882 LDAP-specific encoding of a value of this syntax is defined by the
885 BitString = SQUOTE *binary-digit SQUOTE "B"
887 binary-digit = "0" / "1"
889 The <SQUOTE> rule is defined in [MODELS].
894 The LDAP definition for the Bit String syntax is:
896 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
898 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
902 3.3.21. Name and Optional UID
904 A value of the Name and Optional UID syntax is the distinguished name
905 [MODELS] of an entity optionally accompanied by a unique identifier
906 that serves to differentiate the entity from others with an identical
909 The LDAP-specific encoding of a value of this syntax is defined by
912 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
914 The <BitString> rule is defined in Section 3.3.2. The
915 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
918 Note that although the '#' character may occur in the string
919 representation of a distinguished name, no additional escaping of
920 this character is performed when a <distinguishedName> is encoded in
921 a <NameAndOptionalUID>.
924 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
926 The LDAP definition for the Name and Optional UID syntax is:
928 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
930 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
937 1.4. Common ABNF Productions
940 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
942 SQUOTE = %x27 ; single quote ("'")
946 * Note: normalization strips any leading "0"s, unless the
947 * bit string is exactly "'0'B", so the normalized example,
948 * in slapd, would result in
950 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
952 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
953 * be escaped except when at the beginning of a value, the
954 * definition of Name and Optional UID appears to be flawed,
955 * because there is no clear means to determine whether the
956 * UID part is present or not.
960 * cn=Someone,dc=example,dc=com#'1'B
962 * could be either a NameAndOptionalUID with trailing UID, i.e.
964 * DN = "cn=Someone,dc=example,dc=com"
967 * or a NameAndOptionalUID with no trailing UID, and the AVA
968 * in the last RDN made of
971 * attributeValue = com#'1'B
973 * in fact "com#'1'B" is a valid IA5 string.
975 * As a consequence, current slapd code assumes that the
976 * presence of portions of a BitString at the end of the string
977 * representation of a NameAndOptionalUID means a BitString
978 * is expected, and cause an error otherwise. This is quite
979 * arbitrary, and might change in the future.
989 struct berval dn, uid;
991 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
993 ber_dupbv( &dn, in );
994 if( !dn.bv_val ) return LDAP_OTHER;
996 /* if there's a "#", try bitStringValidate()... */
997 uid.bv_val = strrchr( dn.bv_val, '#' );
998 if ( !BER_BVISNULL( &uid ) ) {
1000 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1002 rc = bitStringValidate( NULL, &uid );
1003 if ( rc == LDAP_SUCCESS ) {
1004 /* in case of success, trim the UID,
1005 * otherwise treat it as part of the DN */
1006 dn.bv_len -= uid.bv_len + 1;
1007 uid.bv_val[-1] = '\0';
1011 rc = dnValidate( NULL, &dn );
1013 ber_memfree( dn.bv_val );
1024 assert( val != NULL );
1025 assert( out != NULL );
1028 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1030 if( BER_BVISEMPTY( val ) ) {
1031 ber_dupbv_x( out, val, ctx );
1033 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1034 return LDAP_INVALID_SYNTAX;
1038 struct berval dnval = *val;
1039 struct berval uidval = BER_BVNULL;
1041 uidval.bv_val = strrchr( val->bv_val, '#' );
1042 if ( !BER_BVISNULL( &uidval ) ) {
1044 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1046 rc = bitStringValidate( NULL, &uidval );
1048 if ( rc == LDAP_SUCCESS ) {
1049 ber_dupbv_x( &dnval, val, ctx );
1050 dnval.bv_len -= uidval.bv_len + 1;
1051 dnval.bv_val[dnval.bv_len] = '\0';
1054 BER_BVZERO( &uidval );
1058 rc = dnPretty( syntax, &dnval, out, ctx );
1059 if ( dnval.bv_val != val->bv_val ) {
1060 slap_sl_free( dnval.bv_val, ctx );
1062 if( rc != LDAP_SUCCESS ) {
1066 if( !BER_BVISNULL( &uidval ) ) {
1070 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1071 + STRLENOF( "#" ) + uidval.bv_len + 1,
1074 ber_memfree_x( out->bv_val, ctx );
1078 out->bv_val[out->bv_len++] = '#';
1079 out->bv_val[out->bv_len++] = '\'';
1081 got1 = uidval.bv_len < sizeof("'0'B");
1082 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1083 c = uidval.bv_val[i];
1086 if( got1 ) out->bv_val[out->bv_len++] = c;
1090 out->bv_val[out->bv_len++] = c;
1095 out->bv_val[out->bv_len++] = '\'';
1096 out->bv_val[out->bv_len++] = 'B';
1097 out->bv_val[out->bv_len] = '\0';
1101 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1103 return LDAP_SUCCESS;
1107 uniqueMemberNormalize(
1112 struct berval *normalized,
1118 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1120 ber_dupbv_x( &out, val, ctx );
1121 if ( BER_BVISEMPTY( &out ) ) {
1125 struct berval uid = BER_BVNULL;
1127 uid.bv_val = strrchr( out.bv_val, '#' );
1128 if ( !BER_BVISNULL( &uid ) ) {
1130 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1132 rc = bitStringValidate( NULL, &uid );
1133 if ( rc == LDAP_SUCCESS ) {
1134 uid.bv_val[-1] = '\0';
1135 out.bv_len -= uid.bv_len + 1;
1141 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1143 if( rc != LDAP_SUCCESS ) {
1144 slap_sl_free( out.bv_val, ctx );
1145 return LDAP_INVALID_SYNTAX;
1148 if( !BER_BVISNULL( &uid ) ) {
1151 tmp = ch_realloc( normalized->bv_val,
1152 normalized->bv_len + uid.bv_len
1153 + STRLENOF("#") + 1 );
1154 if ( tmp == NULL ) {
1155 ber_memfree_x( normalized->bv_val, ctx );
1159 normalized->bv_val = tmp;
1161 /* insert the separator */
1162 normalized->bv_val[normalized->bv_len++] = '#';
1164 /* append the UID */
1165 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1166 uid.bv_val, uid.bv_len );
1167 normalized->bv_len += uid.bv_len;
1170 normalized->bv_val[normalized->bv_len] = '\0';
1173 slap_sl_free( out.bv_val, ctx );
1176 return LDAP_SUCCESS;
1185 struct berval *value,
1186 void *assertedValue )
1189 struct berval *asserted = (struct berval *) assertedValue;
1190 struct berval assertedDN = *asserted;
1191 struct berval assertedUID = BER_BVNULL;
1192 struct berval valueDN = *value;
1193 struct berval valueUID = BER_BVNULL;
1194 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1196 if ( !BER_BVISEMPTY( asserted ) ) {
1197 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1198 if ( !BER_BVISNULL( &assertedUID ) ) {
1199 assertedUID.bv_val++;
1200 assertedUID.bv_len = assertedDN.bv_len
1201 - ( assertedUID.bv_val - assertedDN.bv_val );
1203 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1204 assertedDN.bv_len -= assertedUID.bv_len + 1;
1207 BER_BVZERO( &assertedUID );
1212 if ( !BER_BVISEMPTY( value ) ) {
1214 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1215 if ( !BER_BVISNULL( &valueUID ) ) {
1217 valueUID.bv_len = valueDN.bv_len
1218 - ( valueUID.bv_val - valueDN.bv_val );
1220 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1221 valueDN.bv_len -= valueUID.bv_len + 1;
1224 BER_BVZERO( &valueUID );
1229 if( valueUID.bv_len && assertedUID.bv_len ) {
1230 match = valueUID.bv_len - assertedUID.bv_len;
1233 return LDAP_SUCCESS;
1236 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1239 return LDAP_SUCCESS;
1242 } else if ( !approx && valueUID.bv_len ) {
1245 return LDAP_SUCCESS;
1247 } else if ( !approx && assertedUID.bv_len ) {
1250 return LDAP_SUCCESS;
1253 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1257 uniqueMemberIndexer(
1262 struct berval *prefix,
1270 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1271 /* just count them */
1275 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1277 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1278 struct berval assertedDN = values[i];
1279 struct berval assertedUID = BER_BVNULL;
1281 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1282 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1283 if ( !BER_BVISNULL( &assertedUID ) ) {
1284 assertedUID.bv_val++;
1285 assertedUID.bv_len = assertedDN.bv_len
1286 - ( assertedUID.bv_val - assertedDN.bv_val );
1288 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1289 assertedDN.bv_len -= assertedUID.bv_len + 1;
1292 BER_BVZERO( &assertedUID );
1297 dnvalues[i] = assertedDN;
1299 BER_BVZERO( &dnvalues[i] );
1301 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1302 dnvalues, keysp, ctx );
1304 slap_sl_free( dnvalues, ctx );
1314 struct berval *prefix,
1315 void * assertedValue,
1319 struct berval *asserted = (struct berval *) assertedValue;
1320 struct berval assertedDN = *asserted;
1321 struct berval assertedUID = BER_BVNULL;
1323 if ( !BER_BVISEMPTY( asserted ) ) {
1324 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1325 if ( !BER_BVISNULL( &assertedUID ) ) {
1326 assertedUID.bv_val++;
1327 assertedUID.bv_len = assertedDN.bv_len
1328 - ( assertedUID.bv_val - assertedDN.bv_val );
1330 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1331 assertedDN.bv_len -= assertedUID.bv_len + 1;
1334 BER_BVZERO( &assertedUID );
1339 return octetStringFilter( use, flags, syntax, mr, prefix,
1340 &assertedDN, keysp, ctx );
1345 * Handling boolean syntax and matching is quite rigid.
1346 * A more flexible approach would be to allow a variety
1347 * of strings to be normalized and prettied into TRUE
1355 /* very unforgiving validation, requires no normalization
1356 * before simplistic matching
1359 if( in->bv_len == 4 ) {
1360 if( bvmatch( in, &slap_true_bv ) ) {
1361 return LDAP_SUCCESS;
1363 } else if( in->bv_len == 5 ) {
1364 if( bvmatch( in, &slap_false_bv ) ) {
1365 return LDAP_SUCCESS;
1369 return LDAP_INVALID_SYNTAX;
1378 struct berval *value,
1379 void *assertedValue )
1381 /* simplistic matching allowed by rigid validation */
1382 struct berval *asserted = (struct berval *) assertedValue;
1383 *matchp = value->bv_len != asserted->bv_len;
1384 return LDAP_SUCCESS;
1387 /*-------------------------------------------------------------------
1388 LDAP/X.500 string syntax / matching rules have a few oddities. This
1389 comment attempts to detail how slapd(8) treats them.
1392 StringSyntax X.500 LDAP Matching/Comments
1393 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1394 PrintableString subset subset i/e + ignore insignificant spaces
1395 PrintableString subset subset i/e + ignore insignificant spaces
1396 NumericString subset subset ignore all spaces
1397 IA5String ASCII ASCII i/e + ignore insignificant spaces
1398 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1400 TelephoneNumber subset subset i + ignore all spaces and "-"
1402 See RFC 4518 for details.
1406 In X.500(93), a directory string can be either a PrintableString,
1407 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1408 In later versions, more CHOICEs were added. In all cases the string
1411 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1412 A directory string cannot be zero length.
1414 For matching, there are both case ignore and exact rules. Both
1415 also require that "insignificant" spaces be ignored.
1416 spaces before the first non-space are ignored;
1417 spaces after the last non-space are ignored;
1418 spaces after a space are ignored.
1419 Note: by these rules (and as clarified in X.520), a string of only
1420 spaces is to be treated as if held one space, not empty (which
1421 would be a syntax error).
1424 In ASN.1, numeric string is just a string of digits and spaces
1425 and could be empty. However, in X.500, all attribute values of
1426 numeric string carry a non-empty constraint. For example:
1428 internationalISDNNumber ATTRIBUTE ::= {
1429 WITH SYNTAX InternationalISDNNumber
1430 EQUALITY MATCHING RULE numericStringMatch
1431 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1432 ID id-at-internationalISDNNumber }
1433 InternationalISDNNumber ::=
1434 NumericString (SIZE(1..ub-international-isdn-number))
1436 Unforunately, some assertion values are don't carry the same
1437 constraint (but its unclear how such an assertion could ever
1438 be true). In LDAP, there is one syntax (numericString) not two
1439 (numericString with constraint, numericString without constraint).
1440 This should be treated as numericString with non-empty constraint.
1441 Note that while someone may have no ISDN number, there are no ISDN
1442 numbers which are zero length.
1444 In matching, spaces are ignored.
1447 In ASN.1, Printable string is just a string of printable characters
1448 and can be empty. In X.500, semantics much like NumericString (see
1449 serialNumber for a like example) excepting uses insignificant space
1450 handling instead of ignore all spaces. They must be non-empty.
1453 Basically same as PrintableString. There are no examples in X.500,
1454 but same logic applies. Empty strings are allowed.
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(
3065 struct berval sn, sn2, i, ni;
3066 char sbuf[64], *stmp = sbuf;
3071 assert( in != NULL );
3072 assert( out != NULL );
3074 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3077 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3079 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3080 /* Parse old format */
3081 i.bv_val = ber_bvchr( in, '$' );
3082 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
3084 sn.bv_val = in->bv_val;
3085 sn.bv_len = i.bv_val - in->bv_val;
3088 i.bv_len = in->bv_len - (sn.bv_len + 1);
3090 /* eat leading zeros */
3091 for( n=0; n < (sn.bv_len-1); n++ ) {
3092 if( sn.bv_val[n] != '0' ) break;
3097 for( n=0; n < sn.bv_len; n++ ) {
3098 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3102 /* Parse GSER format */
3103 int havesn=0,haveissuer=0;
3104 struct berval x = *in;
3108 /* eat leading spaces */
3109 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3113 if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) {
3114 return LDAP_INVALID_SYNTAX;
3117 /* should be at issuer or serialNumber NamedValue */
3118 if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) {
3120 x.bv_val += STRLENOF("issuer");
3121 x.bv_len -= STRLENOF("issuer");
3123 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3124 x.bv_val++; x.bv_len--;
3126 /* eat leading spaces */
3127 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3131 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3132 x.bv_val++; x.bv_len--;
3134 i.bv_val = x.bv_val;
3137 for( ; i.bv_len < x.bv_len; ) {
3138 if ( i.bv_val[i.bv_len] != '"' ) {
3142 if ( i.bv_val[i.bv_len+1] == '"' ) {
3149 x.bv_val += i.bv_len+1;
3150 x.bv_len -= i.bv_len+1;
3152 if ( x.bv_len < STRLENOF(",serialNumber 0")) {
3153 return LDAP_INVALID_SYNTAX;
3158 } else if( strncasecmp( x.bv_val, "serialNumber",
3159 STRLENOF("serialNumber")) == 0 )
3161 /* parse serialNumber */
3163 x.bv_val += STRLENOF("serialNumber");
3164 x.bv_len -= STRLENOF("serialNumber");
3166 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3167 x.bv_val++; x.bv_len--;
3169 /* eat leading spaces */
3170 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3174 sn.bv_val = x.bv_val;
3177 if( sn.bv_val[0] == '-' ) {
3182 if ( sn.bv_val[0] == '0' && ( sn.bv_val[1] == 'x' ||
3183 sn.bv_val[1] == 'X' )) {
3185 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3186 if ( !ASCII_HEX( sn.bv_val[sn.bv_len] )) break;
3188 } else if ( sn.bv_val[0] == '\'' ) {
3189 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3190 if ( !ASCII_HEX( sn.bv_val[sn.bv_len] )) break;
3192 if ( sn.bv_val[sn.bv_len] == '\'' &&
3193 sn.bv_val[sn.bv_len+1] == 'H' )
3196 return LDAP_INVALID_SYNTAX;
3199 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3200 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3204 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3205 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3206 return LDAP_INVALID_SYNTAX;
3209 x.bv_val += sn.bv_len; x.bv_len -= sn.bv_len;
3211 if ( x.bv_len < STRLENOF( ",issuer \"\"" )) {
3212 return LDAP_INVALID_SYNTAX;
3217 } else return LDAP_INVALID_SYNTAX;
3219 if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
3220 x.bv_val++; x.bv_len--;
3223 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3227 /* should be at remaining NamedValue */
3228 if( !haveissuer && (strncasecmp( x.bv_val, "issuer",
3229 STRLENOF("issuer" )) == 0 ))
3232 x.bv_val += STRLENOF("issuer");
3233 x.bv_len -= STRLENOF("issuer");
3235 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3236 x.bv_val++; x.bv_len--;
3238 /* eat leading spaces */
3239 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3243 if( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3244 x.bv_val++; x.bv_len--;
3246 i.bv_val = x.bv_val;
3249 for( ; i.bv_len < x.bv_len; ) {
3250 if ( i.bv_val[i.bv_len] != '"' ) {
3254 if ( i.bv_val[i.bv_len+1] == '"' ) {
3261 x.bv_val += i.bv_len+1;
3262 x.bv_len -= i.bv_len+1;
3264 } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber",
3265 STRLENOF("serialNumber")) == 0 ))
3267 /* parse serialNumber */
3269 x.bv_val += STRLENOF("serialNumber");
3270 x.bv_len -= STRLENOF("serialNumber");
3272 if( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3273 x.bv_val++; x.bv_len--;
3275 /* eat leading spaces */
3276 for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) {
3280 sn.bv_val = x.bv_val;
3283 if( sn.bv_val[0] == '-' ) {
3288 if ( sn.bv_val[0] == '0' && ( sn.bv_val[1] == 'x' ||
3289 sn.bv_val[1] == 'X' )) {
3291 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3292 if ( !ASCII_HEX( sn.bv_val[sn.bv_len] )) break;
3294 } else if ( sn.bv_val[0] == '\'' ) {
3295 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3296 if ( !ASCII_HEX( sn.bv_val[sn.bv_len] )) break;
3298 if ( sn.bv_val[sn.bv_len] == '\'' &&
3299 sn.bv_val[sn.bv_len+1] == 'H' )
3302 return LDAP_INVALID_SYNTAX;
3305 for( ; sn.bv_len < x.bv_len; sn.bv_len++ ) {
3306 if ( !ASCII_DIGIT( sn.bv_val[sn.bv_len] )) break;
3310 if (!( sn.bv_len > neg )) return LDAP_INVALID_SYNTAX;
3311 if (( sn.bv_len > 1+neg ) && ( sn.bv_val[neg] == '0' )) {
3312 return LDAP_INVALID_SYNTAX;
3315 x.bv_val += sn.bv_len;
3316 x.bv_len -= sn.bv_len;
3318 } else return LDAP_INVALID_SYNTAX;
3320 /* eat trailing spaces */
3321 for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
3325 /* should have no characters left... */
3326 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
3328 ber_dupbv_x( &ni, &i, ctx );
3331 /* need to handle double dquotes here */
3334 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3336 if( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3337 slap_sl_free( i.bv_val, ctx );
3340 if( rc ) return LDAP_INVALID_SYNTAX;
3342 /* Convert sn to canonical hex */
3343 if ( sn.bv_len > sizeof( sbuf )) {
3344 stmp = slap_sl_malloc( sn.bv_len, ctx );
3347 sn2.bv_len = sn.bv_len;
3348 if ( lutil_str2bin( &sn, &sn2 )) {
3349 rc = LDAP_INVALID_SYNTAX;
3353 /* make room for sn + "$" */
3354 out->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3355 + ( sn2.bv_len * 2 + 3 ) + ni.bv_len;
3356 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3358 if( out->bv_val == NULL ) {
3360 slap_sl_free( ni.bv_val, ctx );
3366 AC_MEMCPY( &out->bv_val[n], "{ serialNumber ",
3367 STRLENOF( "{ serialNumber " ));
3368 n = STRLENOF( "{ serialNumber " );
3370 AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len );
3373 unsigned char *v = sn2.bv_val;
3374 out->bv_val[n++] = '\'';
3375 for ( j = 0; j < sn2.bv_len; j++ ) {
3376 sprintf( &out->bv_val[n], "%02x", v[j] );
3379 out->bv_val[n++] = '\'';
3380 out->bv_val[n++] = 'H';
3383 AC_MEMCPY( &out->bv_val[n], ", issuer \"", STRLENOF( ", issuer \"" ));
3384 n += STRLENOF( ", issuer \"" );
3386 AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len );
3389 AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" ));
3390 n += STRLENOF( "\" }" );
3392 out->bv_val[n] = '\0';
3394 assert( n == out->bv_len );
3396 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3397 out->bv_val, 0, 0 );
3401 slap_sl_free( stmp, ctx );
3402 slap_sl_free( ni.bv_val, ctx );
3408 certificateExactNormalize(
3413 struct berval *normalized,
3416 BerElementBuffer berbuf;
3417 BerElement *ber = (BerElement *)&berbuf;
3421 char serialbuf[64], *serial = serialbuf;
3422 ber_len_t seriallen;
3423 struct berval issuer_dn = BER_BVNULL, bvdn;
3425 int rc = LDAP_INVALID_SYNTAX;
3427 if( BER_BVISEMPTY( val ) ) goto done;
3429 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3430 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
3433 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3435 ber_init2( ber, val, LBER_USE_DER );
3436 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3437 tag = ber_skip_tag( ber, &len ); /* Sequence */
3438 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3439 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3440 tag = ber_skip_tag( ber, &len );
3441 tag = ber_get_int( ber, &i ); /* version */
3444 /* NOTE: move the test here from certificateValidate,
3445 * so that we can validate certs with serial longer
3446 * than sizeof(ber_int_t) */
3447 tag = ber_peek_tag( ber, &len ); /* serial */
3449 /* Use hex format. '123456789abcdef'H
3455 tag = ber_skip_tag( ber, &len );
3456 ptr = (unsigned char *)ber->ber_ptr;
3457 ber_skip_data( ber, len );
3459 /* Check for minimal encodings */
3460 if ( ptr[0] & 0x80 ) {
3461 if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ))
3462 return LDAP_INVALID_SYNTAX;
3463 } else if ( ptr[0] == 0 ) {
3464 if (!( ptr[1] & 0x80 ))
3465 return LDAP_INVALID_SYNTAX;
3470 seriallen = len * 2 + 4; /* quotes, H, NUL */
3471 if ( seriallen > sizeof( serialbuf ))
3472 serial = slap_sl_malloc( seriallen, ctx );
3475 for ( i = 0; i<len; i++ ) {
3476 sprintf( sptr, "%02x", sign ? 256 - ptr[i] : ptr[i] );
3483 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3484 ber_skip_data( ber, len );
3485 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3486 len = ber_ptrlen( ber );
3487 bvdn.bv_val = val->bv_val + len;
3488 bvdn.bv_len = val->bv_len - len;
3490 rc = dnX509normalize( &bvdn, &issuer_dn );
3491 if( rc != LDAP_SUCCESS ) goto done;
3493 normalized->bv_len = STRLENOF( "{ serialNumber , issuer \"\" }" )
3494 + seriallen + issuer_dn.bv_len;
3495 normalized->bv_val = ch_malloc(normalized->bv_len+1);
3497 p = (unsigned char *)normalized->bv_val;
3499 AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3500 p += STRLENOF( "{ serialNumber " );
3502 AC_MEMCPY(p, serial, seriallen);
3505 AC_MEMCPY(p, ", issuer \"", STRLENOF( ", issuer \"" ));
3506 p += STRLENOF( ", issuer \"" );
3508 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3509 p += issuer_dn.bv_len;
3511 AC_MEMCPY(p, "\" }", STRLENOF( "\" }" ));
3512 p += STRLENOF( "\" }" );
3516 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
3517 normalized->bv_val, NULL, NULL );
3522 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3523 if ( serial != serialbuf ) ber_memfree_x( serial, ctx );
3535 assert( in != NULL );
3536 assert( !BER_BVISNULL( in ) );
3538 for ( i = 0; i < in->bv_len; i++ ) {
3539 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3540 return LDAP_INVALID_SYNTAX;
3544 return LDAP_SUCCESS;
3547 /* Normalize a SID as used inside a CSN:
3548 * three-digit numeric string */
3555 struct berval *normalized,
3560 assert( val != NULL );
3561 assert( normalized != NULL );
3563 ber_dupbv_x( normalized, val, ctx );
3565 for ( i = 0; i < normalized->bv_len; i++ ) {
3566 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3567 ber_memfree_x( normalized->bv_val, ctx );
3568 BER_BVZERO( normalized );
3569 return LDAP_INVALID_SYNTAX;
3572 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3575 return LDAP_SUCCESS;
3583 assert( in != NULL );
3584 assert( !BER_BVISNULL( in ) );
3586 if ( in->bv_len != 3 ) {
3587 return LDAP_INVALID_SYNTAX;
3590 return hexValidate( NULL, in );
3593 /* Normalize a SID as used inside a CSN:
3594 * three-digit numeric string */
3601 struct berval *normalized,
3604 if ( val->bv_len != 3 ) {
3605 return LDAP_INVALID_SYNTAX;
3608 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3618 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3621 /* Normalize a SID as used inside a CSN, either as-is
3622 * (assertion value) or extracted from the CSN
3623 * (attribute value) */
3630 struct berval *normalized,
3638 if ( BER_BVISEMPTY( val ) ) {
3639 return LDAP_INVALID_SYNTAX;
3642 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3643 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3646 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3648 ptr = ber_bvchr( val, '#' );
3649 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3650 return LDAP_INVALID_SYNTAX;
3653 bv.bv_val = ptr + 1;
3654 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3656 ptr = ber_bvchr( &bv, '#' );
3657 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3658 return LDAP_INVALID_SYNTAX;
3661 bv.bv_val = ptr + 1;
3662 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3664 ptr = ber_bvchr( &bv, '#' );
3665 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3666 return LDAP_INVALID_SYNTAX;
3669 bv.bv_len = ptr - bv.bv_val;
3671 if ( bv.bv_len == 2 ) {
3672 /* OpenLDAP 2.3 SID */
3674 buf[ 1 ] = bv.bv_val[ 0 ];
3675 buf[ 2 ] = bv.bv_val[ 1 ];
3682 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3694 assert( in != NULL );
3695 assert( !BER_BVISNULL( in ) );
3697 if ( BER_BVISEMPTY( in ) ) {
3698 return LDAP_INVALID_SYNTAX;
3703 ptr = ber_bvchr( &bv, '#' );
3704 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3705 return LDAP_INVALID_SYNTAX;
3708 bv.bv_len = ptr - bv.bv_val;
3709 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3710 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3712 return LDAP_INVALID_SYNTAX;
3715 rc = generalizedTimeValidate( NULL, &bv );
3716 if ( rc != LDAP_SUCCESS ) {
3720 bv.bv_val = ptr + 1;
3721 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3723 ptr = ber_bvchr( &bv, '#' );
3724 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3725 return LDAP_INVALID_SYNTAX;
3728 bv.bv_len = ptr - bv.bv_val;
3729 if ( bv.bv_len != 6 ) {
3730 return LDAP_INVALID_SYNTAX;
3733 rc = hexValidate( NULL, &bv );
3734 if ( rc != LDAP_SUCCESS ) {
3738 bv.bv_val = ptr + 1;
3739 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3741 ptr = ber_bvchr( &bv, '#' );
3742 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3743 return LDAP_INVALID_SYNTAX;
3746 bv.bv_len = ptr - bv.bv_val;
3747 if ( bv.bv_len == 2 ) {
3748 /* tolerate old 2-digit replica-id */
3749 rc = hexValidate( NULL, &bv );
3752 rc = sidValidate( NULL, &bv );
3754 if ( rc != LDAP_SUCCESS ) {
3758 bv.bv_val = ptr + 1;
3759 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3761 if ( bv.bv_len != 6 ) {
3762 return LDAP_INVALID_SYNTAX;
3765 return hexValidate( NULL, &bv );
3768 /* Normalize a CSN in OpenLDAP 2.3 format */
3775 struct berval *normalized,
3778 struct berval gt, cnt, sid, mod;
3782 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3783 assert( !BER_BVISEMPTY( val ) );
3787 ptr = ber_bvchr( >, '#' );
3788 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3789 return LDAP_INVALID_SYNTAX;
3792 gt.bv_len = ptr - gt.bv_val;
3793 assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) );
3795 cnt.bv_val = ptr + 1;
3796 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3798 ptr = ber_bvchr( &cnt, '#' );
3799 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3800 return LDAP_INVALID_SYNTAX;
3803 cnt.bv_len = ptr - cnt.bv_val;
3804 assert( cnt.bv_len == STRLENOF( "000000" ) );
3806 sid.bv_val = ptr + 1;
3807 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3809 ptr = ber_bvchr( &sid, '#' );
3810 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3811 return LDAP_INVALID_SYNTAX;
3814 sid.bv_len = ptr - sid.bv_val;
3815 assert( sid.bv_len == STRLENOF( "00" ) );
3817 mod.bv_val = ptr + 1;
3818 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3819 assert( mod.bv_len == STRLENOF( "000000" ) );
3821 normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3822 normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
3824 ptr = normalized->bv_val;
3825 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3826 ptr = lutil_strcopy( ptr, ".000000Z#" );
3827 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3830 for ( i = 0; i < sid.bv_len; i++ ) {
3831 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3834 for ( i = 0; i < mod.bv_len; i++ ) {
3835 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3839 assert( ptr - normalized->bv_val == normalized->bv_len );
3841 return LDAP_SUCCESS;
3844 /* Normalize a CSN */
3851 struct berval *normalized,
3854 struct berval cnt, sid, mod;
3858 assert( val != NULL );
3859 assert( normalized != NULL );
3861 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3863 if ( BER_BVISEMPTY( val ) ) {
3864 return LDAP_INVALID_SYNTAX;
3867 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3868 /* Openldap <= 2.3 */
3870 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3873 assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) );
3875 ptr = ber_bvchr( val, '#' );
3876 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3877 return LDAP_INVALID_SYNTAX;
3880 assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) );
3882 cnt.bv_val = ptr + 1;
3883 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3885 ptr = ber_bvchr( &cnt, '#' );
3886 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3887 return LDAP_INVALID_SYNTAX;
3890 assert( ptr - cnt.bv_val == STRLENOF( "000000" ) );
3892 sid.bv_val = ptr + 1;
3893 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3895 ptr = ber_bvchr( &sid, '#' );
3896 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3897 return LDAP_INVALID_SYNTAX;
3900 sid.bv_len = ptr - sid.bv_val;
3901 assert( sid.bv_len == STRLENOF( "000" ) );
3903 mod.bv_val = ptr + 1;
3904 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3906 assert( mod.bv_len == STRLENOF( "000000" ) );
3908 ber_dupbv_x( normalized, val, ctx );
3910 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3911 i < normalized->bv_len; i++ )
3913 /* assume it's already validated that's all hex digits */
3914 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3917 return LDAP_SUCCESS;
3927 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3930 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3931 /* slight optimization - does not need the start parameter */
3932 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3937 check_time_syntax (struct berval *val,
3940 struct berval *fraction)
3943 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3944 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3945 * GeneralizedTime supports leap seconds, UTCTime does not.
3947 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3948 static const int mdays[2][12] = {
3949 /* non-leap years */
3950 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3952 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3955 int part, c, c1, c2, tzoffset, leapyear = 0;
3958 e = p + val->bv_len;
3960 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3961 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3963 for (part = start; part < 7 && p < e; part++) {
3965 if (!ASCII_DIGIT(c1)) {
3970 return LDAP_INVALID_SYNTAX;
3973 if (!ASCII_DIGIT(c)) {
3974 return LDAP_INVALID_SYNTAX;
3976 c += c1 * 10 - '0' * 11;
3977 if ((part | 1) == 3) {
3980 return LDAP_INVALID_SYNTAX;
3983 if (c >= ceiling[part]) {
3984 if (! (c == 60 && part == 6 && start == 0))
3985 return LDAP_INVALID_SYNTAX;
3989 if (part < 5 + start) {
3990 return LDAP_INVALID_SYNTAX;
3992 for (; part < 9; part++) {
3996 /* leapyear check for the Gregorian calendar (year>1581) */
3997 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
4001 if (parts[3] >= mdays[leapyear][parts[2]]) {
4002 return LDAP_INVALID_SYNTAX;
4006 fraction->bv_val = p;
4007 fraction->bv_len = 0;
4008 if (p < e && (*p == '.' || *p == ',')) {
4010 while (++p < e && ASCII_DIGIT(*p)) {
4013 if (p - fraction->bv_val == 1) {
4014 return LDAP_INVALID_SYNTAX;
4016 for (end_num = p; end_num[-1] == '0'; --end_num) {
4019 c = end_num - fraction->bv_val;
4020 if (c != 1) fraction->bv_len = c;
4026 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4032 return LDAP_INVALID_SYNTAX;
4038 for (part = 7; part < 9 && p < e; part++) {
4040 if (!ASCII_DIGIT(c1)) {
4045 return LDAP_INVALID_SYNTAX;
4048 if (!ASCII_DIGIT(c2)) {
4049 return LDAP_INVALID_SYNTAX;
4051 parts[part] = c1 * 10 + c2 - '0' * 11;
4052 if (parts[part] >= ceiling[part]) {
4053 return LDAP_INVALID_SYNTAX;
4056 if (part < 8 + start) {
4057 return LDAP_INVALID_SYNTAX;
4060 if (tzoffset == '-') {
4061 /* negative offset to UTC, ie west of Greenwich */
4062 parts[4] += parts[7];
4063 parts[5] += parts[8];
4064 /* offset is just hhmm, no seconds */
4065 for (part = 6; --part >= 0; ) {
4069 c = mdays[leapyear][parts[2]];
4071 if (parts[part] >= c) {
4073 return LDAP_INVALID_SYNTAX;
4078 } else if (part != 5) {
4083 /* positive offset to UTC, ie east of Greenwich */
4084 parts[4] -= parts[7];
4085 parts[5] -= parts[8];
4086 for (part = 6; --part >= 0; ) {
4087 if (parts[part] < 0) {
4089 return LDAP_INVALID_SYNTAX;
4094 /* make first arg to % non-negative */
4095 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4100 } else if (part != 5) {
4107 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4110 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4117 struct berval *normalized )
4121 rc = check_time_syntax(val, 1, parts, NULL);
4122 if (rc != LDAP_SUCCESS) {
4126 normalized->bv_val = ch_malloc( 14 );
4127 if ( normalized->bv_val == NULL ) {
4128 return LBER_ERROR_MEMORY;
4131 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4132 parts[1], parts[2] + 1, parts[3] + 1,
4133 parts[4], parts[5], parts[6] );
4134 normalized->bv_len = 13;
4136 return LDAP_SUCCESS;
4146 return check_time_syntax(in, 1, parts, NULL);
4149 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4152 generalizedTimeValidate(
4157 struct berval fraction;
4158 return check_time_syntax(in, 0, parts, &fraction);
4162 generalizedTimeNormalize(
4167 struct berval *normalized,
4172 struct berval fraction;
4174 rc = check_time_syntax(val, 0, parts, &fraction);
4175 if (rc != LDAP_SUCCESS) {
4179 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4180 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4181 if ( BER_BVISNULL( normalized ) ) {
4182 return LBER_ERROR_MEMORY;
4185 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4186 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4187 parts[4], parts[5], parts[6] );
4188 if ( !BER_BVISEMPTY( &fraction ) ) {
4189 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4190 fraction.bv_val, fraction.bv_len );
4191 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4193 strcpy( normalized->bv_val + len-1, "Z" );
4194 normalized->bv_len = len;
4196 return LDAP_SUCCESS;
4200 generalizedTimeOrderingMatch(
4205 struct berval *value,
4206 void *assertedValue )
4208 struct berval *asserted = (struct berval *) assertedValue;
4209 ber_len_t v_len = value->bv_len;
4210 ber_len_t av_len = asserted->bv_len;
4212 /* ignore trailing 'Z' when comparing */
4213 int match = memcmp( value->bv_val, asserted->bv_val,
4214 (v_len < av_len ? v_len : av_len) - 1 );
4215 if ( match == 0 ) match = v_len - av_len;
4218 return LDAP_SUCCESS;
4221 /* Index generation function */
4222 int generalizedTimeIndexer(
4227 struct berval *prefix,
4235 BerValue bvtmp; /* 40 bit index */
4237 struct lutil_timet tt;
4239 bvtmp.bv_len = sizeof(tmp);
4241 for( i=0; values[i].bv_val != NULL; i++ ) {
4242 /* just count them */
4245 /* we should have at least one value at this point */
4248 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4250 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4251 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4252 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4253 /* Use 40 bits of time for key */
4254 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4255 lutil_tm2time( &tm, &tt );
4256 tmp[0] = tt.tt_gsec & 0xff;
4257 tmp[4] = tt.tt_sec & 0xff;
4259 tmp[3] = tt.tt_sec & 0xff;
4261 tmp[2] = tt.tt_sec & 0xff;
4263 tmp[1] = tt.tt_sec & 0xff;
4265 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4269 keys[j].bv_val = NULL;
4274 return LDAP_SUCCESS;
4277 /* Index generation function */
4278 int generalizedTimeFilter(
4283 struct berval *prefix,
4284 void * assertedValue,
4290 BerValue bvtmp; /* 40 bit index */
4291 BerValue *value = (BerValue *) assertedValue;
4293 struct lutil_timet tt;
4295 bvtmp.bv_len = sizeof(tmp);
4297 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4298 /* Use 40 bits of time for key */
4299 if ( value->bv_val && value->bv_len >= 10 &&
4300 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4302 lutil_tm2time( &tm, &tt );
4303 tmp[0] = tt.tt_gsec & 0xff;
4304 tmp[4] = tt.tt_sec & 0xff;
4306 tmp[3] = tt.tt_sec & 0xff;
4308 tmp[2] = tt.tt_sec & 0xff;
4310 tmp[1] = tt.tt_sec & 0xff;
4312 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4313 ber_dupbv_x(keys, &bvtmp, ctx );
4314 keys[1].bv_val = NULL;
4322 return LDAP_SUCCESS;
4326 deliveryMethodValidate(
4328 struct berval *val )
4331 #define LENOF(s) (sizeof(s)-1)
4332 struct berval tmp = *val;
4334 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4335 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4336 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4339 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4341 switch( tmp.bv_val[0] ) {
4344 if(( tmp.bv_len >= LENOF("any") ) &&
4345 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4347 tmp.bv_len -= LENOF("any");
4348 tmp.bv_val += LENOF("any");
4351 return LDAP_INVALID_SYNTAX;
4355 if(( tmp.bv_len >= LENOF("mhs") ) &&
4356 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4358 tmp.bv_len -= LENOF("mhs");
4359 tmp.bv_val += LENOF("mhs");
4362 return LDAP_INVALID_SYNTAX;
4366 if(( tmp.bv_len >= LENOF("physical") ) &&
4367 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4369 tmp.bv_len -= LENOF("physical");
4370 tmp.bv_val += LENOF("physical");
4373 return LDAP_INVALID_SYNTAX;
4376 case 'T': /* telex or teletex or telephone */
4377 if(( tmp.bv_len >= LENOF("telex") ) &&
4378 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4380 tmp.bv_len -= LENOF("telex");
4381 tmp.bv_val += LENOF("telex");
4384 if(( tmp.bv_len >= LENOF("teletex") ) &&
4385 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4387 tmp.bv_len -= LENOF("teletex");
4388 tmp.bv_val += LENOF("teletex");
4391 if(( tmp.bv_len >= LENOF("telephone") ) &&
4392 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4394 tmp.bv_len -= LENOF("telephone");
4395 tmp.bv_val += LENOF("telephone");
4398 return LDAP_INVALID_SYNTAX;
4401 case 'G': /* g3fax or g4fax */
4402 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4403 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4404 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4406 tmp.bv_len -= LENOF("g3fax");
4407 tmp.bv_val += LENOF("g3fax");
4410 return LDAP_INVALID_SYNTAX;
4414 if(( tmp.bv_len >= LENOF("ia5") ) &&
4415 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4417 tmp.bv_len -= LENOF("ia5");
4418 tmp.bv_val += LENOF("ia5");
4421 return LDAP_INVALID_SYNTAX;
4425 if(( tmp.bv_len >= LENOF("videotex") ) &&
4426 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4428 tmp.bv_len -= LENOF("videotex");
4429 tmp.bv_val += LENOF("videotex");
4432 return LDAP_INVALID_SYNTAX;
4435 return LDAP_INVALID_SYNTAX;
4438 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4440 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4444 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4448 return LDAP_INVALID_SYNTAX;
4450 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4459 nisNetgroupTripleValidate(
4461 struct berval *val )
4466 if ( BER_BVISEMPTY( val ) ) {
4467 return LDAP_INVALID_SYNTAX;
4470 p = (char *)val->bv_val;
4471 e = p + val->bv_len;
4473 if ( *p != '(' /*')'*/ ) {
4474 return LDAP_INVALID_SYNTAX;
4477 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4481 return LDAP_INVALID_SYNTAX;
4484 } else if ( !AD_CHAR( *p ) ) {
4485 return LDAP_INVALID_SYNTAX;
4489 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4490 return LDAP_INVALID_SYNTAX;
4496 return LDAP_INVALID_SYNTAX;
4499 return LDAP_SUCCESS;
4503 bootParameterValidate(
4505 struct berval *val )
4509 if ( BER_BVISEMPTY( val ) ) {
4510 return LDAP_INVALID_SYNTAX;
4513 p = (char *)val->bv_val;
4514 e = p + val->bv_len;
4517 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4518 if ( !AD_CHAR( *p ) ) {
4519 return LDAP_INVALID_SYNTAX;
4524 return LDAP_INVALID_SYNTAX;
4528 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4529 if ( !AD_CHAR( *p ) ) {
4530 return LDAP_INVALID_SYNTAX;
4535 return LDAP_INVALID_SYNTAX;
4539 for ( p++; p < e; p++ ) {
4540 if ( !SLAP_PRINTABLE( *p ) ) {
4541 return LDAP_INVALID_SYNTAX;
4545 return LDAP_SUCCESS;
4549 firstComponentNormalize(
4554 struct berval *normalized,
4561 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4562 ber_dupbv_x( normalized, val, ctx );
4563 return LDAP_SUCCESS;
4566 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4568 if( val->bv_val[0] != '(' /*')'*/ &&
4569 val->bv_val[0] != '{' /*'}'*/ )
4571 return LDAP_INVALID_SYNTAX;
4574 /* trim leading white space */
4576 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4582 /* grab next word */
4583 comp.bv_val = &val->bv_val[len];
4584 len = val->bv_len - len;
4585 for( comp.bv_len = 0;
4586 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4592 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4593 rc = numericoidValidate( NULL, &comp );
4594 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4595 rc = integerValidate( NULL, &comp );
4597 rc = LDAP_INVALID_SYNTAX;
4601 if( rc == LDAP_SUCCESS ) {
4602 ber_dupbv_x( normalized, &comp, ctx );
4608 static char *country_gen_syn[] = {
4609 "1.3.6.1.4.1.1466.115.121.1.15",
4610 "1.3.6.1.4.1.1466.115.121.1.26",
4611 "1.3.6.1.4.1.1466.115.121.1.44",
4615 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4616 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4618 static slap_syntax_defs_rec syntax_defs[] = {
4619 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4620 X_BINARY X_NOT_H_R ")",
4621 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4622 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4623 0, NULL, NULL, NULL},
4624 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4625 0, NULL, NULL, NULL},
4626 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4628 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4629 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4631 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4632 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4633 0, NULL, bitStringValidate, NULL },
4634 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4635 0, NULL, booleanValidate, NULL},
4636 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4637 X_BINARY X_NOT_H_R ")",
4638 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4639 NULL, certificateValidate, NULL},
4640 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4641 X_BINARY X_NOT_H_R ")",
4642 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4643 NULL, certificateListValidate, NULL},
4644 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4645 X_BINARY X_NOT_H_R ")",
4646 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4647 NULL, sequenceValidate, NULL},
4648 #if 0 /* need to go __after__ printableString */
4649 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4650 0, "1.3.6.1.4.1.1466.115.121.1.44",
4651 countryStringValidate, NULL},
4653 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4654 0, NULL, dnValidate, dnPretty},
4655 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4656 0, NULL, rdnValidate, rdnPretty},
4657 #ifdef LDAP_COMP_MATCH
4658 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4659 0, NULL, allComponentsValidate, NULL},
4660 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4661 0, NULL, componentFilterValidate, NULL},
4663 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4664 0, NULL, NULL, NULL},
4665 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4666 0, NULL, deliveryMethodValidate, NULL},
4667 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4668 0, NULL, UTF8StringValidate, NULL},
4669 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4670 0, NULL, NULL, NULL},
4671 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4672 0, NULL, NULL, NULL},
4673 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4674 0, NULL, NULL, NULL},
4675 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4676 0, NULL, NULL, NULL},
4677 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4678 0, NULL, NULL, NULL},
4679 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4680 0, NULL, printablesStringValidate, NULL},
4681 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4682 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4683 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4684 0, NULL, generalizedTimeValidate, NULL},
4685 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4686 0, NULL, NULL, NULL},
4687 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4688 0, NULL, IA5StringValidate, NULL},
4689 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4690 0, NULL, integerValidate, NULL},
4691 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4692 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4693 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4694 0, NULL, NULL, NULL},
4695 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4696 0, NULL, NULL, NULL},
4697 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4698 0, NULL, NULL, NULL},
4699 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4700 0, NULL, NULL, NULL},
4701 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4702 0, NULL, NULL, NULL},
4703 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4704 0, NULL, nameUIDValidate, nameUIDPretty },
4705 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4706 0, NULL, NULL, NULL},
4707 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4708 0, NULL, numericStringValidate, NULL},
4709 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4710 0, NULL, NULL, NULL},
4711 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4712 0, NULL, numericoidValidate, NULL},
4713 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4714 0, NULL, IA5StringValidate, NULL},
4715 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4716 0, NULL, blobValidate, NULL},
4717 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4718 0, NULL, UTF8StringValidate, NULL},
4719 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4720 0, NULL, NULL, NULL},
4721 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4722 0, NULL, NULL, NULL},
4723 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4724 0, NULL, printableStringValidate, NULL},
4725 /* moved here because now depends on Directory String, IA5 String
4726 * and Printable String */
4727 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4728 0, country_gen_syn, countryStringValidate, NULL},
4729 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4730 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4731 0, NULL, subtreeSpecificationValidate, NULL},
4732 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4733 X_BINARY X_NOT_H_R ")",
4734 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4735 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4736 0, NULL, printableStringValidate, NULL},
4737 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4738 0, NULL, NULL, NULL},
4739 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4740 0, NULL, printablesStringValidate, NULL},
4741 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4742 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4743 0, NULL, utcTimeValidate, NULL},
4745 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4746 0, NULL, NULL, NULL},
4747 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4748 0, NULL, NULL, NULL},
4749 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4750 0, NULL, NULL, NULL},
4751 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4752 0, NULL, NULL, NULL},
4753 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4754 0, NULL, NULL, NULL},
4756 /* RFC 2307 NIS Syntaxes */
4757 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4758 0, NULL, nisNetgroupTripleValidate, NULL},
4759 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4760 0, NULL, bootParameterValidate, NULL},
4762 /* draft-zeilenga-ldap-x509 */
4763 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4764 SLAP_SYNTAX_HIDE, NULL,
4765 serialNumberAndIssuerValidate,
4766 serialNumberAndIssuerPretty},
4767 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4768 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4769 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4770 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4771 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4772 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4773 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4774 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4775 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4776 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4777 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4778 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4780 #ifdef SLAPD_AUTHPASSWD
4781 /* needs updating */
4782 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4783 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4786 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4787 0, NULL, UUIDValidate, UUIDPretty},
4789 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4790 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4792 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4793 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4795 /* OpenLDAP Void Syntax */
4796 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4797 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4799 /* FIXME: OID is unused, but not registered yet */
4800 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4801 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4803 {NULL, 0, NULL, NULL, NULL}
4806 char *csnSIDMatchSyntaxes[] = {
4807 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4810 char *certificateExactMatchSyntaxes[] = {
4811 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4814 #ifdef LDAP_COMP_MATCH
4815 char *componentFilterMatchSyntaxes[] = {
4816 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4820 char *directoryStringSyntaxes[] = {
4821 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4824 char *integerFirstComponentMatchSyntaxes[] = {
4825 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4826 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4829 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4830 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4831 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4832 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4833 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4834 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4835 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4836 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4837 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4842 * Other matching rules in X.520 that we do not use (yet):
4844 * 2.5.13.25 uTCTimeMatch
4845 * 2.5.13.26 uTCTimeOrderingMatch
4846 * 2.5.13.31* directoryStringFirstComponentMatch
4847 * 2.5.13.32* wordMatch
4848 * 2.5.13.33* keywordMatch
4849 * 2.5.13.36+ certificatePairExactMatch
4850 * 2.5.13.37+ certificatePairMatch
4851 * 2.5.13.38+ certificateListExactMatch
4852 * 2.5.13.39+ certificateListMatch
4853 * 2.5.13.40+ algorithmIdentifierMatch
4854 * 2.5.13.41* storedPrefixMatch
4855 * 2.5.13.42 attributeCertificateMatch
4856 * 2.5.13.43 readerAndKeyIDMatch
4857 * 2.5.13.44 attributeIntegrityMatch
4859 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4860 * (+) described in draft-zeilenga-ldap-x509
4862 static slap_mrule_defs_rec mrule_defs[] = {
4864 * EQUALITY matching rules must be listed after associated APPROX
4865 * matching rules. So, we list all APPROX matching rules first.
4867 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4868 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4869 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4870 NULL, NULL, directoryStringApproxMatch,
4871 directoryStringApproxIndexer, directoryStringApproxFilter,
4874 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4876 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4877 NULL, NULL, IA5StringApproxMatch,
4878 IA5StringApproxIndexer, IA5StringApproxFilter,
4882 * Other matching rules
4885 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4886 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4887 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4888 NULL, NULL, octetStringMatch,
4889 octetStringIndexer, octetStringFilter,
4892 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4893 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4894 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4895 NULL, dnNormalize, dnMatch,
4896 octetStringIndexer, octetStringFilter,
4899 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4900 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4901 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4902 NULL, dnNormalize, dnRelativeMatch,
4906 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4907 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4908 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4909 NULL, dnNormalize, dnRelativeMatch,
4913 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4915 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4916 NULL, dnNormalize, dnRelativeMatch,
4920 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4922 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4923 NULL, dnNormalize, dnRelativeMatch,
4927 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4928 "SYNTAX 1.2.36.79672281.1.5.0 )",
4929 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4930 NULL, rdnNormalize, rdnMatch,
4931 octetStringIndexer, octetStringFilter,
4934 #ifdef LDAP_COMP_MATCH
4935 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4936 "SYNTAX 1.2.36.79672281.1.5.2 )",
4937 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4938 NULL, NULL , componentFilterMatch,
4939 octetStringIndexer, octetStringFilter,
4942 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4943 "SYNTAX 1.2.36.79672281.1.5.3 )",
4944 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4945 NULL, NULL , allComponentsMatch,
4946 octetStringIndexer, octetStringFilter,
4949 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4950 "SYNTAX 1.2.36.79672281.1.5.3 )",
4951 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4952 NULL, NULL , directoryComponentsMatch,
4953 octetStringIndexer, octetStringFilter,
4957 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4958 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4959 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4960 NULL, UTF8StringNormalize, octetStringMatch,
4961 octetStringIndexer, octetStringFilter,
4962 directoryStringApproxMatchOID },
4964 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4965 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4966 SLAP_MR_ORDERING, directoryStringSyntaxes,
4967 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4969 "caseIgnoreMatch" },
4971 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4973 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4974 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4975 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4976 "caseIgnoreMatch" },
4978 {"( 2.5.13.5 NAME 'caseExactMatch' "
4979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4980 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4981 NULL, UTF8StringNormalize, octetStringMatch,
4982 octetStringIndexer, octetStringFilter,
4983 directoryStringApproxMatchOID },
4985 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4987 SLAP_MR_ORDERING, directoryStringSyntaxes,
4988 NULL, UTF8StringNormalize, octetStringOrderingMatch,
4992 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4994 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4995 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
4996 octetStringSubstringsIndexer, octetStringSubstringsFilter,
4999 {"( 2.5.13.8 NAME 'numericStringMatch' "
5000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5001 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5002 NULL, numericStringNormalize, octetStringMatch,
5003 octetStringIndexer, octetStringFilter,
5006 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
5007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5008 SLAP_MR_ORDERING, NULL,
5009 NULL, numericStringNormalize, octetStringOrderingMatch,
5011 "numericStringMatch" },
5013 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
5014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5015 SLAP_MR_SUBSTR, NULL,
5016 NULL, numericStringNormalize, octetStringSubstringsMatch,
5017 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5018 "numericStringMatch" },
5020 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
5021 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
5022 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5023 NULL, NULL, NULL, NULL, NULL, NULL },
5025 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
5026 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5027 SLAP_MR_SUBSTR, NULL,
5028 NULL, NULL, NULL, NULL, NULL,
5029 "caseIgnoreListMatch" },
5031 {"( 2.5.13.13 NAME 'booleanMatch' "
5032 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
5033 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5034 NULL, NULL, booleanMatch,
5035 octetStringIndexer, octetStringFilter,
5038 {"( 2.5.13.14 NAME 'integerMatch' "
5039 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5040 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5041 NULL, NULL, integerMatch,
5042 octetStringIndexer, octetStringFilter,
5045 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
5046 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5047 SLAP_MR_ORDERING, NULL,
5048 NULL, NULL, integerMatch,
5052 {"( 2.5.13.16 NAME 'bitStringMatch' "
5053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5054 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5055 NULL, NULL, octetStringMatch,
5056 octetStringIndexer, octetStringFilter,
5059 {"( 2.5.13.17 NAME 'octetStringMatch' "
5060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5061 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5062 NULL, NULL, octetStringMatch,
5063 octetStringIndexer, octetStringFilter,
5066 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5068 SLAP_MR_ORDERING, NULL,
5069 NULL, NULL, octetStringOrderingMatch,
5071 "octetStringMatch" },
5073 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5074 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5075 SLAP_MR_SUBSTR, NULL,
5076 NULL, NULL, octetStringSubstringsMatch,
5077 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5078 "octetStringMatch" },
5080 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5081 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5082 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5084 telephoneNumberNormalize, octetStringMatch,
5085 octetStringIndexer, octetStringFilter,
5088 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5089 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5090 SLAP_MR_SUBSTR, NULL,
5091 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5092 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5093 "telephoneNumberMatch" },
5095 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5096 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5097 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5098 NULL, NULL, NULL, NULL, NULL, NULL },
5100 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5101 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5102 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5103 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5104 uniqueMemberIndexer, uniqueMemberFilter,
5107 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5108 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5109 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5110 NULL, NULL, NULL, NULL, NULL, NULL },
5112 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5113 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5114 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5115 NULL, generalizedTimeNormalize, octetStringMatch,
5116 generalizedTimeIndexer, generalizedTimeFilter,
5119 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5120 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5121 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5122 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5124 "generalizedTimeMatch" },
5126 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5127 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5128 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5129 integerFirstComponentMatchSyntaxes,
5130 NULL, firstComponentNormalize, integerMatch,
5131 octetStringIndexer, octetStringFilter,
5134 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5135 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5136 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5137 objectIdentifierFirstComponentMatchSyntaxes,
5138 NULL, firstComponentNormalize, octetStringMatch,
5139 octetStringIndexer, octetStringFilter,
5142 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5143 "SYNTAX 1.3.6.1.1.15.1 )",
5144 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5145 NULL, certificateExactNormalize, octetStringMatch,
5146 octetStringIndexer, octetStringFilter,
5149 {"( 2.5.13.35 NAME 'certificateMatch' "
5150 "SYNTAX 1.3.6.1.1.15.2 )",
5151 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5152 NULL, NULL, NULL, NULL, NULL,
5155 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5156 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5157 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5158 NULL, IA5StringNormalize, octetStringMatch,
5159 octetStringIndexer, octetStringFilter,
5160 IA5StringApproxMatchOID },
5162 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5163 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5164 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5165 NULL, IA5StringNormalize, octetStringMatch,
5166 octetStringIndexer, octetStringFilter,
5167 IA5StringApproxMatchOID },
5169 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5170 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5171 SLAP_MR_SUBSTR, NULL,
5172 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5173 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5174 "caseIgnoreIA5Match" },
5176 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5177 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5178 SLAP_MR_SUBSTR, NULL,
5179 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5180 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5181 "caseExactIA5Match" },
5183 #ifdef SLAPD_AUTHPASSWD
5184 /* needs updating */
5185 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5186 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5187 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5188 NULL, NULL, authPasswordMatch,
5193 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5194 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5196 NULL, NULL, integerBitAndMatch,
5200 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5201 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5203 NULL, NULL, integerBitOrMatch,
5207 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5208 "SYNTAX 1.3.6.1.1.16.1 )",
5209 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5210 NULL, UUIDNormalize, octetStringMatch,
5211 octetStringIndexer, octetStringFilter,
5214 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5215 "SYNTAX 1.3.6.1.1.16.1 )",
5216 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5217 NULL, UUIDNormalize, octetStringOrderingMatch,
5218 octetStringIndexer, octetStringFilter,
5221 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5222 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5223 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5224 NULL, csnNormalize, csnMatch,
5225 csnIndexer, csnFilter,
5228 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5229 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5230 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5231 NULL, NULL, csnOrderingMatch,
5235 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5236 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5237 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5238 NULL, csnSidNormalize, octetStringMatch,
5239 octetStringIndexer, octetStringFilter,
5242 /* FIXME: OID is unused, but not registered yet */
5243 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5244 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5245 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5246 NULL, authzNormalize, authzMatch,
5250 {NULL, SLAP_MR_NONE, NULL,
5251 NULL, NULL, NULL, NULL, NULL,
5256 slap_schema_init( void )
5261 /* we should only be called once (from main) */
5262 assert( schema_init_done == 0 );
5264 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5265 res = register_syntax( &syntax_defs[i] );
5268 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5269 syntax_defs[i].sd_desc );
5274 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5275 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5276 mrule_defs[i].mrd_compat_syntaxes == NULL )
5279 "slap_schema_init: Ignoring unusable matching rule %s\n",
5280 mrule_defs[i].mrd_desc );
5284 res = register_matching_rule( &mrule_defs[i] );
5288 "slap_schema_init: Error registering matching rule %s\n",
5289 mrule_defs[i].mrd_desc );
5294 res = slap_schema_load();
5295 schema_init_done = 1;
5300 schema_destroy( void )
5309 if( schema_init_done ) {
5310 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5311 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );