1 /* schema_init.c - init builtin schema */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/schema_init.c,v 1.386.2.22 2008/07/10 00:02:48 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 unsigned int index_substr_if_minlen
= SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT
;
61 unsigned int index_substr_if_maxlen
= SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT
;
62 unsigned int index_substr_any_len
= SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT
;
63 unsigned int index_substr_any_step
= SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT
;
65 unsigned int index_intlen
= SLAP_INDEX_INTLEN_DEFAULT
;
66 unsigned int index_intlen_strlen
= SLAP_INDEX_INTLEN_STRLEN(
67 SLAP_INDEX_INTLEN_DEFAULT
);
69 ldap_pvt_thread_mutex_t ad_undef_mutex
;
70 ldap_pvt_thread_mutex_t oc_undef_mutex
;
73 generalizedTimeValidate(
82 /* no value allowed */
83 return LDAP_INVALID_SYNTAX
;
91 /* any value allowed */
95 #define berValidate blobValidate
102 if ( in
->bv_len
< 2 ) return LDAP_INVALID_SYNTAX
;
103 if ( in
->bv_val
[0] != LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
108 /* X.509 related stuff */
116 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
119 SLAP_X509_OPT_C_VERSION
= SLAP_X509_OPTION
+ 0,
120 SLAP_X509_OPT_C_ISSUERUNIQUEID
= SLAP_X509_OPTION
+ 1,
121 SLAP_X509_OPT_C_SUBJECTUNIQUEID
= SLAP_X509_OPTION
+ 2,
122 SLAP_X509_OPT_C_EXTENSIONS
= SLAP_X509_OPTION
+ 3
126 SLAP_X509_OPT_CL_CRLEXTENSIONS
= SLAP_X509_OPTION
+ 0
129 /* X.509 certificate validation */
130 static int certificateValidate( Syntax
*syntax
, struct berval
*in
)
132 BerElementBuffer berbuf
;
133 BerElement
*ber
= (BerElement
*)&berbuf
;
136 ber_int_t version
= SLAP_X509_V1
;
138 ber_init2( ber
, in
, LBER_USE_DER
);
139 tag
= ber_skip_tag( ber
, &len
); /* Signed wrapper */
140 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
141 tag
= ber_skip_tag( ber
, &len
); /* Sequence */
142 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
143 tag
= ber_peek_tag( ber
, &len
);
144 /* Optional version */
145 if ( tag
== SLAP_X509_OPT_C_VERSION
) {
146 tag
= ber_skip_tag( ber
, &len
);
147 tag
= ber_get_int( ber
, &version
);
148 if ( tag
!= LBER_INTEGER
) return LDAP_INVALID_SYNTAX
;
150 /* NOTE: don't try to parse Serial, because it might be longer
151 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
152 tag
= ber_skip_tag( ber
, &len
); /* Serial */
153 if ( tag
!= LBER_INTEGER
) return LDAP_INVALID_SYNTAX
;
154 ber_skip_data( ber
, len
);
155 tag
= ber_skip_tag( ber
, &len
); /* Signature Algorithm */
156 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
157 ber_skip_data( ber
, len
);
158 tag
= ber_skip_tag( ber
, &len
); /* Issuer DN */
159 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
160 ber_skip_data( ber
, len
);
161 tag
= ber_skip_tag( ber
, &len
); /* Validity */
162 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
163 ber_skip_data( ber
, len
);
164 tag
= ber_skip_tag( ber
, &len
); /* Subject DN */
165 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
166 ber_skip_data( ber
, len
);
167 tag
= ber_skip_tag( ber
, &len
); /* Subject PublicKeyInfo */
168 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
169 ber_skip_data( ber
, len
);
170 tag
= ber_skip_tag( ber
, &len
);
171 if ( tag
== SLAP_X509_OPT_C_ISSUERUNIQUEID
) { /* issuerUniqueID */
172 if ( version
< SLAP_X509_V2
) return LDAP_INVALID_SYNTAX
;
173 ber_skip_data( ber
, len
);
174 tag
= ber_skip_tag( ber
, &len
);
176 if ( tag
== SLAP_X509_OPT_C_SUBJECTUNIQUEID
) { /* subjectUniqueID */
177 if ( version
< SLAP_X509_V2
) return LDAP_INVALID_SYNTAX
;
178 ber_skip_data( ber
, len
);
179 tag
= ber_skip_tag( ber
, &len
);
181 if ( tag
== SLAP_X509_OPT_C_EXTENSIONS
) { /* Extensions */
182 if ( version
< SLAP_X509_V3
) return LDAP_INVALID_SYNTAX
;
183 tag
= ber_skip_tag( ber
, &len
);
184 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
185 ber_skip_data( ber
, len
);
186 tag
= ber_skip_tag( ber
, &len
);
188 /* signatureAlgorithm */
189 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
190 ber_skip_data( ber
, len
);
191 tag
= ber_skip_tag( ber
, &len
);
193 if ( tag
!= LBER_BITSTRING
) return LDAP_INVALID_SYNTAX
;
194 ber_skip_data( ber
, len
);
195 tag
= ber_skip_tag( ber
, &len
);
196 /* Must be at end now */
197 if ( len
|| tag
!= LBER_DEFAULT
) return LDAP_INVALID_SYNTAX
;
201 /* X.509 certificate list validation */
202 static int certificateListValidate( Syntax
*syntax
, struct berval
*in
)
204 BerElementBuffer berbuf
;
205 BerElement
*ber
= (BerElement
*)&berbuf
;
208 ber_int_t version
= SLAP_X509_V1
;
210 ber_init2( ber
, in
, LBER_USE_DER
);
211 tag
= ber_skip_tag( ber
, &len
); /* Signed wrapper */
212 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
213 tag
= ber_skip_tag( ber
, &len
); /* Sequence */
214 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
215 tag
= ber_peek_tag( ber
, &len
);
216 /* Optional version */
217 if ( tag
== LBER_INTEGER
) {
218 tag
= ber_get_int( ber
, &version
);
219 assert( tag
== LBER_INTEGER
);
220 if ( version
!= SLAP_X509_V2
) return LDAP_INVALID_SYNTAX
;
222 tag
= ber_skip_tag( ber
, &len
); /* Signature Algorithm */
223 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
224 ber_skip_data( ber
, len
);
225 tag
= ber_skip_tag( ber
, &len
); /* Issuer DN */
226 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
227 ber_skip_data( ber
, len
);
228 tag
= ber_skip_tag( ber
, &len
); /* thisUpdate */
229 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
230 if ( tag
!= 0x17U
&& tag
!= 0x18U
) return LDAP_INVALID_SYNTAX
;
231 ber_skip_data( ber
, len
);
232 /* Optional nextUpdate */
233 tag
= ber_skip_tag( ber
, &len
);
234 if ( tag
== 0x17U
|| tag
== 0x18U
) {
235 ber_skip_data( ber
, len
);
236 tag
= ber_skip_tag( ber
, &len
);
238 /* revokedCertificates - Sequence of Sequence, Optional */
239 if ( tag
== LBER_SEQUENCE
) {
241 if ( ber_peek_tag( ber
, &seqlen
) == LBER_SEQUENCE
) {
242 /* Should NOT be empty */
243 ber_skip_data( ber
, len
);
244 tag
= ber_skip_tag( ber
, &len
);
247 /* Optional Extensions */
248 if ( tag
== SLAP_X509_OPT_CL_CRLEXTENSIONS
) { /* ? */
249 if ( version
!= SLAP_X509_V2
) return LDAP_INVALID_SYNTAX
;
250 tag
= ber_skip_tag( ber
, &len
);
251 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
252 ber_skip_data( ber
, len
);
253 tag
= ber_skip_tag( ber
, &len
);
255 /* signatureAlgorithm */
256 if ( tag
!= LBER_SEQUENCE
) return LDAP_INVALID_SYNTAX
;
257 ber_skip_data( ber
, len
);
258 tag
= ber_skip_tag( ber
, &len
);
260 if ( tag
!= LBER_BITSTRING
) return LDAP_INVALID_SYNTAX
;
261 ber_skip_data( ber
, len
);
262 tag
= ber_skip_tag( ber
, &len
);
263 /* Must be at end now */
264 if ( len
|| tag
!= LBER_DEFAULT
) return LDAP_INVALID_SYNTAX
;
274 struct berval
*value
,
275 void *assertedValue
)
277 struct berval
*asserted
= (struct berval
*) assertedValue
;
278 int match
= value
->bv_len
- asserted
->bv_len
;
281 match
= memcmp( value
->bv_val
, asserted
->bv_val
, value
->bv_len
);
289 octetStringOrderingMatch(
294 struct berval
*value
,
295 void *assertedValue
)
297 struct berval
*asserted
= (struct berval
*) assertedValue
;
298 ber_len_t v_len
= value
->bv_len
;
299 ber_len_t av_len
= asserted
->bv_len
;
301 int match
= memcmp( value
->bv_val
, asserted
->bv_val
,
302 (v_len
< av_len
? v_len
: av_len
) );
304 if( match
== 0 ) match
= v_len
- av_len
;
312 HASH_CONTEXT
*HASHcontext
,
313 struct berval
*prefix
,
318 HASH_Init(HASHcontext
);
319 if(prefix
&& prefix
->bv_len
> 0) {
320 HASH_Update(HASHcontext
,
321 (unsigned char *)prefix
->bv_val
, prefix
->bv_len
);
323 if(pre
) HASH_Update(HASHcontext
, (unsigned char*)&pre
, sizeof(pre
));
324 HASH_Update(HASHcontext
, (unsigned char*)syntax
->ssyn_oid
, syntax
->ssyn_oidlen
);
325 HASH_Update(HASHcontext
, (unsigned char*)mr
->smr_oid
, mr
->smr_oidlen
);
331 HASH_CONTEXT
*HASHcontext
,
332 unsigned char *HASHdigest
,
333 unsigned char *value
,
336 HASH_CONTEXT ctx
= *HASHcontext
;
337 HASH_Update( &ctx
, value
, len
);
338 HASH_Final( HASHdigest
, &ctx
);
341 /* Index generation function */
342 int octetStringIndexer(
347 struct berval
*prefix
,
355 HASH_CONTEXT HASHcontext
;
356 unsigned char HASHdigest
[HASH_BYTES
];
357 struct berval digest
;
358 digest
.bv_val
= (char *)HASHdigest
;
359 digest
.bv_len
= sizeof(HASHdigest
);
361 for( i
=0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
362 /* just count them */
365 /* we should have at least one value at this point */
368 keys
= slap_sl_malloc( sizeof( struct berval
) * (i
+1), ctx
);
370 slen
= syntax
->ssyn_oidlen
;
371 mlen
= mr
->smr_oidlen
;
373 hashPreset( &HASHcontext
, prefix
, 0, syntax
, mr
);
374 for( i
=0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
375 hashIter( &HASHcontext
, HASHdigest
,
376 (unsigned char *)values
[i
].bv_val
, values
[i
].bv_len
);
377 ber_dupbv_x( &keys
[i
], &digest
, ctx
);
380 BER_BVZERO( &keys
[i
] );
387 /* Index generation function */
388 int octetStringFilter(
393 struct berval
*prefix
,
394 void * assertedValue
,
400 HASH_CONTEXT HASHcontext
;
401 unsigned char HASHdigest
[HASH_BYTES
];
402 struct berval
*value
= (struct berval
*) assertedValue
;
403 struct berval digest
;
404 digest
.bv_val
= (char *)HASHdigest
;
405 digest
.bv_len
= sizeof(HASHdigest
);
407 slen
= syntax
->ssyn_oidlen
;
408 mlen
= mr
->smr_oidlen
;
410 keys
= slap_sl_malloc( sizeof( struct berval
) * 2, ctx
);
412 hashPreset( &HASHcontext
, prefix
, 0, syntax
, mr
);
413 hashIter( &HASHcontext
, HASHdigest
,
414 (unsigned char *)value
->bv_val
, value
->bv_len
);
416 ber_dupbv_x( keys
, &digest
, ctx
);
417 BER_BVZERO( &keys
[1] );
425 octetStringSubstringsMatch(
430 struct berval
*value
,
431 void *assertedValue
)
434 SubstringsAssertion
*sub
= assertedValue
;
435 struct berval left
= *value
;
439 /* Add up asserted input length */
440 if ( !BER_BVISNULL( &sub
->sa_initial
) ) {
441 inlen
+= sub
->sa_initial
.bv_len
;
444 for ( i
= 0; !BER_BVISNULL( &sub
->sa_any
[i
] ); i
++ ) {
445 inlen
+= sub
->sa_any
[i
].bv_len
;
448 if ( !BER_BVISNULL( &sub
->sa_final
) ) {
449 inlen
+= sub
->sa_final
.bv_len
;
452 if ( !BER_BVISNULL( &sub
->sa_initial
) ) {
453 if ( inlen
> left
.bv_len
) {
458 match
= memcmp( sub
->sa_initial
.bv_val
, left
.bv_val
,
459 sub
->sa_initial
.bv_len
);
465 left
.bv_val
+= sub
->sa_initial
.bv_len
;
466 left
.bv_len
-= sub
->sa_initial
.bv_len
;
467 inlen
-= sub
->sa_initial
.bv_len
;
470 if ( !BER_BVISNULL( &sub
->sa_final
) ) {
471 if ( inlen
> left
.bv_len
) {
476 match
= memcmp( sub
->sa_final
.bv_val
,
477 &left
.bv_val
[left
.bv_len
- sub
->sa_final
.bv_len
],
478 sub
->sa_final
.bv_len
);
484 left
.bv_len
-= sub
->sa_final
.bv_len
;
485 inlen
-= sub
->sa_final
.bv_len
;
489 for ( i
= 0; !BER_BVISNULL( &sub
->sa_any
[i
] ); i
++ ) {
494 if ( inlen
> left
.bv_len
) {
495 /* not enough length */
500 if ( BER_BVISEMPTY( &sub
->sa_any
[i
] ) ) {
504 p
= memchr( left
.bv_val
, *sub
->sa_any
[i
].bv_val
, left
.bv_len
);
511 idx
= p
- left
.bv_val
;
513 if ( idx
>= left
.bv_len
) {
514 /* this shouldn't happen */
521 if ( sub
->sa_any
[i
].bv_len
> left
.bv_len
) {
522 /* not enough left */
527 match
= memcmp( left
.bv_val
,
528 sub
->sa_any
[i
].bv_val
,
529 sub
->sa_any
[i
].bv_len
);
537 left
.bv_val
+= sub
->sa_any
[i
].bv_len
;
538 left
.bv_len
-= sub
->sa_any
[i
].bv_len
;
539 inlen
-= sub
->sa_any
[i
].bv_len
;
548 /* Substrings Index generation function */
550 octetStringSubstringsIndexer(
555 struct berval
*prefix
,
564 HASH_CONTEXT HCany
, HCini
, HCfin
;
565 unsigned char HASHdigest
[HASH_BYTES
];
566 struct berval digest
;
567 digest
.bv_val
= (char *)HASHdigest
;
568 digest
.bv_len
= sizeof(HASHdigest
);
572 for ( i
= 0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
573 /* count number of indices to generate */
574 if( flags
& SLAP_INDEX_SUBSTR_INITIAL
) {
575 if( values
[i
].bv_len
>= index_substr_if_maxlen
) {
576 nkeys
+= index_substr_if_maxlen
-
577 (index_substr_if_minlen
- 1);
578 } else if( values
[i
].bv_len
>= index_substr_if_minlen
) {
579 nkeys
+= values
[i
].bv_len
- (index_substr_if_minlen
- 1);
583 if( flags
& SLAP_INDEX_SUBSTR_ANY
) {
584 if( values
[i
].bv_len
>= index_substr_any_len
) {
585 nkeys
+= values
[i
].bv_len
- (index_substr_any_len
- 1);
589 if( flags
& SLAP_INDEX_SUBSTR_FINAL
) {
590 if( values
[i
].bv_len
>= index_substr_if_maxlen
) {
591 nkeys
+= index_substr_if_maxlen
-
592 (index_substr_if_minlen
- 1);
593 } else if( values
[i
].bv_len
>= index_substr_if_minlen
) {
594 nkeys
+= values
[i
].bv_len
- (index_substr_if_minlen
- 1);
600 /* no keys to generate */
605 keys
= slap_sl_malloc( sizeof( struct berval
) * (nkeys
+1), ctx
);
607 slen
= syntax
->ssyn_oidlen
;
608 mlen
= mr
->smr_oidlen
;
610 if ( flags
& SLAP_INDEX_SUBSTR_ANY
)
611 hashPreset( &HCany
, prefix
, SLAP_INDEX_SUBSTR_PREFIX
, syntax
, mr
);
612 if( flags
& SLAP_INDEX_SUBSTR_INITIAL
)
613 hashPreset( &HCini
, prefix
, SLAP_INDEX_SUBSTR_INITIAL_PREFIX
, syntax
, mr
);
614 if( flags
& SLAP_INDEX_SUBSTR_FINAL
)
615 hashPreset( &HCfin
, prefix
, SLAP_INDEX_SUBSTR_FINAL_PREFIX
, syntax
, mr
);
618 for ( i
= 0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
621 if( ( flags
& SLAP_INDEX_SUBSTR_ANY
) &&
622 ( values
[i
].bv_len
>= index_substr_any_len
) )
624 max
= values
[i
].bv_len
- (index_substr_any_len
- 1);
626 for( j
=0; j
<max
; j
++ ) {
627 hashIter( &HCany
, HASHdigest
,
628 (unsigned char *)&values
[i
].bv_val
[j
],
629 index_substr_any_len
);
630 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
634 /* skip if too short */
635 if( values
[i
].bv_len
< index_substr_if_minlen
) continue;
637 max
= index_substr_if_maxlen
< values
[i
].bv_len
638 ? index_substr_if_maxlen
: values
[i
].bv_len
;
640 for( j
=index_substr_if_minlen
; j
<=max
; j
++ ) {
642 if( flags
& SLAP_INDEX_SUBSTR_INITIAL
) {
643 hashIter( &HCini
, HASHdigest
,
644 (unsigned char *)values
[i
].bv_val
, j
);
645 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
648 if( flags
& SLAP_INDEX_SUBSTR_FINAL
) {
649 hashIter( &HCfin
, HASHdigest
,
650 (unsigned char *)&values
[i
].bv_val
[values
[i
].bv_len
-j
], j
);
651 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
658 BER_BVZERO( &keys
[nkeys
] );
669 octetStringSubstringsFilter (
674 struct berval
*prefix
,
675 void * assertedValue
,
679 SubstringsAssertion
*sa
;
682 size_t slen
, mlen
, klen
;
684 HASH_CONTEXT HASHcontext
;
685 unsigned char HASHdigest
[HASH_BYTES
];
686 struct berval
*value
;
687 struct berval digest
;
689 sa
= (SubstringsAssertion
*) assertedValue
;
691 if( flags
& SLAP_INDEX_SUBSTR_INITIAL
&&
692 !BER_BVISNULL( &sa
->sa_initial
) &&
693 sa
->sa_initial
.bv_len
>= index_substr_if_minlen
)
696 if ( sa
->sa_initial
.bv_len
> index_substr_if_maxlen
&&
697 ( flags
& SLAP_INDEX_SUBSTR_ANY
))
699 nkeys
+= 1 + (sa
->sa_initial
.bv_len
- index_substr_if_maxlen
) / index_substr_any_step
;
703 if ( flags
& SLAP_INDEX_SUBSTR_ANY
&& sa
->sa_any
!= NULL
) {
705 for( i
=0; !BER_BVISNULL( &sa
->sa_any
[i
] ); i
++ ) {
706 if( sa
->sa_any
[i
].bv_len
>= index_substr_any_len
) {
707 /* don't bother accounting with stepping */
708 nkeys
+= sa
->sa_any
[i
].bv_len
-
709 ( index_substr_any_len
- 1 );
714 if( flags
& SLAP_INDEX_SUBSTR_FINAL
&&
715 !BER_BVISNULL( &sa
->sa_final
) &&
716 sa
->sa_final
.bv_len
>= index_substr_if_minlen
)
719 if ( sa
->sa_final
.bv_len
> index_substr_if_maxlen
&&
720 ( flags
& SLAP_INDEX_SUBSTR_ANY
))
722 nkeys
+= 1 + (sa
->sa_final
.bv_len
- index_substr_if_maxlen
) / index_substr_any_step
;
731 digest
.bv_val
= (char *)HASHdigest
;
732 digest
.bv_len
= sizeof(HASHdigest
);
734 slen
= syntax
->ssyn_oidlen
;
735 mlen
= mr
->smr_oidlen
;
737 keys
= slap_sl_malloc( sizeof( struct berval
) * (nkeys
+1), ctx
);
740 if( flags
& SLAP_INDEX_SUBSTR_INITIAL
&&
741 !BER_BVISNULL( &sa
->sa_initial
) &&
742 sa
->sa_initial
.bv_len
>= index_substr_if_minlen
)
744 pre
= SLAP_INDEX_SUBSTR_INITIAL_PREFIX
;
745 value
= &sa
->sa_initial
;
747 klen
= index_substr_if_maxlen
< value
->bv_len
748 ? index_substr_if_maxlen
: value
->bv_len
;
750 hashPreset( &HASHcontext
, prefix
, pre
, syntax
, mr
);
751 hashIter( &HASHcontext
, HASHdigest
,
752 (unsigned char *)value
->bv_val
, klen
);
753 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
755 /* If initial is too long and we have subany indexed, use it
756 * to match the excess...
758 if (value
->bv_len
> index_substr_if_maxlen
&& (flags
& SLAP_INDEX_SUBSTR_ANY
))
761 pre
= SLAP_INDEX_SUBSTR_PREFIX
;
762 hashPreset( &HASHcontext
, prefix
, pre
, syntax
, mr
);
763 for ( j
=index_substr_if_maxlen
-1; j
<= value
->bv_len
- index_substr_any_len
; j
+=index_substr_any_step
)
765 hashIter( &HASHcontext
, HASHdigest
,
766 (unsigned char *)&value
->bv_val
[j
], index_substr_any_len
);
767 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
772 if( flags
& SLAP_INDEX_SUBSTR_ANY
&& sa
->sa_any
!= NULL
) {
774 pre
= SLAP_INDEX_SUBSTR_PREFIX
;
775 klen
= index_substr_any_len
;
777 for( i
=0; !BER_BVISNULL( &sa
->sa_any
[i
] ); i
++ ) {
778 if( sa
->sa_any
[i
].bv_len
< index_substr_any_len
) {
782 value
= &sa
->sa_any
[i
];
784 hashPreset( &HASHcontext
, prefix
, pre
, syntax
, mr
);
786 j
<= value
->bv_len
- index_substr_any_len
;
787 j
+= index_substr_any_step
)
789 hashIter( &HASHcontext
, HASHdigest
,
790 (unsigned char *)&value
->bv_val
[j
], klen
);
791 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
796 if( flags
& SLAP_INDEX_SUBSTR_FINAL
&&
797 !BER_BVISNULL( &sa
->sa_final
) &&
798 sa
->sa_final
.bv_len
>= index_substr_if_minlen
)
800 pre
= SLAP_INDEX_SUBSTR_FINAL_PREFIX
;
801 value
= &sa
->sa_final
;
803 klen
= index_substr_if_maxlen
< value
->bv_len
804 ? index_substr_if_maxlen
: value
->bv_len
;
806 hashPreset( &HASHcontext
, prefix
, pre
, syntax
, mr
);
807 hashIter( &HASHcontext
, HASHdigest
,
808 (unsigned char *)&value
->bv_val
[value
->bv_len
-klen
], klen
);
809 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
811 /* If final is too long and we have subany indexed, use it
812 * to match the excess...
814 if (value
->bv_len
> index_substr_if_maxlen
&& (flags
& SLAP_INDEX_SUBSTR_ANY
))
817 pre
= SLAP_INDEX_SUBSTR_PREFIX
;
818 hashPreset( &HASHcontext
, prefix
, pre
, syntax
, mr
);
819 for ( j
=0; j
<= value
->bv_len
- index_substr_if_maxlen
; j
+=index_substr_any_step
)
821 hashIter( &HASHcontext
, HASHdigest
,
822 (unsigned char *)&value
->bv_val
[j
], index_substr_any_len
);
823 ber_dupbv_x( &keys
[nkeys
++], &digest
, ctx
);
829 BER_BVZERO( &keys
[nkeys
] );
846 /* very unforgiving validation, requires no normalization
847 * before simplistic matching
849 if( in
->bv_len
< 3 ) {
850 return LDAP_INVALID_SYNTAX
;
853 /* RFC 4517 Section 3.3.2 Bit String:
854 * BitString = SQUOTE *binary-digit SQUOTE "B"
855 * binary-digit = "0" / "1"
857 * where SQUOTE [RFC4512] is
858 * SQUOTE = %x27 ; single quote ("'")
860 * Example: '0101111101'B
863 if( in
->bv_val
[0] != '\'' ||
864 in
->bv_val
[in
->bv_len
- 2] != '\'' ||
865 in
->bv_val
[in
->bv_len
- 1] != 'B' )
867 return LDAP_INVALID_SYNTAX
;
870 for( i
= in
->bv_len
- 3; i
> 0; i
-- ) {
871 if( in
->bv_val
[i
] != '0' && in
->bv_val
[i
] != '1' ) {
872 return LDAP_INVALID_SYNTAX
;
880 * Syntaxes from RFC 4517
885 A value of the Bit String syntax is a sequence of binary digits. The
886 LDAP-specific encoding of a value of this syntax is defined by the
889 BitString = SQUOTE *binary-digit SQUOTE "B"
891 binary-digit = "0" / "1"
893 The <SQUOTE> rule is defined in [MODELS].
898 The LDAP definition for the Bit String syntax is:
900 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
902 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
906 3.3.21. Name and Optional UID
908 A value of the Name and Optional UID syntax is the distinguished name
909 [MODELS] of an entity optionally accompanied by a unique identifier
910 that serves to differentiate the entity from others with an identical
913 The LDAP-specific encoding of a value of this syntax is defined by
916 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
918 The <BitString> rule is defined in Section 3.3.2. The
919 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
922 Note that although the '#' character may occur in the string
923 representation of a distinguished name, no additional escaping of
924 this character is performed when a <distinguishedName> is encoded in
925 a <NameAndOptionalUID>.
928 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
930 The LDAP definition for the Name and Optional UID syntax is:
932 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
934 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
941 1.4. Common ABNF Productions
944 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
946 SQUOTE = %x27 ; single quote ("'")
950 * Note: normalization strips any leading "0"s, unless the
951 * bit string is exactly "'0'B", so the normalized example,
952 * in slapd, would result in
954 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
956 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
957 * be escaped except when at the beginning of a value, the
958 * definition of Name and Optional UID appears to be flawed,
959 * because there is no clear means to determine whether the
960 * UID part is present or not.
964 * cn=Someone,dc=example,dc=com#'1'B
966 * could be either a NameAndOptionalUID with trailing UID, i.e.
968 * DN = "cn=Someone,dc=example,dc=com"
971 * or a NameAndOptionalUID with no trailing UID, and the AVA
972 * in the last RDN made of
975 * attributeValue = com#'1'B
977 * in fact "com#'1'B" is a valid IA5 string.
979 * As a consequence, current slapd code assumes that the
980 * presence of portions of a BitString at the end of the string
981 * representation of a NameAndOptionalUID means a BitString
982 * is expected, and cause an error otherwise. This is quite
983 * arbitrary, and might change in the future.
993 struct berval dn
, uid
;
995 if( BER_BVISEMPTY( in
) ) return LDAP_SUCCESS
;
997 ber_dupbv( &dn
, in
);
998 if( !dn
.bv_val
) return LDAP_OTHER
;
1000 /* if there's a "#", try bitStringValidate()... */
1001 uid
.bv_val
= strrchr( dn
.bv_val
, '#' );
1002 if ( !BER_BVISNULL( &uid
) ) {
1004 uid
.bv_len
= dn
.bv_len
- ( uid
.bv_val
- dn
.bv_val
);
1006 rc
= bitStringValidate( NULL
, &uid
);
1007 if ( rc
== LDAP_SUCCESS
) {
1008 /* in case of success, trim the UID,
1009 * otherwise treat it as part of the DN */
1010 dn
.bv_len
-= uid
.bv_len
+ 1;
1011 uid
.bv_val
[-1] = '\0';
1015 rc
= dnValidate( NULL
, &dn
);
1017 ber_memfree( dn
.bv_val
);
1028 assert( val
!= NULL
);
1029 assert( out
!= NULL
);
1032 Debug( LDAP_DEBUG_TRACE
, ">>> nameUIDPretty: <%s>\n", val
->bv_val
, 0, 0 );
1034 if( BER_BVISEMPTY( val
) ) {
1035 ber_dupbv_x( out
, val
, ctx
);
1037 } else if ( val
->bv_len
> SLAP_LDAPDN_MAXLEN
) {
1038 return LDAP_INVALID_SYNTAX
;
1042 struct berval dnval
= *val
;
1043 struct berval uidval
= BER_BVNULL
;
1045 uidval
.bv_val
= strrchr( val
->bv_val
, '#' );
1046 if ( !BER_BVISNULL( &uidval
) ) {
1048 uidval
.bv_len
= val
->bv_len
- ( uidval
.bv_val
- val
->bv_val
);
1050 rc
= bitStringValidate( NULL
, &uidval
);
1052 if ( rc
== LDAP_SUCCESS
) {
1053 ber_dupbv_x( &dnval
, val
, ctx
);
1054 dnval
.bv_len
-= uidval
.bv_len
+ 1;
1055 dnval
.bv_val
[dnval
.bv_len
] = '\0';
1058 BER_BVZERO( &uidval
);
1062 rc
= dnPretty( syntax
, &dnval
, out
, ctx
);
1063 if ( dnval
.bv_val
!= val
->bv_val
) {
1064 slap_sl_free( dnval
.bv_val
, ctx
);
1066 if( rc
!= LDAP_SUCCESS
) {
1070 if( !BER_BVISNULL( &uidval
) ) {
1074 tmp
= slap_sl_realloc( out
->bv_val
, out
->bv_len
1075 + STRLENOF( "#" ) + uidval
.bv_len
+ 1,
1078 ber_memfree_x( out
->bv_val
, ctx
);
1082 out
->bv_val
[out
->bv_len
++] = '#';
1083 out
->bv_val
[out
->bv_len
++] = '\'';
1085 got1
= uidval
.bv_len
< sizeof("'0'B");
1086 for( i
= 1; i
< uidval
.bv_len
- 2; i
++ ) {
1087 c
= uidval
.bv_val
[i
];
1090 if( got1
) out
->bv_val
[out
->bv_len
++] = c
;
1094 out
->bv_val
[out
->bv_len
++] = c
;
1099 out
->bv_val
[out
->bv_len
++] = '\'';
1100 out
->bv_val
[out
->bv_len
++] = 'B';
1101 out
->bv_val
[out
->bv_len
] = '\0';
1105 Debug( LDAP_DEBUG_TRACE
, "<<< nameUIDPretty: <%s>\n", out
->bv_val
, 0, 0 );
1107 return LDAP_SUCCESS
;
1111 uniqueMemberNormalize(
1116 struct berval
*normalized
,
1122 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage
) != 0 );
1124 ber_dupbv_x( &out
, val
, ctx
);
1125 if ( BER_BVISEMPTY( &out
) ) {
1129 struct berval uid
= BER_BVNULL
;
1131 uid
.bv_val
= strrchr( out
.bv_val
, '#' );
1132 if ( !BER_BVISNULL( &uid
) ) {
1134 uid
.bv_len
= out
.bv_len
- ( uid
.bv_val
- out
.bv_val
);
1136 rc
= bitStringValidate( NULL
, &uid
);
1137 if ( rc
== LDAP_SUCCESS
) {
1138 uid
.bv_val
[-1] = '\0';
1139 out
.bv_len
-= uid
.bv_len
+ 1;
1145 rc
= dnNormalize( 0, NULL
, NULL
, &out
, normalized
, ctx
);
1147 if( rc
!= LDAP_SUCCESS
) {
1148 slap_sl_free( out
.bv_val
, ctx
);
1149 return LDAP_INVALID_SYNTAX
;
1152 if( !BER_BVISNULL( &uid
) ) {
1155 tmp
= ch_realloc( normalized
->bv_val
,
1156 normalized
->bv_len
+ uid
.bv_len
1157 + STRLENOF("#") + 1 );
1158 if ( tmp
== NULL
) {
1159 ber_memfree_x( normalized
->bv_val
, ctx
);
1163 normalized
->bv_val
= tmp
;
1165 /* insert the separator */
1166 normalized
->bv_val
[normalized
->bv_len
++] = '#';
1168 /* append the UID */
1169 AC_MEMCPY( &normalized
->bv_val
[normalized
->bv_len
],
1170 uid
.bv_val
, uid
.bv_len
);
1171 normalized
->bv_len
+= uid
.bv_len
;
1174 normalized
->bv_val
[normalized
->bv_len
] = '\0';
1177 slap_sl_free( out
.bv_val
, ctx
);
1180 return LDAP_SUCCESS
;
1189 struct berval
*value
,
1190 void *assertedValue
)
1193 struct berval
*asserted
= (struct berval
*) assertedValue
;
1194 struct berval assertedDN
= *asserted
;
1195 struct berval assertedUID
= BER_BVNULL
;
1196 struct berval valueDN
= *value
;
1197 struct berval valueUID
= BER_BVNULL
;
1198 int approx
= ((flags
& SLAP_MR_EQUALITY_APPROX
) == SLAP_MR_EQUALITY_APPROX
);
1200 if ( !BER_BVISEMPTY( asserted
) ) {
1201 assertedUID
.bv_val
= strrchr( assertedDN
.bv_val
, '#' );
1202 if ( !BER_BVISNULL( &assertedUID
) ) {
1203 assertedUID
.bv_val
++;
1204 assertedUID
.bv_len
= assertedDN
.bv_len
1205 - ( assertedUID
.bv_val
- assertedDN
.bv_val
);
1207 if ( bitStringValidate( NULL
, &assertedUID
) == LDAP_SUCCESS
) {
1208 assertedDN
.bv_len
-= assertedUID
.bv_len
+ 1;
1211 BER_BVZERO( &assertedUID
);
1216 if ( !BER_BVISEMPTY( value
) ) {
1218 valueUID
.bv_val
= strrchr( valueDN
.bv_val
, '#' );
1219 if ( !BER_BVISNULL( &valueUID
) ) {
1221 valueUID
.bv_len
= valueDN
.bv_len
1222 - ( valueUID
.bv_val
- valueDN
.bv_val
);
1224 if ( bitStringValidate( NULL
, &valueUID
) == LDAP_SUCCESS
) {
1225 valueDN
.bv_len
-= valueUID
.bv_len
+ 1;
1228 BER_BVZERO( &valueUID
);
1233 if( valueUID
.bv_len
&& assertedUID
.bv_len
) {
1234 match
= valueUID
.bv_len
- assertedUID
.bv_len
;
1237 return LDAP_SUCCESS
;
1240 match
= memcmp( valueUID
.bv_val
, assertedUID
.bv_val
, valueUID
.bv_len
);
1243 return LDAP_SUCCESS
;
1246 } else if ( !approx
&& valueUID
.bv_len
) {
1249 return LDAP_SUCCESS
;
1251 } else if ( !approx
&& assertedUID
.bv_len
) {
1254 return LDAP_SUCCESS
;
1257 return dnMatch( matchp
, flags
, syntax
, mr
, &valueDN
, &assertedDN
);
1261 uniqueMemberIndexer(
1266 struct berval
*prefix
,
1274 for( i
=0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
1275 /* just count them */
1279 dnvalues
= slap_sl_malloc( sizeof( struct berval
) * (i
+1), ctx
);
1281 for( i
=0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
1282 struct berval assertedDN
= values
[i
];
1283 struct berval assertedUID
= BER_BVNULL
;
1285 if ( !BER_BVISEMPTY( &assertedDN
) ) {
1286 assertedUID
.bv_val
= strrchr( assertedDN
.bv_val
, '#' );
1287 if ( !BER_BVISNULL( &assertedUID
) ) {
1288 assertedUID
.bv_val
++;
1289 assertedUID
.bv_len
= assertedDN
.bv_len
1290 - ( assertedUID
.bv_val
- assertedDN
.bv_val
);
1292 if ( bitStringValidate( NULL
, &assertedUID
) == LDAP_SUCCESS
) {
1293 assertedDN
.bv_len
-= assertedUID
.bv_len
+ 1;
1296 BER_BVZERO( &assertedUID
);
1301 dnvalues
[i
] = assertedDN
;
1303 BER_BVZERO( &dnvalues
[i
] );
1305 rc
= octetStringIndexer( use
, flags
, syntax
, mr
, prefix
,
1306 dnvalues
, keysp
, ctx
);
1308 slap_sl_free( dnvalues
, ctx
);
1318 struct berval
*prefix
,
1319 void * assertedValue
,
1323 struct berval
*asserted
= (struct berval
*) assertedValue
;
1324 struct berval assertedDN
= *asserted
;
1325 struct berval assertedUID
= BER_BVNULL
;
1327 if ( !BER_BVISEMPTY( asserted
) ) {
1328 assertedUID
.bv_val
= strrchr( assertedDN
.bv_val
, '#' );
1329 if ( !BER_BVISNULL( &assertedUID
) ) {
1330 assertedUID
.bv_val
++;
1331 assertedUID
.bv_len
= assertedDN
.bv_len
1332 - ( assertedUID
.bv_val
- assertedDN
.bv_val
);
1334 if ( bitStringValidate( NULL
, &assertedUID
) == LDAP_SUCCESS
) {
1335 assertedDN
.bv_len
-= assertedUID
.bv_len
+ 1;
1338 BER_BVZERO( &assertedUID
);
1343 return octetStringFilter( use
, flags
, syntax
, mr
, prefix
,
1344 &assertedDN
, keysp
, ctx
);
1349 * Handling boolean syntax and matching is quite rigid.
1350 * A more flexible approach would be to allow a variety
1351 * of strings to be normalized and prettied into TRUE
1359 /* very unforgiving validation, requires no normalization
1360 * before simplistic matching
1363 if( in
->bv_len
== 4 ) {
1364 if( bvmatch( in
, &slap_true_bv
) ) {
1365 return LDAP_SUCCESS
;
1367 } else if( in
->bv_len
== 5 ) {
1368 if( bvmatch( in
, &slap_false_bv
) ) {
1369 return LDAP_SUCCESS
;
1373 return LDAP_INVALID_SYNTAX
;
1382 struct berval
*value
,
1383 void *assertedValue
)
1385 /* simplistic matching allowed by rigid validation */
1386 struct berval
*asserted
= (struct berval
*) assertedValue
;
1387 *matchp
= value
->bv_len
!= asserted
->bv_len
;
1388 return LDAP_SUCCESS
;
1391 /*-------------------------------------------------------------------
1392 LDAP/X.500 string syntax / matching rules have a few oddities. This
1393 comment attempts to detail how slapd(8) treats them.
1396 StringSyntax X.500 LDAP Matching/Comments
1397 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1398 PrintableString subset subset i/e + ignore insignificant spaces
1399 PrintableString subset subset i/e + ignore insignificant spaces
1400 NumericString subset subset ignore all spaces
1401 IA5String ASCII ASCII i/e + ignore insignificant spaces
1402 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1404 TelephoneNumber subset subset i + ignore all spaces and "-"
1406 See RFC 4518 for details.
1410 In X.500(93), a directory string can be either a PrintableString,
1411 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1412 In later versions, more CHOICEs were added. In all cases the string
1415 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1416 A directory string cannot be zero length.
1418 For matching, there are both case ignore and exact rules. Both
1419 also require that "insignificant" spaces be ignored.
1420 spaces before the first non-space are ignored;
1421 spaces after the last non-space are ignored;
1422 spaces after a space are ignored.
1423 Note: by these rules (and as clarified in X.520), a string of only
1424 spaces is to be treated as if held one space, not empty (which
1425 would be a syntax error).
1428 In ASN.1, numeric string is just a string of digits and spaces
1429 and could be empty. However, in X.500, all attribute values of
1430 numeric string carry a non-empty constraint. For example:
1432 internationalISDNNumber ATTRIBUTE ::= {
1433 WITH SYNTAX InternationalISDNNumber
1434 EQUALITY MATCHING RULE numericStringMatch
1435 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1436 ID id-at-internationalISDNNumber }
1437 InternationalISDNNumber ::=
1438 NumericString (SIZE(1..ub-international-isdn-number))
1440 Unforunately, some assertion values are don't carry the same
1441 constraint (but its unclear how such an assertion could ever
1442 be true). In LDAP, there is one syntax (numericString) not two
1443 (numericString with constraint, numericString without constraint).
1444 This should be treated as numericString with non-empty constraint.
1445 Note that while someone may have no ISDN number, there are no ISDN
1446 numbers which are zero length.
1448 In matching, spaces are ignored.
1451 In ASN.1, Printable string is just a string of printable characters
1452 and can be empty. In X.500, semantics much like NumericString (see
1453 serialNumber for a like example) excepting uses insignificant space
1454 handling instead of ignore all spaces. They must be non-empty.
1457 Basically same as PrintableString. There are no examples in X.500,
1458 but same logic applies. Empty strings are allowed.
1460 -------------------------------------------------------------------*/
1469 unsigned char *u
= (unsigned char *)in
->bv_val
;
1471 if( BER_BVISEMPTY( in
) && syntax
== slap_schema
.si_syn_directoryString
) {
1472 /* directory strings cannot be empty */
1473 return LDAP_INVALID_SYNTAX
;
1476 for( count
= in
->bv_len
; count
> 0; count
-= len
, u
+= len
) {
1477 /* get the length indicated by the first byte */
1478 len
= LDAP_UTF8_CHARLEN2( u
, len
);
1480 /* very basic checks */
1483 if( (u
[5] & 0xC0) != 0x80 ) {
1484 return LDAP_INVALID_SYNTAX
;
1487 if( (u
[4] & 0xC0) != 0x80 ) {
1488 return LDAP_INVALID_SYNTAX
;
1491 if( (u
[3] & 0xC0) != 0x80 ) {
1492 return LDAP_INVALID_SYNTAX
;
1495 if( (u
[2] & 0xC0 )!= 0x80 ) {
1496 return LDAP_INVALID_SYNTAX
;
1499 if( (u
[1] & 0xC0) != 0x80 ) {
1500 return LDAP_INVALID_SYNTAX
;
1503 /* CHARLEN already validated it */
1506 return LDAP_INVALID_SYNTAX
;
1509 /* make sure len corresponds with the offset
1510 to the next character */
1511 if( LDAP_UTF8_OFFSET( (char *)u
) != len
) return LDAP_INVALID_SYNTAX
;
1515 return LDAP_INVALID_SYNTAX
;
1518 return LDAP_SUCCESS
;
1522 UTF8StringNormalize(
1527 struct berval
*normalized
,
1530 struct berval tmp
, nvalue
;
1534 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use
) != 0 );
1536 if( BER_BVISNULL( val
) ) {
1537 /* assume we're dealing with a syntax (e.g., UTF8String)
1538 * which allows empty strings
1540 BER_BVZERO( normalized
);
1541 return LDAP_SUCCESS
;
1544 flags
= SLAP_MR_ASSOCIATED( mr
, slap_schema
.si_mr_caseExactMatch
)
1545 ? LDAP_UTF8_NOCASEFOLD
: LDAP_UTF8_CASEFOLD
;
1546 flags
|= ( ( use
& SLAP_MR_EQUALITY_APPROX
) == SLAP_MR_EQUALITY_APPROX
)
1547 ? LDAP_UTF8_APPROX
: 0;
1549 val
= UTF8bvnormalize( val
, &tmp
, flags
, ctx
);
1554 /* collapse spaces (in place) */
1556 nvalue
.bv_val
= tmp
.bv_val
;
1558 /* trim leading spaces? */
1559 wasspace
= !((( use
& SLAP_MR_SUBSTR_ANY
) == SLAP_MR_SUBSTR_ANY
) ||
1560 (( use
& SLAP_MR_SUBSTR_FINAL
) == SLAP_MR_SUBSTR_FINAL
));
1562 for( i
= 0; i
< tmp
.bv_len
; i
++) {
1563 if ( ASCII_SPACE( tmp
.bv_val
[i
] )) {
1564 if( wasspace
++ == 0 ) {
1565 /* trim repeated spaces */
1566 nvalue
.bv_val
[nvalue
.bv_len
++] = tmp
.bv_val
[i
];
1570 nvalue
.bv_val
[nvalue
.bv_len
++] = tmp
.bv_val
[i
];
1574 if( !BER_BVISEMPTY( &nvalue
) ) {
1575 /* trim trailing space? */
1577 (( use
& SLAP_MR_SUBSTR_INITIAL
) != SLAP_MR_SUBSTR_INITIAL
) &&
1578 ( use
& SLAP_MR_SUBSTR_ANY
) != SLAP_MR_SUBSTR_ANY
))
1582 nvalue
.bv_val
[nvalue
.bv_len
] = '\0';
1585 /* string of all spaces is treated as one space */
1586 nvalue
.bv_val
[0] = ' ';
1587 nvalue
.bv_val
[1] = '\0';
1591 *normalized
= nvalue
;
1592 return LDAP_SUCCESS
;
1596 directoryStringSubstringsMatch(
1601 struct berval
*value
,
1602 void *assertedValue
)
1605 SubstringsAssertion
*sub
= assertedValue
;
1606 struct berval left
= *value
;
1610 if ( !BER_BVISNULL( &sub
->sa_initial
) ) {
1611 if ( sub
->sa_initial
.bv_len
> left
.bv_len
) {
1612 /* not enough left */
1617 match
= memcmp( sub
->sa_initial
.bv_val
, left
.bv_val
,
1618 sub
->sa_initial
.bv_len
);
1624 left
.bv_val
+= sub
->sa_initial
.bv_len
;
1625 left
.bv_len
-= sub
->sa_initial
.bv_len
;
1627 priorspace
= ASCII_SPACE(
1628 sub
->sa_initial
.bv_val
[sub
->sa_initial
.bv_len
] );
1631 if ( sub
->sa_any
) {
1632 for ( i
= 0; !BER_BVISNULL( &sub
->sa_any
[i
] ); i
++ ) {
1636 if( priorspace
&& !BER_BVISEMPTY( &sub
->sa_any
[i
] )
1637 && ASCII_SPACE( sub
->sa_any
[i
].bv_val
[0] ))
1639 /* allow next space to match */
1646 if ( BER_BVISEMPTY( &sub
->sa_any
[i
] ) ) {
1650 if ( sub
->sa_any
[i
].bv_len
> left
.bv_len
) {
1651 /* not enough left */
1656 p
= memchr( left
.bv_val
, *sub
->sa_any
[i
].bv_val
, left
.bv_len
);
1663 idx
= p
- left
.bv_val
;
1665 if ( idx
>= left
.bv_len
) {
1666 /* this shouldn't happen */
1673 if ( sub
->sa_any
[i
].bv_len
> left
.bv_len
) {
1674 /* not enough left */
1679 match
= memcmp( left
.bv_val
,
1680 sub
->sa_any
[i
].bv_val
,
1681 sub
->sa_any
[i
].bv_len
);
1689 left
.bv_val
+= sub
->sa_any
[i
].bv_len
;
1690 left
.bv_len
-= sub
->sa_any
[i
].bv_len
;
1692 priorspace
= ASCII_SPACE(
1693 sub
->sa_any
[i
].bv_val
[sub
->sa_any
[i
].bv_len
] );
1697 if ( !BER_BVISNULL( &sub
->sa_final
) ) {
1698 if( priorspace
&& !BER_BVISEMPTY( &sub
->sa_final
)
1699 && ASCII_SPACE( sub
->sa_final
.bv_val
[0] ))
1701 /* allow next space to match */
1706 if ( sub
->sa_final
.bv_len
> left
.bv_len
) {
1707 /* not enough left */
1712 match
= memcmp( sub
->sa_final
.bv_val
,
1713 &left
.bv_val
[left
.bv_len
- sub
->sa_final
.bv_len
],
1714 sub
->sa_final
.bv_len
);
1723 return LDAP_SUCCESS
;
1726 #if defined(SLAPD_APPROX_INITIALS)
1727 # define SLAPD_APPROX_DELIMITER "._ "
1728 # define SLAPD_APPROX_WORDLEN 2
1730 # define SLAPD_APPROX_DELIMITER " "
1731 # define SLAPD_APPROX_WORDLEN 1
1740 struct berval
*value
,
1741 void *assertedValue
)
1743 struct berval
*nval
, *assertv
;
1744 char *val
, **values
, **words
, *c
;
1745 int i
, count
, len
, nextchunk
=0, nextavail
=0;
1747 /* Yes, this is necessary */
1748 nval
= UTF8bvnormalize( value
, NULL
, LDAP_UTF8_APPROX
, NULL
);
1749 if( nval
== NULL
) {
1751 return LDAP_SUCCESS
;
1754 /* Yes, this is necessary */
1755 assertv
= UTF8bvnormalize( ((struct berval
*)assertedValue
),
1756 NULL
, LDAP_UTF8_APPROX
, NULL
);
1757 if( assertv
== NULL
) {
1760 return LDAP_SUCCESS
;
1763 /* Isolate how many words there are */
1764 for ( c
= nval
->bv_val
, count
= 1; *c
; c
++ ) {
1765 c
= strpbrk( c
, SLAPD_APPROX_DELIMITER
);
1766 if ( c
== NULL
) break;
1771 /* Get a phonetic copy of each word */
1772 words
= (char **)ch_malloc( count
* sizeof(char *) );
1773 values
= (char **)ch_malloc( count
* sizeof(char *) );
1774 for ( c
= nval
->bv_val
, i
= 0; i
< count
; i
++, c
+= strlen(c
) + 1 ) {
1776 values
[i
] = phonetic(c
);
1779 /* Work through the asserted value's words, to see if at least some
1780 of the words are there, in the same order. */
1782 while ( (ber_len_t
) nextchunk
< assertv
->bv_len
) {
1783 len
= strcspn( assertv
->bv_val
+ nextchunk
, SLAPD_APPROX_DELIMITER
);
1788 #if defined(SLAPD_APPROX_INITIALS)
1789 else if( len
== 1 ) {
1790 /* Single letter words need to at least match one word's initial */
1791 for( i
=nextavail
; i
<count
; i
++ )
1792 if( !strncasecmp( assertv
->bv_val
+ nextchunk
, words
[i
], 1 )) {
1799 /* Isolate the next word in the asserted value and phonetic it */
1800 assertv
->bv_val
[nextchunk
+len
] = '\0';
1801 val
= phonetic( assertv
->bv_val
+ nextchunk
);
1803 /* See if this phonetic chunk is in the remaining words of *value */
1804 for( i
=nextavail
; i
<count
; i
++ ){
1805 if( !strcmp( val
, values
[i
] ) ){
1813 /* This chunk in the asserted value was NOT within the *value. */
1819 /* Go on to the next word in the asserted value */
1823 /* If some of the words were seen, call it a match */
1824 if( nextavail
> 0 ) {
1831 /* Cleanup allocs */
1832 ber_bvfree( assertv
);
1833 for( i
=0; i
<count
; i
++ ) {
1834 ch_free( values
[i
] );
1840 return LDAP_SUCCESS
;
1849 struct berval
*prefix
,
1855 int i
,j
, len
, wordcount
, keycount
=0;
1856 struct berval
*newkeys
;
1857 BerVarray keys
=NULL
;
1859 for( j
= 0; !BER_BVISNULL( &values
[j
] ); j
++ ) {
1860 struct berval val
= BER_BVNULL
;
1861 /* Yes, this is necessary */
1862 UTF8bvnormalize( &values
[j
], &val
, LDAP_UTF8_APPROX
, NULL
);
1863 assert( !BER_BVISNULL( &val
) );
1865 /* Isolate how many words there are. There will be a key for each */
1866 for( wordcount
= 0, c
= val
.bv_val
; *c
; c
++) {
1867 len
= strcspn(c
, SLAPD_APPROX_DELIMITER
);
1868 if( len
>= SLAPD_APPROX_WORDLEN
) wordcount
++;
1870 if (*c
== '\0') break;
1874 /* Allocate/increase storage to account for new keys */
1875 newkeys
= (struct berval
*)ch_malloc( (keycount
+ wordcount
+ 1)
1876 * sizeof(struct berval
) );
1877 AC_MEMCPY( newkeys
, keys
, keycount
* sizeof(struct berval
) );
1878 if( keys
) ch_free( keys
);
1881 /* Get a phonetic copy of each word */
1882 for( c
= val
.bv_val
, i
= 0; i
< wordcount
; c
+= len
+ 1 ) {
1884 if( len
< SLAPD_APPROX_WORDLEN
) continue;
1885 ber_str2bv( phonetic( c
), 0, 0, &keys
[keycount
] );
1890 ber_memfree( val
.bv_val
);
1892 BER_BVZERO( &keys
[keycount
] );
1895 return LDAP_SUCCESS
;
1904 struct berval
*prefix
,
1905 void * assertedValue
,
1914 /* Yes, this is necessary */
1915 val
= UTF8bvnormalize( ((struct berval
*)assertedValue
),
1916 NULL
, LDAP_UTF8_APPROX
, NULL
);
1917 if( val
== NULL
|| BER_BVISNULL( val
) ) {
1918 keys
= (struct berval
*)ch_malloc( sizeof(struct berval
) );
1919 BER_BVZERO( &keys
[0] );
1922 return LDAP_SUCCESS
;
1925 /* Isolate how many words there are. There will be a key for each */
1926 for( count
= 0,c
= val
->bv_val
; *c
; c
++) {
1927 len
= strcspn(c
, SLAPD_APPROX_DELIMITER
);
1928 if( len
>= SLAPD_APPROX_WORDLEN
) count
++;
1930 if (*c
== '\0') break;
1934 /* Allocate storage for new keys */
1935 keys
= (struct berval
*)ch_malloc( (count
+ 1) * sizeof(struct berval
) );
1937 /* Get a phonetic copy of each word */
1938 for( c
= val
->bv_val
, i
= 0; i
< count
; c
+= len
+ 1 ) {
1940 if( len
< SLAPD_APPROX_WORDLEN
) continue;
1941 ber_str2bv( phonetic( c
), 0, 0, &keys
[i
] );
1947 BER_BVZERO( &keys
[count
] );
1950 return LDAP_SUCCESS
;
1953 /* Remove all spaces and '-' characters */
1955 telephoneNumberNormalize(
1960 struct berval
*normalized
,
1965 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage
) != 0 );
1967 /* validator should have refused an empty string */
1968 assert( !BER_BVISEMPTY( val
) );
1970 q
= normalized
->bv_val
= slap_sl_malloc( val
->bv_len
+ 1, ctx
);
1972 for( p
= val
->bv_val
; *p
; p
++ ) {
1973 if ( ! ( ASCII_SPACE( *p
) || *p
== '-' )) {
1979 normalized
->bv_len
= q
- normalized
->bv_val
;
1981 if( BER_BVISEMPTY( normalized
) ) {
1982 slap_sl_free( normalized
->bv_val
, ctx
);
1983 BER_BVZERO( normalized
);
1984 return LDAP_INVALID_SYNTAX
;
1987 return LDAP_SUCCESS
;
1995 struct berval val
= *in
;
1997 if( BER_BVISEMPTY( &val
) ) {
1998 /* disallow empty strings */
1999 return LDAP_INVALID_SYNTAX
;
2002 while( OID_LEADCHAR( val
.bv_val
[0] ) ) {
2003 if ( val
.bv_len
== 1 ) {
2004 return LDAP_SUCCESS
;
2007 if ( val
.bv_val
[0] == '0' && !OID_SEPARATOR( val
.bv_val
[1] )) {
2014 while ( OID_LEADCHAR( val
.bv_val
[0] )) {
2018 if ( val
.bv_len
== 0 ) {
2019 return LDAP_SUCCESS
;
2023 if( !OID_SEPARATOR( val
.bv_val
[0] )) {
2031 return LDAP_INVALID_SYNTAX
;
2040 struct berval val
= *in
;
2042 if ( BER_BVISEMPTY( &val
) ) return LDAP_INVALID_SYNTAX
;
2044 if ( val
.bv_val
[0] == '-' ) {
2048 if( BER_BVISEMPTY( &val
) ) { /* bare "-" */
2049 return LDAP_INVALID_SYNTAX
;
2052 if( val
.bv_val
[0] == '0' ) { /* "-0" */
2053 return LDAP_INVALID_SYNTAX
;
2056 } else if ( val
.bv_val
[0] == '0' ) {
2057 if( val
.bv_len
> 1 ) { /* "0<more>" */
2058 return LDAP_INVALID_SYNTAX
;
2061 return LDAP_SUCCESS
;
2064 for( i
=0; i
< val
.bv_len
; i
++ ) {
2065 if( !ASCII_DIGIT(val
.bv_val
[i
]) ) {
2066 return LDAP_INVALID_SYNTAX
;
2070 return LDAP_SUCCESS
;
2079 struct berval
*value
,
2080 void *assertedValue
)
2082 struct berval
*asserted
= (struct berval
*) assertedValue
;
2083 int vsign
= 1, asign
= 1; /* default sign = '+' */
2088 if( v
.bv_val
[0] == '-' ) {
2094 if( BER_BVISEMPTY( &v
) ) vsign
= 0;
2097 if( a
.bv_val
[0] == '-' ) {
2103 if( BER_BVISEMPTY( &a
) ) vsign
= 0;
2105 match
= vsign
- asign
;
2107 match
= ( v
.bv_len
!= a
.bv_len
2108 ? ( v
.bv_len
< a
.bv_len
? -1 : 1 )
2109 : memcmp( v
.bv_val
, a
.bv_val
, v
.bv_len
));
2110 if( vsign
< 0 ) match
= -match
;
2114 return LDAP_SUCCESS
;
2117 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2118 #define INDEX_INTLEN_CHOP 7
2119 #define INDEX_INTLEN_CHOPBYTES 3
2129 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2130 * two's complement value (sign-extended or chopped as needed),
2131 * however the top <number of exponent-bytes + 1> bits of first byte
2132 * above is the inverse sign. The next bit is the sign as delimiter.
2134 ber_slen_t k
= index_intlen_strlen
;
2136 unsigned signmask
= ~0x7fU
;
2137 unsigned char lenbuf
[sizeof(k
) + 2], *lenp
, neg
= 0xff;
2138 struct berval val
= *in
, itmp
= *tmp
;
2140 if ( val
.bv_val
[0] != '-' ) {
2145 /* Chop least significant digits, increase length instead */
2146 if ( val
.bv_len
> (ber_len_t
) k
) {
2147 chop
= (val
.bv_len
-k
+2)/INDEX_INTLEN_CHOP
; /* 2 fewer digits */
2148 val
.bv_len
-= chop
* INDEX_INTLEN_CHOP
; /* #digits chopped */
2149 chop
*= INDEX_INTLEN_CHOPBYTES
; /* #bytes added */
2152 if ( lutil_str2bin( &val
, &itmp
, ctx
)) {
2153 return LDAP_INVALID_SYNTAX
;
2156 /* Omit leading sign byte */
2157 if ( itmp
.bv_val
[0] == neg
) {
2162 k
= (ber_slen_t
) index_intlen
- (ber_slen_t
) (itmp
.bv_len
+ chop
);
2164 assert( chop
== 0 );
2165 memset( key
->bv_val
, neg
, k
); /* sign-extend */
2166 } else if ( k
!= 0 || ((itmp
.bv_val
[0] ^ neg
) & 0xc0) ) {
2167 lenp
= lenbuf
+ sizeof(lenbuf
);
2168 chop
= - (ber_len_t
) k
;
2170 *--lenp
= ((unsigned char) chop
& 0xff) ^ neg
;
2172 } while ( (chop
>>= 8) != 0 || (signmask
>> 1) & (*lenp
^ neg
) );
2173 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2174 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2175 k
= (lenbuf
+ sizeof(lenbuf
)) - lenp
;
2176 if ( k
> (ber_slen_t
) index_intlen
)
2178 memcpy( key
->bv_val
, lenp
, k
);
2179 itmp
.bv_len
= index_intlen
- k
;
2181 memcpy( key
->bv_val
+ k
, itmp
.bv_val
, itmp
.bv_len
);
2182 key
->bv_val
[0] ^= (unsigned char) signmask
& 0xff; /* invert sign */
2186 /* Index generation function */
2193 struct berval
*prefix
,
2203 unsigned maxstrlen
= index_intlen_strlen
+ INDEX_INTLEN_CHOP
-1;
2205 /* count the values and find max needed length */
2207 for( i
= 0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
2208 if ( vlen
< values
[i
].bv_len
)
2209 vlen
= values
[i
].bv_len
;
2211 if ( vlen
> maxstrlen
)
2214 /* we should have at least one value at this point */
2217 keys
= slap_sl_malloc( sizeof( struct berval
) * (i
+1), ctx
);
2218 for ( i
= 0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
2219 keys
[i
].bv_len
= index_intlen
;
2220 keys
[i
].bv_val
= slap_sl_malloc( index_intlen
, ctx
);
2223 keys
[i
].bv_val
= NULL
;
2225 if ( vlen
> sizeof(ibuf
) ) {
2226 itmp
.bv_val
= slap_sl_malloc( vlen
, ctx
);
2230 itmp
.bv_len
= sizeof(ibuf
);
2232 for ( i
=0; !BER_BVISNULL( &values
[i
] ); i
++ ) {
2233 if ( itmp
.bv_val
!= ibuf
) {
2234 itmp
.bv_len
= values
[i
].bv_len
;
2235 if ( itmp
.bv_len
<= sizeof(ibuf
) )
2236 itmp
.bv_len
= sizeof(ibuf
);
2237 else if ( itmp
.bv_len
> maxstrlen
)
2238 itmp
.bv_len
= maxstrlen
;
2240 rc
= integerVal2Key( &values
[i
], &keys
[i
], &itmp
, ctx
);
2246 if ( itmp
.bv_val
!= ibuf
) {
2247 slap_sl_free( itmp
.bv_val
, ctx
);
2252 /* Index generation function */
2259 struct berval
*prefix
,
2260 void * assertedValue
,
2267 struct berval
*value
;
2270 value
= (struct berval
*) assertedValue
;
2272 keys
= slap_sl_malloc( sizeof( struct berval
) * 2, ctx
);
2274 keys
[0].bv_len
= index_intlen
;
2275 keys
[0].bv_val
= slap_sl_malloc( index_intlen
, ctx
);
2277 keys
[1].bv_val
= NULL
;
2279 iv
.bv_len
= value
->bv_len
< index_intlen_strlen
+ INDEX_INTLEN_CHOP
-1
2280 ? value
->bv_len
: index_intlen_strlen
+ INDEX_INTLEN_CHOP
-1;
2281 if ( iv
.bv_len
> (int) sizeof(ibuf
) ) {
2282 iv
.bv_val
= slap_sl_malloc( iv
.bv_len
, ctx
);
2285 iv
.bv_len
= sizeof(ibuf
);
2288 rc
= integerVal2Key( value
, keys
, &iv
, ctx
);
2292 if ( iv
.bv_val
!= ibuf
) {
2293 slap_sl_free( iv
.bv_val
, ctx
);
2299 countryStringValidate(
2301 struct berval
*val
)
2303 if( val
->bv_len
!= 2 ) return LDAP_INVALID_SYNTAX
;
2305 if( !SLAP_PRINTABLE(val
->bv_val
[0]) ) {
2306 return LDAP_INVALID_SYNTAX
;
2308 if( !SLAP_PRINTABLE(val
->bv_val
[1]) ) {
2309 return LDAP_INVALID_SYNTAX
;
2312 return LDAP_SUCCESS
;
2316 printableStringValidate(
2318 struct berval
*val
)
2322 if( BER_BVISEMPTY( val
) ) return LDAP_INVALID_SYNTAX
;
2324 for(i
=0; i
< val
->bv_len
; i
++) {
2325 if( !SLAP_PRINTABLE(val
->bv_val
[i
]) ) {
2326 return LDAP_INVALID_SYNTAX
;
2330 return LDAP_SUCCESS
;
2334 printablesStringValidate(
2336 struct berval
*val
)
2340 if( BER_BVISEMPTY( val
) ) return LDAP_INVALID_SYNTAX
;
2342 for(i
=0,len
=0; i
< val
->bv_len
; i
++) {
2343 int c
= val
->bv_val
[i
];
2347 return LDAP_INVALID_SYNTAX
;
2351 } else if ( SLAP_PRINTABLE(c
) ) {
2354 return LDAP_INVALID_SYNTAX
;
2359 return LDAP_INVALID_SYNTAX
;
2362 return LDAP_SUCCESS
;
2368 struct berval
*val
)
2372 for(i
=0; i
< val
->bv_len
; i
++) {
2373 if( !LDAP_ASCII(val
->bv_val
[i
]) ) {
2374 return LDAP_INVALID_SYNTAX
;
2378 return LDAP_SUCCESS
;
2387 struct berval
*normalized
,
2391 int casefold
= !SLAP_MR_ASSOCIATED( mr
,
2392 slap_schema
.si_mr_caseExactIA5Match
);
2394 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use
) != 0 );
2398 /* Ignore initial whitespace */
2399 while ( ASCII_SPACE( *p
) ) p
++;
2401 normalized
->bv_len
= val
->bv_len
- ( p
- val
->bv_val
);
2402 normalized
->bv_val
= slap_sl_malloc( normalized
->bv_len
+ 1, ctx
);
2403 AC_MEMCPY( normalized
->bv_val
, p
, normalized
->bv_len
);
2404 normalized
->bv_val
[normalized
->bv_len
] = '\0';
2406 p
= q
= normalized
->bv_val
;
2409 if ( ASCII_SPACE( *p
) ) {
2412 /* Ignore the extra whitespace */
2413 while ( ASCII_SPACE( *p
) ) {
2417 } else if ( casefold
) {
2418 /* Most IA5 rules require casefolding */
2419 *q
++ = TOLOWER(*p
); p
++;
2426 assert( normalized
->bv_val
<= p
);
2430 * If the string ended in space, backup the pointer one
2431 * position. One is enough because the above loop collapsed
2432 * all whitespace to a single space.
2434 if ( q
> normalized
->bv_val
&& ASCII_SPACE( q
[-1] ) ) --q
;
2436 /* null terminate */
2439 normalized
->bv_len
= q
- normalized
->bv_val
;
2441 return LDAP_SUCCESS
;
2450 if( in
->bv_len
!= 36 ) {
2451 return LDAP_INVALID_SYNTAX
;
2454 for( i
=0; i
<36; i
++ ) {
2460 if( in
->bv_val
[i
] != '-' ) {
2461 return LDAP_INVALID_SYNTAX
;
2465 if( !ASCII_HEX( in
->bv_val
[i
]) ) {
2466 return LDAP_INVALID_SYNTAX
;
2471 return LDAP_SUCCESS
;
2482 int rc
=LDAP_INVALID_SYNTAX
;
2484 assert( in
!= NULL
);
2485 assert( out
!= NULL
);
2487 if( in
->bv_len
!= 36 ) return LDAP_INVALID_SYNTAX
;
2490 out
->bv_val
= slap_sl_malloc( out
->bv_len
+ 1, ctx
);
2492 for( i
=0; i
<36; i
++ ) {
2498 if( in
->bv_val
[i
] != '-' ) {
2501 out
->bv_val
[i
] = '-';
2505 if( !ASCII_HEX( in
->bv_val
[i
]) ) {
2508 out
->bv_val
[i
] = TOLOWER( in
->bv_val
[i
] );
2513 out
->bv_val
[ out
->bv_len
] = '\0';
2517 slap_sl_free( out
->bv_val
, ctx
);
2530 struct berval
*normalized
,
2533 unsigned char octet
= '\0';
2537 if ( SLAP_MR_IS_DENORMALIZE( usage
) ) {
2538 /* NOTE: must be a normalized UUID */
2539 assert( val
->bv_len
== 16 );
2541 normalized
->bv_val
= slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE
, ctx
);
2542 normalized
->bv_len
= lutil_uuidstr_from_normalized( val
->bv_val
,
2543 val
->bv_len
, normalized
->bv_val
, LDAP_LUTIL_UUIDSTR_BUFSIZE
);
2544 assert( normalized
->bv_len
== STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2546 return LDAP_SUCCESS
;
2549 normalized
->bv_len
= 16;
2550 normalized
->bv_val
= slap_sl_malloc( normalized
->bv_len
+ 1, ctx
);
2552 for( i
=0, j
=0; i
<36; i
++ ) {
2553 unsigned char nibble
;
2554 if( val
->bv_val
[i
] == '-' ) {
2557 } else if( ASCII_DIGIT( val
->bv_val
[i
] ) ) {
2558 nibble
= val
->bv_val
[i
] - '0';
2560 } else if( ASCII_HEXLOWER( val
->bv_val
[i
] ) ) {
2561 nibble
= val
->bv_val
[i
] - ('a'-10);
2563 } else if( ASCII_HEXUPPER( val
->bv_val
[i
] ) ) {
2564 nibble
= val
->bv_val
[i
] - ('A'-10);
2567 slap_sl_free( normalized
->bv_val
, ctx
);
2568 return LDAP_INVALID_SYNTAX
;
2573 normalized
->bv_val
[j
>>1] = octet
;
2575 octet
= nibble
<< 4;
2580 normalized
->bv_val
[normalized
->bv_len
] = 0;
2581 return LDAP_SUCCESS
;
2587 numericStringValidate(
2593 if( BER_BVISEMPTY( in
) ) return LDAP_INVALID_SYNTAX
;
2595 for(i
=0; i
< in
->bv_len
; i
++) {
2596 if( !SLAP_NUMERIC(in
->bv_val
[i
]) ) {
2597 return LDAP_INVALID_SYNTAX
;
2601 return LDAP_SUCCESS
;
2605 numericStringNormalize(
2610 struct berval
*normalized
,
2613 /* removal all spaces */
2616 assert( !BER_BVISEMPTY( val
) );
2618 normalized
->bv_val
= slap_sl_malloc( val
->bv_len
+ 1, ctx
);
2621 q
= normalized
->bv_val
;
2624 if ( ASCII_SPACE( *p
) ) {
2625 /* Ignore whitespace */
2632 /* we should have copied no more than is in val */
2633 assert( (q
- normalized
->bv_val
) <= (p
- val
->bv_val
) );
2635 /* null terminate */
2638 normalized
->bv_len
= q
- normalized
->bv_val
;
2640 if( BER_BVISEMPTY( normalized
) ) {
2641 normalized
->bv_val
= slap_sl_realloc( normalized
->bv_val
, 2, ctx
);
2642 normalized
->bv_val
[0] = ' ';
2643 normalized
->bv_val
[1] = '\0';
2644 normalized
->bv_len
= 1;
2647 return LDAP_SUCCESS
;
2651 * Integer conversion macros that will use the largest available
2654 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2655 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2656 # define SLAP_LONG long long
2658 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2659 # define SLAP_LONG long
2660 #endif /* HAVE_STRTOLL ... */
2668 struct berval
*value
,
2669 void *assertedValue
)
2671 SLAP_LONG lValue
, lAssertedValue
;
2674 /* safe to assume integers are NUL terminated? */
2675 lValue
= SLAP_STRTOL(value
->bv_val
, NULL
, 10);
2676 if( errno
== ERANGE
)
2678 return LDAP_CONSTRAINT_VIOLATION
;
2681 lAssertedValue
= SLAP_STRTOL(((struct berval
*)assertedValue
)->bv_val
,
2683 if( errno
== ERANGE
)
2685 return LDAP_CONSTRAINT_VIOLATION
;
2688 *matchp
= ((lValue
& lAssertedValue
) == lAssertedValue
) ? 0 : 1;
2689 return LDAP_SUCCESS
;
2698 struct berval
*value
,
2699 void *assertedValue
)
2701 SLAP_LONG lValue
, lAssertedValue
;
2704 /* safe to assume integers are NUL terminated? */
2705 lValue
= SLAP_STRTOL(value
->bv_val
, NULL
, 10);
2706 if( errno
== ERANGE
)
2708 return LDAP_CONSTRAINT_VIOLATION
;
2711 lAssertedValue
= SLAP_STRTOL( ((struct berval
*)assertedValue
)->bv_val
,
2713 if( errno
== ERANGE
)
2715 return LDAP_CONSTRAINT_VIOLATION
;
2718 *matchp
= ((lValue
& lAssertedValue
) != 0) ? 0 : -1;
2719 return LDAP_SUCCESS
;
2723 serialNumberAndIssuerCheck(
2732 if( in
->bv_len
< 3 ) return LDAP_INVALID_SYNTAX
;
2734 if( in
->bv_val
[0] != '{' && in
->bv_val
[in
->bv_len
-1] != '}' ) {
2735 /* Parse old format */
2736 is
->bv_val
= ber_bvchr( in
, '$' );
2737 if( BER_BVISNULL( is
) ) return LDAP_INVALID_SYNTAX
;
2739 sn
->bv_val
= in
->bv_val
;
2740 sn
->bv_len
= is
->bv_val
- in
->bv_val
;
2743 is
->bv_len
= in
->bv_len
- (sn
->bv_len
+ 1);
2745 /* eat leading zeros */
2746 for( n
=0; n
< (sn
->bv_len
-1); n
++ ) {
2747 if( sn
->bv_val
[n
] != '0' ) break;
2752 for( n
=0; n
< sn
->bv_len
; n
++ ) {
2753 if( !ASCII_DIGIT(sn
->bv_val
[n
]) ) return LDAP_INVALID_SYNTAX
;
2757 /* Parse GSER format */
2758 int havesn
= 0, haveissuer
= 0, numdquotes
= 0;
2759 struct berval x
= *in
;
2764 /* eat leading spaces */
2765 for( ; (x
.bv_val
[0] == ' ') && x
.bv_len
; x
.bv_val
++, x
.bv_len
--) {
2769 if ( x
.bv_len
< STRLENOF("serialNumber 0,issuer \"\"")) {
2770 return LDAP_INVALID_SYNTAX
;
2773 /* should be at issuer or serialNumber NamedValue */
2774 if( strncasecmp( x
.bv_val
, "issuer", STRLENOF("issuer")) == 0 ) {
2776 x
.bv_val
+= STRLENOF("issuer");
2777 x
.bv_len
-= STRLENOF("issuer");
2779 if( x
.bv_val
[0] != ' ' ) return LDAP_INVALID_SYNTAX
;
2780 x
.bv_val
++; x
.bv_len
--;
2782 /* eat leading spaces */
2783 for( ; (x
.bv_val
[0] == ' ') && x
.bv_len
; x
.bv_val
++, x
.bv_len
--) {
2787 /* For backward compatibility, this part is optional */
2788 if( !strncasecmp( x
.bv_val
, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2789 x
.bv_val
+= STRLENOF("rdnSequence:");
2790 x
.bv_len
-= STRLENOF("rdnSequence:");
2793 if( x
.bv_val
[0] != '"' ) return LDAP_INVALID_SYNTAX
;
2794 x
.bv_val
++; x
.bv_len
--;
2796 is
->bv_val
= x
.bv_val
;
2799 for( ; is
->bv_len
< x
.bv_len
; ) {
2800 if ( is
->bv_val
[is
->bv_len
] != '"' ) {
2804 if ( is
->bv_val
[is
->bv_len
+1] == '"' ) {
2811 x
.bv_val
+= is
->bv_len
+1;
2812 x
.bv_len
-= is
->bv_len
+1;
2814 if ( x
.bv_len
< STRLENOF(",serialNumber 0")) {
2815 return LDAP_INVALID_SYNTAX
;
2820 } else if( strncasecmp( x
.bv_val
, "serialNumber",
2821 STRLENOF("serialNumber")) == 0 )
2823 /* parse serialNumber */
2828 x
.bv_val
+= STRLENOF("serialNumber");
2829 x
.bv_len
-= STRLENOF("serialNumber");
2831 if( x
.bv_val
[0] != ' ' ) return LDAP_INVALID_SYNTAX
;
2832 x
.bv_val
++; x
.bv_len
--;
2834 /* eat leading spaces */
2835 for( ; (x
.bv_val
[0] == ' ') && x
.bv_len
; x
.bv_val
++, x
.bv_len
--) {
2839 sn
->bv_val
= x
.bv_val
;
2842 if( sn
->bv_val
[0] == '-' ) {
2847 if ( sn
->bv_val
[0] == '0' && ( sn
->bv_val
[1] == 'x' ||
2848 sn
->bv_val
[1] == 'X' ))
2851 first
= sn
->bv_val
[2];
2854 sn
->bv_len
+= STRLENOF("0x");
2855 for( ; sn
->bv_len
< x
.bv_len
; sn
->bv_len
++ ) {
2856 if ( !ASCII_HEX( sn
->bv_val
[sn
->bv_len
] )) break;
2859 } else if ( sn
->bv_val
[0] == '\'' ) {
2860 first
= sn
->bv_val
[1];
2863 sn
->bv_len
+= STRLENOF("'");
2865 for( ; sn
->bv_len
< x
.bv_len
; sn
->bv_len
++ ) {
2866 if ( !ASCII_HEX( sn
->bv_val
[sn
->bv_len
] )) break;
2868 if ( sn
->bv_val
[sn
->bv_len
] == '\'' &&
2869 sn
->bv_val
[sn
->bv_len
+ 1] == 'H' )
2871 sn
->bv_len
+= STRLENOF("'H");
2875 return LDAP_INVALID_SYNTAX
;
2879 first
= sn
->bv_val
[0];
2880 for( ; sn
->bv_len
< x
.bv_len
; sn
->bv_len
++ ) {
2881 if ( !ASCII_DIGIT( sn
->bv_val
[sn
->bv_len
] )) break;
2885 if (!( sn
->bv_len
> neg
)) return LDAP_INVALID_SYNTAX
;
2886 if (( sn
->bv_len
> extra
+1+neg
) && ( first
== '0' )) {
2887 return LDAP_INVALID_SYNTAX
;
2890 x
.bv_val
+= sn
->bv_len
; x
.bv_len
-= sn
->bv_len
;
2892 if ( x
.bv_len
< STRLENOF( ",issuer \"\"" )) {
2893 return LDAP_INVALID_SYNTAX
;
2898 } else return LDAP_INVALID_SYNTAX
;
2900 if( x
.bv_val
[0] != ',' ) return LDAP_INVALID_SYNTAX
;
2901 x
.bv_val
++; x
.bv_len
--;
2904 for( ; (x
.bv_val
[0] == ' ') && x
.bv_len
; x
.bv_val
++, x
.bv_len
--) {
2908 /* should be at remaining NamedValue */
2909 if( !haveissuer
&& (strncasecmp( x
.bv_val
, "issuer",
2910 STRLENOF("issuer" )) == 0 ))
2913 x
.bv_val
+= STRLENOF("issuer");
2914 x
.bv_len
-= STRLENOF("issuer");
2916 if( x
.bv_val
[0] != ' ' ) return LDAP_INVALID_SYNTAX
;
2917 x
.bv_val
++; x
.bv_len
--;
2919 /* eat leading spaces */
2920 for( ; (x
.bv_val
[0] == ' ') && x
.bv_len
; x
.bv_val
++, x
.bv_len
--) {
2924 /* For backward compatibility, this part is optional */
2925 if( !strncasecmp( x
.bv_val
, "rdnSequence:", STRLENOF("rdnSequence:"))) {
2926 x
.bv_val
+= STRLENOF("rdnSequence:");
2927 x
.bv_len
-= STRLENOF("rdnSequence:");
2930 if( x
.bv_val
[0] != '"' ) return LDAP_INVALID_SYNTAX
;
2931 x
.bv_val
++; x
.bv_len
--;
2933 is
->bv_val
= x
.bv_val
;
2936 for( ; is
->bv_len
< x
.bv_len
; ) {
2937 if ( is
->bv_val
[is
->bv_len
] != '"' ) {
2941 if ( is
->bv_val
[is
->bv_len
+1] == '"' ) {
2949 x
.bv_val
+= is
->bv_len
+1;
2950 x
.bv_len
-= is
->bv_len
+1;
2952 } else if( !havesn
&& (strncasecmp( x
.bv_val
, "serialNumber",
2953 STRLENOF("serialNumber")) == 0 ))
2955 /* parse serialNumber */
2957 x
.bv_val
+= STRLENOF("serialNumber");
2958 x
.bv_len
-= STRLENOF("serialNumber");
2960 if( x
.bv_val
[0] != ' ' ) return LDAP_INVALID_SYNTAX
;
2961 x
.bv_val
++; x
.bv_len
--;
2963 /* eat leading spaces */
2964 for( ; (x
.bv_val
[0] == ' ') && x
.bv_len
; x
.bv_val
++, x
.bv_len
--) {
2968 sn
->bv_val
= x
.bv_val
;
2971 if( sn
->bv_val
[0] == '-' ) {
2976 if ( sn
->bv_val
[0] == '0' && ( sn
->bv_val
[1] == 'x' ||
2977 sn
->bv_val
[1] == 'X' )) {
2979 for( ; sn
->bv_len
< x
.bv_len
; sn
->bv_len
++ ) {
2980 if ( !ASCII_HEX( sn
->bv_val
[sn
->bv_len
] )) break;
2982 } else if ( sn
->bv_val
[0] == '\'' ) {
2983 for( ; sn
->bv_len
< x
.bv_len
; sn
->bv_len
++ ) {
2984 if ( !ASCII_HEX( sn
->bv_val
[sn
->bv_len
] )) break;
2986 if ( sn
->bv_val
[sn
->bv_len
] == '\'' &&
2987 sn
->bv_val
[sn
->bv_len
+1] == 'H' )
2990 return LDAP_INVALID_SYNTAX
;
2993 for( ; sn
->bv_len
< x
.bv_len
; sn
->bv_len
++ ) {
2994 if ( !ASCII_DIGIT( sn
->bv_val
[sn
->bv_len
] )) break;
2998 if (!( sn
->bv_len
> neg
)) return LDAP_INVALID_SYNTAX
;
2999 if (( sn
->bv_len
> 1+neg
) && ( sn
->bv_val
[neg
] == '0' )) {
3000 return LDAP_INVALID_SYNTAX
;
3003 x
.bv_val
+= sn
->bv_len
;
3004 x
.bv_len
-= sn
->bv_len
;
3006 } else return LDAP_INVALID_SYNTAX
;
3008 /* eat trailing spaces */
3009 for( ; (x
.bv_val
[0] == ' ') && x
.bv_len
; x
.bv_val
++, x
.bv_len
--) {
3013 /* should have no characters left... */
3014 if( x
.bv_len
) return LDAP_INVALID_SYNTAX
;
3016 if ( numdquotes
== 0 ) {
3017 ber_dupbv_x( &ni
, is
, ctx
);
3021 ni
.bv_len
= is
->bv_len
- numdquotes
;
3022 ni
.bv_val
= ber_memalloc_x( ni
.bv_len
+ 1, ctx
);
3023 for ( src
= 0, dst
= 0; src
< is
->bv_len
; src
++, dst
++ ) {
3024 if ( is
->bv_val
[src
] == '"' ) {
3027 ni
.bv_val
[dst
] = is
->bv_val
[src
];
3029 ni
.bv_val
[dst
] = '\0';
3039 serialNumberAndIssuerValidate(
3044 struct berval sn
, i
;
3046 Debug( LDAP_DEBUG_TRACE
, ">>> serialNumberAndIssuerValidate: <%s>\n",
3049 rc
= serialNumberAndIssuerCheck( in
, &sn
, &i
, NULL
);
3053 /* validate DN -- doesn't handle double dquote */
3054 rc
= dnValidate( NULL
, &i
);
3056 rc
= LDAP_INVALID_SYNTAX
;
3058 if( in
->bv_val
[0] == '{' && in
->bv_val
[in
->bv_len
-1] == '}' ) {
3059 slap_sl_free( i
.bv_val
, NULL
);
3062 Debug( LDAP_DEBUG_TRACE
, "<<< serialNumberAndIssuerValidate: OKAY\n",
3068 serialNumberAndIssuerPretty(
3075 struct berval sn
, i
, ni
;
3077 assert( in
!= NULL
);
3078 assert( out
!= NULL
);
3080 Debug( LDAP_DEBUG_TRACE
, ">>> serialNumberAndIssuerPretty: <%s>\n",
3083 rc
= serialNumberAndIssuerCheck( in
, &sn
, &i
, ctx
);
3087 rc
= dnPretty( syntax
, &i
, &ni
, ctx
);
3089 if( in
->bv_val
[0] == '{' && in
->bv_val
[in
->bv_len
-1] == '}' ) {
3090 slap_sl_free( i
.bv_val
, ctx
);
3093 if( rc
) return LDAP_INVALID_SYNTAX
;
3095 /* make room from sn + "$" */
3096 out
->bv_len
= STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3097 + sn
.bv_len
+ ni
.bv_len
;
3098 out
->bv_val
= slap_sl_malloc( out
->bv_len
+ 1, ctx
);
3100 if( out
->bv_val
== NULL
) {
3102 slap_sl_free( ni
.bv_val
, ctx
);
3107 AC_MEMCPY( &out
->bv_val
[n
], "{ serialNumber ",
3108 STRLENOF("{ serialNumber "));
3109 n
= STRLENOF("{ serialNumber ");
3111 AC_MEMCPY( &out
->bv_val
[n
], sn
.bv_val
, sn
.bv_len
);
3114 AC_MEMCPY( &out
->bv_val
[n
], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\""));
3115 n
+= STRLENOF(", issuer rdnSequence:\"");
3117 AC_MEMCPY( &out
->bv_val
[n
], ni
.bv_val
, ni
.bv_len
);
3120 AC_MEMCPY( &out
->bv_val
[n
], "\" }", STRLENOF("\" }"));
3121 n
+= STRLENOF("\" }");
3123 out
->bv_val
[n
] = '\0';
3125 assert( n
== out
->bv_len
);
3127 Debug( LDAP_DEBUG_TRACE
, "<<< serialNumberAndIssuerPretty: <%s>\n",
3128 out
->bv_val
, 0, 0 );
3130 slap_sl_free( ni
.bv_val
, ctx
);
3132 return LDAP_SUCCESS
;
3136 * This routine is called by certificateExactNormalize when
3137 * certificateExactNormalize receives a search string instead of
3138 * a certificate. This routine checks if the search value is valid
3139 * and then returns the normalized value
3142 serialNumberAndIssuerNormalize(
3150 struct berval sn
, sn2
, i
, ni
;
3151 char sbuf
[64], *stmp
= sbuf
;
3155 assert( in
!= NULL
);
3156 assert( out
!= NULL
);
3158 Debug( LDAP_DEBUG_TRACE
, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3161 rc
= serialNumberAndIssuerCheck( in
, &sn
, &i
, ctx
);
3165 rc
= dnNormalize( usage
, syntax
, mr
, &i
, &ni
, ctx
);
3167 if( in
->bv_val
[0] == '{' && in
->bv_val
[in
->bv_len
-1] == '}' ) {
3168 slap_sl_free( i
.bv_val
, ctx
);
3171 if( rc
) return LDAP_INVALID_SYNTAX
;
3173 /* Convert sn to canonical hex */
3174 if ( sn
.bv_len
> sizeof( sbuf
)) {
3175 stmp
= slap_sl_malloc( sn
.bv_len
, ctx
);
3178 sn2
.bv_len
= sn
.bv_len
;
3179 if ( lutil_str2bin( &sn
, &sn2
, ctx
)) {
3180 rc
= LDAP_INVALID_SYNTAX
;
3184 /* make room for sn + "$" */
3185 out
->bv_len
= STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3186 + ( sn2
.bv_len
* 2 + 3 ) + ni
.bv_len
;
3187 out
->bv_val
= slap_sl_malloc( out
->bv_len
+ 1, ctx
);
3189 if( out
->bv_val
== NULL
) {
3191 slap_sl_free( ni
.bv_val
, ctx
);
3197 AC_MEMCPY( &out
->bv_val
[n
], "{ serialNumber ",
3198 STRLENOF( "{ serialNumber " ));
3199 n
= STRLENOF( "{ serialNumber " );
3201 AC_MEMCPY( &out
->bv_val
[n
], sn
.bv_val
, sn
.bv_len
);
3204 unsigned char *v
= (unsigned char *)sn2
.bv_val
;
3205 out
->bv_val
[n
++] = '\'';
3206 for ( j
= 0; j
< sn2
.bv_len
; j
++ ) {
3207 snprintf( &out
->bv_val
[n
], out
->bv_len
- n
+ 1,
3211 out
->bv_val
[n
++] = '\'';
3212 out
->bv_val
[n
++] = 'H';
3215 AC_MEMCPY( &out
->bv_val
[n
], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3216 n
+= STRLENOF( ", issuer rdnSequence:\"" );
3218 AC_MEMCPY( &out
->bv_val
[n
], ni
.bv_val
, ni
.bv_len
);
3221 AC_MEMCPY( &out
->bv_val
[n
], "\" }", STRLENOF( "\" }" ));
3222 n
+= STRLENOF( "\" }" );
3224 out
->bv_val
[n
] = '\0';
3226 assert( n
== out
->bv_len
);
3228 Debug( LDAP_DEBUG_TRACE
, "<<< serialNumberAndIssuerNormalize: <%s>\n",
3229 out
->bv_val
, 0, 0 );
3233 slap_sl_free( stmp
, ctx
);
3234 slap_sl_free( ni
.bv_val
, ctx
);
3240 certificateExactNormalize(
3245 struct berval
*normalized
,
3248 BerElementBuffer berbuf
;
3249 BerElement
*ber
= (BerElement
*)&berbuf
;
3253 char serialbuf
[64], *serial
= serialbuf
;
3254 ber_len_t seriallen
;
3255 struct berval issuer_dn
= BER_BVNULL
, bvdn
;
3257 int rc
= LDAP_INVALID_SYNTAX
;
3259 if( BER_BVISEMPTY( val
) ) goto done
;
3261 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage
) ) {
3262 return serialNumberAndIssuerNormalize(0,NULL
,NULL
,val
,normalized
,ctx
);
3265 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage
) != 0 );
3267 ber_init2( ber
, val
, LBER_USE_DER
);
3268 tag
= ber_skip_tag( ber
, &len
); /* Signed Sequence */
3269 tag
= ber_skip_tag( ber
, &len
); /* Sequence */
3270 tag
= ber_peek_tag( ber
, &len
); /* Optional version? */
3271 if ( tag
== SLAP_X509_OPT_C_VERSION
) {
3272 tag
= ber_skip_tag( ber
, &len
);
3273 tag
= ber_get_int( ber
, &i
); /* version */
3276 /* NOTE: move the test here from certificateValidate,
3277 * so that we can validate certs with serial longer
3278 * than sizeof(ber_int_t) */
3279 tag
= ber_peek_tag( ber
, &len
); /* serial */
3281 /* Use hex format. '123456789abcdef'H
3287 tag
= ber_skip_tag( ber
, &len
);
3288 ptr
= (unsigned char *)ber
->ber_ptr
;
3289 ber_skip_data( ber
, len
);
3291 /* Check for minimal encodings */
3293 if ( ptr
[0] & 0x80 ) {
3294 if (( ptr
[0] == 0xff ) && ( ptr
[1] & 0x80 ))
3295 return LDAP_INVALID_SYNTAX
;
3296 } else if ( ptr
[0] == 0 ) {
3297 if (!( ptr
[1] & 0x80 ))
3298 return LDAP_INVALID_SYNTAX
;
3302 seriallen
= len
* 2 + 4; /* quotes, H, NUL */
3303 if ( seriallen
> sizeof( serialbuf
))
3304 serial
= slap_sl_malloc( seriallen
, ctx
);
3307 for ( i
= 0; i
<len
; i
++ ) {
3308 sprintf( sptr
, "%02X", ptr
[i
] );
3315 tag
= ber_skip_tag( ber
, &len
); /* SignatureAlg */
3316 ber_skip_data( ber
, len
);
3317 tag
= ber_peek_tag( ber
, &len
); /* IssuerDN */
3318 len
= ber_ptrlen( ber
);
3319 bvdn
.bv_val
= val
->bv_val
+ len
;
3320 bvdn
.bv_len
= val
->bv_len
- len
;
3322 rc
= dnX509normalize( &bvdn
, &issuer_dn
);
3323 if( rc
!= LDAP_SUCCESS
) goto done
;
3325 normalized
->bv_len
= STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3326 + seriallen
+ issuer_dn
.bv_len
;
3327 normalized
->bv_val
= ch_malloc(normalized
->bv_len
+1);
3329 p
= (unsigned char *)normalized
->bv_val
;
3331 AC_MEMCPY(p
, "{ serialNumber ", STRLENOF( "{ serialNumber " ));
3332 p
+= STRLENOF( "{ serialNumber " );
3334 AC_MEMCPY(p
, serial
, seriallen
);
3337 AC_MEMCPY(p
, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" ));
3338 p
+= STRLENOF( ", issuer rdnSequence:\"" );
3340 AC_MEMCPY(p
, issuer_dn
.bv_val
, issuer_dn
.bv_len
);
3341 p
+= issuer_dn
.bv_len
;
3343 AC_MEMCPY(p
, "\" }", STRLENOF( "\" }" ));
3344 p
+= STRLENOF( "\" }" );
3348 Debug( LDAP_DEBUG_TRACE
, "certificateExactNormalize: %s\n",
3349 normalized
->bv_val
, NULL
, NULL
);
3354 if ( issuer_dn
.bv_val
) ber_memfree( issuer_dn
.bv_val
);
3355 if ( serial
!= serialbuf
) ber_memfree_x( serial
, ctx
);
3367 assert( in
!= NULL
);
3368 assert( !BER_BVISNULL( in
) );
3370 for ( i
= 0; i
< in
->bv_len
; i
++ ) {
3371 if ( !ASCII_HEX( in
->bv_val
[ i
] ) ) {
3372 return LDAP_INVALID_SYNTAX
;
3376 return LDAP_SUCCESS
;
3379 /* Normalize a SID as used inside a CSN:
3380 * three-digit numeric string */
3387 struct berval
*normalized
,
3392 assert( val
!= NULL
);
3393 assert( normalized
!= NULL
);
3395 ber_dupbv_x( normalized
, val
, ctx
);
3397 for ( i
= 0; i
< normalized
->bv_len
; i
++ ) {
3398 if ( !ASCII_HEX( normalized
->bv_val
[ i
] ) ) {
3399 ber_memfree_x( normalized
->bv_val
, ctx
);
3400 BER_BVZERO( normalized
);
3401 return LDAP_INVALID_SYNTAX
;
3404 normalized
->bv_val
[ i
] = TOLOWER( normalized
->bv_val
[ i
] );
3407 return LDAP_SUCCESS
;
3415 assert( in
!= NULL
);
3416 assert( !BER_BVISNULL( in
) );
3418 if ( in
->bv_len
!= 3 ) {
3419 return LDAP_INVALID_SYNTAX
;
3422 return hexValidate( NULL
, in
);
3425 /* Normalize a SID as used inside a CSN:
3426 * three-digit numeric string */
3433 struct berval
*normalized
,
3436 if ( val
->bv_len
!= 3 ) {
3437 return LDAP_INVALID_SYNTAX
;
3440 return hexNormalize( 0, NULL
, NULL
, val
, normalized
, ctx
);
3450 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX
, NULL
, NULL
, val
, out
, ctx
);
3453 /* Normalize a SID as used inside a CSN, either as-is
3454 * (assertion value) or extracted from the CSN
3455 * (attribute value) */
3462 struct berval
*normalized
,
3470 if ( BER_BVISEMPTY( val
) ) {
3471 return LDAP_INVALID_SYNTAX
;
3474 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage
) ) {
3475 return sidNormalize( 0, NULL
, NULL
, val
, normalized
, ctx
);
3478 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage
) != 0 );
3480 ptr
= ber_bvchr( val
, '#' );
3481 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3482 return LDAP_INVALID_SYNTAX
;
3485 bv
.bv_val
= ptr
+ 1;
3486 bv
.bv_len
= val
->bv_len
- ( ptr
+ 1 - val
->bv_val
);
3488 ptr
= ber_bvchr( &bv
, '#' );
3489 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3490 return LDAP_INVALID_SYNTAX
;
3493 bv
.bv_val
= ptr
+ 1;
3494 bv
.bv_len
= val
->bv_len
- ( ptr
+ 1 - val
->bv_val
);
3496 ptr
= ber_bvchr( &bv
, '#' );
3497 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3498 return LDAP_INVALID_SYNTAX
;
3501 bv
.bv_len
= ptr
- bv
.bv_val
;
3503 if ( bv
.bv_len
== 2 ) {
3504 /* OpenLDAP 2.3 SID */
3506 buf
[ 1 ] = bv
.bv_val
[ 0 ];
3507 buf
[ 2 ] = bv
.bv_val
[ 1 ];
3514 return sidNormalize( 0, NULL
, NULL
, &bv
, normalized
, ctx
);
3526 assert( in
!= NULL
);
3527 assert( !BER_BVISNULL( in
) );
3529 if ( BER_BVISEMPTY( in
) ) {
3530 return LDAP_INVALID_SYNTAX
;
3535 ptr
= ber_bvchr( &bv
, '#' );
3536 if ( ptr
== NULL
|| ptr
- bv
.bv_val
== bv
.bv_len
) {
3537 return LDAP_INVALID_SYNTAX
;
3540 bv
.bv_len
= ptr
- bv
.bv_val
;
3541 if ( bv
.bv_len
!= STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
3542 bv
.bv_len
!= STRLENOF( "YYYYmmddHHMMSSZ" ) )
3544 return LDAP_INVALID_SYNTAX
;
3547 rc
= generalizedTimeValidate( NULL
, &bv
);
3548 if ( rc
!= LDAP_SUCCESS
) {
3552 bv
.bv_val
= ptr
+ 1;
3553 bv
.bv_len
= in
->bv_len
- ( bv
.bv_val
- in
->bv_val
);
3555 ptr
= ber_bvchr( &bv
, '#' );
3556 if ( ptr
== NULL
|| ptr
- in
->bv_val
== in
->bv_len
) {
3557 return LDAP_INVALID_SYNTAX
;
3560 bv
.bv_len
= ptr
- bv
.bv_val
;
3561 if ( bv
.bv_len
!= 6 ) {
3562 return LDAP_INVALID_SYNTAX
;
3565 rc
= hexValidate( NULL
, &bv
);
3566 if ( rc
!= LDAP_SUCCESS
) {
3570 bv
.bv_val
= ptr
+ 1;
3571 bv
.bv_len
= in
->bv_len
- ( bv
.bv_val
- in
->bv_val
);
3573 ptr
= ber_bvchr( &bv
, '#' );
3574 if ( ptr
== NULL
|| ptr
- in
->bv_val
== in
->bv_len
) {
3575 return LDAP_INVALID_SYNTAX
;
3578 bv
.bv_len
= ptr
- bv
.bv_val
;
3579 if ( bv
.bv_len
== 2 ) {
3580 /* tolerate old 2-digit replica-id */
3581 rc
= hexValidate( NULL
, &bv
);
3584 rc
= sidValidate( NULL
, &bv
);
3586 if ( rc
!= LDAP_SUCCESS
) {
3590 bv
.bv_val
= ptr
+ 1;
3591 bv
.bv_len
= in
->bv_len
- ( bv
.bv_val
- in
->bv_val
);
3593 if ( bv
.bv_len
!= 6 ) {
3594 return LDAP_INVALID_SYNTAX
;
3597 return hexValidate( NULL
, &bv
);
3600 /* Normalize a CSN in OpenLDAP 2.1 format */
3607 struct berval
*normalized
,
3610 struct berval gt
, cnt
, sid
, mod
;
3612 char buf
[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3616 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage
) != 0 );
3617 assert( !BER_BVISEMPTY( val
) );
3621 ptr
= ber_bvchr( >
, '#' );
3622 if ( ptr
== NULL
|| ptr
- gt
.bv_val
== gt
.bv_len
) {
3623 return LDAP_INVALID_SYNTAX
;
3626 gt
.bv_len
= ptr
- gt
.bv_val
;
3627 if ( gt
.bv_len
!= STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
3628 return LDAP_INVALID_SYNTAX
;
3631 if ( gt
.bv_val
[ 10 ] != ':' || gt
.bv_val
[ 13 ] != ':' ) {
3632 return LDAP_INVALID_SYNTAX
;
3635 cnt
.bv_val
= ptr
+ 1;
3636 cnt
.bv_len
= val
->bv_len
- ( cnt
.bv_val
- val
->bv_val
);
3638 ptr
= ber_bvchr( &cnt
, '#' );
3639 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3640 return LDAP_INVALID_SYNTAX
;
3643 cnt
.bv_len
= ptr
- cnt
.bv_val
;
3644 if ( cnt
.bv_len
!= STRLENOF( "0x0000" ) ) {
3645 return LDAP_INVALID_SYNTAX
;
3648 if ( strncmp( cnt
.bv_val
, "0x", STRLENOF( "0x" ) ) != 0 ) {
3649 return LDAP_INVALID_SYNTAX
;
3652 cnt
.bv_val
+= STRLENOF( "0x" );
3653 cnt
.bv_len
-= STRLENOF( "0x" );
3655 sid
.bv_val
= ptr
+ 1;
3656 sid
.bv_len
= val
->bv_len
- ( sid
.bv_val
- val
->bv_val
);
3658 ptr
= ber_bvchr( &sid
, '#' );
3659 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3660 return LDAP_INVALID_SYNTAX
;
3663 sid
.bv_len
= ptr
- sid
.bv_val
;
3664 if ( sid
.bv_len
!= STRLENOF( "0" ) ) {
3665 return LDAP_INVALID_SYNTAX
;
3668 mod
.bv_val
= ptr
+ 1;
3669 mod
.bv_len
= val
->bv_len
- ( mod
.bv_val
- val
->bv_val
);
3670 if ( mod
.bv_len
!= STRLENOF( "0000" ) ) {
3671 return LDAP_INVALID_SYNTAX
;
3674 bv
.bv_len
= STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3678 ptr
= lutil_strncopy( ptr
, gt
.bv_val
, STRLENOF( "YYYYmmddHH" ) );
3679 ptr
= lutil_strncopy( ptr
, >
.bv_val
[ STRLENOF( "YYYYmmddHH:" ) ],
3681 ptr
= lutil_strncopy( ptr
, >
.bv_val
[ STRLENOF( "YYYYmmddHH:MM:" ) ],
3683 ptr
= lutil_strcopy( ptr
, ".000000Z#00" );
3684 ptr
= lutil_strncopy( ptr
, cnt
.bv_val
, cnt
.bv_len
);
3688 *ptr
++ = sid
.bv_val
[ 0 ];
3692 for ( i
= 0; i
< mod
.bv_len
; i
++ ) {
3693 *ptr
++ = TOLOWER( mod
.bv_val
[ i
] );
3697 assert( ptr
- bv
.bv_val
== bv
.bv_len
);
3699 if ( csnValidate( syntax
, &bv
) != LDAP_SUCCESS
) {
3700 return LDAP_INVALID_SYNTAX
;
3703 ber_dupbv_x( normalized
, &bv
, ctx
);
3705 return LDAP_SUCCESS
;
3708 /* Normalize a CSN in OpenLDAP 2.3 format */
3715 struct berval
*normalized
,
3718 struct berval gt
, cnt
, sid
, mod
;
3720 char buf
[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
3724 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage
) != 0 );
3725 assert( !BER_BVISEMPTY( val
) );
3729 ptr
= ber_bvchr( >
, '#' );
3730 if ( ptr
== NULL
|| ptr
- gt
.bv_val
== gt
.bv_len
) {
3731 return LDAP_INVALID_SYNTAX
;
3734 gt
.bv_len
= ptr
- gt
.bv_val
;
3735 if ( gt
.bv_len
!= STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3736 return LDAP_INVALID_SYNTAX
;
3739 cnt
.bv_val
= ptr
+ 1;
3740 cnt
.bv_len
= val
->bv_len
- ( cnt
.bv_val
- val
->bv_val
);
3742 ptr
= ber_bvchr( &cnt
, '#' );
3743 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3744 return LDAP_INVALID_SYNTAX
;
3747 cnt
.bv_len
= ptr
- cnt
.bv_val
;
3748 if ( cnt
.bv_len
!= STRLENOF( "000000" ) ) {
3749 return LDAP_INVALID_SYNTAX
;
3752 sid
.bv_val
= ptr
+ 1;
3753 sid
.bv_len
= val
->bv_len
- ( sid
.bv_val
- val
->bv_val
);
3755 ptr
= ber_bvchr( &sid
, '#' );
3756 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3757 return LDAP_INVALID_SYNTAX
;
3760 sid
.bv_len
= ptr
- sid
.bv_val
;
3761 if ( sid
.bv_len
!= STRLENOF( "00" ) ) {
3762 return LDAP_INVALID_SYNTAX
;
3765 mod
.bv_val
= ptr
+ 1;
3766 mod
.bv_len
= val
->bv_len
- ( mod
.bv_val
- val
->bv_val
);
3767 if ( mod
.bv_len
!= STRLENOF( "000000" ) ) {
3768 return LDAP_INVALID_SYNTAX
;
3771 bv
.bv_len
= STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
3775 ptr
= lutil_strncopy( ptr
, gt
.bv_val
, gt
.bv_len
- 1 );
3776 ptr
= lutil_strcopy( ptr
, ".000000Z#" );
3777 ptr
= lutil_strncopy( ptr
, cnt
.bv_val
, cnt
.bv_len
);
3780 for ( i
= 0; i
< sid
.bv_len
; i
++ ) {
3781 *ptr
++ = TOLOWER( sid
.bv_val
[ i
] );
3784 for ( i
= 0; i
< mod
.bv_len
; i
++ ) {
3785 *ptr
++ = TOLOWER( mod
.bv_val
[ i
] );
3789 assert( ptr
- bv
.bv_val
== bv
.bv_len
);
3790 if ( csnValidate( syntax
, &bv
) != LDAP_SUCCESS
) {
3791 return LDAP_INVALID_SYNTAX
;
3794 ber_dupbv_x( normalized
, &bv
, ctx
);
3796 return LDAP_SUCCESS
;
3799 /* Normalize a CSN */
3806 struct berval
*normalized
,
3809 struct berval cnt
, sid
, mod
;
3813 assert( val
!= NULL
);
3814 assert( normalized
!= NULL
);
3816 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage
) != 0 );
3818 if ( BER_BVISEMPTY( val
) ) {
3819 return LDAP_INVALID_SYNTAX
;
3822 if ( val
->bv_len
== STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
3823 /* Openldap <= 2.3 */
3825 return csnNormalize23( usage
, syntax
, mr
, val
, normalized
, ctx
);
3828 if ( val
->bv_len
== STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
3831 return csnNormalize21( usage
, syntax
, mr
, val
, normalized
, ctx
);
3834 if ( val
->bv_len
!= STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
3835 return LDAP_INVALID_SYNTAX
;
3838 ptr
= ber_bvchr( val
, '#' );
3839 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3840 return LDAP_INVALID_SYNTAX
;
3843 if ( ptr
- val
->bv_val
!= STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
3844 return LDAP_INVALID_SYNTAX
;
3847 cnt
.bv_val
= ptr
+ 1;
3848 cnt
.bv_len
= val
->bv_len
- ( cnt
.bv_val
- val
->bv_val
);
3850 ptr
= ber_bvchr( &cnt
, '#' );
3851 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3852 return LDAP_INVALID_SYNTAX
;
3855 if ( ptr
- cnt
.bv_val
!= STRLENOF( "000000" ) ) {
3856 return LDAP_INVALID_SYNTAX
;
3859 sid
.bv_val
= ptr
+ 1;
3860 sid
.bv_len
= val
->bv_len
- ( sid
.bv_val
- val
->bv_val
);
3862 ptr
= ber_bvchr( &sid
, '#' );
3863 if ( ptr
== NULL
|| ptr
- val
->bv_val
== val
->bv_len
) {
3864 return LDAP_INVALID_SYNTAX
;
3867 sid
.bv_len
= ptr
- sid
.bv_val
;
3868 if ( sid
.bv_len
!= STRLENOF( "000" ) ) {
3869 return LDAP_INVALID_SYNTAX
;
3872 mod
.bv_val
= ptr
+ 1;
3873 mod
.bv_len
= val
->bv_len
- ( mod
.bv_val
- val
->bv_val
);
3875 if ( mod
.bv_len
!= STRLENOF( "000000" ) ) {
3876 return LDAP_INVALID_SYNTAX
;
3879 ber_dupbv_x( normalized
, val
, ctx
);
3881 for ( i
= STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
3882 i
< normalized
->bv_len
; i
++ )
3884 /* assume it's already validated that's all hex digits */
3885 normalized
->bv_val
[ i
] = TOLOWER( normalized
->bv_val
[ i
] );
3888 return LDAP_SUCCESS
;
3898 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX
, NULL
, NULL
, val
, out
, ctx
);
3901 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
3902 /* slight optimization - does not need the start parameter */
3903 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
3908 check_time_syntax (struct berval
*val
,
3911 struct berval
*fraction
)
3914 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
3915 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
3916 * GeneralizedTime supports leap seconds, UTCTime does not.
3918 static const int ceiling
[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
3919 static const int mdays
[2][12] = {
3920 /* non-leap years */
3921 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
3923 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3926 int part
, c
, c1
, c2
, tzoffset
, leapyear
= 0;
3929 e
= p
+ val
->bv_len
;
3931 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3932 parts
[0] = 20; /* century - any multiple of 4 from 04 to 96 */
3934 for (part
= start
; part
< 7 && p
< e
; part
++) {
3936 if (!ASCII_DIGIT(c1
)) {
3941 return LDAP_INVALID_SYNTAX
;
3944 if (!ASCII_DIGIT(c
)) {
3945 return LDAP_INVALID_SYNTAX
;
3947 c
+= c1
* 10 - '0' * 11;
3948 if ((part
| 1) == 3) {
3951 return LDAP_INVALID_SYNTAX
;
3954 if (c
>= ceiling
[part
]) {
3955 if (! (c
== 60 && part
== 6 && start
== 0))
3956 return LDAP_INVALID_SYNTAX
;
3960 if (part
< 5 + start
) {
3961 return LDAP_INVALID_SYNTAX
;
3963 for (; part
< 9; part
++) {
3967 /* leapyear check for the Gregorian calendar (year>1581) */
3968 if (parts
[parts
[1] == 0 ? 0 : 1] % 4 == 0) {
3972 if (parts
[3] >= mdays
[leapyear
][parts
[2]]) {
3973 return LDAP_INVALID_SYNTAX
;
3977 fraction
->bv_val
= p
;
3978 fraction
->bv_len
= 0;
3979 if (p
< e
&& (*p
== '.' || *p
== ',')) {
3981 while (++p
< e
&& ASCII_DIGIT(*p
)) {
3984 if (p
- fraction
->bv_val
== 1) {
3985 return LDAP_INVALID_SYNTAX
;
3987 for (end_num
= p
; end_num
[-1] == '0'; --end_num
) {
3990 c
= end_num
- fraction
->bv_val
;
3991 if (c
!= 1) fraction
->bv_len
= c
;
3997 return start
== 0 ? LDAP_INVALID_SYNTAX
: LDAP_SUCCESS
;
4003 return LDAP_INVALID_SYNTAX
;
4009 for (part
= 7; part
< 9 && p
< e
; part
++) {
4011 if (!ASCII_DIGIT(c1
)) {
4016 return LDAP_INVALID_SYNTAX
;
4019 if (!ASCII_DIGIT(c2
)) {
4020 return LDAP_INVALID_SYNTAX
;
4022 parts
[part
] = c1
* 10 + c2
- '0' * 11;
4023 if (parts
[part
] >= ceiling
[part
]) {
4024 return LDAP_INVALID_SYNTAX
;
4027 if (part
< 8 + start
) {
4028 return LDAP_INVALID_SYNTAX
;
4031 if (tzoffset
== '-') {
4032 /* negative offset to UTC, ie west of Greenwich */
4033 parts
[4] += parts
[7];
4034 parts
[5] += parts
[8];
4035 /* offset is just hhmm, no seconds */
4036 for (part
= 6; --part
>= 0; ) {
4040 c
= mdays
[leapyear
][parts
[2]];
4042 if (parts
[part
] >= c
) {
4044 return LDAP_INVALID_SYNTAX
;
4049 } else if (part
!= 5) {
4054 /* positive offset to UTC, ie east of Greenwich */
4055 parts
[4] -= parts
[7];
4056 parts
[5] -= parts
[8];
4057 for (part
= 6; --part
>= 0; ) {
4058 if (parts
[part
] < 0) {
4060 return LDAP_INVALID_SYNTAX
;
4065 /* make first arg to % non-negative */
4066 c
= mdays
[leapyear
][(parts
[2] - 1 + 12) % 12];
4071 } else if (part
!= 5) {
4078 return p
!= e
? LDAP_INVALID_SYNTAX
: LDAP_SUCCESS
;
4081 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4088 struct berval
*normalized
)
4092 rc
= check_time_syntax(val
, 1, parts
, NULL
);
4093 if (rc
!= LDAP_SUCCESS
) {
4097 normalized
->bv_val
= ch_malloc( 14 );
4098 if ( normalized
->bv_val
== NULL
) {
4099 return LBER_ERROR_MEMORY
;
4102 sprintf( normalized
->bv_val
, "%02d%02d%02d%02d%02d%02dZ",
4103 parts
[1], parts
[2] + 1, parts
[3] + 1,
4104 parts
[4], parts
[5], parts
[6] );
4105 normalized
->bv_len
= 13;
4107 return LDAP_SUCCESS
;
4117 return check_time_syntax(in
, 1, parts
, NULL
);
4120 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
4123 generalizedTimeValidate(
4128 struct berval fraction
;
4129 return check_time_syntax(in
, 0, parts
, &fraction
);
4133 generalizedTimeNormalize(
4138 struct berval
*normalized
,
4143 struct berval fraction
;
4145 rc
= check_time_syntax(val
, 0, parts
, &fraction
);
4146 if (rc
!= LDAP_SUCCESS
) {
4150 len
= STRLENOF("YYYYmmddHHMMSSZ") + fraction
.bv_len
;
4151 normalized
->bv_val
= slap_sl_malloc( len
+ 1, ctx
);
4152 if ( BER_BVISNULL( normalized
) ) {
4153 return LBER_ERROR_MEMORY
;
4156 sprintf( normalized
->bv_val
, "%02d%02d%02d%02d%02d%02d%02d",
4157 parts
[0], parts
[1], parts
[2] + 1, parts
[3] + 1,
4158 parts
[4], parts
[5], parts
[6] );
4159 if ( !BER_BVISEMPTY( &fraction
) ) {
4160 memcpy( normalized
->bv_val
+ STRLENOF("YYYYmmddHHMMSSZ")-1,
4161 fraction
.bv_val
, fraction
.bv_len
);
4162 normalized
->bv_val
[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
4164 strcpy( normalized
->bv_val
+ len
-1, "Z" );
4165 normalized
->bv_len
= len
;
4167 return LDAP_SUCCESS
;
4171 generalizedTimeOrderingMatch(
4176 struct berval
*value
,
4177 void *assertedValue
)
4179 struct berval
*asserted
= (struct berval
*) assertedValue
;
4180 ber_len_t v_len
= value
->bv_len
;
4181 ber_len_t av_len
= asserted
->bv_len
;
4183 /* ignore trailing 'Z' when comparing */
4184 int match
= memcmp( value
->bv_val
, asserted
->bv_val
,
4185 (v_len
< av_len
? v_len
: av_len
) - 1 );
4186 if ( match
== 0 ) match
= v_len
- av_len
;
4189 return LDAP_SUCCESS
;
4192 /* Index generation function */
4193 int generalizedTimeIndexer(
4198 struct berval
*prefix
,
4206 BerValue bvtmp
; /* 40 bit index */
4208 struct lutil_timet tt
;
4210 bvtmp
.bv_len
= sizeof(tmp
);
4212 for( i
=0; values
[i
].bv_val
!= NULL
; i
++ ) {
4213 /* just count them */
4216 /* we should have at least one value at this point */
4219 keys
= slap_sl_malloc( sizeof( struct berval
) * (i
+1), ctx
);
4221 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4222 for( i
=0, j
=0; values
[i
].bv_val
!= NULL
; i
++ ) {
4223 assert(values
[i
].bv_val
!= NULL
&& values
[i
].bv_len
>= 10);
4224 /* Use 40 bits of time for key */
4225 if ( lutil_parsetime( values
[i
].bv_val
, &tm
) == 0 ) {
4226 lutil_tm2time( &tm
, &tt
);
4227 tmp
[0] = tt
.tt_gsec
& 0xff;
4228 tmp
[4] = tt
.tt_sec
& 0xff;
4230 tmp
[3] = tt
.tt_sec
& 0xff;
4232 tmp
[2] = tt
.tt_sec
& 0xff;
4234 tmp
[1] = tt
.tt_sec
& 0xff;
4236 ber_dupbv_x(&keys
[j
++], &bvtmp
, ctx
);
4240 keys
[j
].bv_val
= NULL
;
4245 return LDAP_SUCCESS
;
4248 /* Index generation function */
4249 int generalizedTimeFilter(
4254 struct berval
*prefix
,
4255 void * assertedValue
,
4261 BerValue bvtmp
; /* 40 bit index */
4262 BerValue
*value
= (BerValue
*) assertedValue
;
4264 struct lutil_timet tt
;
4266 bvtmp
.bv_len
= sizeof(tmp
);
4268 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
4269 /* Use 40 bits of time for key */
4270 if ( value
->bv_val
&& value
->bv_len
>= 10 &&
4271 lutil_parsetime( value
->bv_val
, &tm
) == 0 ) {
4273 lutil_tm2time( &tm
, &tt
);
4274 tmp
[0] = tt
.tt_gsec
& 0xff;
4275 tmp
[4] = tt
.tt_sec
& 0xff;
4277 tmp
[3] = tt
.tt_sec
& 0xff;
4279 tmp
[2] = tt
.tt_sec
& 0xff;
4281 tmp
[1] = tt
.tt_sec
& 0xff;
4283 keys
= slap_sl_malloc( sizeof( struct berval
) * 2, ctx
);
4284 ber_dupbv_x(keys
, &bvtmp
, ctx
);
4285 keys
[1].bv_val
= NULL
;
4293 return LDAP_SUCCESS
;
4297 deliveryMethodValidate(
4299 struct berval
*val
)
4302 #define LENOF(s) (sizeof(s)-1)
4303 struct berval tmp
= *val
;
4305 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
4306 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
4307 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
4310 if( tmp
.bv_len
< 3 ) return LDAP_INVALID_SYNTAX
;
4312 switch( tmp
.bv_val
[0] ) {
4315 if(( tmp
.bv_len
>= LENOF("any") ) &&
4316 ( strncasecmp(tmp
.bv_val
, "any", LENOF("any")) == 0 ))
4318 tmp
.bv_len
-= LENOF("any");
4319 tmp
.bv_val
+= LENOF("any");
4322 return LDAP_INVALID_SYNTAX
;
4326 if(( tmp
.bv_len
>= LENOF("mhs") ) &&
4327 ( strncasecmp(tmp
.bv_val
, "mhs", LENOF("mhs")) == 0 ))
4329 tmp
.bv_len
-= LENOF("mhs");
4330 tmp
.bv_val
+= LENOF("mhs");
4333 return LDAP_INVALID_SYNTAX
;
4337 if(( tmp
.bv_len
>= LENOF("physical") ) &&
4338 ( strncasecmp(tmp
.bv_val
, "physical", LENOF("physical")) == 0 ))
4340 tmp
.bv_len
-= LENOF("physical");
4341 tmp
.bv_val
+= LENOF("physical");
4344 return LDAP_INVALID_SYNTAX
;
4347 case 'T': /* telex or teletex or telephone */
4348 if(( tmp
.bv_len
>= LENOF("telex") ) &&
4349 ( strncasecmp(tmp
.bv_val
, "telex", LENOF("telex")) == 0 ))
4351 tmp
.bv_len
-= LENOF("telex");
4352 tmp
.bv_val
+= LENOF("telex");
4355 if(( tmp
.bv_len
>= LENOF("teletex") ) &&
4356 ( strncasecmp(tmp
.bv_val
, "teletex", LENOF("teletex")) == 0 ))
4358 tmp
.bv_len
-= LENOF("teletex");
4359 tmp
.bv_val
+= LENOF("teletex");
4362 if(( tmp
.bv_len
>= LENOF("telephone") ) &&
4363 ( strncasecmp(tmp
.bv_val
, "telephone", LENOF("telephone")) == 0 ))
4365 tmp
.bv_len
-= LENOF("telephone");
4366 tmp
.bv_val
+= LENOF("telephone");
4369 return LDAP_INVALID_SYNTAX
;
4372 case 'G': /* g3fax or g4fax */
4373 if(( tmp
.bv_len
>= LENOF("g3fax") ) && (
4374 ( strncasecmp(tmp
.bv_val
, "g3fax", LENOF("g3fax")) == 0 ) ||
4375 ( strncasecmp(tmp
.bv_val
, "g4fax", LENOF("g4fax")) == 0 )))
4377 tmp
.bv_len
-= LENOF("g3fax");
4378 tmp
.bv_val
+= LENOF("g3fax");
4381 return LDAP_INVALID_SYNTAX
;
4385 if(( tmp
.bv_len
>= LENOF("ia5") ) &&
4386 ( strncasecmp(tmp
.bv_val
, "ia5", LENOF("ia5")) == 0 ))
4388 tmp
.bv_len
-= LENOF("ia5");
4389 tmp
.bv_val
+= LENOF("ia5");
4392 return LDAP_INVALID_SYNTAX
;
4396 if(( tmp
.bv_len
>= LENOF("videotex") ) &&
4397 ( strncasecmp(tmp
.bv_val
, "videotex", LENOF("videotex")) == 0 ))
4399 tmp
.bv_len
-= LENOF("videotex");
4400 tmp
.bv_val
+= LENOF("videotex");
4403 return LDAP_INVALID_SYNTAX
;
4406 return LDAP_INVALID_SYNTAX
;
4409 if( BER_BVISEMPTY( &tmp
) ) return LDAP_SUCCESS
;
4411 while( !BER_BVISEMPTY( &tmp
) && ( tmp
.bv_val
[0] == ' ' ) ) {
4415 if( !BER_BVISEMPTY( &tmp
) && ( tmp
.bv_val
[0] == '$' ) ) {
4419 return LDAP_INVALID_SYNTAX
;
4421 while( !BER_BVISEMPTY( &tmp
) && ( tmp
.bv_val
[0] == ' ' ) ) {
4430 nisNetgroupTripleValidate(
4432 struct berval
*val
)
4437 if ( BER_BVISEMPTY( val
) ) {
4438 return LDAP_INVALID_SYNTAX
;
4441 p
= (char *)val
->bv_val
;
4442 e
= p
+ val
->bv_len
;
4444 if ( *p
!= '(' /*')'*/ ) {
4445 return LDAP_INVALID_SYNTAX
;
4448 for ( p
++; ( p
< e
) && ( *p
!= /*'('*/ ')' ); p
++ ) {
4452 return LDAP_INVALID_SYNTAX
;
4455 } else if ( !AD_CHAR( *p
) ) {
4456 return LDAP_INVALID_SYNTAX
;
4460 if ( ( commas
!= 2 ) || ( *p
!= /*'('*/ ')' ) ) {
4461 return LDAP_INVALID_SYNTAX
;
4467 return LDAP_INVALID_SYNTAX
;
4470 return LDAP_SUCCESS
;
4474 bootParameterValidate(
4476 struct berval
*val
)
4480 if ( BER_BVISEMPTY( val
) ) {
4481 return LDAP_INVALID_SYNTAX
;
4484 p
= (char *)val
->bv_val
;
4485 e
= p
+ val
->bv_len
;
4488 for (; ( p
< e
) && ( *p
!= '=' ); p
++ ) {
4489 if ( !AD_CHAR( *p
) ) {
4490 return LDAP_INVALID_SYNTAX
;
4495 return LDAP_INVALID_SYNTAX
;
4499 for ( p
++; ( p
< e
) && ( *p
!= ':' ); p
++ ) {
4500 if ( !AD_CHAR( *p
) ) {
4501 return LDAP_INVALID_SYNTAX
;
4506 return LDAP_INVALID_SYNTAX
;
4510 for ( p
++; p
< e
; p
++ ) {
4511 if ( !SLAP_PRINTABLE( *p
) ) {
4512 return LDAP_INVALID_SYNTAX
;
4516 return LDAP_SUCCESS
;
4520 firstComponentNormalize(
4525 struct berval
*normalized
,
4532 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage
)) {
4533 ber_dupbv_x( normalized
, val
, ctx
);
4534 return LDAP_SUCCESS
;
4537 if( val
->bv_len
< 3 ) return LDAP_INVALID_SYNTAX
;
4539 if( val
->bv_val
[0] != '(' /*')'*/ &&
4540 val
->bv_val
[0] != '{' /*'}'*/ )
4542 return LDAP_INVALID_SYNTAX
;
4545 /* trim leading white space */
4547 len
< val
->bv_len
&& ASCII_SPACE(val
->bv_val
[len
]);
4553 /* grab next word */
4554 comp
.bv_val
= &val
->bv_val
[len
];
4555 len
= val
->bv_len
- len
;
4556 for( comp
.bv_len
= 0;
4557 !ASCII_SPACE(comp
.bv_val
[comp
.bv_len
]) && comp
.bv_len
< len
;
4563 if( mr
== slap_schema
.si_mr_objectIdentifierFirstComponentMatch
) {
4564 rc
= numericoidValidate( NULL
, &comp
);
4565 } else if( mr
== slap_schema
.si_mr_integerFirstComponentMatch
) {
4566 rc
= integerValidate( NULL
, &comp
);
4568 rc
= LDAP_INVALID_SYNTAX
;
4572 if( rc
== LDAP_SUCCESS
) {
4573 ber_dupbv_x( normalized
, &comp
, ctx
);
4579 static char *country_gen_syn
[] = {
4580 "1.3.6.1.4.1.1466.115.121.1.15",
4581 "1.3.6.1.4.1.1466.115.121.1.26",
4582 "1.3.6.1.4.1.1466.115.121.1.44",
4586 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4587 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4589 static slap_syntax_defs_rec syntax_defs
[] = {
4590 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4591 X_BINARY X_NOT_H_R
")",
4592 SLAP_SYNTAX_BINARY
|SLAP_SYNTAX_BER
, NULL
, NULL
, NULL
},
4593 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R
")",
4594 0, NULL
, NULL
, NULL
},
4595 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4596 0, NULL
, NULL
, NULL
},
4597 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4599 SLAP_SYNTAX_BLOB
, NULL
, blobValidate
, NULL
},
4600 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4602 SLAP_SYNTAX_BER
, NULL
, berValidate
, NULL
},
4603 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4604 0, NULL
, bitStringValidate
, NULL
},
4605 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4606 0, NULL
, booleanValidate
, NULL
},
4607 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4608 X_BINARY X_NOT_H_R
")",
4609 SLAP_SYNTAX_BINARY
|SLAP_SYNTAX_BER
,
4610 NULL
, certificateValidate
, NULL
},
4611 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4612 X_BINARY X_NOT_H_R
")",
4613 SLAP_SYNTAX_BINARY
|SLAP_SYNTAX_BER
,
4614 NULL
, certificateListValidate
, NULL
},
4615 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4616 X_BINARY X_NOT_H_R
")",
4617 SLAP_SYNTAX_BINARY
|SLAP_SYNTAX_BER
,
4618 NULL
, sequenceValidate
, NULL
},
4619 #if 0 /* need to go __after__ printableString */
4620 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4621 0, "1.3.6.1.4.1.1466.115.121.1.44",
4622 countryStringValidate
, NULL
},
4624 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4625 0, NULL
, dnValidate
, dnPretty
},
4626 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
4627 0, NULL
, rdnValidate
, rdnPretty
},
4628 #ifdef LDAP_COMP_MATCH
4629 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
4630 0, NULL
, allComponentsValidate
, NULL
},
4631 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
4632 0, NULL
, componentFilterValidate
, NULL
},
4634 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4635 0, NULL
, NULL
, NULL
},
4636 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4637 0, NULL
, deliveryMethodValidate
, NULL
},
4638 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4639 0, NULL
, UTF8StringValidate
, NULL
},
4640 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4641 0, NULL
, NULL
, NULL
},
4642 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4643 0, NULL
, NULL
, NULL
},
4644 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4645 0, NULL
, NULL
, NULL
},
4646 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4647 0, NULL
, NULL
, NULL
},
4648 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4649 0, NULL
, NULL
, NULL
},
4650 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4651 0, NULL
, printablesStringValidate
, NULL
},
4652 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R
")",
4653 SLAP_SYNTAX_BLOB
, NULL
, NULL
, NULL
},
4654 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4655 0, NULL
, generalizedTimeValidate
, NULL
},
4656 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4657 0, NULL
, NULL
, NULL
},
4658 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4659 0, NULL
, IA5StringValidate
, NULL
},
4660 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4661 0, NULL
, integerValidate
, NULL
},
4662 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R
")",
4663 SLAP_SYNTAX_BLOB
, NULL
, blobValidate
, NULL
},
4664 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4665 0, NULL
, NULL
, NULL
},
4666 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4667 0, NULL
, NULL
, NULL
},
4668 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4669 0, NULL
, NULL
, NULL
},
4670 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4671 0, NULL
, NULL
, NULL
},
4672 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4673 0, NULL
, NULL
, NULL
},
4674 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4675 0, NULL
, nameUIDValidate
, nameUIDPretty
},
4676 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4677 0, NULL
, NULL
, NULL
},
4678 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4679 0, NULL
, numericStringValidate
, NULL
},
4680 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4681 0, NULL
, NULL
, NULL
},
4682 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4683 0, NULL
, numericoidValidate
, NULL
},
4684 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4685 0, NULL
, IA5StringValidate
, NULL
},
4686 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4687 0, NULL
, blobValidate
, NULL
},
4688 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4689 0, NULL
, UTF8StringValidate
, NULL
},
4690 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4691 0, NULL
, NULL
, NULL
},
4692 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4693 0, NULL
, NULL
, NULL
},
4694 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4695 0, NULL
, printableStringValidate
, NULL
},
4696 /* moved here because now depends on Directory String, IA5 String
4697 * and Printable String */
4698 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4699 0, country_gen_syn
, countryStringValidate
, NULL
},
4700 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
4701 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
4702 0, NULL
, subtreeSpecificationValidate
, NULL
},
4703 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4704 X_BINARY X_NOT_H_R
")",
4705 SLAP_SYNTAX_BINARY
|SLAP_SYNTAX_BER
, NULL
, berValidate
, NULL
},
4706 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4707 0, NULL
, printableStringValidate
, NULL
},
4708 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4709 0, NULL
, NULL
, NULL
},
4710 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4711 0, NULL
, printablesStringValidate
, NULL
},
4712 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4713 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4714 0, NULL
, utcTimeValidate
, NULL
},
4716 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4717 0, NULL
, NULL
, NULL
},
4718 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4719 0, NULL
, NULL
, NULL
},
4720 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4721 0, NULL
, NULL
, NULL
},
4722 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4723 0, NULL
, NULL
, NULL
},
4724 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4725 0, NULL
, NULL
, NULL
},
4727 /* RFC 2307 NIS Syntaxes */
4728 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4729 0, NULL
, nisNetgroupTripleValidate
, NULL
},
4730 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4731 0, NULL
, bootParameterValidate
, NULL
},
4733 /* draft-zeilenga-ldap-x509 */
4734 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
4735 SLAP_SYNTAX_HIDE
, NULL
,
4736 serialNumberAndIssuerValidate
,
4737 serialNumberAndIssuerPretty
},
4738 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
4739 SLAP_SYNTAX_HIDE
, NULL
, NULL
, NULL
},
4740 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
4741 SLAP_SYNTAX_HIDE
, NULL
, NULL
, NULL
},
4742 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
4743 SLAP_SYNTAX_HIDE
, NULL
, NULL
, NULL
},
4744 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
4745 SLAP_SYNTAX_HIDE
, NULL
, NULL
, NULL
},
4746 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
4747 SLAP_SYNTAX_HIDE
, NULL
, NULL
, NULL
},
4748 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
4749 SLAP_SYNTAX_HIDE
, NULL
, NULL
, NULL
},
4751 #ifdef SLAPD_AUTHPASSWD
4752 /* needs updating */
4753 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4754 SLAP_SYNTAX_HIDE
, NULL
, NULL
, NULL
},
4757 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
4758 0, NULL
, UUIDValidate
, UUIDPretty
},
4760 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
4761 SLAP_SYNTAX_HIDE
, NULL
, csnValidate
, csnPretty
},
4763 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
4764 SLAP_SYNTAX_HIDE
, NULL
, sidValidate
, sidPretty
},
4766 /* OpenLDAP Void Syntax */
4767 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4768 SLAP_SYNTAX_HIDE
, NULL
, inValidate
, NULL
},
4770 /* FIXME: OID is unused, but not registered yet */
4771 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
4772 SLAP_SYNTAX_HIDE
, NULL
, authzValidate
, authzPretty
},
4774 {NULL
, 0, NULL
, NULL
, NULL
}
4777 char *csnSIDMatchSyntaxes
[] = {
4778 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
4781 char *certificateExactMatchSyntaxes
[] = {
4782 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4785 #ifdef LDAP_COMP_MATCH
4786 char *componentFilterMatchSyntaxes
[] = {
4787 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4791 char *directoryStringSyntaxes
[] = {
4792 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4795 char *integerFirstComponentMatchSyntaxes
[] = {
4796 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4797 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
4800 char *objectIdentifierFirstComponentMatchSyntaxes
[] = {
4801 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4802 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4803 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
4804 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4805 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4806 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4807 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4808 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4813 * Other matching rules in X.520 that we do not use (yet):
4815 * 2.5.13.25 uTCTimeMatch
4816 * 2.5.13.26 uTCTimeOrderingMatch
4817 * 2.5.13.31* directoryStringFirstComponentMatch
4818 * 2.5.13.32* wordMatch
4819 * 2.5.13.33* keywordMatch
4820 * 2.5.13.36+ certificatePairExactMatch
4821 * 2.5.13.37+ certificatePairMatch
4822 * 2.5.13.38+ certificateListExactMatch
4823 * 2.5.13.39+ certificateListMatch
4824 * 2.5.13.40+ algorithmIdentifierMatch
4825 * 2.5.13.41* storedPrefixMatch
4826 * 2.5.13.42 attributeCertificateMatch
4827 * 2.5.13.43 readerAndKeyIDMatch
4828 * 2.5.13.44 attributeIntegrityMatch
4830 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
4831 * (+) described in draft-zeilenga-ldap-x509
4833 static slap_mrule_defs_rec mrule_defs
[] = {
4835 * EQUALITY matching rules must be listed after associated APPROX
4836 * matching rules. So, we list all APPROX matching rules first.
4838 {"( " directoryStringApproxMatchOID
" NAME 'directoryStringApproxMatch' "
4839 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4840 SLAP_MR_HIDE
| SLAP_MR_EQUALITY_APPROX
| SLAP_MR_EXT
, NULL
,
4841 NULL
, NULL
, directoryStringApproxMatch
,
4842 directoryStringApproxIndexer
, directoryStringApproxFilter
,
4845 {"( " IA5StringApproxMatchOID
" NAME 'IA5StringApproxMatch' "
4846 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4847 SLAP_MR_HIDE
| SLAP_MR_EQUALITY_APPROX
| SLAP_MR_EXT
, NULL
,
4848 NULL
, NULL
, IA5StringApproxMatch
,
4849 IA5StringApproxIndexer
, IA5StringApproxFilter
,
4853 * Other matching rules
4856 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4857 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4858 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
4859 NULL
, NULL
, octetStringMatch
,
4860 octetStringIndexer
, octetStringFilter
,
4863 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4864 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4865 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
4866 NULL
, dnNormalize
, dnMatch
,
4867 octetStringIndexer
, octetStringFilter
,
4870 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
4871 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4872 SLAP_MR_HIDE
| SLAP_MR_EXT
, NULL
,
4873 NULL
, dnNormalize
, dnRelativeMatch
,
4877 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
4878 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4879 SLAP_MR_HIDE
| SLAP_MR_EXT
, NULL
,
4880 NULL
, dnNormalize
, dnRelativeMatch
,
4884 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
4885 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4886 SLAP_MR_HIDE
| SLAP_MR_EXT
, NULL
,
4887 NULL
, dnNormalize
, dnRelativeMatch
,
4891 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
4892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4893 SLAP_MR_HIDE
| SLAP_MR_EXT
, NULL
,
4894 NULL
, dnNormalize
, dnRelativeMatch
,
4898 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
4899 "SYNTAX 1.2.36.79672281.1.5.0 )",
4900 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
4901 NULL
, rdnNormalize
, rdnMatch
,
4902 octetStringIndexer
, octetStringFilter
,
4905 #ifdef LDAP_COMP_MATCH
4906 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
4907 "SYNTAX 1.2.36.79672281.1.5.2 )",
4908 SLAP_MR_EXT
|SLAP_MR_COMPONENT
, componentFilterMatchSyntaxes
,
4909 NULL
, NULL
, componentFilterMatch
,
4910 octetStringIndexer
, octetStringFilter
,
4913 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
4914 "SYNTAX 1.2.36.79672281.1.5.3 )",
4915 SLAP_MR_EQUALITY
|SLAP_MR_EXT
|SLAP_MR_COMPONENT
, NULL
,
4916 NULL
, NULL
, allComponentsMatch
,
4917 octetStringIndexer
, octetStringFilter
,
4920 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
4921 "SYNTAX 1.2.36.79672281.1.5.3 )",
4922 SLAP_MR_EQUALITY
|SLAP_MR_EXT
|SLAP_MR_COMPONENT
, NULL
,
4923 NULL
, NULL
, directoryComponentsMatch
,
4924 octetStringIndexer
, octetStringFilter
,
4928 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4929 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4930 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, directoryStringSyntaxes
,
4931 NULL
, UTF8StringNormalize
, octetStringMatch
,
4932 octetStringIndexer
, octetStringFilter
,
4933 directoryStringApproxMatchOID
},
4935 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4936 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4937 SLAP_MR_ORDERING
, directoryStringSyntaxes
,
4938 NULL
, UTF8StringNormalize
, octetStringOrderingMatch
,
4940 "caseIgnoreMatch" },
4942 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4943 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4944 SLAP_MR_SUBSTR
, directoryStringSyntaxes
,
4945 NULL
, UTF8StringNormalize
, directoryStringSubstringsMatch
,
4946 octetStringSubstringsIndexer
, octetStringSubstringsFilter
,
4947 "caseIgnoreMatch" },
4949 {"( 2.5.13.5 NAME 'caseExactMatch' "
4950 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4951 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, directoryStringSyntaxes
,
4952 NULL
, UTF8StringNormalize
, octetStringMatch
,
4953 octetStringIndexer
, octetStringFilter
,
4954 directoryStringApproxMatchOID
},
4956 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4957 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4958 SLAP_MR_ORDERING
, directoryStringSyntaxes
,
4959 NULL
, UTF8StringNormalize
, octetStringOrderingMatch
,
4963 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4964 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4965 SLAP_MR_SUBSTR
, directoryStringSyntaxes
,
4966 NULL
, UTF8StringNormalize
, directoryStringSubstringsMatch
,
4967 octetStringSubstringsIndexer
, octetStringSubstringsFilter
,
4970 {"( 2.5.13.8 NAME 'numericStringMatch' "
4971 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4972 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
4973 NULL
, numericStringNormalize
, octetStringMatch
,
4974 octetStringIndexer
, octetStringFilter
,
4977 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
4978 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4979 SLAP_MR_ORDERING
, NULL
,
4980 NULL
, numericStringNormalize
, octetStringOrderingMatch
,
4982 "numericStringMatch" },
4984 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4985 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4986 SLAP_MR_SUBSTR
, NULL
,
4987 NULL
, numericStringNormalize
, octetStringSubstringsMatch
,
4988 octetStringSubstringsIndexer
, octetStringSubstringsFilter
,
4989 "numericStringMatch" },
4991 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4992 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4993 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
4994 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
},
4996 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4997 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4998 SLAP_MR_SUBSTR
, NULL
,
4999 NULL
, NULL
, NULL
, NULL
, NULL
,
5000 "caseIgnoreListMatch" },
5002 {"( 2.5.13.13 NAME 'booleanMatch' "
5003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
5004 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5005 NULL
, NULL
, booleanMatch
,
5006 octetStringIndexer
, octetStringFilter
,
5009 {"( 2.5.13.14 NAME 'integerMatch' "
5010 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5011 SLAP_MR_EQUALITY
| SLAP_MR_EXT
| SLAP_MR_ORDERED_INDEX
, NULL
,
5012 NULL
, NULL
, integerMatch
,
5013 integerIndexer
, integerFilter
,
5016 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
5017 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5018 SLAP_MR_ORDERING
| SLAP_MR_ORDERED_INDEX
, NULL
,
5019 NULL
, NULL
, integerMatch
,
5023 {"( 2.5.13.16 NAME 'bitStringMatch' "
5024 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
5025 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5026 NULL
, NULL
, octetStringMatch
,
5027 octetStringIndexer
, octetStringFilter
,
5030 {"( 2.5.13.17 NAME 'octetStringMatch' "
5031 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5032 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5033 NULL
, NULL
, octetStringMatch
,
5034 octetStringIndexer
, octetStringFilter
,
5037 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
5038 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5039 SLAP_MR_ORDERING
, NULL
,
5040 NULL
, NULL
, octetStringOrderingMatch
,
5042 "octetStringMatch" },
5044 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
5045 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5046 SLAP_MR_SUBSTR
, NULL
,
5047 NULL
, NULL
, octetStringSubstringsMatch
,
5048 octetStringSubstringsIndexer
, octetStringSubstringsFilter
,
5049 "octetStringMatch" },
5051 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
5052 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
5053 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5055 telephoneNumberNormalize
, octetStringMatch
,
5056 octetStringIndexer
, octetStringFilter
,
5059 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
5060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
5061 SLAP_MR_SUBSTR
, NULL
,
5062 NULL
, telephoneNumberNormalize
, octetStringSubstringsMatch
,
5063 octetStringSubstringsIndexer
, octetStringSubstringsFilter
,
5064 "telephoneNumberMatch" },
5066 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
5067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
5068 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5069 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
},
5071 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
5072 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
5073 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5074 NULL
, uniqueMemberNormalize
, uniqueMemberMatch
,
5075 uniqueMemberIndexer
, uniqueMemberFilter
,
5078 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
5079 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
5080 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5081 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
},
5083 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
5084 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5085 SLAP_MR_EQUALITY
| SLAP_MR_EXT
| SLAP_MR_ORDERED_INDEX
, NULL
,
5086 NULL
, generalizedTimeNormalize
, octetStringMatch
,
5087 generalizedTimeIndexer
, generalizedTimeFilter
,
5090 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
5091 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
5092 SLAP_MR_ORDERING
| SLAP_MR_ORDERED_INDEX
, NULL
,
5093 NULL
, generalizedTimeNormalize
, generalizedTimeOrderingMatch
,
5095 "generalizedTimeMatch" },
5097 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
5098 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5099 SLAP_MR_EQUALITY
| SLAP_MR_EXT
,
5100 integerFirstComponentMatchSyntaxes
,
5101 NULL
, firstComponentNormalize
, integerMatch
,
5102 octetStringIndexer
, octetStringFilter
,
5105 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
5106 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
5107 SLAP_MR_EQUALITY
| SLAP_MR_EXT
,
5108 objectIdentifierFirstComponentMatchSyntaxes
,
5109 NULL
, firstComponentNormalize
, octetStringMatch
,
5110 octetStringIndexer
, octetStringFilter
,
5113 {"( 2.5.13.34 NAME 'certificateExactMatch' "
5114 "SYNTAX 1.3.6.1.1.15.1 )",
5115 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, certificateExactMatchSyntaxes
,
5116 NULL
, certificateExactNormalize
, octetStringMatch
,
5117 octetStringIndexer
, octetStringFilter
,
5120 {"( 2.5.13.35 NAME 'certificateMatch' "
5121 "SYNTAX 1.3.6.1.1.15.2 )",
5122 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5123 NULL
, NULL
, NULL
, NULL
, NULL
,
5126 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
5127 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5128 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5129 NULL
, IA5StringNormalize
, octetStringMatch
,
5130 octetStringIndexer
, octetStringFilter
,
5131 IA5StringApproxMatchOID
},
5133 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
5134 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5135 SLAP_MR_EQUALITY
| SLAP_MR_EXT
, NULL
,
5136 NULL
, IA5StringNormalize
, octetStringMatch
,
5137 octetStringIndexer
, octetStringFilter
,
5138 IA5StringApproxMatchOID
},
5140 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
5141 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5142 SLAP_MR_SUBSTR
, NULL
,
5143 NULL
, IA5StringNormalize
, directoryStringSubstringsMatch
,
5144 octetStringSubstringsIndexer
, octetStringSubstringsFilter
,
5145 "caseIgnoreIA5Match" },
5147 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
5148 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
5149 SLAP_MR_SUBSTR
, NULL
,
5150 NULL
, IA5StringNormalize
, directoryStringSubstringsMatch
,
5151 octetStringSubstringsIndexer
, octetStringSubstringsFilter
,
5152 "caseExactIA5Match" },
5154 #ifdef SLAPD_AUTHPASSWD
5155 /* needs updating */
5156 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
5157 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
5158 SLAP_MR_HIDE
| SLAP_MR_EQUALITY
, NULL
,
5159 NULL
, NULL
, authPasswordMatch
,
5164 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
5165 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5167 NULL
, NULL
, integerBitAndMatch
,
5171 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
5172 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
5174 NULL
, NULL
, integerBitOrMatch
,
5178 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
5179 "SYNTAX 1.3.6.1.1.16.1 )",
5180 SLAP_MR_EQUALITY
| SLAP_MR_MUTATION_NORMALIZER
, NULL
,
5181 NULL
, UUIDNormalize
, octetStringMatch
,
5182 octetStringIndexer
, octetStringFilter
,
5185 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
5186 "SYNTAX 1.3.6.1.1.16.1 )",
5187 SLAP_MR_ORDERING
| SLAP_MR_MUTATION_NORMALIZER
, NULL
,
5188 NULL
, UUIDNormalize
, octetStringOrderingMatch
,
5189 octetStringIndexer
, octetStringFilter
,
5192 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
5193 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5194 SLAP_MR_HIDE
| SLAP_MR_EQUALITY
| SLAP_MR_ORDERED_INDEX
, NULL
,
5195 NULL
, csnNormalize
, csnMatch
,
5196 csnIndexer
, csnFilter
,
5199 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
5200 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
5201 SLAP_MR_HIDE
| SLAP_MR_ORDERING
| SLAP_MR_ORDERED_INDEX
, NULL
,
5202 NULL
, NULL
, csnOrderingMatch
,
5206 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
5207 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
5208 SLAP_MR_HIDE
| SLAP_MR_EQUALITY
| SLAP_MR_EXT
, csnSIDMatchSyntaxes
,
5209 NULL
, csnSidNormalize
, octetStringMatch
,
5210 octetStringIndexer
, octetStringFilter
,
5213 /* FIXME: OID is unused, but not registered yet */
5214 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
5215 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
5216 SLAP_MR_HIDE
| SLAP_MR_EQUALITY
, NULL
,
5217 NULL
, authzNormalize
, authzMatch
,
5221 {NULL
, SLAP_MR_NONE
, NULL
,
5222 NULL
, NULL
, NULL
, NULL
, NULL
,
5227 slap_schema_init( void )
5232 /* we should only be called once (from main) */
5233 assert( schema_init_done
== 0 );
5235 for ( i
=0; syntax_defs
[i
].sd_desc
!= NULL
; i
++ ) {
5236 res
= register_syntax( &syntax_defs
[i
] );
5239 fprintf( stderr
, "slap_schema_init: Error registering syntax %s\n",
5240 syntax_defs
[i
].sd_desc
);
5245 for ( i
=0; mrule_defs
[i
].mrd_desc
!= NULL
; i
++ ) {
5246 if( mrule_defs
[i
].mrd_usage
== SLAP_MR_NONE
&&
5247 mrule_defs
[i
].mrd_compat_syntaxes
== NULL
)
5250 "slap_schema_init: Ignoring unusable matching rule %s\n",
5251 mrule_defs
[i
].mrd_desc
);
5255 res
= register_matching_rule( &mrule_defs
[i
] );
5259 "slap_schema_init: Error registering matching rule %s\n",
5260 mrule_defs
[i
].mrd_desc
);
5265 res
= slap_schema_load();
5266 schema_init_done
= 1;
5271 schema_destroy( void )
5280 if( schema_init_done
) {
5281 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex
);
5282 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex
);