1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
61 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
62 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
63 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
65 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
66 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
67 SLAP_INDEX_INTLEN_DEFAULT );
69 ldap_pvt_thread_mutex_t ad_undef_mutex;
70 ldap_pvt_thread_mutex_t oc_undef_mutex;
73 generalizedTimeValidate(
82 /* no value allowed */
83 return LDAP_INVALID_SYNTAX;
91 /* any value allowed */
95 #define berValidate blobValidate
102 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
103 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
108 /* X.509 related stuff */
117 SLAP_TAG_UTCTIME = 0x17U,
118 SLAP_TAG_GENERALIZEDTIME = 0x18U
122 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
125 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
126 SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1,
127 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2,
128 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
132 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
135 /* X.509 certificate validation */
137 certificateValidate( Syntax *syntax, struct berval *in )
139 BerElementBuffer berbuf;
140 BerElement *ber = (BerElement *)&berbuf;
143 ber_int_t version = SLAP_X509_V1;
145 ber_init2( ber, in, LBER_USE_DER );
146 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
147 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
148 tag = ber_skip_tag( ber, &len ); /* Sequence */
149 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
150 tag = ber_peek_tag( ber, &len );
151 /* Optional version */
152 if ( tag == SLAP_X509_OPT_C_VERSION ) {
153 tag = ber_skip_tag( ber, &len );
154 tag = ber_get_int( ber, &version );
155 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
157 /* NOTE: don't try to parse Serial, because it might be longer
158 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
159 tag = ber_skip_tag( ber, &len ); /* Serial */
160 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
161 ber_skip_data( ber, len );
162 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
163 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
164 ber_skip_data( ber, len );
165 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
166 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
167 ber_skip_data( ber, len );
168 tag = ber_skip_tag( ber, &len ); /* Validity */
169 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
170 ber_skip_data( ber, len );
171 tag = ber_skip_tag( ber, &len ); /* Subject DN */
172 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
173 ber_skip_data( ber, len );
174 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
175 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
176 ber_skip_data( ber, len );
177 tag = ber_skip_tag( ber, &len );
178 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
179 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
180 ber_skip_data( ber, len );
181 tag = ber_skip_tag( ber, &len );
183 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
184 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
185 ber_skip_data( ber, len );
186 tag = ber_skip_tag( ber, &len );
188 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
189 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
190 tag = ber_skip_tag( ber, &len );
191 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
192 ber_skip_data( ber, len );
193 tag = ber_skip_tag( ber, &len );
195 /* signatureAlgorithm */
196 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
197 ber_skip_data( ber, len );
198 tag = ber_skip_tag( ber, &len );
200 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
201 ber_skip_data( ber, len );
202 tag = ber_skip_tag( ber, &len );
203 /* Must be at end now */
204 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
208 /* X.509 certificate list validation */
210 certificateListValidate( Syntax *syntax, struct berval *in )
212 BerElementBuffer berbuf;
213 BerElement *ber = (BerElement *)&berbuf;
216 ber_int_t version = SLAP_X509_V1;
218 ber_init2( ber, in, LBER_USE_DER );
219 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
220 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
221 tag = ber_skip_tag( ber, &len ); /* Sequence */
222 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
223 tag = ber_peek_tag( ber, &len );
224 /* Optional version */
225 if ( tag == LBER_INTEGER ) {
226 tag = ber_get_int( ber, &version );
227 assert( tag == LBER_INTEGER );
228 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
230 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
231 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
232 ber_skip_data( ber, len );
233 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
234 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
235 ber_skip_data( ber, len );
236 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
237 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
238 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
239 ber_skip_data( ber, len );
240 /* Optional nextUpdate */
241 tag = ber_skip_tag( ber, &len );
242 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
243 ber_skip_data( ber, len );
244 tag = ber_skip_tag( ber, &len );
246 /* revokedCertificates - Sequence of Sequence, Optional */
247 if ( tag == LBER_SEQUENCE ) {
249 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
250 /* Should NOT be empty */
251 ber_skip_data( ber, len );
252 tag = ber_skip_tag( ber, &len );
255 /* Optional Extensions */
256 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
257 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
258 tag = ber_skip_tag( ber, &len );
259 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
260 ber_skip_data( ber, len );
261 tag = ber_skip_tag( ber, &len );
263 /* signatureAlgorithm */
264 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
265 ber_skip_data( ber, len );
266 tag = ber_skip_tag( ber, &len );
268 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
269 ber_skip_data( ber, len );
270 tag = ber_skip_tag( ber, &len );
271 /* Must be at end now */
272 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
282 struct berval *value,
283 void *assertedValue )
285 struct berval *asserted = (struct berval *) assertedValue;
286 int match = value->bv_len - asserted->bv_len;
289 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
297 octetStringOrderingMatch(
302 struct berval *value,
303 void *assertedValue )
305 struct berval *asserted = (struct berval *) assertedValue;
306 ber_len_t v_len = value->bv_len;
307 ber_len_t av_len = asserted->bv_len;
309 int match = memcmp( value->bv_val, asserted->bv_val,
310 (v_len < av_len ? v_len : av_len) );
312 if( match == 0 ) match = v_len - av_len;
320 HASH_CONTEXT *HASHcontext,
321 struct berval *prefix,
326 HASH_Init(HASHcontext);
327 if(prefix && prefix->bv_len > 0) {
328 HASH_Update(HASHcontext,
329 (unsigned char *)prefix->bv_val, prefix->bv_len);
331 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
332 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
333 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
339 HASH_CONTEXT *HASHcontext,
340 unsigned char *HASHdigest,
341 unsigned char *value,
344 HASH_CONTEXT ctx = *HASHcontext;
345 HASH_Update( &ctx, value, len );
346 HASH_Final( HASHdigest, &ctx );
349 /* Index generation function */
350 int octetStringIndexer(
355 struct berval *prefix,
363 HASH_CONTEXT HASHcontext;
364 unsigned char HASHdigest[HASH_BYTES];
365 struct berval digest;
366 digest.bv_val = (char *)HASHdigest;
367 digest.bv_len = sizeof(HASHdigest);
369 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
370 /* just count them */
373 /* we should have at least one value at this point */
376 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
378 slen = syntax->ssyn_oidlen;
379 mlen = mr->smr_oidlen;
381 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
382 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
383 hashIter( &HASHcontext, HASHdigest,
384 (unsigned char *)values[i].bv_val, values[i].bv_len );
385 ber_dupbv_x( &keys[i], &digest, ctx );
388 BER_BVZERO( &keys[i] );
395 /* Index generation function */
396 int octetStringFilter(
401 struct berval *prefix,
402 void * assertedValue,
408 HASH_CONTEXT HASHcontext;
409 unsigned char HASHdigest[HASH_BYTES];
410 struct berval *value = (struct berval *) assertedValue;
411 struct berval digest;
412 digest.bv_val = (char *)HASHdigest;
413 digest.bv_len = sizeof(HASHdigest);
415 slen = syntax->ssyn_oidlen;
416 mlen = mr->smr_oidlen;
418 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
420 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
421 hashIter( &HASHcontext, HASHdigest,
422 (unsigned char *)value->bv_val, value->bv_len );
424 ber_dupbv_x( keys, &digest, ctx );
425 BER_BVZERO( &keys[1] );
433 octetStringSubstringsMatch(
438 struct berval *value,
439 void *assertedValue )
442 SubstringsAssertion *sub = assertedValue;
443 struct berval left = *value;
447 /* Add up asserted input length */
448 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
449 inlen += sub->sa_initial.bv_len;
452 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
453 inlen += sub->sa_any[i].bv_len;
456 if ( !BER_BVISNULL( &sub->sa_final ) ) {
457 inlen += sub->sa_final.bv_len;
460 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
461 if ( inlen > left.bv_len ) {
466 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
467 sub->sa_initial.bv_len );
473 left.bv_val += sub->sa_initial.bv_len;
474 left.bv_len -= sub->sa_initial.bv_len;
475 inlen -= sub->sa_initial.bv_len;
478 if ( !BER_BVISNULL( &sub->sa_final ) ) {
479 if ( inlen > left.bv_len ) {
484 match = memcmp( sub->sa_final.bv_val,
485 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
486 sub->sa_final.bv_len );
492 left.bv_len -= sub->sa_final.bv_len;
493 inlen -= sub->sa_final.bv_len;
497 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
502 if ( inlen > left.bv_len ) {
503 /* not enough length */
508 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
512 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
519 idx = p - left.bv_val;
521 if ( idx >= left.bv_len ) {
522 /* this shouldn't happen */
529 if ( sub->sa_any[i].bv_len > left.bv_len ) {
530 /* not enough left */
535 match = memcmp( left.bv_val,
536 sub->sa_any[i].bv_val,
537 sub->sa_any[i].bv_len );
545 left.bv_val += sub->sa_any[i].bv_len;
546 left.bv_len -= sub->sa_any[i].bv_len;
547 inlen -= sub->sa_any[i].bv_len;
556 /* Substrings Index generation function */
558 octetStringSubstringsIndexer(
563 struct berval *prefix,
572 HASH_CONTEXT HCany, HCini, HCfin;
573 unsigned char HASHdigest[HASH_BYTES];
574 struct berval digest;
575 digest.bv_val = (char *)HASHdigest;
576 digest.bv_len = sizeof(HASHdigest);
580 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
581 /* count number of indices to generate */
582 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
583 if( values[i].bv_len >= index_substr_if_maxlen ) {
584 nkeys += index_substr_if_maxlen -
585 (index_substr_if_minlen - 1);
586 } else if( values[i].bv_len >= index_substr_if_minlen ) {
587 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
591 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
592 if( values[i].bv_len >= index_substr_any_len ) {
593 nkeys += values[i].bv_len - (index_substr_any_len - 1);
597 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
598 if( values[i].bv_len >= index_substr_if_maxlen ) {
599 nkeys += index_substr_if_maxlen -
600 (index_substr_if_minlen - 1);
601 } else if( values[i].bv_len >= index_substr_if_minlen ) {
602 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
608 /* no keys to generate */
613 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
615 slen = syntax->ssyn_oidlen;
616 mlen = mr->smr_oidlen;
618 if ( flags & SLAP_INDEX_SUBSTR_ANY )
619 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
620 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
621 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
622 if( flags & SLAP_INDEX_SUBSTR_FINAL )
623 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
626 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
629 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
630 ( values[i].bv_len >= index_substr_any_len ) )
632 max = values[i].bv_len - (index_substr_any_len - 1);
634 for( j=0; j<max; j++ ) {
635 hashIter( &HCany, HASHdigest,
636 (unsigned char *)&values[i].bv_val[j],
637 index_substr_any_len );
638 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
642 /* skip if too short */
643 if( values[i].bv_len < index_substr_if_minlen ) continue;
645 max = index_substr_if_maxlen < values[i].bv_len
646 ? index_substr_if_maxlen : values[i].bv_len;
648 for( j=index_substr_if_minlen; j<=max; j++ ) {
650 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
651 hashIter( &HCini, HASHdigest,
652 (unsigned char *)values[i].bv_val, j );
653 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
656 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
657 hashIter( &HCfin, HASHdigest,
658 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
659 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
666 BER_BVZERO( &keys[nkeys] );
677 octetStringSubstringsFilter (
682 struct berval *prefix,
683 void * assertedValue,
687 SubstringsAssertion *sa;
690 size_t slen, mlen, klen;
692 HASH_CONTEXT HASHcontext;
693 unsigned char HASHdigest[HASH_BYTES];
694 struct berval *value;
695 struct berval digest;
697 sa = (SubstringsAssertion *) assertedValue;
699 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
700 !BER_BVISNULL( &sa->sa_initial ) &&
701 sa->sa_initial.bv_len >= index_substr_if_minlen )
704 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
705 ( flags & SLAP_INDEX_SUBSTR_ANY ))
707 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
711 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
713 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
714 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
715 /* don't bother accounting with stepping */
716 nkeys += sa->sa_any[i].bv_len -
717 ( index_substr_any_len - 1 );
722 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
723 !BER_BVISNULL( &sa->sa_final ) &&
724 sa->sa_final.bv_len >= index_substr_if_minlen )
727 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
728 ( flags & SLAP_INDEX_SUBSTR_ANY ))
730 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
739 digest.bv_val = (char *)HASHdigest;
740 digest.bv_len = sizeof(HASHdigest);
742 slen = syntax->ssyn_oidlen;
743 mlen = mr->smr_oidlen;
745 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
748 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
749 !BER_BVISNULL( &sa->sa_initial ) &&
750 sa->sa_initial.bv_len >= index_substr_if_minlen )
752 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
753 value = &sa->sa_initial;
755 klen = index_substr_if_maxlen < value->bv_len
756 ? index_substr_if_maxlen : value->bv_len;
758 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
759 hashIter( &HASHcontext, HASHdigest,
760 (unsigned char *)value->bv_val, klen );
761 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
763 /* If initial is too long and we have subany indexed, use it
764 * to match the excess...
766 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
769 pre = SLAP_INDEX_SUBSTR_PREFIX;
770 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
771 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
773 hashIter( &HASHcontext, HASHdigest,
774 (unsigned char *)&value->bv_val[j], index_substr_any_len );
775 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
780 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
782 pre = SLAP_INDEX_SUBSTR_PREFIX;
783 klen = index_substr_any_len;
785 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
786 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
790 value = &sa->sa_any[i];
792 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
794 j <= value->bv_len - index_substr_any_len;
795 j += index_substr_any_step )
797 hashIter( &HASHcontext, HASHdigest,
798 (unsigned char *)&value->bv_val[j], klen );
799 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
804 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
805 !BER_BVISNULL( &sa->sa_final ) &&
806 sa->sa_final.bv_len >= index_substr_if_minlen )
808 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
809 value = &sa->sa_final;
811 klen = index_substr_if_maxlen < value->bv_len
812 ? index_substr_if_maxlen : value->bv_len;
814 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
815 hashIter( &HASHcontext, HASHdigest,
816 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
817 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
819 /* If final is too long and we have subany indexed, use it
820 * to match the excess...
822 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
825 pre = SLAP_INDEX_SUBSTR_PREFIX;
826 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
827 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
829 hashIter( &HASHcontext, HASHdigest,
830 (unsigned char *)&value->bv_val[j], index_substr_any_len );
831 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
837 BER_BVZERO( &keys[nkeys] );
854 /* very unforgiving validation, requires no normalization
855 * before simplistic matching
857 if( in->bv_len < 3 ) {
858 return LDAP_INVALID_SYNTAX;
861 /* RFC 4517 Section 3.3.2 Bit String:
862 * BitString = SQUOTE *binary-digit SQUOTE "B"
863 * binary-digit = "0" / "1"
865 * where SQUOTE [RFC4512] is
866 * SQUOTE = %x27 ; single quote ("'")
868 * Example: '0101111101'B
871 if( in->bv_val[0] != '\'' ||
872 in->bv_val[in->bv_len - 2] != '\'' ||
873 in->bv_val[in->bv_len - 1] != 'B' )
875 return LDAP_INVALID_SYNTAX;
878 for( i = in->bv_len - 3; i > 0; i-- ) {
879 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
880 return LDAP_INVALID_SYNTAX;
888 * Syntaxes from RFC 4517
893 A value of the Bit String syntax is a sequence of binary digits. The
894 LDAP-specific encoding of a value of this syntax is defined by the
897 BitString = SQUOTE *binary-digit SQUOTE "B"
899 binary-digit = "0" / "1"
901 The <SQUOTE> rule is defined in [MODELS].
906 The LDAP definition for the Bit String syntax is:
908 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
910 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
914 3.3.21. Name and Optional UID
916 A value of the Name and Optional UID syntax is the distinguished name
917 [MODELS] of an entity optionally accompanied by a unique identifier
918 that serves to differentiate the entity from others with an identical
921 The LDAP-specific encoding of a value of this syntax is defined by
924 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
926 The <BitString> rule is defined in Section 3.3.2. The
927 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
930 Note that although the '#' character may occur in the string
931 representation of a distinguished name, no additional escaping of
932 this character is performed when a <distinguishedName> is encoded in
933 a <NameAndOptionalUID>.
936 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
938 The LDAP definition for the Name and Optional UID syntax is:
940 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
942 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
949 1.4. Common ABNF Productions
952 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
954 SQUOTE = %x27 ; single quote ("'")
958 * Note: normalization strips any leading "0"s, unless the
959 * bit string is exactly "'0'B", so the normalized example,
960 * in slapd, would result in
962 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
964 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
965 * be escaped except when at the beginning of a value, the
966 * definition of Name and Optional UID appears to be flawed,
967 * because there is no clear means to determine whether the
968 * UID part is present or not.
972 * cn=Someone,dc=example,dc=com#'1'B
974 * could be either a NameAndOptionalUID with trailing UID, i.e.
976 * DN = "cn=Someone,dc=example,dc=com"
979 * or a NameAndOptionalUID with no trailing UID, and the AVA
980 * in the last RDN made of
983 * attributeValue = com#'1'B
985 * in fact "com#'1'B" is a valid IA5 string.
987 * As a consequence, current slapd code assumes that the
988 * presence of portions of a BitString at the end of the string
989 * representation of a NameAndOptionalUID means a BitString
990 * is expected, and cause an error otherwise. This is quite
991 * arbitrary, and might change in the future.
1001 struct berval dn, uid;
1003 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1005 ber_dupbv( &dn, in );
1006 if( !dn.bv_val ) return LDAP_OTHER;
1008 /* if there's a "#", try bitStringValidate()... */
1009 uid.bv_val = strrchr( dn.bv_val, '#' );
1010 if ( !BER_BVISNULL( &uid ) ) {
1012 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1014 rc = bitStringValidate( NULL, &uid );
1015 if ( rc == LDAP_SUCCESS ) {
1016 /* in case of success, trim the UID,
1017 * otherwise treat it as part of the DN */
1018 dn.bv_len -= uid.bv_len + 1;
1019 uid.bv_val[-1] = '\0';
1023 rc = dnValidate( NULL, &dn );
1025 ber_memfree( dn.bv_val );
1036 assert( val != NULL );
1037 assert( out != NULL );
1040 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1042 if( BER_BVISEMPTY( val ) ) {
1043 ber_dupbv_x( out, val, ctx );
1045 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1046 return LDAP_INVALID_SYNTAX;
1050 struct berval dnval = *val;
1051 struct berval uidval = BER_BVNULL;
1053 uidval.bv_val = strrchr( val->bv_val, '#' );
1054 if ( !BER_BVISNULL( &uidval ) ) {
1056 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1058 rc = bitStringValidate( NULL, &uidval );
1060 if ( rc == LDAP_SUCCESS ) {
1061 ber_dupbv_x( &dnval, val, ctx );
1062 dnval.bv_len -= uidval.bv_len + 1;
1063 dnval.bv_val[dnval.bv_len] = '\0';
1066 BER_BVZERO( &uidval );
1070 rc = dnPretty( syntax, &dnval, out, ctx );
1071 if ( dnval.bv_val != val->bv_val ) {
1072 slap_sl_free( dnval.bv_val, ctx );
1074 if( rc != LDAP_SUCCESS ) {
1078 if( !BER_BVISNULL( &uidval ) ) {
1082 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1083 + STRLENOF( "#" ) + uidval.bv_len + 1,
1086 ber_memfree_x( out->bv_val, ctx );
1090 out->bv_val[out->bv_len++] = '#';
1091 out->bv_val[out->bv_len++] = '\'';
1093 got1 = uidval.bv_len < sizeof("'0'B");
1094 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1095 c = uidval.bv_val[i];
1098 if( got1 ) out->bv_val[out->bv_len++] = c;
1102 out->bv_val[out->bv_len++] = c;
1107 out->bv_val[out->bv_len++] = '\'';
1108 out->bv_val[out->bv_len++] = 'B';
1109 out->bv_val[out->bv_len] = '\0';
1113 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1115 return LDAP_SUCCESS;
1119 uniqueMemberNormalize(
1124 struct berval *normalized,
1130 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1132 ber_dupbv_x( &out, val, ctx );
1133 if ( BER_BVISEMPTY( &out ) ) {
1137 struct berval uid = BER_BVNULL;
1139 uid.bv_val = strrchr( out.bv_val, '#' );
1140 if ( !BER_BVISNULL( &uid ) ) {
1142 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1144 rc = bitStringValidate( NULL, &uid );
1145 if ( rc == LDAP_SUCCESS ) {
1146 uid.bv_val[-1] = '\0';
1147 out.bv_len -= uid.bv_len + 1;
1153 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1155 if( rc != LDAP_SUCCESS ) {
1156 slap_sl_free( out.bv_val, ctx );
1157 return LDAP_INVALID_SYNTAX;
1160 if( !BER_BVISNULL( &uid ) ) {
1163 tmp = ch_realloc( normalized->bv_val,
1164 normalized->bv_len + uid.bv_len
1165 + STRLENOF("#") + 1 );
1166 if ( tmp == NULL ) {
1167 ber_memfree_x( normalized->bv_val, ctx );
1171 normalized->bv_val = tmp;
1173 /* insert the separator */
1174 normalized->bv_val[normalized->bv_len++] = '#';
1176 /* append the UID */
1177 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1178 uid.bv_val, uid.bv_len );
1179 normalized->bv_len += uid.bv_len;
1182 normalized->bv_val[normalized->bv_len] = '\0';
1185 slap_sl_free( out.bv_val, ctx );
1188 return LDAP_SUCCESS;
1197 struct berval *value,
1198 void *assertedValue )
1201 struct berval *asserted = (struct berval *) assertedValue;
1202 struct berval assertedDN = *asserted;
1203 struct berval assertedUID = BER_BVNULL;
1204 struct berval valueDN = *value;
1205 struct berval valueUID = BER_BVNULL;
1206 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1208 if ( !BER_BVISEMPTY( asserted ) ) {
1209 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1210 if ( !BER_BVISNULL( &assertedUID ) ) {
1211 assertedUID.bv_val++;
1212 assertedUID.bv_len = assertedDN.bv_len
1213 - ( assertedUID.bv_val - assertedDN.bv_val );
1215 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1216 assertedDN.bv_len -= assertedUID.bv_len + 1;
1219 BER_BVZERO( &assertedUID );
1224 if ( !BER_BVISEMPTY( value ) ) {
1226 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1227 if ( !BER_BVISNULL( &valueUID ) ) {
1229 valueUID.bv_len = valueDN.bv_len
1230 - ( valueUID.bv_val - valueDN.bv_val );
1232 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1233 valueDN.bv_len -= valueUID.bv_len + 1;
1236 BER_BVZERO( &valueUID );
1241 if( valueUID.bv_len && assertedUID.bv_len ) {
1242 match = valueUID.bv_len - assertedUID.bv_len;
1245 return LDAP_SUCCESS;
1248 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1251 return LDAP_SUCCESS;
1254 } else if ( !approx && valueUID.bv_len ) {
1257 return LDAP_SUCCESS;
1259 } else if ( !approx && assertedUID.bv_len ) {
1262 return LDAP_SUCCESS;
1265 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1269 uniqueMemberIndexer(
1274 struct berval *prefix,
1282 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1283 /* just count them */
1287 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1289 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1290 struct berval assertedDN = values[i];
1291 struct berval assertedUID = BER_BVNULL;
1293 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1294 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1295 if ( !BER_BVISNULL( &assertedUID ) ) {
1296 assertedUID.bv_val++;
1297 assertedUID.bv_len = assertedDN.bv_len
1298 - ( assertedUID.bv_val - assertedDN.bv_val );
1300 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1301 assertedDN.bv_len -= assertedUID.bv_len + 1;
1304 BER_BVZERO( &assertedUID );
1309 dnvalues[i] = assertedDN;
1311 BER_BVZERO( &dnvalues[i] );
1313 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1314 dnvalues, keysp, ctx );
1316 slap_sl_free( dnvalues, ctx );
1326 struct berval *prefix,
1327 void * assertedValue,
1331 struct berval *asserted = (struct berval *) assertedValue;
1332 struct berval assertedDN = *asserted;
1333 struct berval assertedUID = BER_BVNULL;
1335 if ( !BER_BVISEMPTY( asserted ) ) {
1336 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1337 if ( !BER_BVISNULL( &assertedUID ) ) {
1338 assertedUID.bv_val++;
1339 assertedUID.bv_len = assertedDN.bv_len
1340 - ( assertedUID.bv_val - assertedDN.bv_val );
1342 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1343 assertedDN.bv_len -= assertedUID.bv_len + 1;
1346 BER_BVZERO( &assertedUID );
1351 return octetStringFilter( use, flags, syntax, mr, prefix,
1352 &assertedDN, keysp, ctx );
1357 * Handling boolean syntax and matching is quite rigid.
1358 * A more flexible approach would be to allow a variety
1359 * of strings to be normalized and prettied into TRUE
1367 /* very unforgiving validation, requires no normalization
1368 * before simplistic matching
1371 if( in->bv_len == 4 ) {
1372 if( bvmatch( in, &slap_true_bv ) ) {
1373 return LDAP_SUCCESS;
1375 } else if( in->bv_len == 5 ) {
1376 if( bvmatch( in, &slap_false_bv ) ) {
1377 return LDAP_SUCCESS;
1381 return LDAP_INVALID_SYNTAX;
1390 struct berval *value,
1391 void *assertedValue )
1393 /* simplistic matching allowed by rigid validation */
1394 struct berval *asserted = (struct berval *) assertedValue;
1395 *matchp = value->bv_len != asserted->bv_len;
1396 return LDAP_SUCCESS;
1399 /*-------------------------------------------------------------------
1400 LDAP/X.500 string syntax / matching rules have a few oddities. This
1401 comment attempts to detail how slapd(8) treats them.
1404 StringSyntax X.500 LDAP Matching/Comments
1405 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1406 PrintableString subset subset i/e + ignore insignificant spaces
1407 PrintableString subset subset i/e + ignore insignificant spaces
1408 NumericString subset subset ignore all spaces
1409 IA5String ASCII ASCII i/e + ignore insignificant spaces
1410 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1412 TelephoneNumber subset subset i + ignore all spaces and "-"
1414 See RFC 4518 for details.
1418 In X.500(93), a directory string can be either a PrintableString,
1419 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1420 In later versions, more CHOICEs were added. In all cases the string
1423 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1424 A directory string cannot be zero length.
1426 For matching, there are both case ignore and exact rules. Both
1427 also require that "insignificant" spaces be ignored.
1428 spaces before the first non-space are ignored;
1429 spaces after the last non-space are ignored;
1430 spaces after a space are ignored.
1431 Note: by these rules (and as clarified in X.520), a string of only
1432 spaces is to be treated as if held one space, not empty (which
1433 would be a syntax error).
1436 In ASN.1, numeric string is just a string of digits and spaces
1437 and could be empty. However, in X.500, all attribute values of
1438 numeric string carry a non-empty constraint. For example:
1440 internationalISDNNumber ATTRIBUTE ::= {
1441 WITH SYNTAX InternationalISDNNumber
1442 EQUALITY MATCHING RULE numericStringMatch
1443 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1444 ID id-at-internationalISDNNumber }
1445 InternationalISDNNumber ::=
1446 NumericString (SIZE(1..ub-international-isdn-number))
1448 Unforunately, some assertion values are don't carry the same
1449 constraint (but its unclear how such an assertion could ever
1450 be true). In LDAP, there is one syntax (numericString) not two
1451 (numericString with constraint, numericString without constraint).
1452 This should be treated as numericString with non-empty constraint.
1453 Note that while someone may have no ISDN number, there are no ISDN
1454 numbers which are zero length.
1456 In matching, spaces are ignored.
1459 In ASN.1, Printable string is just a string of printable characters
1460 and can be empty. In X.500, semantics much like NumericString (see
1461 serialNumber for a like example) excepting uses insignificant space
1462 handling instead of ignore all spaces. They must be non-empty.
1465 Basically same as PrintableString. There are no examples in X.500,
1466 but same logic applies. Empty strings are allowed.
1468 -------------------------------------------------------------------*/
1477 unsigned char *u = (unsigned char *)in->bv_val;
1479 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1480 /* directory strings cannot be empty */
1481 return LDAP_INVALID_SYNTAX;
1484 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1485 /* get the length indicated by the first byte */
1486 len = LDAP_UTF8_CHARLEN2( u, len );
1488 /* very basic checks */
1491 if( (u[5] & 0xC0) != 0x80 ) {
1492 return LDAP_INVALID_SYNTAX;
1495 if( (u[4] & 0xC0) != 0x80 ) {
1496 return LDAP_INVALID_SYNTAX;
1499 if( (u[3] & 0xC0) != 0x80 ) {
1500 return LDAP_INVALID_SYNTAX;
1503 if( (u[2] & 0xC0 )!= 0x80 ) {
1504 return LDAP_INVALID_SYNTAX;
1507 if( (u[1] & 0xC0) != 0x80 ) {
1508 return LDAP_INVALID_SYNTAX;
1511 /* CHARLEN already validated it */
1514 return LDAP_INVALID_SYNTAX;
1517 /* make sure len corresponds with the offset
1518 to the next character */
1519 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1523 return LDAP_INVALID_SYNTAX;
1526 return LDAP_SUCCESS;
1530 UTF8StringNormalize(
1535 struct berval *normalized,
1538 struct berval tmp, nvalue;
1542 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1544 if( BER_BVISNULL( val ) ) {
1545 /* assume we're dealing with a syntax (e.g., UTF8String)
1546 * which allows empty strings
1548 BER_BVZERO( normalized );
1549 return LDAP_SUCCESS;
1552 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1553 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1554 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1555 ? LDAP_UTF8_APPROX : 0;
1557 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1562 /* collapse spaces (in place) */
1564 nvalue.bv_val = tmp.bv_val;
1566 /* trim leading spaces? */
1567 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1568 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1570 for( i = 0; i < tmp.bv_len; i++) {
1571 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1572 if( wasspace++ == 0 ) {
1573 /* trim repeated spaces */
1574 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1578 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1582 if( !BER_BVISEMPTY( &nvalue ) ) {
1583 /* trim trailing space? */
1585 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1586 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1590 nvalue.bv_val[nvalue.bv_len] = '\0';
1593 /* string of all spaces is treated as one space */
1594 nvalue.bv_val[0] = ' ';
1595 nvalue.bv_val[1] = '\0';
1599 *normalized = nvalue;
1600 return LDAP_SUCCESS;
1604 directoryStringSubstringsMatch(
1609 struct berval *value,
1610 void *assertedValue )
1613 SubstringsAssertion *sub = assertedValue;
1614 struct berval left = *value;
1618 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1619 if ( sub->sa_initial.bv_len > left.bv_len ) {
1620 /* not enough left */
1625 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1626 sub->sa_initial.bv_len );
1632 left.bv_val += sub->sa_initial.bv_len;
1633 left.bv_len -= sub->sa_initial.bv_len;
1635 priorspace = ASCII_SPACE(
1636 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1639 if ( sub->sa_any ) {
1640 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1644 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1645 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1647 /* allow next space to match */
1654 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1658 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1659 /* not enough left */
1664 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1671 idx = p - left.bv_val;
1673 if ( idx >= left.bv_len ) {
1674 /* this shouldn't happen */
1681 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1682 /* not enough left */
1687 match = memcmp( left.bv_val,
1688 sub->sa_any[i].bv_val,
1689 sub->sa_any[i].bv_len );
1697 left.bv_val += sub->sa_any[i].bv_len;
1698 left.bv_len -= sub->sa_any[i].bv_len;
1700 priorspace = ASCII_SPACE(
1701 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1705 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1706 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1707 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1709 /* allow next space to match */
1714 if ( sub->sa_final.bv_len > left.bv_len ) {
1715 /* not enough left */
1720 match = memcmp( sub->sa_final.bv_val,
1721 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1722 sub->sa_final.bv_len );
1731 return LDAP_SUCCESS;
1734 #if defined(SLAPD_APPROX_INITIALS)
1735 # define SLAPD_APPROX_DELIMITER "._ "
1736 # define SLAPD_APPROX_WORDLEN 2
1738 # define SLAPD_APPROX_DELIMITER " "
1739 # define SLAPD_APPROX_WORDLEN 1
1748 struct berval *value,
1749 void *assertedValue )
1751 struct berval *nval, *assertv;
1752 char *val, **values, **words, *c;
1753 int i, count, len, nextchunk=0, nextavail=0;
1755 /* Yes, this is necessary */
1756 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1757 if( nval == NULL ) {
1759 return LDAP_SUCCESS;
1762 /* Yes, this is necessary */
1763 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1764 NULL, LDAP_UTF8_APPROX, NULL );
1765 if( assertv == NULL ) {
1768 return LDAP_SUCCESS;
1771 /* Isolate how many words there are */
1772 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1773 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1774 if ( c == NULL ) break;
1779 /* Get a phonetic copy of each word */
1780 words = (char **)ch_malloc( count * sizeof(char *) );
1781 values = (char **)ch_malloc( count * sizeof(char *) );
1782 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1784 values[i] = phonetic(c);
1787 /* Work through the asserted value's words, to see if at least some
1788 * of the words are there, in the same order. */
1790 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1791 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1796 #if defined(SLAPD_APPROX_INITIALS)
1797 else if( len == 1 ) {
1798 /* Single letter words need to at least match one word's initial */
1799 for( i=nextavail; i<count; i++ )
1800 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1807 /* Isolate the next word in the asserted value and phonetic it */
1808 assertv->bv_val[nextchunk+len] = '\0';
1809 val = phonetic( assertv->bv_val + nextchunk );
1811 /* See if this phonetic chunk is in the remaining words of *value */
1812 for( i=nextavail; i<count; i++ ){
1813 if( !strcmp( val, values[i] ) ){
1821 /* This chunk in the asserted value was NOT within the *value. */
1827 /* Go on to the next word in the asserted value */
1831 /* If some of the words were seen, call it a match */
1832 if( nextavail > 0 ) {
1839 /* Cleanup allocs */
1840 ber_bvfree( assertv );
1841 for( i=0; i<count; i++ ) {
1842 ch_free( values[i] );
1848 return LDAP_SUCCESS;
1857 struct berval *prefix,
1863 int i,j, len, wordcount, keycount=0;
1864 struct berval *newkeys;
1865 BerVarray keys=NULL;
1867 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1868 struct berval val = BER_BVNULL;
1869 /* Yes, this is necessary */
1870 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1871 assert( !BER_BVISNULL( &val ) );
1873 /* Isolate how many words there are. There will be a key for each */
1874 for( wordcount = 0, c = val.bv_val; *c; c++) {
1875 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1876 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1878 if (*c == '\0') break;
1882 /* Allocate/increase storage to account for new keys */
1883 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1884 * sizeof(struct berval) );
1885 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1886 if( keys ) ch_free( keys );
1889 /* Get a phonetic copy of each word */
1890 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1892 if( len < SLAPD_APPROX_WORDLEN ) continue;
1893 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1898 ber_memfree( val.bv_val );
1900 BER_BVZERO( &keys[keycount] );
1903 return LDAP_SUCCESS;
1912 struct berval *prefix,
1913 void * assertedValue,
1922 /* Yes, this is necessary */
1923 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1924 NULL, LDAP_UTF8_APPROX, NULL );
1925 if( val == NULL || BER_BVISNULL( val ) ) {
1926 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1927 BER_BVZERO( &keys[0] );
1930 return LDAP_SUCCESS;
1933 /* Isolate how many words there are. There will be a key for each */
1934 for( count = 0,c = val->bv_val; *c; c++) {
1935 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1936 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1938 if (*c == '\0') break;
1942 /* Allocate storage for new keys */
1943 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1945 /* Get a phonetic copy of each word */
1946 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1948 if( len < SLAPD_APPROX_WORDLEN ) continue;
1949 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1955 BER_BVZERO( &keys[count] );
1958 return LDAP_SUCCESS;
1961 /* Remove all spaces and '-' characters */
1963 telephoneNumberNormalize(
1968 struct berval *normalized,
1973 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1975 /* validator should have refused an empty string */
1976 assert( !BER_BVISEMPTY( val ) );
1978 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1980 for( p = val->bv_val; *p; p++ ) {
1981 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1987 normalized->bv_len = q - normalized->bv_val;
1989 if( BER_BVISEMPTY( normalized ) ) {
1990 slap_sl_free( normalized->bv_val, ctx );
1991 BER_BVZERO( normalized );
1992 return LDAP_INVALID_SYNTAX;
1995 return LDAP_SUCCESS;
1999 postalAddressValidate(
2003 struct berval bv = *in;
2006 for ( c = 0; c < in->bv_len; c++ ) {
2007 if ( in->bv_val[c] == '\\' ) {
2009 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2010 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2012 return LDAP_INVALID_SYNTAX;
2017 if ( in->bv_val[c] == '$' ) {
2018 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2019 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2020 return LDAP_INVALID_SYNTAX;
2022 bv.bv_val = &in->bv_val[c] + 1;
2026 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2027 return UTF8StringValidate( NULL, &bv );
2031 postalAddressNormalize(
2036 struct berval *normalized,
2039 BerVarray lines = NULL, nlines = NULL;
2041 int rc = LDAP_SUCCESS;
2042 MatchingRule *xmr = NULL;
2045 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2046 xmr = slap_schema.si_mr_caseIgnoreMatch;
2049 xmr = slap_schema.si_mr_caseExactMatch;
2052 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2053 if ( val->bv_val[c] == '$' ) {
2058 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2059 nlines = &lines[l + 2];
2061 lines[0].bv_val = val->bv_val;
2062 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2063 if ( val->bv_val[c] == '$' ) {
2064 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2066 lines[l].bv_val = &val->bv_val[c + 1];
2069 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2071 normalized->bv_len = l;
2073 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2074 /* NOTE: we directly normalize each line,
2075 * without unescaping the values, since the special
2076 * values '\24' ('$') and '\5C' ('\') are not affected
2077 * by normalization */
2078 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2079 if ( rc != LDAP_SUCCESS ) {
2080 rc = LDAP_INVALID_SYNTAX;
2084 normalized->bv_len += nlines[l].bv_len;
2087 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2089 p = normalized->bv_val;
2090 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2091 p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2097 assert( p - normalized->bv_val == normalized->bv_len );
2100 if ( nlines != NULL ) {
2101 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2102 slap_sl_free( nlines[l].bv_val, ctx );
2105 slap_sl_free( lines, ctx );
2116 struct berval val = *in;
2118 if( BER_BVISEMPTY( &val ) ) {
2119 /* disallow empty strings */
2120 return LDAP_INVALID_SYNTAX;
2123 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2124 if ( val.bv_len == 1 ) {
2125 return LDAP_SUCCESS;
2128 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2135 while ( OID_LEADCHAR( val.bv_val[0] )) {
2139 if ( val.bv_len == 0 ) {
2140 return LDAP_SUCCESS;
2144 if( !OID_SEPARATOR( val.bv_val[0] )) {
2152 return LDAP_INVALID_SYNTAX;
2161 struct berval val = *in;
2163 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2165 if ( val.bv_val[0] == '-' ) {
2169 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2170 return LDAP_INVALID_SYNTAX;
2173 if( val.bv_val[0] == '0' ) { /* "-0" */
2174 return LDAP_INVALID_SYNTAX;
2177 } else if ( val.bv_val[0] == '0' ) {
2178 if( val.bv_len > 1 ) { /* "0<more>" */
2179 return LDAP_INVALID_SYNTAX;
2182 return LDAP_SUCCESS;
2185 for( i=0; i < val.bv_len; i++ ) {
2186 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2187 return LDAP_INVALID_SYNTAX;
2191 return LDAP_SUCCESS;
2200 struct berval *value,
2201 void *assertedValue )
2203 struct berval *asserted = (struct berval *) assertedValue;
2204 int vsign = 1, asign = 1; /* default sign = '+' */
2209 if( v.bv_val[0] == '-' ) {
2215 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2218 if( a.bv_val[0] == '-' ) {
2224 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2226 match = vsign - asign;
2228 match = ( v.bv_len != a.bv_len
2229 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2230 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2231 if( vsign < 0 ) match = -match;
2235 return LDAP_SUCCESS;
2238 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2239 #define INDEX_INTLEN_CHOP 7
2240 #define INDEX_INTLEN_CHOPBYTES 3
2250 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2251 * two's complement value (sign-extended or chopped as needed),
2252 * however the top <number of exponent-bytes + 1> bits of first byte
2253 * above is the inverse sign. The next bit is the sign as delimiter.
2255 ber_slen_t k = index_intlen_strlen;
2257 unsigned signmask = ~0x7fU;
2258 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2259 struct berval val = *in, itmp = *tmp;
2261 if ( val.bv_val[0] != '-' ) {
2266 /* Chop least significant digits, increase length instead */
2267 if ( val.bv_len > (ber_len_t) k ) {
2268 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2269 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2270 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2273 if ( lutil_str2bin( &val, &itmp, ctx )) {
2274 return LDAP_INVALID_SYNTAX;
2277 /* Omit leading sign byte */
2278 if ( itmp.bv_val[0] == neg ) {
2283 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2285 assert( chop == 0 );
2286 memset( key->bv_val, neg, k ); /* sign-extend */
2287 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2288 lenp = lenbuf + sizeof(lenbuf);
2289 chop = - (ber_len_t) k;
2291 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2293 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2294 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2295 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2296 k = (lenbuf + sizeof(lenbuf)) - lenp;
2297 if ( k > (ber_slen_t) index_intlen )
2299 memcpy( key->bv_val, lenp, k );
2300 itmp.bv_len = index_intlen - k;
2302 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2303 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2307 /* Index generation function */
2314 struct berval *prefix,
2324 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2326 /* count the values and find max needed length */
2328 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2329 if ( vlen < values[i].bv_len )
2330 vlen = values[i].bv_len;
2332 if ( vlen > maxstrlen )
2335 /* we should have at least one value at this point */
2338 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2339 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2340 keys[i].bv_len = index_intlen;
2341 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2344 keys[i].bv_val = NULL;
2346 if ( vlen > sizeof(ibuf) ) {
2347 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2351 itmp.bv_len = sizeof(ibuf);
2353 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2354 if ( itmp.bv_val != ibuf ) {
2355 itmp.bv_len = values[i].bv_len;
2356 if ( itmp.bv_len <= sizeof(ibuf) )
2357 itmp.bv_len = sizeof(ibuf);
2358 else if ( itmp.bv_len > maxstrlen )
2359 itmp.bv_len = maxstrlen;
2361 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2367 if ( itmp.bv_val != ibuf ) {
2368 slap_sl_free( itmp.bv_val, ctx );
2373 /* Index generation function */
2380 struct berval *prefix,
2381 void * assertedValue,
2388 struct berval *value;
2391 value = (struct berval *) assertedValue;
2393 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2395 keys[0].bv_len = index_intlen;
2396 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2398 keys[1].bv_val = NULL;
2400 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2401 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2402 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2403 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2406 iv.bv_len = sizeof(ibuf);
2409 rc = integerVal2Key( value, keys, &iv, ctx );
2413 if ( iv.bv_val != ibuf ) {
2414 slap_sl_free( iv.bv_val, ctx );
2420 countryStringValidate(
2422 struct berval *val )
2424 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2426 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2427 return LDAP_INVALID_SYNTAX;
2429 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2430 return LDAP_INVALID_SYNTAX;
2433 return LDAP_SUCCESS;
2437 printableStringValidate(
2439 struct berval *val )
2443 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2445 for(i=0; i < val->bv_len; i++) {
2446 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2447 return LDAP_INVALID_SYNTAX;
2451 return LDAP_SUCCESS;
2455 printablesStringValidate(
2457 struct berval *val )
2461 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2463 for(i=0,len=0; i < val->bv_len; i++) {
2464 int c = val->bv_val[i];
2468 return LDAP_INVALID_SYNTAX;
2472 } else if ( SLAP_PRINTABLE(c) ) {
2475 return LDAP_INVALID_SYNTAX;
2480 return LDAP_INVALID_SYNTAX;
2483 return LDAP_SUCCESS;
2489 struct berval *val )
2493 for(i=0; i < val->bv_len; i++) {
2494 if( !LDAP_ASCII(val->bv_val[i]) ) {
2495 return LDAP_INVALID_SYNTAX;
2499 return LDAP_SUCCESS;
2508 struct berval *normalized,
2512 int casefold = !SLAP_MR_ASSOCIATED( mr,
2513 slap_schema.si_mr_caseExactIA5Match );
2515 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2519 /* Ignore initial whitespace */
2520 while ( ASCII_SPACE( *p ) ) p++;
2522 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2523 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2524 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2525 normalized->bv_val[normalized->bv_len] = '\0';
2527 p = q = normalized->bv_val;
2530 if ( ASCII_SPACE( *p ) ) {
2533 /* Ignore the extra whitespace */
2534 while ( ASCII_SPACE( *p ) ) {
2538 } else if ( casefold ) {
2539 /* Most IA5 rules require casefolding */
2540 *q++ = TOLOWER(*p); p++;
2547 assert( normalized->bv_val <= p );
2551 * If the string ended in space, backup the pointer one
2552 * position. One is enough because the above loop collapsed
2553 * all whitespace to a single space.
2555 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2557 /* null terminate */
2560 normalized->bv_len = q - normalized->bv_val;
2562 return LDAP_SUCCESS;
2571 if( in->bv_len != 36 ) {
2572 return LDAP_INVALID_SYNTAX;
2575 for( i=0; i<36; i++ ) {
2581 if( in->bv_val[i] != '-' ) {
2582 return LDAP_INVALID_SYNTAX;
2586 if( !ASCII_HEX( in->bv_val[i]) ) {
2587 return LDAP_INVALID_SYNTAX;
2592 return LDAP_SUCCESS;
2603 int rc=LDAP_INVALID_SYNTAX;
2605 assert( in != NULL );
2606 assert( out != NULL );
2608 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2611 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2613 for( i=0; i<36; i++ ) {
2619 if( in->bv_val[i] != '-' ) {
2622 out->bv_val[i] = '-';
2626 if( !ASCII_HEX( in->bv_val[i]) ) {
2629 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2634 out->bv_val[ out->bv_len ] = '\0';
2638 slap_sl_free( out->bv_val, ctx );
2651 struct berval *normalized,
2654 unsigned char octet = '\0';
2658 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2659 /* NOTE: must be a normalized UUID */
2660 assert( val->bv_len == 16 );
2662 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2663 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2664 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2665 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2667 return LDAP_SUCCESS;
2670 normalized->bv_len = 16;
2671 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2673 for( i=0, j=0; i<36; i++ ) {
2674 unsigned char nibble;
2675 if( val->bv_val[i] == '-' ) {
2678 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2679 nibble = val->bv_val[i] - '0';
2681 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2682 nibble = val->bv_val[i] - ('a'-10);
2684 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2685 nibble = val->bv_val[i] - ('A'-10);
2688 slap_sl_free( normalized->bv_val, ctx );
2689 return LDAP_INVALID_SYNTAX;
2694 normalized->bv_val[j>>1] = octet;
2696 octet = nibble << 4;
2701 normalized->bv_val[normalized->bv_len] = 0;
2702 return LDAP_SUCCESS;
2708 numericStringValidate(
2714 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2716 for(i=0; i < in->bv_len; i++) {
2717 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2718 return LDAP_INVALID_SYNTAX;
2722 return LDAP_SUCCESS;
2726 numericStringNormalize(
2731 struct berval *normalized,
2734 /* removal all spaces */
2737 assert( !BER_BVISEMPTY( val ) );
2739 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2742 q = normalized->bv_val;
2745 if ( ASCII_SPACE( *p ) ) {
2746 /* Ignore whitespace */
2753 /* we should have copied no more than is in val */
2754 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2756 /* null terminate */
2759 normalized->bv_len = q - normalized->bv_val;
2761 if( BER_BVISEMPTY( normalized ) ) {
2762 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2763 normalized->bv_val[0] = ' ';
2764 normalized->bv_val[1] = '\0';
2765 normalized->bv_len = 1;
2768 return LDAP_SUCCESS;
2772 * Integer conversion macros that will use the largest available
2775 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2776 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2777 # define SLAP_LONG long long
2779 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2780 # define SLAP_LONG long
2781 #endif /* HAVE_STRTOLL ... */
2789 struct berval *value,
2790 void *assertedValue )
2792 SLAP_LONG lValue, lAssertedValue;
2795 /* safe to assume integers are NUL terminated? */
2796 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2797 if( errno == ERANGE )
2799 return LDAP_CONSTRAINT_VIOLATION;
2802 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2804 if( errno == ERANGE )
2806 return LDAP_CONSTRAINT_VIOLATION;
2809 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2810 return LDAP_SUCCESS;
2819 struct berval *value,
2820 void *assertedValue )
2822 SLAP_LONG lValue, lAssertedValue;
2825 /* safe to assume integers are NUL terminated? */
2826 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2827 if( errno == ERANGE )
2829 return LDAP_CONSTRAINT_VIOLATION;
2832 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2834 if( errno == ERANGE )
2836 return LDAP_CONSTRAINT_VIOLATION;
2839 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2840 return LDAP_SUCCESS;
2844 checkNum( struct berval *in, struct berval *out )
2846 /* parse serialNumber */
2851 out->bv_val = in->bv_val;
2854 if ( out->bv_val[0] == '-' ) {
2859 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
2860 first = out->bv_val[2];
2863 out->bv_len += STRLENOF("0x");
2864 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2865 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2868 } else if ( out->bv_val[0] == '\'' ) {
2869 first = out->bv_val[1];
2872 out->bv_len += STRLENOF("'");
2874 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2875 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2877 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
2880 out->bv_len += STRLENOF("'H");
2883 first = out->bv_val[0];
2884 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2885 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
2889 if ( !( out->bv_len > neg ) ) {
2893 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
2901 serialNumberAndIssuerCheck(
2909 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2911 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
2912 /* Parse old format */
2913 is->bv_val = ber_bvchr( in, '$' );
2914 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
2916 sn->bv_val = in->bv_val;
2917 sn->bv_len = is->bv_val - in->bv_val;
2920 is->bv_len = in->bv_len - (sn->bv_len + 1);
2922 /* eat leading zeros */
2923 for( n=0; n < (sn->bv_len-1); n++ ) {
2924 if( sn->bv_val[n] != '0' ) break;
2929 for( n=0; n < sn->bv_len; n++ ) {
2930 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2934 /* Parse GSER format */
2939 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
2943 struct berval x = *in;
2949 /* eat leading spaces */
2950 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
2954 /* should be at issuer or serialNumber NamedValue */
2955 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
2956 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
2959 x.bv_val += STRLENOF("issuer");
2960 x.bv_len -= STRLENOF("issuer");
2962 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
2966 /* eat leading spaces */
2967 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
2971 /* For backward compatibility, this part is optional */
2972 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
2973 x.bv_val += STRLENOF("rdnSequence:");
2974 x.bv_len -= STRLENOF("rdnSequence:");
2977 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
2981 is->bv_val = x.bv_val;
2984 for ( ; is->bv_len < x.bv_len; ) {
2985 if ( is->bv_val[is->bv_len] != '"' ) {
2989 if ( is->bv_val[is->bv_len+1] == '"' ) {
2996 x.bv_val += is->bv_len + 1;
2997 x.bv_len -= is->bv_len + 1;
2999 have |= HAVE_ISSUER;
3001 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3003 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3005 /* parse serialNumber */
3006 x.bv_val += STRLENOF("serialNumber");
3007 x.bv_len -= STRLENOF("serialNumber");
3009 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3013 /* eat leading spaces */
3014 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3018 if ( checkNum( &x, sn ) ) {
3019 return LDAP_INVALID_SYNTAX;
3022 x.bv_val += sn->bv_len;
3023 x.bv_len -= sn->bv_len;
3028 return LDAP_INVALID_SYNTAX;
3031 /* eat leading spaces */
3032 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3036 if ( have == HAVE_ALL ) {
3040 if ( x.bv_val[0] != ',' ) {
3041 return LDAP_INVALID_SYNTAX;
3048 /* should have no characters left... */
3049 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3051 if ( numdquotes == 0 ) {
3052 ber_dupbv_x( &ni, is, ctx );
3057 ni.bv_len = is->bv_len - numdquotes;
3058 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3059 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3060 if ( is->bv_val[src] == '"' ) {
3063 ni.bv_val[dst] = is->bv_val[src];
3065 ni.bv_val[dst] = '\0';
3075 serialNumberAndIssuerValidate(
3080 struct berval sn, i;
3082 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3085 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3090 /* validate DN -- doesn't handle double dquote */
3091 rc = dnValidate( NULL, &i );
3093 rc = LDAP_INVALID_SYNTAX;
3096 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3097 slap_sl_free( i.bv_val, NULL );
3100 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3101 in->bv_val, rc, 0 );
3108 serialNumberAndIssuerPretty(
3115 struct berval sn, i, ni = BER_BVNULL;
3118 assert( in != NULL );
3119 assert( out != NULL );
3123 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3126 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3131 rc = dnPretty( syntax, &i, &ni, ctx );
3133 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3134 slap_sl_free( i.bv_val, ctx );
3138 rc = LDAP_INVALID_SYNTAX;
3142 /* make room from sn + "$" */
3143 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3144 + sn.bv_len + ni.bv_len;
3145 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3147 if ( out->bv_val == NULL ) {
3154 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3155 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3156 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3157 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3158 p = lutil_strcopy( p, /*{*/ "\" }" );
3160 assert( p - out->bv_val == out->bv_len );
3163 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3164 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3166 slap_sl_free( ni.bv_val, ctx );
3168 return LDAP_SUCCESS;
3178 /* Use hex format. '123456789abcdef'H */
3179 unsigned char *ptr, zero = '\0';
3183 ber_len_t len, nlen;
3185 assert( in != NULL );
3186 assert( !BER_BVISNULL( in ) );
3187 assert( out != NULL );
3188 assert( !BER_BVISNULL( out ) );
3190 ptr = (unsigned char *)in->bv_val;
3193 /* Check for minimal encodings */
3195 if ( ptr[0] & 0x80 ) {
3196 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3200 } else if ( ptr[0] == 0 ) {
3201 if ( !( ptr[1] & 0x80 ) ) {
3208 } else if ( len == 0 ) {
3209 /* FIXME: this should not be possible,
3210 * since a value of zero would have length 1 */
3215 first = !( ptr[0] & 0xf0U );
3216 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3217 if ( nlen >= out->bv_len ) {
3218 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3224 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3228 for ( ; i < len; i++ ) {
3229 sprintf( sptr, "%02X", ptr[i] );
3236 assert( sptr - out->bv_val == nlen );
3243 #define SLAP_SN_BUFLEN (64)
3246 * This routine is called by certificateExactNormalize when
3247 * certificateExactNormalize receives a search string instead of
3248 * a certificate. This routine checks if the search value is valid
3249 * and then returns the normalized value
3252 serialNumberAndIssuerNormalize(
3260 struct berval sn, sn2, sn3, i, ni;
3261 char sbuf2[SLAP_SN_BUFLEN];
3262 char sbuf3[SLAP_SN_BUFLEN];
3266 assert( in != NULL );
3267 assert( out != NULL );
3269 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3272 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3277 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3279 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3280 slap_sl_free( i.bv_val, ctx );
3284 return LDAP_INVALID_SYNTAX;
3287 /* Convert sn to canonical hex */
3289 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3290 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3292 sn2.bv_len = sn.bv_len;
3293 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3294 rc = LDAP_INVALID_SYNTAX;
3299 sn3.bv_len = sizeof(sbuf3);
3300 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3301 rc = LDAP_INVALID_SYNTAX;
3305 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3306 + sn3.bv_len + ni.bv_len;
3307 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3309 if ( out->bv_val == NULL ) {
3317 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3318 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3319 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3320 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3321 p = lutil_strcopy( p, /*{*/ "\" }" );
3323 assert( p - out->bv_val == out->bv_len );
3326 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3327 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3329 if ( sn2.bv_val != sbuf2 ) {
3330 slap_sl_free( sn2.bv_val, ctx );
3333 if ( sn3.bv_val != sbuf3 ) {
3334 slap_sl_free( sn3.bv_val, ctx );
3337 slap_sl_free( ni.bv_val, ctx );
3343 certificateExactNormalize(
3348 struct berval *normalized,
3351 BerElementBuffer berbuf;
3352 BerElement *ber = (BerElement *)&berbuf;
3356 char serialbuf2[SLAP_SN_BUFLEN];
3357 struct berval sn, sn2 = BER_BVNULL;
3358 struct berval issuer_dn = BER_BVNULL, bvdn;
3360 int rc = LDAP_INVALID_SYNTAX;
3362 assert( val != NULL );
3364 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3365 val->bv_val, val->bv_len, 0 );
3367 if ( BER_BVISEMPTY( val ) ) goto done;
3369 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3370 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3373 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3375 ber_init2( ber, val, LBER_USE_DER );
3376 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3377 tag = ber_skip_tag( ber, &len ); /* Sequence */
3378 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3379 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3380 tag = ber_skip_tag( ber, &len );
3381 tag = ber_get_int( ber, &i ); /* version */
3384 /* NOTE: move the test here from certificateValidate,
3385 * so that we can validate certs with serial longer
3386 * than sizeof(ber_int_t) */
3387 tag = ber_skip_tag( ber, &len ); /* serial */
3389 sn.bv_val = (char *)ber->ber_ptr;
3390 sn2.bv_val = serialbuf2;
3391 sn2.bv_len = sizeof(serialbuf2);
3392 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3393 rc = LDAP_INVALID_SYNTAX;
3396 ber_skip_data( ber, len );
3398 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3399 ber_skip_data( ber, len );
3400 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3401 len = ber_ptrlen( ber );
3402 bvdn.bv_val = val->bv_val + len;
3403 bvdn.bv_len = val->bv_len - len;
3405 rc = dnX509normalize( &bvdn, &issuer_dn );
3406 if ( rc != LDAP_SUCCESS ) goto done;
3408 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3409 + sn2.bv_len + issuer_dn.bv_len;
3410 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3412 p = normalized->bv_val;
3414 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3415 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3416 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3417 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3418 p = lutil_strcopy( p, /*{*/ "\" }" );
3423 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3424 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3426 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3427 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3439 assert( in != NULL );
3440 assert( !BER_BVISNULL( in ) );
3442 for ( i = 0; i < in->bv_len; i++ ) {
3443 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
3444 return LDAP_INVALID_SYNTAX;
3448 return LDAP_SUCCESS;
3451 /* Normalize a SID as used inside a CSN:
3452 * three-digit numeric string */
3459 struct berval *normalized,
3464 assert( val != NULL );
3465 assert( normalized != NULL );
3467 ber_dupbv_x( normalized, val, ctx );
3469 for ( i = 0; i < normalized->bv_len; i++ ) {
3470 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
3471 ber_memfree_x( normalized->bv_val, ctx );
3472 BER_BVZERO( normalized );
3473 return LDAP_INVALID_SYNTAX;
3476 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3479 return LDAP_SUCCESS;
3487 assert( in != NULL );
3488 assert( !BER_BVISNULL( in ) );
3490 if ( in->bv_len != 3 ) {
3491 return LDAP_INVALID_SYNTAX;
3494 return hexValidate( NULL, in );
3497 /* Normalize a SID as used inside a CSN:
3498 * three-digit numeric string */
3505 struct berval *normalized,
3508 if ( val->bv_len != 3 ) {
3509 return LDAP_INVALID_SYNTAX;
3512 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
3522 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3525 /* Normalize a SID as used inside a CSN, either as-is
3526 * (assertion value) or extracted from the CSN
3527 * (attribute value) */
3534 struct berval *normalized,
3542 if ( BER_BVISEMPTY( val ) ) {
3543 return LDAP_INVALID_SYNTAX;
3546 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3547 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
3550 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3552 ptr = ber_bvchr( val, '#' );
3553 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3554 return LDAP_INVALID_SYNTAX;
3557 bv.bv_val = ptr + 1;
3558 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3560 ptr = ber_bvchr( &bv, '#' );
3561 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3562 return LDAP_INVALID_SYNTAX;
3565 bv.bv_val = ptr + 1;
3566 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
3568 ptr = ber_bvchr( &bv, '#' );
3569 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3570 return LDAP_INVALID_SYNTAX;
3573 bv.bv_len = ptr - bv.bv_val;
3575 if ( bv.bv_len == 2 ) {
3576 /* OpenLDAP 2.3 SID */
3578 buf[ 1 ] = bv.bv_val[ 0 ];
3579 buf[ 2 ] = bv.bv_val[ 1 ];
3586 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
3598 assert( in != NULL );
3599 assert( !BER_BVISNULL( in ) );
3601 if ( BER_BVISEMPTY( in ) ) {
3602 return LDAP_INVALID_SYNTAX;
3607 ptr = ber_bvchr( &bv, '#' );
3608 if ( ptr == NULL || ptr - bv.bv_val == bv.bv_len ) {
3609 return LDAP_INVALID_SYNTAX;
3612 bv.bv_len = ptr - bv.bv_val;
3613 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3614 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
3616 return LDAP_INVALID_SYNTAX;
3619 rc = generalizedTimeValidate( NULL, &bv );
3620 if ( rc != LDAP_SUCCESS ) {
3624 bv.bv_val = ptr + 1;
3625 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3627 ptr = ber_bvchr( &bv, '#' );
3628 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3629 return LDAP_INVALID_SYNTAX;
3632 bv.bv_len = ptr - bv.bv_val;
3633 if ( bv.bv_len != 6 ) {
3634 return LDAP_INVALID_SYNTAX;
3637 rc = hexValidate( NULL, &bv );
3638 if ( rc != LDAP_SUCCESS ) {
3642 bv.bv_val = ptr + 1;
3643 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3645 ptr = ber_bvchr( &bv, '#' );
3646 if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) {
3647 return LDAP_INVALID_SYNTAX;
3650 bv.bv_len = ptr - bv.bv_val;
3651 if ( bv.bv_len == 2 ) {
3652 /* tolerate old 2-digit replica-id */
3653 rc = hexValidate( NULL, &bv );
3656 rc = sidValidate( NULL, &bv );
3658 if ( rc != LDAP_SUCCESS ) {
3662 bv.bv_val = ptr + 1;
3663 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
3665 if ( bv.bv_len != 6 ) {
3666 return LDAP_INVALID_SYNTAX;
3669 return hexValidate( NULL, &bv );
3672 /* Normalize a CSN in OpenLDAP 2.1 format */
3679 struct berval *normalized,
3682 struct berval gt, cnt, sid, mod;
3684 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3688 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3689 assert( !BER_BVISEMPTY( val ) );
3693 ptr = ber_bvchr( >, '#' );
3694 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3695 return LDAP_INVALID_SYNTAX;
3698 gt.bv_len = ptr - gt.bv_val;
3699 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
3700 return LDAP_INVALID_SYNTAX;
3703 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
3704 return LDAP_INVALID_SYNTAX;
3707 cnt.bv_val = ptr + 1;
3708 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3710 ptr = ber_bvchr( &cnt, '#' );
3711 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3712 return LDAP_INVALID_SYNTAX;
3715 cnt.bv_len = ptr - cnt.bv_val;
3716 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
3717 return LDAP_INVALID_SYNTAX;
3720 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
3721 return LDAP_INVALID_SYNTAX;
3724 cnt.bv_val += STRLENOF( "0x" );
3725 cnt.bv_len -= STRLENOF( "0x" );
3727 sid.bv_val = ptr + 1;
3728 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3730 ptr = ber_bvchr( &sid, '#' );
3731 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3732 return LDAP_INVALID_SYNTAX;
3735 sid.bv_len = ptr - sid.bv_val;
3736 if ( sid.bv_len != STRLENOF( "0" ) ) {
3737 return LDAP_INVALID_SYNTAX;
3740 mod.bv_val = ptr + 1;
3741 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3742 if ( mod.bv_len != STRLENOF( "0000" ) ) {
3743 return LDAP_INVALID_SYNTAX;
3746 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3750 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
3751 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
3753 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
3755 ptr = lutil_strcopy( ptr, ".000000Z#00" );
3756 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3760 *ptr++ = sid.bv_val[ 0 ];
3764 for ( i = 0; i < mod.bv_len; i++ ) {
3765 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3769 assert( ptr - bv.bv_val == bv.bv_len );
3771 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3772 return LDAP_INVALID_SYNTAX;
3775 ber_dupbv_x( normalized, &bv, ctx );
3777 return LDAP_SUCCESS;
3780 /* Normalize a CSN in OpenLDAP 2.3 format */
3787 struct berval *normalized,
3790 struct berval gt, cnt, sid, mod;
3792 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3796 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3797 assert( !BER_BVISEMPTY( val ) );
3801 ptr = ber_bvchr( >, '#' );
3802 if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) {
3803 return LDAP_INVALID_SYNTAX;
3806 gt.bv_len = ptr - gt.bv_val;
3807 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3808 return LDAP_INVALID_SYNTAX;
3811 cnt.bv_val = ptr + 1;
3812 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3814 ptr = ber_bvchr( &cnt, '#' );
3815 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3816 return LDAP_INVALID_SYNTAX;
3819 cnt.bv_len = ptr - cnt.bv_val;
3820 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
3821 return LDAP_INVALID_SYNTAX;
3824 sid.bv_val = ptr + 1;
3825 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3827 ptr = ber_bvchr( &sid, '#' );
3828 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3829 return LDAP_INVALID_SYNTAX;
3832 sid.bv_len = ptr - sid.bv_val;
3833 if ( sid.bv_len != STRLENOF( "00" ) ) {
3834 return LDAP_INVALID_SYNTAX;
3837 mod.bv_val = ptr + 1;
3838 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3839 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3840 return LDAP_INVALID_SYNTAX;
3843 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3847 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
3848 ptr = lutil_strcopy( ptr, ".000000Z#" );
3849 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
3852 for ( i = 0; i < sid.bv_len; i++ ) {
3853 *ptr++ = TOLOWER( sid.bv_val[ i ] );
3856 for ( i = 0; i < mod.bv_len; i++ ) {
3857 *ptr++ = TOLOWER( mod.bv_val[ i ] );
3861 assert( ptr - bv.bv_val == bv.bv_len );
3862 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
3863 return LDAP_INVALID_SYNTAX;
3866 ber_dupbv_x( normalized, &bv, ctx );
3868 return LDAP_SUCCESS;
3871 /* Normalize a CSN */
3878 struct berval *normalized,
3881 struct berval cnt, sid, mod;
3885 assert( val != NULL );
3886 assert( normalized != NULL );
3888 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
3890 if ( BER_BVISEMPTY( val ) ) {
3891 return LDAP_INVALID_SYNTAX;
3894 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3895 /* Openldap <= 2.3 */
3897 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
3900 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
3903 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
3906 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
3907 return LDAP_INVALID_SYNTAX;
3910 ptr = ber_bvchr( val, '#' );
3911 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3912 return LDAP_INVALID_SYNTAX;
3915 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
3916 return LDAP_INVALID_SYNTAX;
3919 cnt.bv_val = ptr + 1;
3920 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
3922 ptr = ber_bvchr( &cnt, '#' );
3923 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3924 return LDAP_INVALID_SYNTAX;
3927 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
3928 return LDAP_INVALID_SYNTAX;
3931 sid.bv_val = ptr + 1;
3932 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
3934 ptr = ber_bvchr( &sid, '#' );
3935 if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) {
3936 return LDAP_INVALID_SYNTAX;
3939 sid.bv_len = ptr - sid.bv_val;
3940 if ( sid.bv_len != STRLENOF( "000" ) ) {
3941 return LDAP_INVALID_SYNTAX;
3944 mod.bv_val = ptr + 1;
3945 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
3947 if ( mod.bv_len != STRLENOF( "000000" ) ) {
3948 return LDAP_INVALID_SYNTAX;
3951 ber_dupbv_x( normalized, val, ctx );
3953 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3954 i < normalized->bv_len; i++ )
3956 /* assume it's already validated that's all hex digits */
3957 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
3960 return LDAP_SUCCESS;
3970 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
3973 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3974 /* slight optimization - does not need the start parameter */
3975 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3980 check_time_syntax (struct berval *val,
3983 struct berval *fraction)
3986 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3987 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3988 * GeneralizedTime supports leap seconds, UTCTime does not.
3990 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3991 static const int mdays[2][12] = {
3992 /* non-leap years */
3993 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3995 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3998 int part, c, c1, c2, tzoffset, leapyear = 0;
4001 e = p + val->bv_len;
4003 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4004 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
4006 for (part = start; part < 7 && p < e; part++) {
4008 if (!ASCII_DIGIT(c1)) {
4013 return LDAP_INVALID_SYNTAX;
4016 if (!ASCII_DIGIT(c)) {
4017 return LDAP_INVALID_SYNTAX;
4019 c += c1 * 10 - '0' * 11;
4020 if ((part | 1) == 3) {
4023 return LDAP_INVALID_SYNTAX;
4026 if (c >= ceiling[part]) {
4027 if (! (c == 60 && part == 6 && start == 0))
4028 return LDAP_INVALID_SYNTAX;
4032 if (part < 5 + start) {
4033 return LDAP_INVALID_SYNTAX;
4035 for (; part < 9; part++) {
4039 /* leapyear check for the Gregorian calendar (year>1581) */
4040 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
4044 if (parts[3] >= mdays[leapyear][parts[2]]) {
4045 return LDAP_INVALID_SYNTAX;
4049 fraction->bv_val = p;
4050 fraction->bv_len = 0;
4051 if (p < e && (*p == '.' || *p == ',')) {
4053 while (++p < e && ASCII_DIGIT(*p)) {
4056 if (p - fraction->bv_val == 1) {
4057 return LDAP_INVALID_SYNTAX;
4059 for (end_num = p; end_num[-1] == '0'; --end_num) {
4062 c = end_num - fraction->bv_val;
4063 if (c != 1) fraction->bv_len = c;
4069 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4075 return LDAP_INVALID_SYNTAX;
4081 for (part = 7; part < 9 && p < e; part++) {
4083 if (!ASCII_DIGIT(c1)) {
4088 return LDAP_INVALID_SYNTAX;
4091 if (!ASCII_DIGIT(c2)) {
4092 return LDAP_INVALID_SYNTAX;
4094 parts[part] = c1 * 10 + c2 - '0' * 11;
4095 if (parts[part] >= ceiling[part]) {
4096 return LDAP_INVALID_SYNTAX;
4099 if (part < 8 + start) {
4100 return LDAP_INVALID_SYNTAX;
4103 if (tzoffset == '-') {
4104 /* negative offset to UTC, ie west of Greenwich */
4105 parts[4] += parts[7];
4106 parts[5] += parts[8];
4107 /* offset is just hhmm, no seconds */
4108 for (part = 6; --part >= 0; ) {
4112 c = mdays[leapyear][parts[2]];
4114 if (parts[part] >= c) {
4116 return LDAP_INVALID_SYNTAX;
4121 } else if (part != 5) {
4126 /* positive offset to UTC, ie east of Greenwich */
4127 parts[4] -= parts[7];
4128 parts[5] -= parts[8];
4129 for (part = 6; --part >= 0; ) {
4130 if (parts[part] < 0) {
4132 return LDAP_INVALID_SYNTAX;
4137 /* make first arg to % non-negative */
4138 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4143 } else if (part != 5) {
4150 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
4153 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4160 struct berval *normalized )
4164 rc = check_time_syntax(val, 1, parts, NULL);
4165 if (rc != LDAP_SUCCESS) {
4169 normalized->bv_val = ch_malloc( 14 );
4170 if ( normalized->bv_val == NULL ) {
4171 return LBER_ERROR_MEMORY;
4174 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4175 parts[1], parts[2] + 1, parts[3] + 1,
4176 parts[4], parts[5], parts[6] );
4177 normalized->bv_len = 13;
4179 return LDAP_SUCCESS;
4189 return check_time_syntax(in, 1, parts, NULL);
4192 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4195 generalizedTimeValidate(
4200 struct berval fraction;
4201 return check_time_syntax(in, 0, parts, &fraction);
4205 generalizedTimeNormalize(
4210 struct berval *normalized,
4215 struct berval fraction;
4217 rc = check_time_syntax(val, 0, parts, &fraction);
4218 if (rc != LDAP_SUCCESS) {
4222 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
4223 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
4224 if ( BER_BVISNULL( normalized ) ) {
4225 return LBER_ERROR_MEMORY;
4228 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
4229 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4230 parts[4], parts[5], parts[6] );
4231 if ( !BER_BVISEMPTY( &fraction ) ) {
4232 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
4233 fraction.bv_val, fraction.bv_len );
4234 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4236 strcpy( normalized->bv_val + len-1, "Z" );
4237 normalized->bv_len = len;
4239 return LDAP_SUCCESS;
4243 generalizedTimeOrderingMatch(
4248 struct berval *value,
4249 void *assertedValue )
4251 struct berval *asserted = (struct berval *) assertedValue;
4252 ber_len_t v_len = value->bv_len;
4253 ber_len_t av_len = asserted->bv_len;
4255 /* ignore trailing 'Z' when comparing */
4256 int match = memcmp( value->bv_val, asserted->bv_val,
4257 (v_len < av_len ? v_len : av_len) - 1 );
4258 if ( match == 0 ) match = v_len - av_len;
4261 return LDAP_SUCCESS;
4264 /* Index generation function */
4265 int generalizedTimeIndexer(
4270 struct berval *prefix,
4278 BerValue bvtmp; /* 40 bit index */
4280 struct lutil_timet tt;
4282 bvtmp.bv_len = sizeof(tmp);
4284 for( i=0; values[i].bv_val != NULL; i++ ) {
4285 /* just count them */
4288 /* we should have at least one value at this point */
4291 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
4293 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4294 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
4295 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
4296 /* Use 40 bits of time for key */
4297 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
4298 lutil_tm2time( &tm, &tt );
4299 tmp[0] = tt.tt_gsec & 0xff;
4300 tmp[4] = tt.tt_sec & 0xff;
4302 tmp[3] = tt.tt_sec & 0xff;
4304 tmp[2] = tt.tt_sec & 0xff;
4306 tmp[1] = tt.tt_sec & 0xff;
4308 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
4312 keys[j].bv_val = NULL;
4317 return LDAP_SUCCESS;
4320 /* Index generation function */
4321 int generalizedTimeFilter(
4326 struct berval *prefix,
4327 void * assertedValue,
4333 BerValue bvtmp; /* 40 bit index */
4334 BerValue *value = (BerValue *) assertedValue;
4336 struct lutil_timet tt;
4338 bvtmp.bv_len = sizeof(tmp);
4340 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4341 /* Use 40 bits of time for key */
4342 if ( value->bv_val && value->bv_len >= 10 &&
4343 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
4345 lutil_tm2time( &tm, &tt );
4346 tmp[0] = tt.tt_gsec & 0xff;
4347 tmp[4] = tt.tt_sec & 0xff;
4349 tmp[3] = tt.tt_sec & 0xff;
4351 tmp[2] = tt.tt_sec & 0xff;
4353 tmp[1] = tt.tt_sec & 0xff;
4355 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
4356 ber_dupbv_x(keys, &bvtmp, ctx );
4357 keys[1].bv_val = NULL;
4365 return LDAP_SUCCESS;
4369 deliveryMethodValidate(
4371 struct berval *val )
4374 #define LENOF(s) (sizeof(s)-1)
4375 struct berval tmp = *val;
4377 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4378 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4379 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4382 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4384 switch( tmp.bv_val[0] ) {
4387 if(( tmp.bv_len >= LENOF("any") ) &&
4388 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
4390 tmp.bv_len -= LENOF("any");
4391 tmp.bv_val += LENOF("any");
4394 return LDAP_INVALID_SYNTAX;
4398 if(( tmp.bv_len >= LENOF("mhs") ) &&
4399 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
4401 tmp.bv_len -= LENOF("mhs");
4402 tmp.bv_val += LENOF("mhs");
4405 return LDAP_INVALID_SYNTAX;
4409 if(( tmp.bv_len >= LENOF("physical") ) &&
4410 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
4412 tmp.bv_len -= LENOF("physical");
4413 tmp.bv_val += LENOF("physical");
4416 return LDAP_INVALID_SYNTAX;
4419 case 'T': /* telex or teletex or telephone */
4420 if(( tmp.bv_len >= LENOF("telex") ) &&
4421 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
4423 tmp.bv_len -= LENOF("telex");
4424 tmp.bv_val += LENOF("telex");
4427 if(( tmp.bv_len >= LENOF("teletex") ) &&
4428 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
4430 tmp.bv_len -= LENOF("teletex");
4431 tmp.bv_val += LENOF("teletex");
4434 if(( tmp.bv_len >= LENOF("telephone") ) &&
4435 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
4437 tmp.bv_len -= LENOF("telephone");
4438 tmp.bv_val += LENOF("telephone");
4441 return LDAP_INVALID_SYNTAX;
4444 case 'G': /* g3fax or g4fax */
4445 if(( tmp.bv_len >= LENOF("g3fax") ) && (
4446 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
4447 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
4449 tmp.bv_len -= LENOF("g3fax");
4450 tmp.bv_val += LENOF("g3fax");
4453 return LDAP_INVALID_SYNTAX;
4457 if(( tmp.bv_len >= LENOF("ia5") ) &&
4458 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
4460 tmp.bv_len -= LENOF("ia5");
4461 tmp.bv_val += LENOF("ia5");
4464 return LDAP_INVALID_SYNTAX;
4468 if(( tmp.bv_len >= LENOF("videotex") ) &&
4469 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
4471 tmp.bv_len -= LENOF("videotex");
4472 tmp.bv_val += LENOF("videotex");
4475 return LDAP_INVALID_SYNTAX;
4478 return LDAP_INVALID_SYNTAX;
4481 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
4483 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4487 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
4491 return LDAP_INVALID_SYNTAX;
4493 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
4502 nisNetgroupTripleValidate(
4504 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;
4516 if ( *p != '(' /*')'*/ ) {
4517 return LDAP_INVALID_SYNTAX;
4520 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4524 return LDAP_INVALID_SYNTAX;
4527 } else if ( !AD_CHAR( *p ) ) {
4528 return LDAP_INVALID_SYNTAX;
4532 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4533 return LDAP_INVALID_SYNTAX;
4539 return LDAP_INVALID_SYNTAX;
4542 return LDAP_SUCCESS;
4546 bootParameterValidate(
4548 struct berval *val )
4552 if ( BER_BVISEMPTY( val ) ) {
4553 return LDAP_INVALID_SYNTAX;
4556 p = (char *)val->bv_val;
4557 e = p + val->bv_len;
4560 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4561 if ( !AD_CHAR( *p ) ) {
4562 return LDAP_INVALID_SYNTAX;
4567 return LDAP_INVALID_SYNTAX;
4571 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4572 if ( !AD_CHAR( *p ) ) {
4573 return LDAP_INVALID_SYNTAX;
4578 return LDAP_INVALID_SYNTAX;
4582 for ( p++; p < e; p++ ) {
4583 if ( !SLAP_PRINTABLE( *p ) ) {
4584 return LDAP_INVALID_SYNTAX;
4588 return LDAP_SUCCESS;
4592 firstComponentNormalize(
4597 struct berval *normalized,
4604 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
4605 ber_dupbv_x( normalized, val, ctx );
4606 return LDAP_SUCCESS;
4609 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4611 if( ! ( val->bv_val[0] == '(' /*')'*/
4612 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
4613 && ! ( val->bv_val[0] == '{' /*'}'*/
4614 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
4616 return LDAP_INVALID_SYNTAX;
4619 /* trim leading white space */
4621 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
4627 /* grab next word */
4628 comp.bv_val = &val->bv_val[len];
4629 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
4630 for( comp.bv_len = 0;
4631 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
4637 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
4638 rc = numericoidValidate( NULL, &comp );
4639 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
4640 rc = integerValidate( NULL, &comp );
4642 rc = LDAP_INVALID_SYNTAX;
4646 if( rc == LDAP_SUCCESS ) {
4647 ber_dupbv_x( normalized, &comp, ctx );
4653 static char *country_gen_syn[] = {
4654 "1.3.6.1.4.1.1466.115.121.1.15",
4655 "1.3.6.1.4.1.1466.115.121.1.26",
4656 "1.3.6.1.4.1.1466.115.121.1.44",
4660 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4661 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4663 static slap_syntax_defs_rec syntax_defs[] = {
4664 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4665 X_BINARY X_NOT_H_R ")",
4666 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4667 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4668 0, NULL, NULL, NULL},
4669 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4670 0, NULL, NULL, NULL},
4671 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4673 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4674 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4676 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4677 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4678 0, NULL, bitStringValidate, NULL },
4679 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4680 0, NULL, booleanValidate, NULL},
4681 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4682 X_BINARY X_NOT_H_R ")",
4683 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4684 NULL, certificateValidate, NULL},
4685 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4686 X_BINARY X_NOT_H_R ")",
4687 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4688 NULL, certificateListValidate, NULL},
4689 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4690 X_BINARY X_NOT_H_R ")",
4691 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
4692 NULL, sequenceValidate, NULL},
4693 #if 0 /* need to go __after__ printableString */
4694 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4695 0, "1.3.6.1.4.1.1466.115.121.1.44",
4696 countryStringValidate, NULL},
4698 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4699 0, NULL, dnValidate, dnPretty},
4700 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4701 0, NULL, rdnValidate, rdnPretty},
4702 #ifdef LDAP_COMP_MATCH
4703 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4704 0, NULL, allComponentsValidate, NULL},
4705 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4706 0, NULL, componentFilterValidate, NULL},
4708 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4709 0, NULL, NULL, NULL},
4710 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4711 0, NULL, deliveryMethodValidate, NULL},
4712 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4713 0, NULL, UTF8StringValidate, NULL},
4714 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4715 0, NULL, NULL, NULL},
4716 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4717 0, NULL, NULL, NULL},
4718 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4719 0, NULL, NULL, NULL},
4720 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4721 0, NULL, NULL, NULL},
4722 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4723 0, NULL, NULL, NULL},
4724 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4725 0, NULL, printablesStringValidate, NULL},
4726 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4727 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4728 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4729 0, NULL, generalizedTimeValidate, NULL},
4730 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4731 0, NULL, NULL, NULL},
4732 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4733 0, NULL, IA5StringValidate, NULL},
4734 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4735 0, NULL, integerValidate, NULL},
4736 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4737 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
4738 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4739 0, NULL, NULL, NULL},
4740 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4741 0, NULL, NULL, NULL},
4742 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4743 0, NULL, NULL, NULL},
4744 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4745 0, NULL, NULL, NULL},
4746 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4747 0, NULL, NULL, NULL},
4748 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4749 0, NULL, nameUIDValidate, nameUIDPretty },
4750 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4751 0, NULL, NULL, NULL},
4752 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4753 0, NULL, numericStringValidate, NULL},
4754 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4755 0, NULL, NULL, NULL},
4756 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4757 0, NULL, numericoidValidate, NULL},
4758 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4759 0, NULL, IA5StringValidate, NULL},
4760 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4761 0, NULL, blobValidate, NULL},
4762 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4763 0, NULL, postalAddressValidate, NULL},
4764 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4765 0, NULL, NULL, NULL},
4766 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4767 0, NULL, NULL, NULL},
4768 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4769 0, NULL, printableStringValidate, NULL},
4770 /* moved here because now depends on Directory String, IA5 String
4771 * and Printable String */
4772 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4773 0, country_gen_syn, countryStringValidate, NULL},
4774 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4775 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4776 0, NULL, subtreeSpecificationValidate, NULL},
4777 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4778 X_BINARY X_NOT_H_R ")",
4779 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
4780 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4781 0, NULL, printableStringValidate, NULL},
4782 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4783 0, NULL, NULL, NULL},
4784 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4785 0, NULL, printablesStringValidate, NULL},
4786 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4787 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4788 0, NULL, utcTimeValidate, NULL},
4790 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4791 0, NULL, NULL, NULL},
4792 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4793 0, NULL, NULL, NULL},
4794 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4795 0, NULL, NULL, NULL},
4796 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4797 0, NULL, NULL, NULL},
4798 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4799 0, NULL, NULL, NULL},
4801 /* RFC 2307 NIS Syntaxes */
4802 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4803 0, NULL, nisNetgroupTripleValidate, NULL},
4804 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4805 0, NULL, bootParameterValidate, NULL},
4807 /* draft-zeilenga-ldap-x509 */
4808 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4809 SLAP_SYNTAX_HIDE, NULL,
4810 serialNumberAndIssuerValidate,
4811 serialNumberAndIssuerPretty},
4812 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4813 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4814 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4815 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4816 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4817 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4818 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4819 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4820 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4821 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4822 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4823 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4825 #ifdef SLAPD_AUTHPASSWD
4826 /* needs updating */
4827 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4828 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4831 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4832 0, NULL, UUIDValidate, UUIDPretty},
4834 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4835 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
4837 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4838 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
4840 /* OpenLDAP Void Syntax */
4841 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4842 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
4844 /* FIXME: OID is unused, but not registered yet */
4845 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4846 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
4848 {NULL, 0, NULL, NULL, NULL}
4851 char *csnSIDMatchSyntaxes[] = {
4852 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4855 char *certificateExactMatchSyntaxes[] = {
4856 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4859 #ifdef LDAP_COMP_MATCH
4860 char *componentFilterMatchSyntaxes[] = {
4861 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4865 char *directoryStringSyntaxes[] = {
4866 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4869 char *integerFirstComponentMatchSyntaxes[] = {
4870 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4871 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4874 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4875 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4876 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4877 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4878 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4879 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4880 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4881 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4882 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4887 * Other matching rules in X.520 that we do not use (yet):
4889 * 2.5.13.25 uTCTimeMatch
4890 * 2.5.13.26 uTCTimeOrderingMatch
4891 * 2.5.13.31* directoryStringFirstComponentMatch
4892 * 2.5.13.32* wordMatch
4893 * 2.5.13.33* keywordMatch
4894 * 2.5.13.36+ certificatePairExactMatch
4895 * 2.5.13.37+ certificatePairMatch
4896 * 2.5.13.38+ certificateListExactMatch
4897 * 2.5.13.39+ certificateListMatch
4898 * 2.5.13.40+ algorithmIdentifierMatch
4899 * 2.5.13.41* storedPrefixMatch
4900 * 2.5.13.42 attributeCertificateMatch
4901 * 2.5.13.43 readerAndKeyIDMatch
4902 * 2.5.13.44 attributeIntegrityMatch
4904 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4905 * (+) described in draft-zeilenga-ldap-x509
4907 static slap_mrule_defs_rec mrule_defs[] = {
4909 * EQUALITY matching rules must be listed after associated APPROX
4910 * matching rules. So, we list all APPROX matching rules first.
4912 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4913 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4914 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4915 NULL, NULL, directoryStringApproxMatch,
4916 directoryStringApproxIndexer, directoryStringApproxFilter,
4919 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4920 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4921 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4922 NULL, NULL, IA5StringApproxMatch,
4923 IA5StringApproxIndexer, IA5StringApproxFilter,
4927 * Other matching rules
4930 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4931 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4932 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4933 NULL, NULL, octetStringMatch,
4934 octetStringIndexer, octetStringFilter,
4937 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4938 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4939 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4940 NULL, dnNormalize, dnMatch,
4941 octetStringIndexer, octetStringFilter,
4944 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4945 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4946 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4947 NULL, dnNormalize, dnRelativeMatch,
4951 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4952 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4953 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4954 NULL, dnNormalize, dnRelativeMatch,
4958 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4959 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4960 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4961 NULL, dnNormalize, dnRelativeMatch,
4965 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4966 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4967 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
4968 NULL, dnNormalize, dnRelativeMatch,
4972 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4973 "SYNTAX 1.2.36.79672281.1.5.0 )",
4974 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4975 NULL, rdnNormalize, rdnMatch,
4976 octetStringIndexer, octetStringFilter,
4979 #ifdef LDAP_COMP_MATCH
4980 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4981 "SYNTAX 1.2.36.79672281.1.5.2 )",
4982 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
4983 NULL, NULL , componentFilterMatch,
4984 octetStringIndexer, octetStringFilter,
4987 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4988 "SYNTAX 1.2.36.79672281.1.5.3 )",
4989 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4990 NULL, NULL , allComponentsMatch,
4991 octetStringIndexer, octetStringFilter,
4994 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4995 "SYNTAX 1.2.36.79672281.1.5.3 )",
4996 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
4997 NULL, NULL , directoryComponentsMatch,
4998 octetStringIndexer, octetStringFilter,
5002 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
5003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5004 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5005 NULL, UTF8StringNormalize, octetStringMatch,
5006 octetStringIndexer, octetStringFilter,
5007 directoryStringApproxMatchOID },
5009 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
5010 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5011 SLAP_MR_ORDERING, directoryStringSyntaxes,
5012 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5014 "caseIgnoreMatch" },
5016 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
5017 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5018 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5019 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5020 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5021 "caseIgnoreMatch" },
5023 {"( 2.5.13.5 NAME 'caseExactMatch' "
5024 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5025 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
5026 NULL, UTF8StringNormalize, octetStringMatch,
5027 octetStringIndexer, octetStringFilter,
5028 directoryStringApproxMatchOID },
5030 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
5031 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
5032 SLAP_MR_ORDERING, directoryStringSyntaxes,
5033 NULL, UTF8StringNormalize, octetStringOrderingMatch,
5037 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
5038 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5039 SLAP_MR_SUBSTR, directoryStringSyntaxes,
5040 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
5041 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5044 {"( 2.5.13.8 NAME 'numericStringMatch' "
5045 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5046 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5047 NULL, numericStringNormalize, octetStringMatch,
5048 octetStringIndexer, octetStringFilter,
5051 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
5052 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
5053 SLAP_MR_ORDERING, NULL,
5054 NULL, numericStringNormalize, octetStringOrderingMatch,
5056 "numericStringMatch" },
5058 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
5059 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5060 SLAP_MR_SUBSTR, NULL,
5061 NULL, numericStringNormalize, octetStringSubstringsMatch,
5062 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5063 "numericStringMatch" },
5065 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
5066 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
5067 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5068 NULL, postalAddressNormalize, octetStringMatch,
5069 octetStringIndexer, octetStringFilter,
5072 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
5073 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5074 SLAP_MR_SUBSTR, NULL,
5075 NULL, NULL, NULL, NULL, NULL,
5076 "caseIgnoreListMatch" },
5078 {"( 2.5.13.13 NAME 'booleanMatch' "
5079 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
5080 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5081 NULL, NULL, booleanMatch,
5082 octetStringIndexer, octetStringFilter,
5085 {"( 2.5.13.14 NAME 'integerMatch' "
5086 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5087 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5088 NULL, NULL, integerMatch,
5089 integerIndexer, integerFilter,
5092 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
5093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5094 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5095 NULL, NULL, integerMatch,
5099 {"( 2.5.13.16 NAME 'bitStringMatch' "
5100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5101 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5102 NULL, NULL, octetStringMatch,
5103 octetStringIndexer, octetStringFilter,
5106 {"( 2.5.13.17 NAME 'octetStringMatch' "
5107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5108 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5109 NULL, NULL, octetStringMatch,
5110 octetStringIndexer, octetStringFilter,
5113 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5115 SLAP_MR_ORDERING, NULL,
5116 NULL, NULL, octetStringOrderingMatch,
5118 "octetStringMatch" },
5120 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5121 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5122 SLAP_MR_SUBSTR, NULL,
5123 NULL, NULL, octetStringSubstringsMatch,
5124 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5125 "octetStringMatch" },
5127 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5128 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5129 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5131 telephoneNumberNormalize, octetStringMatch,
5132 octetStringIndexer, octetStringFilter,
5135 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5136 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5137 SLAP_MR_SUBSTR, NULL,
5138 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
5139 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5140 "telephoneNumberMatch" },
5142 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5143 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5144 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5145 NULL, NULL, NULL, NULL, NULL, NULL },
5147 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5148 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5149 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5150 NULL, uniqueMemberNormalize, uniqueMemberMatch,
5151 uniqueMemberIndexer, uniqueMemberFilter,
5154 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5155 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5156 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5157 NULL, NULL, NULL, NULL, NULL, NULL },
5159 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5160 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5161 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
5162 NULL, generalizedTimeNormalize, octetStringMatch,
5163 generalizedTimeIndexer, generalizedTimeFilter,
5166 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5167 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5168 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5169 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
5171 "generalizedTimeMatch" },
5173 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5174 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5175 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5176 integerFirstComponentMatchSyntaxes,
5177 NULL, firstComponentNormalize, integerMatch,
5178 octetStringIndexer, octetStringFilter,
5181 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5182 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5183 SLAP_MR_EQUALITY | SLAP_MR_EXT,
5184 objectIdentifierFirstComponentMatchSyntaxes,
5185 NULL, firstComponentNormalize, octetStringMatch,
5186 octetStringIndexer, octetStringFilter,
5189 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5190 "SYNTAX 1.3.6.1.1.15.1 )",
5191 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
5192 NULL, certificateExactNormalize, octetStringMatch,
5193 octetStringIndexer, octetStringFilter,
5196 {"( 2.5.13.35 NAME 'certificateMatch' "
5197 "SYNTAX 1.3.6.1.1.15.2 )",
5198 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5199 NULL, NULL, NULL, NULL, NULL,
5202 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5203 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5204 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5205 NULL, IA5StringNormalize, octetStringMatch,
5206 octetStringIndexer, octetStringFilter,
5207 IA5StringApproxMatchOID },
5209 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5210 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5211 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
5212 NULL, IA5StringNormalize, octetStringMatch,
5213 octetStringIndexer, octetStringFilter,
5214 IA5StringApproxMatchOID },
5216 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5217 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5218 SLAP_MR_SUBSTR, NULL,
5219 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5220 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5221 "caseIgnoreIA5Match" },
5223 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5224 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5225 SLAP_MR_SUBSTR, NULL,
5226 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
5227 octetStringSubstringsIndexer, octetStringSubstringsFilter,
5228 "caseExactIA5Match" },
5230 #ifdef SLAPD_AUTHPASSWD
5231 /* needs updating */
5232 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5233 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5234 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5235 NULL, NULL, authPasswordMatch,
5240 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5241 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5243 NULL, NULL, integerBitAndMatch,
5247 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5248 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5250 NULL, NULL, integerBitOrMatch,
5254 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5255 "SYNTAX 1.3.6.1.1.16.1 )",
5256 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
5257 NULL, UUIDNormalize, octetStringMatch,
5258 octetStringIndexer, octetStringFilter,
5261 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5262 "SYNTAX 1.3.6.1.1.16.1 )",
5263 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
5264 NULL, UUIDNormalize, octetStringOrderingMatch,
5265 octetStringIndexer, octetStringFilter,
5268 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5269 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5270 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
5271 NULL, csnNormalize, csnMatch,
5272 csnIndexer, csnFilter,
5275 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5276 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5277 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
5278 NULL, NULL, csnOrderingMatch,
5282 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5283 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5284 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
5285 NULL, csnSidNormalize, octetStringMatch,
5286 octetStringIndexer, octetStringFilter,
5289 /* FIXME: OID is unused, but not registered yet */
5290 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5291 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5292 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
5293 NULL, authzNormalize, authzMatch,
5297 {NULL, SLAP_MR_NONE, NULL,
5298 NULL, NULL, NULL, NULL, NULL,
5303 slap_schema_init( void )
5308 /* we should only be called once (from main) */
5309 assert( schema_init_done == 0 );
5311 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
5312 res = register_syntax( &syntax_defs[i] );
5315 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
5316 syntax_defs[i].sd_desc );
5321 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
5322 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
5323 mrule_defs[i].mrd_compat_syntaxes == NULL )
5326 "slap_schema_init: Ignoring unusable matching rule %s\n",
5327 mrule_defs[i].mrd_desc );
5331 res = register_matching_rule( &mrule_defs[i] );
5335 "slap_schema_init: Error registering matching rule %s\n",
5336 mrule_defs[i].mrd_desc );
5341 res = slap_schema_load();
5342 schema_init_done = 1;
5347 schema_destroy( void )
5356 if( schema_init_done ) {
5357 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
5358 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );