1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2009 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 /* X.509 PMI ldapSyntaxes */
61 /* FIXME: need to create temporary OIDs under OpenLDAP's arc;
62 * these are currently hijacked
64 * 1.3.6.1.4.1.4203.666 OpenLDAP
65 * 1.3.6.1.4.1.4203.666.11 self-contained works
66 * 1.3.6.1.4.1.4203.666.11.10 X.509 PMI
67 * 1.3.6.1.4.1.4203.666.11.10.2 X.509 PMI ldapSyntaxes
68 * 1.3.6.1.4.1.4203.666.11.10.2.1 AttributeCertificate (supported)
69 * 1.3.6.1.4.1.4203.666.11.10.2.2 AttributeCertificateExactAssertion (supported)
70 * 1.3.6.1.4.1.4203.666.11.10.2.3 AttributeCertificateAssertion (not supported)
71 * 1.3.6.1.4.1.4203.666.11.10.2.4 AttCertPath (X-SUBST'ed right now in pmi.schema)
72 * 1.3.6.1.4.1.4203.666.11.10.2.5 PolicySyntax (X-SUBST'ed right now in pmi.schema)
73 * 1.3.6.1.4.1.4203.666.11.10.2.6 RoleSyntax (X-SUBST'ed right now in pmi.schema)
75 #if 0 /* from <draft-ietf-pkix-ldap-schema-02.txt> (expired) */
76 #define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5"
77 #define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6"
78 #define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7"
79 #else /* from OpenLDAP's experimental oid arc */
80 #define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2"
81 #define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1"
82 #define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2"
83 #define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3"
86 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
87 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
88 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
89 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
91 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
92 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
93 SLAP_INDEX_INTLEN_DEFAULT );
95 ldap_pvt_thread_mutex_t ad_undef_mutex;
96 ldap_pvt_thread_mutex_t oc_undef_mutex;
99 generalizedTimeValidate(
103 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
108 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
115 /* no value allowed */
116 return LDAP_INVALID_SYNTAX;
124 /* any value allowed */
128 #define berValidate blobValidate
135 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
136 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 /* X.509 related stuff */
150 SLAP_TAG_UTCTIME = 0x17U,
151 SLAP_TAG_GENERALIZEDTIME = 0x18U
155 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
158 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
159 SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1,
160 SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2,
161 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
165 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
169 GeneralName ::= CHOICE {
170 otherName [0] INSTANCE OF OTHER-NAME,
171 rfc822Name [1] IA5String,
172 dNSName [2] IA5String,
173 x400Address [3] ORAddress,
174 directoryName [4] Name,
175 ediPartyName [5] EDIPartyName,
176 uniformResourceIdentifier [6] IA5String,
177 iPAddress [7] OCTET STRING,
178 registeredID [8] OBJECT IDENTIFIER }
181 SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0,
182 SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1,
183 SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2,
184 SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3,
185 SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4,
186 SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5,
187 SLAP_X509_GN_URI = SLAP_X509_OPTION + 6,
188 SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7,
189 SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8
192 /* X.509 PMI related stuff */
199 SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0
202 /* X.509 certificate validation */
204 certificateValidate( Syntax *syntax, struct berval *in )
206 BerElementBuffer berbuf;
207 BerElement *ber = (BerElement *)&berbuf;
210 ber_int_t version = SLAP_X509_V1;
212 ber_init2( ber, in, LBER_USE_DER );
213 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
214 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
215 tag = ber_skip_tag( ber, &len ); /* Sequence */
216 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
217 tag = ber_peek_tag( ber, &len );
218 /* Optional version */
219 if ( tag == SLAP_X509_OPT_C_VERSION ) {
220 tag = ber_skip_tag( ber, &len );
221 tag = ber_get_int( ber, &version );
222 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
224 /* NOTE: don't try to parse Serial, because it might be longer
225 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
226 tag = ber_skip_tag( ber, &len ); /* Serial */
227 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
228 ber_skip_data( ber, len );
229 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
230 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
231 ber_skip_data( ber, len );
232 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
233 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
234 ber_skip_data( ber, len );
235 tag = ber_skip_tag( ber, &len ); /* Validity */
236 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
237 ber_skip_data( ber, len );
238 tag = ber_skip_tag( ber, &len ); /* Subject DN */
239 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
240 ber_skip_data( ber, len );
241 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
242 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
243 ber_skip_data( ber, len );
244 tag = ber_skip_tag( ber, &len );
245 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
246 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
247 ber_skip_data( ber, len );
248 tag = ber_skip_tag( ber, &len );
250 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
251 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
252 ber_skip_data( ber, len );
253 tag = ber_skip_tag( ber, &len );
255 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
256 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
257 tag = ber_skip_tag( ber, &len );
258 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
259 ber_skip_data( ber, len );
260 tag = ber_skip_tag( ber, &len );
262 /* signatureAlgorithm */
263 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
264 ber_skip_data( ber, len );
265 tag = ber_skip_tag( ber, &len );
267 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
268 ber_skip_data( ber, len );
269 tag = ber_skip_tag( ber, &len );
270 /* Must be at end now */
271 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
275 /* X.509 certificate list validation */
277 certificateListValidate( Syntax *syntax, struct berval *in )
279 BerElementBuffer berbuf;
280 BerElement *ber = (BerElement *)&berbuf;
283 ber_int_t version = SLAP_X509_V1;
285 ber_init2( ber, in, LBER_USE_DER );
286 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
287 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
288 tag = ber_skip_tag( ber, &len ); /* Sequence */
289 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
290 tag = ber_peek_tag( ber, &len );
291 /* Optional version */
292 if ( tag == LBER_INTEGER ) {
293 tag = ber_get_int( ber, &version );
294 assert( tag == LBER_INTEGER );
295 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
297 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
298 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
299 ber_skip_data( ber, len );
300 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
301 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
302 ber_skip_data( ber, len );
303 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
304 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
305 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
306 ber_skip_data( ber, len );
307 /* Optional nextUpdate */
308 tag = ber_skip_tag( ber, &len );
309 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
310 ber_skip_data( ber, len );
311 tag = ber_skip_tag( ber, &len );
313 /* revokedCertificates - Sequence of Sequence, Optional */
314 if ( tag == LBER_SEQUENCE ) {
316 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
317 /* Should NOT be empty */
318 ber_skip_data( ber, len );
319 tag = ber_skip_tag( ber, &len );
322 /* Optional Extensions - Sequence of Sequence */
323 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
325 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
326 tag = ber_peek_tag( ber, &seqlen );
327 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
328 ber_skip_data( ber, len );
329 tag = ber_skip_tag( ber, &len );
331 /* signatureAlgorithm */
332 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
333 ber_skip_data( ber, len );
334 tag = ber_skip_tag( ber, &len );
336 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
337 ber_skip_data( ber, len );
338 tag = ber_skip_tag( ber, &len );
339 /* Must be at end now */
340 /* NOTE: OpenSSL tolerates CL with garbage past the end */
341 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
345 /* X.509 PMI Attribute Certificate Validate */
347 attributeCertificateValidate( Syntax *syntax, struct berval *in )
349 BerElementBuffer berbuf;
350 BerElement *ber = (BerElement *)&berbuf;
356 ber_init2( ber, in, LBER_USE_DER );
358 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
359 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
361 tag = ber_skip_tag( ber, &len ); /* Sequence */
362 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
364 tag = ber_peek_tag( ber, &len ); /* Version */
365 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
366 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
367 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
369 tag = ber_skip_tag( ber, &len ); /* Holder */
370 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
371 ber_skip_data( ber, len );
373 tag = ber_skip_tag( ber, &len ); /* Issuer */
374 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
375 ber_skip_data( ber, len );
377 tag = ber_skip_tag( ber, &len ); /* Signature */
378 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
379 ber_skip_data( ber, len );
381 tag = ber_skip_tag( ber, &len ); /* Serial number */
382 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
383 ber_skip_data( ber, len );
385 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
386 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
387 ber_skip_data( ber, len );
389 tag = ber_skip_tag( ber, &len ); /* Attributes */
390 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
391 ber_skip_data( ber, len );
393 tag = ber_peek_tag( ber, &len );
395 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
396 tag = ber_skip_tag( ber, &len );
397 ber_skip_data( ber, len );
398 tag = ber_peek_tag( ber, &len );
401 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
402 tag = ber_skip_tag( ber, &len );
403 ber_skip_data( ber, len );
405 tag = ber_peek_tag( ber, &len );
408 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
409 tag = ber_skip_tag( ber, &len );
410 ber_skip_data( ber, len );
412 tag = ber_peek_tag( ber, &len );
415 if ( tag == LBER_BITSTRING ) { /* Signature */
416 tag = ber_skip_tag( ber, &len );
417 ber_skip_data( ber, len );
419 tag = ber_peek_tag( ber, &len );
422 /* Must be at end now */
423 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
434 struct berval *value,
435 void *assertedValue )
437 struct berval *asserted = (struct berval *) assertedValue;
438 int match = value->bv_len - asserted->bv_len;
441 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
449 octetStringOrderingMatch(
454 struct berval *value,
455 void *assertedValue )
457 struct berval *asserted = (struct berval *) assertedValue;
458 ber_len_t v_len = value->bv_len;
459 ber_len_t av_len = asserted->bv_len;
461 int match = memcmp( value->bv_val, asserted->bv_val,
462 (v_len < av_len ? v_len : av_len) );
464 if( match == 0 ) match = v_len - av_len;
472 HASH_CONTEXT *HASHcontext,
473 struct berval *prefix,
478 HASH_Init(HASHcontext);
479 if(prefix && prefix->bv_len > 0) {
480 HASH_Update(HASHcontext,
481 (unsigned char *)prefix->bv_val, prefix->bv_len);
483 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
484 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
485 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
491 HASH_CONTEXT *HASHcontext,
492 unsigned char *HASHdigest,
493 unsigned char *value,
496 HASH_CONTEXT ctx = *HASHcontext;
497 HASH_Update( &ctx, value, len );
498 HASH_Final( HASHdigest, &ctx );
501 /* Index generation function */
502 int octetStringIndexer(
507 struct berval *prefix,
515 HASH_CONTEXT HASHcontext;
516 unsigned char HASHdigest[HASH_BYTES];
517 struct berval digest;
518 digest.bv_val = (char *)HASHdigest;
519 digest.bv_len = sizeof(HASHdigest);
521 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
522 /* just count them */
525 /* we should have at least one value at this point */
528 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
530 slen = syntax->ssyn_oidlen;
531 mlen = mr->smr_oidlen;
533 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
534 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
535 hashIter( &HASHcontext, HASHdigest,
536 (unsigned char *)values[i].bv_val, values[i].bv_len );
537 ber_dupbv_x( &keys[i], &digest, ctx );
540 BER_BVZERO( &keys[i] );
547 /* Index generation function */
548 int octetStringFilter(
553 struct berval *prefix,
554 void * assertedValue,
560 HASH_CONTEXT HASHcontext;
561 unsigned char HASHdigest[HASH_BYTES];
562 struct berval *value = (struct berval *) assertedValue;
563 struct berval digest;
564 digest.bv_val = (char *)HASHdigest;
565 digest.bv_len = sizeof(HASHdigest);
567 slen = syntax->ssyn_oidlen;
568 mlen = mr->smr_oidlen;
570 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
572 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
573 hashIter( &HASHcontext, HASHdigest,
574 (unsigned char *)value->bv_val, value->bv_len );
576 ber_dupbv_x( keys, &digest, ctx );
577 BER_BVZERO( &keys[1] );
585 octetStringSubstringsMatch(
590 struct berval *value,
591 void *assertedValue )
594 SubstringsAssertion *sub = assertedValue;
595 struct berval left = *value;
599 /* Add up asserted input length */
600 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
601 inlen += sub->sa_initial.bv_len;
604 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
605 inlen += sub->sa_any[i].bv_len;
608 if ( !BER_BVISNULL( &sub->sa_final ) ) {
609 inlen += sub->sa_final.bv_len;
612 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
613 if ( inlen > left.bv_len ) {
618 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
619 sub->sa_initial.bv_len );
625 left.bv_val += sub->sa_initial.bv_len;
626 left.bv_len -= sub->sa_initial.bv_len;
627 inlen -= sub->sa_initial.bv_len;
630 if ( !BER_BVISNULL( &sub->sa_final ) ) {
631 if ( inlen > left.bv_len ) {
636 match = memcmp( sub->sa_final.bv_val,
637 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
638 sub->sa_final.bv_len );
644 left.bv_len -= sub->sa_final.bv_len;
645 inlen -= sub->sa_final.bv_len;
649 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
654 if ( inlen > left.bv_len ) {
655 /* not enough length */
660 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
664 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
671 idx = p - left.bv_val;
673 if ( idx >= left.bv_len ) {
674 /* this shouldn't happen */
681 if ( sub->sa_any[i].bv_len > left.bv_len ) {
682 /* not enough left */
687 match = memcmp( left.bv_val,
688 sub->sa_any[i].bv_val,
689 sub->sa_any[i].bv_len );
697 left.bv_val += sub->sa_any[i].bv_len;
698 left.bv_len -= sub->sa_any[i].bv_len;
699 inlen -= sub->sa_any[i].bv_len;
708 /* Substrings Index generation function */
710 octetStringSubstringsIndexer(
715 struct berval *prefix,
724 HASH_CONTEXT HCany, HCini, HCfin;
725 unsigned char HASHdigest[HASH_BYTES];
726 struct berval digest;
727 digest.bv_val = (char *)HASHdigest;
728 digest.bv_len = sizeof(HASHdigest);
732 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
733 /* count number of indices to generate */
734 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
735 if( values[i].bv_len >= index_substr_if_maxlen ) {
736 nkeys += index_substr_if_maxlen -
737 (index_substr_if_minlen - 1);
738 } else if( values[i].bv_len >= index_substr_if_minlen ) {
739 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
743 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
744 if( values[i].bv_len >= index_substr_any_len ) {
745 nkeys += values[i].bv_len - (index_substr_any_len - 1);
749 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
750 if( values[i].bv_len >= index_substr_if_maxlen ) {
751 nkeys += index_substr_if_maxlen -
752 (index_substr_if_minlen - 1);
753 } else if( values[i].bv_len >= index_substr_if_minlen ) {
754 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
760 /* no keys to generate */
765 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
767 slen = syntax->ssyn_oidlen;
768 mlen = mr->smr_oidlen;
770 if ( flags & SLAP_INDEX_SUBSTR_ANY )
771 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
772 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
773 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
774 if( flags & SLAP_INDEX_SUBSTR_FINAL )
775 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
778 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
781 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
782 ( values[i].bv_len >= index_substr_any_len ) )
784 max = values[i].bv_len - (index_substr_any_len - 1);
786 for( j=0; j<max; j++ ) {
787 hashIter( &HCany, HASHdigest,
788 (unsigned char *)&values[i].bv_val[j],
789 index_substr_any_len );
790 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
794 /* skip if too short */
795 if( values[i].bv_len < index_substr_if_minlen ) continue;
797 max = index_substr_if_maxlen < values[i].bv_len
798 ? index_substr_if_maxlen : values[i].bv_len;
800 for( j=index_substr_if_minlen; j<=max; j++ ) {
802 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
803 hashIter( &HCini, HASHdigest,
804 (unsigned char *)values[i].bv_val, j );
805 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
808 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
809 hashIter( &HCfin, HASHdigest,
810 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
811 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
818 BER_BVZERO( &keys[nkeys] );
829 octetStringSubstringsFilter (
834 struct berval *prefix,
835 void * assertedValue,
839 SubstringsAssertion *sa;
842 size_t slen, mlen, klen;
844 HASH_CONTEXT HASHcontext;
845 unsigned char HASHdigest[HASH_BYTES];
846 struct berval *value;
847 struct berval digest;
849 sa = (SubstringsAssertion *) assertedValue;
851 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
852 !BER_BVISNULL( &sa->sa_initial ) &&
853 sa->sa_initial.bv_len >= index_substr_if_minlen )
856 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
857 ( flags & SLAP_INDEX_SUBSTR_ANY ))
859 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
863 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
865 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
866 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
867 /* don't bother accounting with stepping */
868 nkeys += sa->sa_any[i].bv_len -
869 ( index_substr_any_len - 1 );
874 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
875 !BER_BVISNULL( &sa->sa_final ) &&
876 sa->sa_final.bv_len >= index_substr_if_minlen )
879 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
880 ( flags & SLAP_INDEX_SUBSTR_ANY ))
882 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
891 digest.bv_val = (char *)HASHdigest;
892 digest.bv_len = sizeof(HASHdigest);
894 slen = syntax->ssyn_oidlen;
895 mlen = mr->smr_oidlen;
897 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
900 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
901 !BER_BVISNULL( &sa->sa_initial ) &&
902 sa->sa_initial.bv_len >= index_substr_if_minlen )
904 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
905 value = &sa->sa_initial;
907 klen = index_substr_if_maxlen < value->bv_len
908 ? index_substr_if_maxlen : value->bv_len;
910 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
911 hashIter( &HASHcontext, HASHdigest,
912 (unsigned char *)value->bv_val, klen );
913 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
915 /* If initial is too long and we have subany indexed, use it
916 * to match the excess...
918 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
921 pre = SLAP_INDEX_SUBSTR_PREFIX;
922 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
923 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
925 hashIter( &HASHcontext, HASHdigest,
926 (unsigned char *)&value->bv_val[j], index_substr_any_len );
927 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
932 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
934 pre = SLAP_INDEX_SUBSTR_PREFIX;
935 klen = index_substr_any_len;
937 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
938 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
942 value = &sa->sa_any[i];
944 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
946 j <= value->bv_len - index_substr_any_len;
947 j += index_substr_any_step )
949 hashIter( &HASHcontext, HASHdigest,
950 (unsigned char *)&value->bv_val[j], klen );
951 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
956 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
957 !BER_BVISNULL( &sa->sa_final ) &&
958 sa->sa_final.bv_len >= index_substr_if_minlen )
960 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
961 value = &sa->sa_final;
963 klen = index_substr_if_maxlen < value->bv_len
964 ? index_substr_if_maxlen : value->bv_len;
966 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
967 hashIter( &HASHcontext, HASHdigest,
968 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
969 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
971 /* If final is too long and we have subany indexed, use it
972 * to match the excess...
974 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
977 pre = SLAP_INDEX_SUBSTR_PREFIX;
978 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
979 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
981 hashIter( &HASHcontext, HASHdigest,
982 (unsigned char *)&value->bv_val[j], index_substr_any_len );
983 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
989 BER_BVZERO( &keys[nkeys] );
1006 /* very unforgiving validation, requires no normalization
1007 * before simplistic matching
1009 if( in->bv_len < 3 ) {
1010 return LDAP_INVALID_SYNTAX;
1013 /* RFC 4517 Section 3.3.2 Bit String:
1014 * BitString = SQUOTE *binary-digit SQUOTE "B"
1015 * binary-digit = "0" / "1"
1017 * where SQUOTE [RFC4512] is
1018 * SQUOTE = %x27 ; single quote ("'")
1020 * Example: '0101111101'B
1023 if( in->bv_val[0] != '\'' ||
1024 in->bv_val[in->bv_len - 2] != '\'' ||
1025 in->bv_val[in->bv_len - 1] != 'B' )
1027 return LDAP_INVALID_SYNTAX;
1030 for( i = in->bv_len - 3; i > 0; i-- ) {
1031 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1032 return LDAP_INVALID_SYNTAX;
1036 return LDAP_SUCCESS;
1040 * Syntaxes from RFC 4517
1045 A value of the Bit String syntax is a sequence of binary digits. The
1046 LDAP-specific encoding of a value of this syntax is defined by the
1049 BitString = SQUOTE *binary-digit SQUOTE "B"
1051 binary-digit = "0" / "1"
1053 The <SQUOTE> rule is defined in [MODELS].
1058 The LDAP definition for the Bit String syntax is:
1060 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1062 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1066 3.3.21. Name and Optional UID
1068 A value of the Name and Optional UID syntax is the distinguished name
1069 [MODELS] of an entity optionally accompanied by a unique identifier
1070 that serves to differentiate the entity from others with an identical
1073 The LDAP-specific encoding of a value of this syntax is defined by
1076 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1078 The <BitString> rule is defined in Section 3.3.2. The
1079 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1080 defined in [MODELS].
1082 Note that although the '#' character may occur in the string
1083 representation of a distinguished name, no additional escaping of
1084 this character is performed when a <distinguishedName> is encoded in
1085 a <NameAndOptionalUID>.
1088 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1090 The LDAP definition for the Name and Optional UID syntax is:
1092 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1094 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1101 1.4. Common ABNF Productions
1104 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1106 SQUOTE = %x27 ; single quote ("'")
1111 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1112 * be escaped except when at the beginning of a value, the
1113 * definition of Name and Optional UID appears to be flawed,
1114 * because there is no clear means to determine whether the
1115 * UID part is present or not.
1119 * cn=Someone,dc=example,dc=com#'1'B
1121 * could be either a NameAndOptionalUID with trailing UID, i.e.
1123 * DN = "cn=Someone,dc=example,dc=com"
1126 * or a NameAndOptionalUID with no trailing UID, and the AVA
1127 * in the last RDN made of
1129 * attributeType = dc
1130 * attributeValue = com#'1'B
1132 * in fact "com#'1'B" is a valid IA5 string.
1134 * As a consequence, current slapd code takes the presence of
1135 * #<valid BitString> at the end of the string representation
1136 * of a NameAndOptionalUID to mean this is indeed a BitString.
1137 * This is quite arbitrary - it has changed the past and might
1138 * change in the future.
1148 struct berval dn, uid;
1150 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1152 ber_dupbv( &dn, in );
1153 if( !dn.bv_val ) return LDAP_OTHER;
1155 /* if there's a "#", try bitStringValidate()... */
1156 uid.bv_val = strrchr( dn.bv_val, '#' );
1157 if ( !BER_BVISNULL( &uid ) ) {
1159 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1161 rc = bitStringValidate( NULL, &uid );
1162 if ( rc == LDAP_SUCCESS ) {
1163 /* in case of success, trim the UID,
1164 * otherwise treat it as part of the DN */
1165 dn.bv_len -= uid.bv_len + 1;
1166 uid.bv_val[-1] = '\0';
1170 rc = dnValidate( NULL, &dn );
1172 ber_memfree( dn.bv_val );
1183 assert( val != NULL );
1184 assert( out != NULL );
1187 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1189 if( BER_BVISEMPTY( val ) ) {
1190 ber_dupbv_x( out, val, ctx );
1192 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1193 return LDAP_INVALID_SYNTAX;
1197 struct berval dnval = *val;
1198 struct berval uidval = BER_BVNULL;
1200 uidval.bv_val = strrchr( val->bv_val, '#' );
1201 if ( !BER_BVISNULL( &uidval ) ) {
1203 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1205 rc = bitStringValidate( NULL, &uidval );
1207 if ( rc == LDAP_SUCCESS ) {
1208 ber_dupbv_x( &dnval, val, ctx );
1210 dnval.bv_len -= ++uidval.bv_len;
1211 dnval.bv_val[dnval.bv_len] = '\0';
1214 BER_BVZERO( &uidval );
1218 rc = dnPretty( syntax, &dnval, out, ctx );
1219 if ( dnval.bv_val != val->bv_val ) {
1220 slap_sl_free( dnval.bv_val, ctx );
1222 if( rc != LDAP_SUCCESS ) {
1226 if( !BER_BVISNULL( &uidval ) ) {
1229 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1230 + uidval.bv_len + 1,
1233 ber_memfree_x( out->bv_val, ctx );
1237 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1238 out->bv_len += uidval.bv_len;
1239 out->bv_val[out->bv_len] = '\0';
1243 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1245 return LDAP_SUCCESS;
1249 uniqueMemberNormalize(
1254 struct berval *normalized,
1260 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1262 ber_dupbv_x( &out, val, ctx );
1263 if ( BER_BVISEMPTY( &out ) ) {
1267 struct berval uid = BER_BVNULL;
1269 uid.bv_val = strrchr( out.bv_val, '#' );
1270 if ( !BER_BVISNULL( &uid ) ) {
1272 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1274 rc = bitStringValidate( NULL, &uid );
1275 if ( rc == LDAP_SUCCESS ) {
1276 uid.bv_val[-1] = '\0';
1277 out.bv_len -= uid.bv_len + 1;
1283 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1285 if( rc != LDAP_SUCCESS ) {
1286 slap_sl_free( out.bv_val, ctx );
1287 return LDAP_INVALID_SYNTAX;
1290 if( !BER_BVISNULL( &uid ) ) {
1293 tmp = ch_realloc( normalized->bv_val,
1294 normalized->bv_len + uid.bv_len
1295 + STRLENOF("#") + 1 );
1296 if ( tmp == NULL ) {
1297 ber_memfree_x( normalized->bv_val, ctx );
1301 normalized->bv_val = tmp;
1303 /* insert the separator */
1304 normalized->bv_val[normalized->bv_len++] = '#';
1306 /* append the UID */
1307 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1308 uid.bv_val, uid.bv_len );
1309 normalized->bv_len += uid.bv_len;
1312 normalized->bv_val[normalized->bv_len] = '\0';
1315 slap_sl_free( out.bv_val, ctx );
1318 return LDAP_SUCCESS;
1327 struct berval *value,
1328 void *assertedValue )
1331 struct berval *asserted = (struct berval *) assertedValue;
1332 struct berval assertedDN = *asserted;
1333 struct berval assertedUID = BER_BVNULL;
1334 struct berval valueDN = *value;
1335 struct berval valueUID = BER_BVNULL;
1336 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1338 if ( !BER_BVISEMPTY( asserted ) ) {
1339 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1340 if ( !BER_BVISNULL( &assertedUID ) ) {
1341 assertedUID.bv_val++;
1342 assertedUID.bv_len = assertedDN.bv_len
1343 - ( assertedUID.bv_val - assertedDN.bv_val );
1345 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1346 assertedDN.bv_len -= assertedUID.bv_len + 1;
1349 BER_BVZERO( &assertedUID );
1354 if ( !BER_BVISEMPTY( value ) ) {
1356 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1357 if ( !BER_BVISNULL( &valueUID ) ) {
1359 valueUID.bv_len = valueDN.bv_len
1360 - ( valueUID.bv_val - valueDN.bv_val );
1362 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1363 valueDN.bv_len -= valueUID.bv_len + 1;
1366 BER_BVZERO( &valueUID );
1371 if( valueUID.bv_len && assertedUID.bv_len ) {
1372 match = valueUID.bv_len - assertedUID.bv_len;
1375 return LDAP_SUCCESS;
1378 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1381 return LDAP_SUCCESS;
1384 } else if ( !approx && valueUID.bv_len ) {
1387 return LDAP_SUCCESS;
1389 } else if ( !approx && assertedUID.bv_len ) {
1392 return LDAP_SUCCESS;
1395 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1399 uniqueMemberIndexer(
1404 struct berval *prefix,
1412 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1413 /* just count them */
1417 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1419 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1420 struct berval assertedDN = values[i];
1421 struct berval assertedUID = BER_BVNULL;
1423 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1424 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1425 if ( !BER_BVISNULL( &assertedUID ) ) {
1426 assertedUID.bv_val++;
1427 assertedUID.bv_len = assertedDN.bv_len
1428 - ( assertedUID.bv_val - assertedDN.bv_val );
1430 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1431 assertedDN.bv_len -= assertedUID.bv_len + 1;
1434 BER_BVZERO( &assertedUID );
1439 dnvalues[i] = assertedDN;
1441 BER_BVZERO( &dnvalues[i] );
1443 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1444 dnvalues, keysp, ctx );
1446 slap_sl_free( dnvalues, ctx );
1456 struct berval *prefix,
1457 void * assertedValue,
1461 struct berval *asserted = (struct berval *) assertedValue;
1462 struct berval assertedDN = *asserted;
1463 struct berval assertedUID = BER_BVNULL;
1465 if ( !BER_BVISEMPTY( asserted ) ) {
1466 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1467 if ( !BER_BVISNULL( &assertedUID ) ) {
1468 assertedUID.bv_val++;
1469 assertedUID.bv_len = assertedDN.bv_len
1470 - ( assertedUID.bv_val - assertedDN.bv_val );
1472 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1473 assertedDN.bv_len -= assertedUID.bv_len + 1;
1476 BER_BVZERO( &assertedUID );
1481 return octetStringFilter( use, flags, syntax, mr, prefix,
1482 &assertedDN, keysp, ctx );
1487 * Handling boolean syntax and matching is quite rigid.
1488 * A more flexible approach would be to allow a variety
1489 * of strings to be normalized and prettied into TRUE
1497 /* very unforgiving validation, requires no normalization
1498 * before simplistic matching
1501 if( in->bv_len == 4 ) {
1502 if( bvmatch( in, &slap_true_bv ) ) {
1503 return LDAP_SUCCESS;
1505 } else if( in->bv_len == 5 ) {
1506 if( bvmatch( in, &slap_false_bv ) ) {
1507 return LDAP_SUCCESS;
1511 return LDAP_INVALID_SYNTAX;
1520 struct berval *value,
1521 void *assertedValue )
1523 /* simplistic matching allowed by rigid validation */
1524 struct berval *asserted = (struct berval *) assertedValue;
1525 *matchp = value->bv_len != asserted->bv_len;
1526 return LDAP_SUCCESS;
1529 /*-------------------------------------------------------------------
1530 LDAP/X.500 string syntax / matching rules have a few oddities. This
1531 comment attempts to detail how slapd(8) treats them.
1534 StringSyntax X.500 LDAP Matching/Comments
1535 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1536 PrintableString subset subset i/e + ignore insignificant spaces
1537 PrintableString subset subset i/e + ignore insignificant spaces
1538 NumericString subset subset ignore all spaces
1539 IA5String ASCII ASCII i/e + ignore insignificant spaces
1540 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1542 TelephoneNumber subset subset i + ignore all spaces and "-"
1544 See RFC 4518 for details.
1548 In X.500(93), a directory string can be either a PrintableString,
1549 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1550 In later versions, more CHOICEs were added. In all cases the string
1553 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1554 A directory string cannot be zero length.
1556 For matching, there are both case ignore and exact rules. Both
1557 also require that "insignificant" spaces be ignored.
1558 spaces before the first non-space are ignored;
1559 spaces after the last non-space are ignored;
1560 spaces after a space are ignored.
1561 Note: by these rules (and as clarified in X.520), a string of only
1562 spaces is to be treated as if held one space, not empty (which
1563 would be a syntax error).
1566 In ASN.1, numeric string is just a string of digits and spaces
1567 and could be empty. However, in X.500, all attribute values of
1568 numeric string carry a non-empty constraint. For example:
1570 internationalISDNNumber ATTRIBUTE ::= {
1571 WITH SYNTAX InternationalISDNNumber
1572 EQUALITY MATCHING RULE numericStringMatch
1573 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1574 ID id-at-internationalISDNNumber }
1575 InternationalISDNNumber ::=
1576 NumericString (SIZE(1..ub-international-isdn-number))
1578 Unforunately, some assertion values are don't carry the same
1579 constraint (but its unclear how such an assertion could ever
1580 be true). In LDAP, there is one syntax (numericString) not two
1581 (numericString with constraint, numericString without constraint).
1582 This should be treated as numericString with non-empty constraint.
1583 Note that while someone may have no ISDN number, there are no ISDN
1584 numbers which are zero length.
1586 In matching, spaces are ignored.
1589 In ASN.1, Printable string is just a string of printable characters
1590 and can be empty. In X.500, semantics much like NumericString (see
1591 serialNumber for a like example) excepting uses insignificant space
1592 handling instead of ignore all spaces. They must be non-empty.
1595 Basically same as PrintableString. There are no examples in X.500,
1596 but same logic applies. Empty strings are allowed.
1598 -------------------------------------------------------------------*/
1607 unsigned char *u = (unsigned char *)in->bv_val;
1609 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1610 /* directory strings cannot be empty */
1611 return LDAP_INVALID_SYNTAX;
1614 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1615 /* get the length indicated by the first byte */
1616 len = LDAP_UTF8_CHARLEN2( u, len );
1618 /* very basic checks */
1621 if( (u[5] & 0xC0) != 0x80 ) {
1622 return LDAP_INVALID_SYNTAX;
1625 if( (u[4] & 0xC0) != 0x80 ) {
1626 return LDAP_INVALID_SYNTAX;
1629 if( (u[3] & 0xC0) != 0x80 ) {
1630 return LDAP_INVALID_SYNTAX;
1633 if( (u[2] & 0xC0 )!= 0x80 ) {
1634 return LDAP_INVALID_SYNTAX;
1637 if( (u[1] & 0xC0) != 0x80 ) {
1638 return LDAP_INVALID_SYNTAX;
1641 /* CHARLEN already validated it */
1644 return LDAP_INVALID_SYNTAX;
1647 /* make sure len corresponds with the offset
1648 to the next character */
1649 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1653 return LDAP_INVALID_SYNTAX;
1656 return LDAP_SUCCESS;
1660 UTF8StringNormalize(
1665 struct berval *normalized,
1668 struct berval tmp, nvalue;
1669 int flags, wasspace;
1672 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1674 if( BER_BVISNULL( val ) ) {
1675 /* assume we're dealing with a syntax (e.g., UTF8String)
1676 * which allows empty strings
1678 BER_BVZERO( normalized );
1679 return LDAP_SUCCESS;
1682 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1683 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1684 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1685 ? LDAP_UTF8_APPROX : 0;
1687 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1692 /* collapse spaces (in place) */
1694 nvalue.bv_val = tmp.bv_val;
1696 /* trim leading spaces? */
1697 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1698 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1700 for( i = 0; i < tmp.bv_len; i++) {
1701 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1702 if( wasspace++ == 0 ) {
1703 /* trim repeated spaces */
1704 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1708 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1712 if( !BER_BVISEMPTY( &nvalue ) ) {
1713 /* trim trailing space? */
1715 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1716 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1720 nvalue.bv_val[nvalue.bv_len] = '\0';
1723 /* string of all spaces is treated as one space */
1724 nvalue.bv_val[0] = ' ';
1725 nvalue.bv_val[1] = '\0';
1729 *normalized = nvalue;
1730 return LDAP_SUCCESS;
1734 directoryStringSubstringsMatch(
1739 struct berval *value,
1740 void *assertedValue )
1743 SubstringsAssertion *sub = assertedValue;
1744 struct berval left = *value;
1748 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1749 if ( sub->sa_initial.bv_len > left.bv_len ) {
1750 /* not enough left */
1755 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1756 sub->sa_initial.bv_len );
1762 left.bv_val += sub->sa_initial.bv_len;
1763 left.bv_len -= sub->sa_initial.bv_len;
1765 priorspace = ASCII_SPACE(
1766 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1769 if ( sub->sa_any ) {
1770 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1774 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1775 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1777 /* allow next space to match */
1784 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1788 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1789 /* not enough left */
1794 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1801 idx = p - left.bv_val;
1803 if ( idx >= left.bv_len ) {
1804 /* this shouldn't happen */
1811 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1812 /* not enough left */
1817 match = memcmp( left.bv_val,
1818 sub->sa_any[i].bv_val,
1819 sub->sa_any[i].bv_len );
1827 left.bv_val += sub->sa_any[i].bv_len;
1828 left.bv_len -= sub->sa_any[i].bv_len;
1830 priorspace = ASCII_SPACE(
1831 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1835 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1836 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1837 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1839 /* allow next space to match */
1844 if ( sub->sa_final.bv_len > left.bv_len ) {
1845 /* not enough left */
1850 match = memcmp( sub->sa_final.bv_val,
1851 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1852 sub->sa_final.bv_len );
1861 return LDAP_SUCCESS;
1864 #if defined(SLAPD_APPROX_INITIALS)
1865 # define SLAPD_APPROX_DELIMITER "._ "
1866 # define SLAPD_APPROX_WORDLEN 2
1868 # define SLAPD_APPROX_DELIMITER " "
1869 # define SLAPD_APPROX_WORDLEN 1
1878 struct berval *value,
1879 void *assertedValue )
1881 struct berval *nval, *assertv;
1882 char *val, **values, **words, *c;
1883 int i, count, len, nextchunk=0, nextavail=0;
1885 /* Yes, this is necessary */
1886 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1887 if( nval == NULL ) {
1889 return LDAP_SUCCESS;
1892 /* Yes, this is necessary */
1893 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1894 NULL, LDAP_UTF8_APPROX, NULL );
1895 if( assertv == NULL ) {
1898 return LDAP_SUCCESS;
1901 /* Isolate how many words there are */
1902 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1903 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1904 if ( c == NULL ) break;
1909 /* Get a phonetic copy of each word */
1910 words = (char **)ch_malloc( count * sizeof(char *) );
1911 values = (char **)ch_malloc( count * sizeof(char *) );
1912 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1914 values[i] = phonetic(c);
1917 /* Work through the asserted value's words, to see if at least some
1918 * of the words are there, in the same order. */
1920 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1921 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1926 #if defined(SLAPD_APPROX_INITIALS)
1927 else if( len == 1 ) {
1928 /* Single letter words need to at least match one word's initial */
1929 for( i=nextavail; i<count; i++ )
1930 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1937 /* Isolate the next word in the asserted value and phonetic it */
1938 assertv->bv_val[nextchunk+len] = '\0';
1939 val = phonetic( assertv->bv_val + nextchunk );
1941 /* See if this phonetic chunk is in the remaining words of *value */
1942 for( i=nextavail; i<count; i++ ){
1943 if( !strcmp( val, values[i] ) ){
1951 /* This chunk in the asserted value was NOT within the *value. */
1957 /* Go on to the next word in the asserted value */
1961 /* If some of the words were seen, call it a match */
1962 if( nextavail > 0 ) {
1969 /* Cleanup allocs */
1970 ber_bvfree( assertv );
1971 for( i=0; i<count; i++ ) {
1972 ch_free( values[i] );
1978 return LDAP_SUCCESS;
1987 struct berval *prefix,
1993 int i,j, len, wordcount, keycount=0;
1994 struct berval *newkeys;
1995 BerVarray keys=NULL;
1997 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1998 struct berval val = BER_BVNULL;
1999 /* Yes, this is necessary */
2000 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2001 assert( !BER_BVISNULL( &val ) );
2003 /* Isolate how many words there are. There will be a key for each */
2004 for( wordcount = 0, c = val.bv_val; *c; c++) {
2005 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2006 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2008 if (*c == '\0') break;
2012 /* Allocate/increase storage to account for new keys */
2013 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2014 * sizeof(struct berval) );
2015 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2016 if( keys ) ch_free( keys );
2019 /* Get a phonetic copy of each word */
2020 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2022 if( len < SLAPD_APPROX_WORDLEN ) continue;
2023 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2028 ber_memfree( val.bv_val );
2030 BER_BVZERO( &keys[keycount] );
2033 return LDAP_SUCCESS;
2042 struct berval *prefix,
2043 void * assertedValue,
2052 /* Yes, this is necessary */
2053 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2054 NULL, LDAP_UTF8_APPROX, NULL );
2055 if( val == NULL || BER_BVISNULL( val ) ) {
2056 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2057 BER_BVZERO( &keys[0] );
2060 return LDAP_SUCCESS;
2063 /* Isolate how many words there are. There will be a key for each */
2064 for( count = 0,c = val->bv_val; *c; c++) {
2065 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2066 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2068 if (*c == '\0') break;
2072 /* Allocate storage for new keys */
2073 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2075 /* Get a phonetic copy of each word */
2076 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2078 if( len < SLAPD_APPROX_WORDLEN ) continue;
2079 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2085 BER_BVZERO( &keys[count] );
2088 return LDAP_SUCCESS;
2091 /* Remove all spaces and '-' characters */
2093 telephoneNumberNormalize(
2098 struct berval *normalized,
2103 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2105 /* validator should have refused an empty string */
2106 assert( !BER_BVISEMPTY( val ) );
2108 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2110 for( p = val->bv_val; *p; p++ ) {
2111 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2117 normalized->bv_len = q - normalized->bv_val;
2119 if( BER_BVISEMPTY( normalized ) ) {
2120 slap_sl_free( normalized->bv_val, ctx );
2121 BER_BVZERO( normalized );
2122 return LDAP_INVALID_SYNTAX;
2125 return LDAP_SUCCESS;
2129 postalAddressValidate(
2133 struct berval bv = *in;
2136 for ( c = 0; c < in->bv_len; c++ ) {
2137 if ( in->bv_val[c] == '\\' ) {
2139 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2140 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2142 return LDAP_INVALID_SYNTAX;
2147 if ( in->bv_val[c] == '$' ) {
2148 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2149 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2150 return LDAP_INVALID_SYNTAX;
2152 bv.bv_val = &in->bv_val[c] + 1;
2156 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2157 return UTF8StringValidate( NULL, &bv );
2161 postalAddressNormalize(
2166 struct berval *normalized,
2169 BerVarray lines = NULL, nlines = NULL;
2171 int rc = LDAP_SUCCESS;
2172 MatchingRule *xmr = NULL;
2175 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2176 xmr = slap_schema.si_mr_caseIgnoreMatch;
2179 xmr = slap_schema.si_mr_caseExactMatch;
2182 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2183 if ( val->bv_val[c] == '$' ) {
2188 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2189 nlines = &lines[l + 2];
2191 lines[0].bv_val = val->bv_val;
2192 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2193 if ( val->bv_val[c] == '$' ) {
2194 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2196 lines[l].bv_val = &val->bv_val[c + 1];
2199 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2201 normalized->bv_len = l;
2203 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2204 /* NOTE: we directly normalize each line,
2205 * without unescaping the values, since the special
2206 * values '\24' ('$') and '\5C' ('\') are not affected
2207 * by normalization */
2208 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2209 if ( rc != LDAP_SUCCESS ) {
2210 rc = LDAP_INVALID_SYNTAX;
2214 normalized->bv_len += nlines[l].bv_len;
2217 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2219 p = normalized->bv_val;
2220 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2221 p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2227 assert( p == &normalized->bv_val[normalized->bv_len] );
2230 if ( nlines != NULL ) {
2231 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2232 slap_sl_free( nlines[l].bv_val, ctx );
2235 slap_sl_free( lines, ctx );
2246 struct berval val = *in;
2248 if( BER_BVISEMPTY( &val ) ) {
2249 /* disallow empty strings */
2250 return LDAP_INVALID_SYNTAX;
2253 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2254 if ( val.bv_len == 1 ) {
2255 return LDAP_SUCCESS;
2258 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2265 while ( OID_LEADCHAR( val.bv_val[0] )) {
2269 if ( val.bv_len == 0 ) {
2270 return LDAP_SUCCESS;
2274 if( !OID_SEPARATOR( val.bv_val[0] )) {
2282 return LDAP_INVALID_SYNTAX;
2291 struct berval val = *in;
2293 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2295 if ( val.bv_val[0] == '-' ) {
2299 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2300 return LDAP_INVALID_SYNTAX;
2303 if( val.bv_val[0] == '0' ) { /* "-0" */
2304 return LDAP_INVALID_SYNTAX;
2307 } else if ( val.bv_val[0] == '0' ) {
2308 if( val.bv_len > 1 ) { /* "0<more>" */
2309 return LDAP_INVALID_SYNTAX;
2312 return LDAP_SUCCESS;
2315 for( i=0; i < val.bv_len; i++ ) {
2316 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2317 return LDAP_INVALID_SYNTAX;
2321 return LDAP_SUCCESS;
2330 struct berval *value,
2331 void *assertedValue )
2333 struct berval *asserted = (struct berval *) assertedValue;
2334 int vsign = 1, asign = 1; /* default sign = '+' */
2339 if( v.bv_val[0] == '-' ) {
2345 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2348 if( a.bv_val[0] == '-' ) {
2354 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2356 match = vsign - asign;
2358 match = ( v.bv_len != a.bv_len
2359 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2360 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2361 if( vsign < 0 ) match = -match;
2365 return LDAP_SUCCESS;
2368 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2369 #define INDEX_INTLEN_CHOP 7
2370 #define INDEX_INTLEN_CHOPBYTES 3
2380 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2381 * two's complement value (sign-extended or chopped as needed),
2382 * however the top <number of exponent-bytes + 1> bits of first byte
2383 * above is the inverse sign. The next bit is the sign as delimiter.
2385 ber_slen_t k = index_intlen_strlen;
2387 unsigned signmask = ~0x7fU;
2388 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2389 struct berval val = *in, itmp = *tmp;
2391 if ( val.bv_val[0] != '-' ) {
2396 /* Chop least significant digits, increase length instead */
2397 if ( val.bv_len > (ber_len_t) k ) {
2398 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2399 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2400 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2403 if ( lutil_str2bin( &val, &itmp, ctx )) {
2404 return LDAP_INVALID_SYNTAX;
2407 /* Omit leading sign byte */
2408 if ( itmp.bv_val[0] == neg ) {
2413 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2415 assert( chop == 0 );
2416 memset( key->bv_val, neg, k ); /* sign-extend */
2417 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2418 lenp = lenbuf + sizeof(lenbuf);
2419 chop = - (ber_len_t) k;
2421 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2423 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2424 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2425 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2426 k = (lenbuf + sizeof(lenbuf)) - lenp;
2427 if ( k > (ber_slen_t) index_intlen )
2429 memcpy( key->bv_val, lenp, k );
2430 itmp.bv_len = index_intlen - k;
2432 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2433 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2437 /* Index generation function */
2444 struct berval *prefix,
2454 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2456 /* count the values and find max needed length */
2458 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2459 if ( vlen < values[i].bv_len )
2460 vlen = values[i].bv_len;
2462 if ( vlen > maxstrlen )
2465 /* we should have at least one value at this point */
2468 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2469 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2470 keys[i].bv_len = index_intlen;
2471 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2474 keys[i].bv_val = NULL;
2476 if ( vlen > sizeof(ibuf) ) {
2477 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2481 itmp.bv_len = sizeof(ibuf);
2483 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2484 if ( itmp.bv_val != ibuf ) {
2485 itmp.bv_len = values[i].bv_len;
2486 if ( itmp.bv_len <= sizeof(ibuf) )
2487 itmp.bv_len = sizeof(ibuf);
2488 else if ( itmp.bv_len > maxstrlen )
2489 itmp.bv_len = maxstrlen;
2491 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2497 if ( itmp.bv_val != ibuf ) {
2498 slap_sl_free( itmp.bv_val, ctx );
2503 /* Index generation function */
2510 struct berval *prefix,
2511 void * assertedValue,
2518 struct berval *value;
2521 value = (struct berval *) assertedValue;
2523 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2525 keys[0].bv_len = index_intlen;
2526 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2528 keys[1].bv_val = NULL;
2530 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2531 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2532 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2533 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2536 iv.bv_len = sizeof(ibuf);
2539 rc = integerVal2Key( value, keys, &iv, ctx );
2543 if ( iv.bv_val != ibuf ) {
2544 slap_sl_free( iv.bv_val, ctx );
2550 countryStringValidate(
2552 struct berval *val )
2554 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2556 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2557 return LDAP_INVALID_SYNTAX;
2559 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2560 return LDAP_INVALID_SYNTAX;
2563 return LDAP_SUCCESS;
2567 printableStringValidate(
2569 struct berval *val )
2573 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2575 for(i=0; i < val->bv_len; i++) {
2576 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2577 return LDAP_INVALID_SYNTAX;
2581 return LDAP_SUCCESS;
2585 printablesStringValidate(
2587 struct berval *val )
2591 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2593 for(i=0,len=0; i < val->bv_len; i++) {
2594 int c = val->bv_val[i];
2598 return LDAP_INVALID_SYNTAX;
2602 } else if ( SLAP_PRINTABLE(c) ) {
2605 return LDAP_INVALID_SYNTAX;
2610 return LDAP_INVALID_SYNTAX;
2613 return LDAP_SUCCESS;
2619 struct berval *val )
2623 for(i=0; i < val->bv_len; i++) {
2624 if( !LDAP_ASCII(val->bv_val[i]) ) {
2625 return LDAP_INVALID_SYNTAX;
2629 return LDAP_SUCCESS;
2638 struct berval *normalized,
2642 int casefold = !SLAP_MR_ASSOCIATED( mr,
2643 slap_schema.si_mr_caseExactIA5Match );
2645 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2649 /* Ignore initial whitespace */
2650 while ( ASCII_SPACE( *p ) ) p++;
2652 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2653 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2654 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2655 normalized->bv_val[normalized->bv_len] = '\0';
2657 p = q = normalized->bv_val;
2660 if ( ASCII_SPACE( *p ) ) {
2663 /* Ignore the extra whitespace */
2664 while ( ASCII_SPACE( *p ) ) {
2668 } else if ( casefold ) {
2669 /* Most IA5 rules require casefolding */
2670 *q++ = TOLOWER(*p); p++;
2677 assert( normalized->bv_val <= p );
2681 * If the string ended in space, backup the pointer one
2682 * position. One is enough because the above loop collapsed
2683 * all whitespace to a single space.
2685 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2687 /* null terminate */
2690 normalized->bv_len = q - normalized->bv_val;
2692 return LDAP_SUCCESS;
2701 if( in->bv_len != 36 ) {
2702 return LDAP_INVALID_SYNTAX;
2705 for( i=0; i<36; i++ ) {
2711 if( in->bv_val[i] != '-' ) {
2712 return LDAP_INVALID_SYNTAX;
2716 if( !ASCII_HEX( in->bv_val[i]) ) {
2717 return LDAP_INVALID_SYNTAX;
2722 return LDAP_SUCCESS;
2733 int rc=LDAP_INVALID_SYNTAX;
2735 assert( in != NULL );
2736 assert( out != NULL );
2738 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2741 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2743 for( i=0; i<36; i++ ) {
2749 if( in->bv_val[i] != '-' ) {
2752 out->bv_val[i] = '-';
2756 if( !ASCII_HEX( in->bv_val[i]) ) {
2759 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2764 out->bv_val[ out->bv_len ] = '\0';
2768 slap_sl_free( out->bv_val, ctx );
2781 struct berval *normalized,
2784 unsigned char octet = '\0';
2788 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2789 /* NOTE: must be a normalized UUID */
2790 assert( val->bv_len == 16 );
2792 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2793 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2794 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2795 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2797 return LDAP_SUCCESS;
2800 normalized->bv_len = 16;
2801 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2803 for( i=0, j=0; i<36; i++ ) {
2804 unsigned char nibble;
2805 if( val->bv_val[i] == '-' ) {
2808 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2809 nibble = val->bv_val[i] - '0';
2811 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2812 nibble = val->bv_val[i] - ('a'-10);
2814 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2815 nibble = val->bv_val[i] - ('A'-10);
2818 slap_sl_free( normalized->bv_val, ctx );
2819 BER_BVZERO( normalized );
2820 return LDAP_INVALID_SYNTAX;
2825 normalized->bv_val[j>>1] = octet;
2827 octet = nibble << 4;
2832 normalized->bv_val[normalized->bv_len] = 0;
2833 return LDAP_SUCCESS;
2839 numericStringValidate(
2845 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2847 for(i=0; i < in->bv_len; i++) {
2848 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2849 return LDAP_INVALID_SYNTAX;
2853 return LDAP_SUCCESS;
2857 numericStringNormalize(
2862 struct berval *normalized,
2865 /* removal all spaces */
2868 assert( !BER_BVISEMPTY( val ) );
2870 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2873 q = normalized->bv_val;
2876 if ( ASCII_SPACE( *p ) ) {
2877 /* Ignore whitespace */
2884 /* we should have copied no more than is in val */
2885 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2887 /* null terminate */
2890 normalized->bv_len = q - normalized->bv_val;
2892 if( BER_BVISEMPTY( normalized ) ) {
2893 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2894 normalized->bv_val[0] = ' ';
2895 normalized->bv_val[1] = '\0';
2896 normalized->bv_len = 1;
2899 return LDAP_SUCCESS;
2903 * Integer conversion macros that will use the largest available
2906 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2907 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2908 # define SLAP_LONG long long
2910 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2911 # define SLAP_LONG long
2912 #endif /* HAVE_STRTOLL ... */
2920 struct berval *value,
2921 void *assertedValue )
2923 SLAP_LONG lValue, lAssertedValue;
2926 /* safe to assume integers are NUL terminated? */
2927 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2928 if( errno == ERANGE )
2930 return LDAP_CONSTRAINT_VIOLATION;
2933 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2935 if( errno == ERANGE )
2937 return LDAP_CONSTRAINT_VIOLATION;
2940 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2941 return LDAP_SUCCESS;
2950 struct berval *value,
2951 void *assertedValue )
2953 SLAP_LONG lValue, lAssertedValue;
2956 /* safe to assume integers are NUL terminated? */
2957 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2958 if( errno == ERANGE )
2960 return LDAP_CONSTRAINT_VIOLATION;
2963 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2965 if( errno == ERANGE )
2967 return LDAP_CONSTRAINT_VIOLATION;
2970 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2971 return LDAP_SUCCESS;
2975 checkNum( struct berval *in, struct berval *out )
2977 /* parse serialNumber */
2978 ber_len_t neg = 0, extra = 0;
2981 out->bv_val = in->bv_val;
2984 if ( out->bv_val[0] == '-' ) {
2989 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
2990 first = out->bv_val[2];
2993 out->bv_len += STRLENOF("0x");
2994 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2995 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2998 } else if ( out->bv_val[0] == '\'' ) {
2999 first = out->bv_val[1];
3002 out->bv_len += STRLENOF("'");
3004 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3005 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3007 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3010 out->bv_len += STRLENOF("'H");
3013 first = out->bv_val[0];
3014 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3015 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3019 if ( !( out->bv_len > neg ) ) {
3023 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3031 serialNumberAndIssuerCheck(
3039 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3041 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3042 /* Parse old format */
3043 is->bv_val = ber_bvchr( in, '$' );
3044 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3046 sn->bv_val = in->bv_val;
3047 sn->bv_len = is->bv_val - in->bv_val;
3050 is->bv_len = in->bv_len - (sn->bv_len + 1);
3052 /* eat leading zeros */
3053 for( n=0; n < (sn->bv_len-1); n++ ) {
3054 if( sn->bv_val[n] != '0' ) break;
3059 for( n=0; n < sn->bv_len; n++ ) {
3060 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3064 /* Parse GSER format */
3069 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3073 struct berval x = *in;
3079 /* eat leading spaces */
3080 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3084 /* should be at issuer or serialNumber NamedValue */
3085 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3086 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3089 x.bv_val += STRLENOF("issuer");
3090 x.bv_len -= STRLENOF("issuer");
3092 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3096 /* eat leading spaces */
3097 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3101 /* For backward compatibility, this part is optional */
3102 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3103 x.bv_val += STRLENOF("rdnSequence:");
3104 x.bv_len -= STRLENOF("rdnSequence:");
3107 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3111 is->bv_val = x.bv_val;
3114 for ( ; is->bv_len < x.bv_len; ) {
3115 if ( is->bv_val[is->bv_len] != '"' ) {
3119 if ( is->bv_val[is->bv_len+1] == '"' ) {
3126 x.bv_val += is->bv_len + 1;
3127 x.bv_len -= is->bv_len + 1;
3129 have |= HAVE_ISSUER;
3131 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3133 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3135 /* parse serialNumber */
3136 x.bv_val += STRLENOF("serialNumber");
3137 x.bv_len -= STRLENOF("serialNumber");
3139 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3143 /* eat leading spaces */
3144 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3148 if ( checkNum( &x, sn ) ) {
3149 return LDAP_INVALID_SYNTAX;
3152 x.bv_val += sn->bv_len;
3153 x.bv_len -= sn->bv_len;
3158 return LDAP_INVALID_SYNTAX;
3161 /* eat leading spaces */
3162 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3166 if ( have == HAVE_ALL ) {
3170 if ( x.bv_val[0] != ',' ) {
3171 return LDAP_INVALID_SYNTAX;
3178 /* should have no characters left... */
3179 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3181 if ( numdquotes == 0 ) {
3182 ber_dupbv_x( &ni, is, ctx );
3187 ni.bv_len = is->bv_len - numdquotes;
3188 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3189 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3190 if ( is->bv_val[src] == '"' ) {
3193 ni.bv_val[dst] = is->bv_val[src];
3195 ni.bv_val[dst] = '\0';
3205 serialNumberAndIssuerValidate(
3210 struct berval sn, i;
3212 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3215 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3220 /* validate DN -- doesn't handle double dquote */
3221 rc = dnValidate( NULL, &i );
3223 rc = LDAP_INVALID_SYNTAX;
3226 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3227 slap_sl_free( i.bv_val, NULL );
3230 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3231 in->bv_val, rc, 0 );
3238 serialNumberAndIssuerPretty(
3245 struct berval sn, i, ni = BER_BVNULL;
3248 assert( in != NULL );
3249 assert( out != NULL );
3253 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3256 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3261 rc = dnPretty( syntax, &i, &ni, ctx );
3263 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3264 slap_sl_free( i.bv_val, ctx );
3268 rc = LDAP_INVALID_SYNTAX;
3272 /* make room from sn + "$" */
3273 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3274 + sn.bv_len + ni.bv_len;
3275 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3277 if ( out->bv_val == NULL ) {
3284 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3285 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3286 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3287 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3288 p = lutil_strcopy( p, /*{*/ "\" }" );
3290 assert( p == &out->bv_val[out->bv_len] );
3293 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3294 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3296 slap_sl_free( ni.bv_val, ctx );
3298 return LDAP_SUCCESS;
3308 /* Use hex format. '123456789abcdef'H */
3309 unsigned char *ptr, zero = '\0';
3312 ber_len_t i, len, nlen;
3314 assert( in != NULL );
3315 assert( !BER_BVISNULL( in ) );
3316 assert( out != NULL );
3317 assert( !BER_BVISNULL( out ) );
3319 ptr = (unsigned char *)in->bv_val;
3322 /* Check for minimal encodings */
3324 if ( ptr[0] & 0x80 ) {
3325 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3329 } else if ( ptr[0] == 0 ) {
3330 if ( !( ptr[1] & 0x80 ) ) {
3337 } else if ( len == 0 ) {
3338 /* FIXME: this should not be possible,
3339 * since a value of zero would have length 1 */
3344 first = !( ptr[0] & 0xf0U );
3345 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3346 if ( nlen >= out->bv_len ) {
3347 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3353 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3357 for ( ; i < len; i++ ) {
3358 sprintf( sptr, "%02X", ptr[i] );
3365 assert( sptr == &out->bv_val[nlen] );
3372 #define SLAP_SN_BUFLEN (64)
3375 * This routine is called by certificateExactNormalize when
3376 * certificateExactNormalize receives a search string instead of
3377 * a certificate. This routine checks if the search value is valid
3378 * and then returns the normalized value
3381 serialNumberAndIssuerNormalize(
3389 struct berval sn, sn2, sn3, i, ni;
3390 char sbuf2[SLAP_SN_BUFLEN];
3391 char sbuf3[SLAP_SN_BUFLEN];
3395 assert( in != NULL );
3396 assert( out != NULL );
3398 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3401 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3406 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3408 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3409 slap_sl_free( i.bv_val, ctx );
3413 return LDAP_INVALID_SYNTAX;
3416 /* Convert sn to canonical hex */
3418 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3419 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3421 sn2.bv_len = sn.bv_len;
3422 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3423 rc = LDAP_INVALID_SYNTAX;
3428 sn3.bv_len = sizeof(sbuf3);
3429 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3430 rc = LDAP_INVALID_SYNTAX;
3434 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3435 + sn3.bv_len + ni.bv_len;
3436 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3438 if ( out->bv_val == NULL ) {
3446 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3447 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3448 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3449 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3450 p = lutil_strcopy( p, /*{*/ "\" }" );
3452 assert( p == &out->bv_val[out->bv_len] );
3455 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3456 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3458 if ( sn2.bv_val != sbuf2 ) {
3459 slap_sl_free( sn2.bv_val, ctx );
3462 if ( sn3.bv_val != sbuf3 ) {
3463 slap_sl_free( sn3.bv_val, ctx );
3466 slap_sl_free( ni.bv_val, ctx );
3472 certificateExactNormalize(
3477 struct berval *normalized,
3480 BerElementBuffer berbuf;
3481 BerElement *ber = (BerElement *)&berbuf;
3485 char serialbuf2[SLAP_SN_BUFLEN];
3486 struct berval sn, sn2 = BER_BVNULL;
3487 struct berval issuer_dn = BER_BVNULL, bvdn;
3489 int rc = LDAP_INVALID_SYNTAX;
3491 assert( val != NULL );
3493 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3494 val->bv_val, val->bv_len, 0 );
3496 if ( BER_BVISEMPTY( val ) ) goto done;
3498 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3499 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3502 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3504 ber_init2( ber, val, LBER_USE_DER );
3505 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3506 tag = ber_skip_tag( ber, &len ); /* Sequence */
3507 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3508 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3509 tag = ber_skip_tag( ber, &len );
3510 tag = ber_get_int( ber, &i ); /* version */
3513 /* NOTE: move the test here from certificateValidate,
3514 * so that we can validate certs with serial longer
3515 * than sizeof(ber_int_t) */
3516 tag = ber_skip_tag( ber, &len ); /* serial */
3518 sn.bv_val = (char *)ber->ber_ptr;
3519 sn2.bv_val = serialbuf2;
3520 sn2.bv_len = sizeof(serialbuf2);
3521 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3522 rc = LDAP_INVALID_SYNTAX;
3525 ber_skip_data( ber, len );
3527 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3528 ber_skip_data( ber, len );
3529 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3530 len = ber_ptrlen( ber );
3531 bvdn.bv_val = val->bv_val + len;
3532 bvdn.bv_len = val->bv_len - len;
3534 rc = dnX509normalize( &bvdn, &issuer_dn );
3535 if ( rc != LDAP_SUCCESS ) goto done;
3537 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3538 + sn2.bv_len + issuer_dn.bv_len;
3539 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3541 p = normalized->bv_val;
3543 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3544 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3545 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3546 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3547 p = lutil_strcopy( p, /*{*/ "\" }" );
3552 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3553 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3555 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3556 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3561 /* X.509 PKI certificateList stuff */
3563 checkTime( struct berval *in, struct berval *out )
3567 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3570 assert( in != NULL );
3571 assert( !BER_BVISNULL( in ) );
3572 assert( !BER_BVISEMPTY( in ) );
3574 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3578 if ( out != NULL ) {
3579 assert( !BER_BVISNULL( out ) );
3580 assert( out->bv_len >= sizeof( buf ) );
3581 bv.bv_val = out->bv_val;
3587 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3588 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3591 if ( in->bv_val[i] != 'Z' ) {
3596 if ( i != in->bv_len ) {
3600 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3601 lutil_strncopy( bv.bv_val, in->bv_val, i );
3604 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3605 char *p = bv.bv_val;
3606 if ( in->bv_val[0] < '7' ) {
3607 p = lutil_strcopy( p, "20" );
3610 p = lutil_strcopy( p, "19" );
3612 lutil_strncopy( p, in->bv_val, i );
3619 rc = generalizedTimeValidate( NULL, &bv );
3620 if ( rc == LDAP_SUCCESS && out != NULL ) {
3621 out->bv_len = bv.bv_len;
3624 return rc != LDAP_SUCCESS;
3628 issuerAndThisUpdateCheck(
3635 struct berval x = *in;
3636 struct berval ni = BER_BVNULL;
3637 /* Parse GSER format */
3641 HAVE_THISUPDATE = 0x2,
3642 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3646 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3648 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3649 return LDAP_INVALID_SYNTAX;
3653 x.bv_len -= STRLENOF("{}");
3656 /* eat leading spaces */
3657 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3661 /* should be at issuer or thisUpdate */
3662 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3663 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3666 x.bv_val += STRLENOF("issuer");
3667 x.bv_len -= STRLENOF("issuer");
3669 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3673 /* eat leading spaces */
3674 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3678 /* For backward compatibility, this part is optional */
3679 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3680 return LDAP_INVALID_SYNTAX;
3682 x.bv_val += STRLENOF("rdnSequence:");
3683 x.bv_len -= STRLENOF("rdnSequence:");
3685 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3689 is->bv_val = x.bv_val;
3692 for ( ; is->bv_len < x.bv_len; ) {
3693 if ( is->bv_val[is->bv_len] != '"' ) {
3697 if ( is->bv_val[is->bv_len+1] == '"' ) {
3704 x.bv_val += is->bv_len + 1;
3705 x.bv_len -= is->bv_len + 1;
3707 have |= HAVE_ISSUER;
3709 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3711 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3713 /* parse thisUpdate */
3714 x.bv_val += STRLENOF("thisUpdate");
3715 x.bv_len -= STRLENOF("thisUpdate");
3717 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3721 /* eat leading spaces */
3722 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3726 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3730 tu->bv_val = x.bv_val;
3733 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3734 if ( tu->bv_val[tu->bv_len] == '"' ) {
3738 x.bv_val += tu->bv_len + 1;
3739 x.bv_len -= tu->bv_len + 1;
3741 have |= HAVE_THISUPDATE;
3744 return LDAP_INVALID_SYNTAX;
3747 /* eat leading spaces */
3748 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3752 if ( have == HAVE_ALL ) {
3756 if ( x.bv_val[0] != ',' ) {
3757 return LDAP_INVALID_SYNTAX;
3764 /* should have no characters left... */
3765 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3767 if ( numdquotes == 0 ) {
3768 ber_dupbv_x( &ni, is, ctx );
3773 ni.bv_len = is->bv_len - numdquotes;
3774 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3775 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3776 if ( is->bv_val[src] == '"' ) {
3779 ni.bv_val[dst] = is->bv_val[src];
3781 ni.bv_val[dst] = '\0';
3790 issuerAndThisUpdateValidate(
3795 struct berval i, tu;
3797 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3800 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3805 /* validate DN -- doesn't handle double dquote */
3806 rc = dnValidate( NULL, &i );
3808 rc = LDAP_INVALID_SYNTAX;
3810 } else if ( checkTime( &tu, NULL ) ) {
3811 rc = LDAP_INVALID_SYNTAX;
3814 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3815 slap_sl_free( i.bv_val, NULL );
3818 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3819 in->bv_val, rc, 0 );
3826 issuerAndThisUpdatePretty(
3833 struct berval i, tu, ni = BER_BVNULL;
3836 assert( in != NULL );
3837 assert( out != NULL );
3841 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3844 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3849 rc = dnPretty( syntax, &i, &ni, ctx );
3851 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3852 slap_sl_free( i.bv_val, ctx );
3855 if ( rc || checkTime( &tu, NULL ) ) {
3856 rc = LDAP_INVALID_SYNTAX;
3861 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3862 + ni.bv_len + tu.bv_len;
3863 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3865 if ( out->bv_val == NULL ) {
3872 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3873 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3874 p = lutil_strcopy( p, "\", thisUpdate \"" );
3875 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3876 p = lutil_strcopy( p, /*{*/ "\" }" );
3878 assert( p == &out->bv_val[out->bv_len] );
3881 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3882 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3884 slap_sl_free( ni.bv_val, ctx );
3890 issuerAndThisUpdateNormalize(
3898 struct berval i, ni, tu, tu2;
3899 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3903 assert( in != NULL );
3904 assert( out != NULL );
3906 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3909 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3914 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3916 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3917 slap_sl_free( i.bv_val, ctx );
3921 tu2.bv_len = sizeof( sbuf );
3922 if ( rc || checkTime( &tu, &tu2 ) ) {
3923 return LDAP_INVALID_SYNTAX;
3926 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3927 + ni.bv_len + tu2.bv_len;
3928 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3930 if ( out->bv_val == NULL ) {
3938 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3939 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3940 p = lutil_strcopy( p, "\", thisUpdate \"" );
3941 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3942 p = lutil_strcopy( p, /*{*/ "\" }" );
3944 assert( p == &out->bv_val[out->bv_len] );
3947 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3948 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3950 slap_sl_free( ni.bv_val, ctx );
3956 certificateListExactNormalize(
3961 struct berval *normalized,
3964 BerElementBuffer berbuf;
3965 BerElement *ber = (BerElement *)&berbuf;
3969 struct berval issuer_dn = BER_BVNULL, bvdn,
3971 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3972 int rc = LDAP_INVALID_SYNTAX;
3974 assert( val != NULL );
3976 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
3977 val->bv_val, val->bv_len, 0 );
3979 if ( BER_BVISEMPTY( val ) ) goto done;
3981 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3982 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
3985 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3987 ber_init2( ber, val, LBER_USE_DER );
3988 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
3989 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3990 tag = ber_skip_tag( ber, &len ); /* Sequence */
3991 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3992 tag = ber_peek_tag( ber, &len );
3993 /* Optional version */
3994 if ( tag == LBER_INTEGER ) {
3995 tag = ber_get_int( ber, &version );
3996 assert( tag == LBER_INTEGER );
3997 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
3999 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4000 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4001 ber_skip_data( ber, len );
4003 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4004 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4005 len = ber_ptrlen( ber );
4006 bvdn.bv_val = val->bv_val + len;
4007 bvdn.bv_len = val->bv_len - len;
4008 tag = ber_skip_tag( ber, &len );
4009 ber_skip_data( ber, len );
4011 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4012 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4013 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4014 bvtu.bv_val = (char *)ber->ber_ptr;
4017 rc = dnX509normalize( &bvdn, &issuer_dn );
4018 if ( rc != LDAP_SUCCESS ) goto done;
4020 thisUpdate.bv_val = tubuf;
4021 thisUpdate.bv_len = sizeof(tubuf);
4022 if ( checkTime( &bvtu, &thisUpdate ) ) {
4023 rc = LDAP_INVALID_SYNTAX;
4027 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4028 + issuer_dn.bv_len + thisUpdate.bv_len;
4029 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4031 p = normalized->bv_val;
4033 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4034 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4035 p = lutil_strcopy( p, "\", thisUpdate \"" );
4036 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
4037 p = lutil_strcopy( p, /*{*/ "\" }" );
4042 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4043 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4045 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4050 /* X.509 PMI serialNumberAndIssuerSerialCheck
4052 AttributeCertificateExactAssertion ::= SEQUENCE {
4053 serialNumber CertificateSerialNumber,
4054 issuer AttCertIssuer }
4056 CertificateSerialNumber ::= INTEGER
4058 AttCertIssuer ::= [0] SEQUENCE {
4059 issuerName GeneralNames OPTIONAL,
4060 baseCertificateID [0] IssuerSerial OPTIONAL,
4061 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4062 -- At least one component shall be present
4064 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4066 GeneralName ::= CHOICE {
4067 otherName [0] INSTANCE OF OTHER-NAME,
4068 rfc822Name [1] IA5String,
4069 dNSName [2] IA5String,
4070 x400Address [3] ORAddress,
4071 directoryName [4] Name,
4072 ediPartyName [5] EDIPartyName,
4073 uniformResourceIdentifier [6] IA5String,
4074 iPAddress [7] OCTET STRING,
4075 registeredID [8] OBJECT IDENTIFIER }
4077 IssuerSerial ::= SEQUENCE {
4078 issuer GeneralNames,
4079 serial CertificateSerialNumber,
4080 issuerUID UniqueIdentifier OPTIONAL }
4082 ObjectDigestInfo ::= SEQUENCE {
4083 digestedObjectType ENUMERATED {
4086 otherObjectTypes (2) },
4087 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4088 digestAlgorithm AlgorithmIdentifier,
4089 objectDigest BIT STRING }
4091 * The way I interpret it, an assertion should look like
4093 { serialNumber 'dd'H,
4094 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4095 baseCertificateID { serial '1d'H,
4096 issuer { directoryName:rdnSequence:"cn=zzz" },
4097 issuerUID <value> -- optional
4099 objectDigestInfo { ... } -- optional
4103 * with issuerName, baseCertificateID and objectDigestInfo optional,
4104 * at least one present; the way it's currently implemented, it is
4106 { serialNumber 'dd'H,
4107 issuer { baseCertificateID { serial '1d'H,
4108 issuer { directoryName:rdnSequence:"cn=zzz" }
4113 * with all the above parts mandatory.
4116 serialNumberAndIssuerSerialCheck(
4120 struct berval *i_sn, /* contain serial of baseCertificateID */
4123 /* Parse GSER format */
4128 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4129 } have = HAVE_NONE, have2 = HAVE_NONE;
4131 struct berval x = *in;
4134 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4137 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4144 /* eat leading spaces */
4145 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4149 /* should be at issuer or serialNumber NamedValue */
4150 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4151 if ( have & HAVE_ISSUER ) {
4152 return LDAP_INVALID_SYNTAX;
4155 /* parse IssuerSerial */
4156 x.bv_val += STRLENOF("issuer");
4157 x.bv_len -= STRLENOF("issuer");
4159 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4163 /* eat leading spaces */
4164 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4168 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4172 /* eat leading spaces */
4173 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4177 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4178 return LDAP_INVALID_SYNTAX;
4180 x.bv_val += STRLENOF("baseCertificateID ");
4181 x.bv_len -= STRLENOF("baseCertificateID ");
4183 /* eat leading spaces */
4184 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4188 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4193 /* eat leading spaces */
4194 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4198 /* parse issuer of baseCertificateID */
4199 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4200 if ( have2 & HAVE_ISSUER ) {
4201 return LDAP_INVALID_SYNTAX;
4204 x.bv_val += STRLENOF("issuer ");
4205 x.bv_len -= STRLENOF("issuer ");
4207 /* eat leading spaces */
4208 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4212 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4216 /* eat leading spaces */
4217 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4221 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4222 return LDAP_INVALID_SYNTAX;
4224 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4225 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4227 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4231 is->bv_val = x.bv_val;
4234 for ( ; is->bv_len < x.bv_len; ) {
4235 if ( is->bv_val[is->bv_len] != '"' ) {
4239 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4246 x.bv_val += is->bv_len + 1;
4247 x.bv_len -= is->bv_len + 1;
4249 /* eat leading spaces */
4250 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4254 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4258 have2 |= HAVE_ISSUER;
4260 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4261 if ( have2 & HAVE_SN ) {
4262 return LDAP_INVALID_SYNTAX;
4265 x.bv_val += STRLENOF("serial ");
4266 x.bv_len -= STRLENOF("serial ");
4268 /* eat leading spaces */
4269 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4273 if ( checkNum( &x, i_sn ) ) {
4274 return LDAP_INVALID_SYNTAX;
4277 x.bv_val += i_sn->bv_len;
4278 x.bv_len -= i_sn->bv_len;
4283 return LDAP_INVALID_SYNTAX;
4286 /* eat leading spaces */
4287 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4291 if ( have2 == HAVE_ALL ) {
4295 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4300 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4304 /* eat leading spaces */
4305 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4309 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4313 have |= HAVE_ISSUER;
4315 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4316 if ( have & HAVE_SN ) {
4317 return LDAP_INVALID_SYNTAX;
4320 /* parse serialNumber */
4321 x.bv_val += STRLENOF("serialNumber");
4322 x.bv_len -= STRLENOF("serialNumber");
4324 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4328 /* eat leading spaces */
4329 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4333 if ( checkNum( &x, sn ) ) {
4334 return LDAP_INVALID_SYNTAX;
4337 x.bv_val += sn->bv_len;
4338 x.bv_len -= sn->bv_len;
4343 return LDAP_INVALID_SYNTAX;
4347 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4351 if ( have == HAVE_ALL ) {
4355 if ( x.bv_val[0] != ',' ) {
4356 return LDAP_INVALID_SYNTAX;
4362 /* should have no characters left... */
4363 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4365 if ( numdquotes == 0 ) {
4366 ber_dupbv_x( &ni, is, ctx );
4371 ni.bv_len = is->bv_len - numdquotes;
4372 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4373 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4374 if ( is->bv_val[src] == '"' ) {
4377 ni.bv_val[dst] = is->bv_val[src];
4379 ni.bv_val[dst] = '\0';
4384 /* need to handle double dquotes here */
4388 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4390 serialNumberAndIssuerSerialValidate(
4395 struct berval sn, i, i_sn;
4397 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4400 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4405 /* validate DN -- doesn't handle double dquote */
4406 rc = dnValidate( NULL, &i );
4408 rc = LDAP_INVALID_SYNTAX;
4411 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4412 slap_sl_free( i.bv_val, NULL );
4416 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4417 in->bv_val, rc, 0 );
4422 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4424 serialNumberAndIssuerSerialPretty(
4430 struct berval sn, i, i_sn, ni = BER_BVNULL;
4434 assert( in != NULL );
4435 assert( out != NULL );
4437 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4440 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4445 rc = dnPretty( syntax, &i, &ni, ctx );
4447 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4448 slap_sl_free( i.bv_val, ctx );
4452 rc = LDAP_INVALID_SYNTAX;
4456 /* make room from sn + "$" */
4457 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4458 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4459 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4461 if ( out->bv_val == NULL ) {
4468 p = lutil_strcopy( p, "{ serialNumber " );
4469 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
4470 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4471 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4472 p = lutil_strcopy( p, "\" }, serial " );
4473 p = lutil_strncopy( p, i_sn.bv_val, i_sn.bv_len );
4474 p = lutil_strcopy( p, " } } }" );
4476 assert( p == &out->bv_val[out->bv_len] );
4479 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4480 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4482 slap_sl_free( ni.bv_val, ctx );
4487 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4489 * This routine is called by attributeCertificateExactNormalize
4490 * when attributeCertificateExactNormalize receives a search
4491 * string instead of a attribute certificate. This routine
4492 * checks if the search value is valid and then returns the
4496 serialNumberAndIssuerSerialNormalize(
4504 struct berval i, ni = BER_BVNULL,
4505 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4506 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4507 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4508 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4512 assert( in != NULL );
4513 assert( out != NULL );
4515 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4518 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4523 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4525 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4526 slap_sl_free( i.bv_val, ctx );
4530 rc = LDAP_INVALID_SYNTAX;
4534 /* Convert sn to canonical hex */
4536 sn2.bv_len = sn.bv_len;
4537 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4538 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4540 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4541 rc = LDAP_INVALID_SYNTAX;
4545 /* Convert i_sn to canonical hex */
4546 i_sn2.bv_val = i_sbuf2;
4547 i_sn2.bv_len = i_sn.bv_len;
4548 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4549 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4551 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4552 rc = LDAP_INVALID_SYNTAX;
4557 sn3.bv_len = sizeof(sbuf3);
4558 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4559 rc = LDAP_INVALID_SYNTAX;
4563 i_sn3.bv_val = i_sbuf3;
4564 i_sn3.bv_len = sizeof(i_sbuf3);
4565 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4566 rc = LDAP_INVALID_SYNTAX;
4570 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4571 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4572 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4574 if ( out->bv_val == NULL ) {
4582 p = lutil_strcopy( p, "{ serialNumber " );
4583 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
4584 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4585 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4586 p = lutil_strcopy( p, "\" }, serial " );
4587 p = lutil_strncopy( p, i_sn3.bv_val, i_sn3.bv_len );
4588 p = lutil_strcopy( p, " } } }" );
4590 assert( p == &out->bv_val[out->bv_len] );
4593 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4594 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4596 if ( sn2.bv_val != sbuf2 ) {
4597 slap_sl_free( sn2.bv_val, ctx );
4600 if ( i_sn2.bv_val != i_sbuf2 ) {
4601 slap_sl_free( i_sn2.bv_val, ctx );
4604 if ( sn3.bv_val != sbuf3 ) {
4605 slap_sl_free( sn3.bv_val, ctx );
4608 if ( i_sn3.bv_val != i_sbuf3 ) {
4609 slap_sl_free( i_sn3.bv_val, ctx );
4612 slap_sl_free( ni.bv_val, ctx );
4617 /* X.509 PMI attributeCertificateExactNormalize */
4619 attributeCertificateExactNormalize(
4624 struct berval *normalized,
4627 BerElementBuffer berbuf;
4628 BerElement *ber = (BerElement *)&berbuf;
4631 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4632 struct berval sn, i_sn, sn2, i_sn2;
4633 struct berval issuer_dn = BER_BVNULL, bvdn;
4635 int rc = LDAP_INVALID_SYNTAX;
4637 if ( BER_BVISEMPTY( val ) ) {
4641 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4642 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4645 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4647 ber_init2( ber, val, LBER_USE_DER );
4648 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4649 tag = ber_skip_tag( ber, &len ); /* Sequence */
4650 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4651 ber_skip_data( ber, len );
4652 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4653 ber_skip_data( ber, len );
4656 tag = ber_skip_tag( ber, &len ); /* Sequence */
4657 /* issuerName (GeneralNames sequence; optional)? */
4658 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4659 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4660 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4661 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4662 rc = LDAP_INVALID_SYNTAX;
4665 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4666 len = ber_ptrlen( ber );
4667 bvdn.bv_val = val->bv_val + len;
4668 bvdn.bv_len = val->bv_len - len;
4669 rc = dnX509normalize( &bvdn, &issuer_dn );
4670 if ( rc != LDAP_SUCCESS ) goto done;
4672 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4673 ber_skip_data( ber, len );
4674 tag = ber_skip_tag( ber, &len ); /* serial number */
4675 if ( tag != LBER_INTEGER ) {
4676 rc = LDAP_INVALID_SYNTAX;
4679 i_sn.bv_val = (char *)ber->ber_ptr;
4681 i_sn2.bv_val = issuer_serialbuf;
4682 i_sn2.bv_len = sizeof(issuer_serialbuf);
4683 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4684 rc = LDAP_INVALID_SYNTAX;
4687 ber_skip_data( ber, len );
4689 /* issuerUID (bitstring; optional)? */
4690 /* objectDigestInfo (sequence; optional)? */
4692 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4693 ber_skip_data( ber, len );
4694 tag = ber_skip_tag( ber, &len ); /* serial number */
4695 if ( tag != LBER_INTEGER ) {
4696 rc = LDAP_INVALID_SYNTAX;
4699 sn.bv_val = (char *)ber->ber_ptr;
4701 sn2.bv_val = serialbuf;
4702 sn2.bv_len = sizeof(serialbuf);
4703 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4704 rc = LDAP_INVALID_SYNTAX;
4707 ber_skip_data( ber, len );
4709 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4710 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4711 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4713 p = normalized->bv_val;
4715 p = lutil_strcopy( p, "{ serialNumber " );
4716 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
4717 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4718 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4719 p = lutil_strcopy( p, "\" }, serial " );
4720 p = lutil_strncopy( p, i_sn2.bv_val, i_sn2.bv_len );
4721 p = lutil_strcopy( p, " } } }" );
4723 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4724 normalized->bv_val, NULL, NULL );
4729 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4730 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4731 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4744 assert( in != NULL );
4745 assert( !BER_BVISNULL( in ) );
4747 for ( i = 0; i < in->bv_len; i++ ) {
4748 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4749 return LDAP_INVALID_SYNTAX;
4753 return LDAP_SUCCESS;
4756 /* Normalize a SID as used inside a CSN:
4757 * three-digit numeric string */
4764 struct berval *normalized,
4769 assert( val != NULL );
4770 assert( normalized != NULL );
4772 ber_dupbv_x( normalized, val, ctx );
4774 for ( i = 0; i < normalized->bv_len; i++ ) {
4775 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4776 ber_memfree_x( normalized->bv_val, ctx );
4777 BER_BVZERO( normalized );
4778 return LDAP_INVALID_SYNTAX;
4781 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4784 return LDAP_SUCCESS;
4792 assert( in != NULL );
4793 assert( !BER_BVISNULL( in ) );
4795 if ( in->bv_len != 3 ) {
4796 return LDAP_INVALID_SYNTAX;
4799 return hexValidate( NULL, in );
4802 /* Normalize a SID as used inside a CSN:
4803 * three-digit numeric string */
4810 struct berval *normalized,
4813 if ( val->bv_len != 3 ) {
4814 return LDAP_INVALID_SYNTAX;
4817 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4827 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4830 /* Normalize a SID as used inside a CSN, either as-is
4831 * (assertion value) or extracted from the CSN
4832 * (attribute value) */
4839 struct berval *normalized,
4847 if ( BER_BVISEMPTY( val ) ) {
4848 return LDAP_INVALID_SYNTAX;
4851 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4852 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4855 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4857 ptr = ber_bvchr( val, '#' );
4858 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4859 return LDAP_INVALID_SYNTAX;
4862 bv.bv_val = ptr + 1;
4863 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4865 ptr = ber_bvchr( &bv, '#' );
4866 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4867 return LDAP_INVALID_SYNTAX;
4870 bv.bv_val = ptr + 1;
4871 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4873 ptr = ber_bvchr( &bv, '#' );
4874 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4875 return LDAP_INVALID_SYNTAX;
4878 bv.bv_len = ptr - bv.bv_val;
4880 if ( bv.bv_len == 2 ) {
4881 /* OpenLDAP 2.3 SID */
4883 buf[ 1 ] = bv.bv_val[ 0 ];
4884 buf[ 2 ] = bv.bv_val[ 1 ];
4891 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4903 assert( in != NULL );
4904 assert( !BER_BVISNULL( in ) );
4906 if ( BER_BVISEMPTY( in ) ) {
4907 return LDAP_INVALID_SYNTAX;
4912 ptr = ber_bvchr( &bv, '#' );
4913 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4914 return LDAP_INVALID_SYNTAX;
4917 bv.bv_len = ptr - bv.bv_val;
4918 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4919 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4921 return LDAP_INVALID_SYNTAX;
4924 rc = generalizedTimeValidate( NULL, &bv );
4925 if ( rc != LDAP_SUCCESS ) {
4929 bv.bv_val = ptr + 1;
4930 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4932 ptr = ber_bvchr( &bv, '#' );
4933 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4934 return LDAP_INVALID_SYNTAX;
4937 bv.bv_len = ptr - bv.bv_val;
4938 if ( bv.bv_len != 6 ) {
4939 return LDAP_INVALID_SYNTAX;
4942 rc = hexValidate( NULL, &bv );
4943 if ( rc != LDAP_SUCCESS ) {
4947 bv.bv_val = ptr + 1;
4948 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4950 ptr = ber_bvchr( &bv, '#' );
4951 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4952 return LDAP_INVALID_SYNTAX;
4955 bv.bv_len = ptr - bv.bv_val;
4956 if ( bv.bv_len == 2 ) {
4957 /* tolerate old 2-digit replica-id */
4958 rc = hexValidate( NULL, &bv );
4961 rc = sidValidate( NULL, &bv );
4963 if ( rc != LDAP_SUCCESS ) {
4967 bv.bv_val = ptr + 1;
4968 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4970 if ( bv.bv_len != 6 ) {
4971 return LDAP_INVALID_SYNTAX;
4974 return hexValidate( NULL, &bv );
4977 /* Normalize a CSN in OpenLDAP 2.1 format */
4984 struct berval *normalized,
4987 struct berval gt, cnt, sid, mod;
4989 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4993 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4994 assert( !BER_BVISEMPTY( val ) );
4998 ptr = ber_bvchr( >, '#' );
4999 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5000 return LDAP_INVALID_SYNTAX;
5003 gt.bv_len = ptr - gt.bv_val;
5004 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5005 return LDAP_INVALID_SYNTAX;
5008 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5009 return LDAP_INVALID_SYNTAX;
5012 cnt.bv_val = ptr + 1;
5013 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5015 ptr = ber_bvchr( &cnt, '#' );
5016 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5017 return LDAP_INVALID_SYNTAX;
5020 cnt.bv_len = ptr - cnt.bv_val;
5021 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5022 return LDAP_INVALID_SYNTAX;
5025 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5026 return LDAP_INVALID_SYNTAX;
5029 cnt.bv_val += STRLENOF( "0x" );
5030 cnt.bv_len -= STRLENOF( "0x" );
5032 sid.bv_val = ptr + 1;
5033 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5035 ptr = ber_bvchr( &sid, '#' );
5036 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5037 return LDAP_INVALID_SYNTAX;
5040 sid.bv_len = ptr - sid.bv_val;
5041 if ( sid.bv_len != STRLENOF( "0" ) ) {
5042 return LDAP_INVALID_SYNTAX;
5045 mod.bv_val = ptr + 1;
5046 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5047 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5048 return LDAP_INVALID_SYNTAX;
5051 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5055 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5056 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5058 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5060 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5061 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5065 *ptr++ = sid.bv_val[ 0 ];
5069 for ( i = 0; i < mod.bv_len; i++ ) {
5070 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5074 assert( ptr == &bv.bv_val[bv.bv_len] );
5076 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5077 return LDAP_INVALID_SYNTAX;
5080 ber_dupbv_x( normalized, &bv, ctx );
5082 return LDAP_SUCCESS;
5085 /* Normalize a CSN in OpenLDAP 2.3 format */
5092 struct berval *normalized,
5095 struct berval gt, cnt, sid, mod;
5097 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5101 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5102 assert( !BER_BVISEMPTY( val ) );
5106 ptr = ber_bvchr( >, '#' );
5107 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5108 return LDAP_INVALID_SYNTAX;
5111 gt.bv_len = ptr - gt.bv_val;
5112 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5113 return LDAP_INVALID_SYNTAX;
5116 cnt.bv_val = ptr + 1;
5117 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5119 ptr = ber_bvchr( &cnt, '#' );
5120 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5121 return LDAP_INVALID_SYNTAX;
5124 cnt.bv_len = ptr - cnt.bv_val;
5125 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5126 return LDAP_INVALID_SYNTAX;
5129 sid.bv_val = ptr + 1;
5130 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5132 ptr = ber_bvchr( &sid, '#' );
5133 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5134 return LDAP_INVALID_SYNTAX;
5137 sid.bv_len = ptr - sid.bv_val;
5138 if ( sid.bv_len != STRLENOF( "00" ) ) {
5139 return LDAP_INVALID_SYNTAX;
5142 mod.bv_val = ptr + 1;
5143 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5144 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5145 return LDAP_INVALID_SYNTAX;
5148 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5152 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5153 ptr = lutil_strcopy( ptr, ".000000Z#" );
5154 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5157 for ( i = 0; i < sid.bv_len; i++ ) {
5158 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5161 for ( i = 0; i < mod.bv_len; i++ ) {
5162 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5166 assert( ptr == &bv.bv_val[bv.bv_len] );
5167 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5168 return LDAP_INVALID_SYNTAX;
5171 ber_dupbv_x( normalized, &bv, ctx );
5173 return LDAP_SUCCESS;
5176 /* Normalize a CSN */
5183 struct berval *normalized,
5186 struct berval cnt, sid, mod;
5190 assert( val != NULL );
5191 assert( normalized != NULL );
5193 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5195 if ( BER_BVISEMPTY( val ) ) {
5196 return LDAP_INVALID_SYNTAX;
5199 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5200 /* Openldap <= 2.3 */
5202 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5205 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5208 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5211 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5212 return LDAP_INVALID_SYNTAX;
5215 ptr = ber_bvchr( val, '#' );
5216 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5217 return LDAP_INVALID_SYNTAX;
5220 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5221 return LDAP_INVALID_SYNTAX;
5224 cnt.bv_val = ptr + 1;
5225 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5227 ptr = ber_bvchr( &cnt, '#' );
5228 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5229 return LDAP_INVALID_SYNTAX;
5232 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5233 return LDAP_INVALID_SYNTAX;
5236 sid.bv_val = ptr + 1;
5237 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5239 ptr = ber_bvchr( &sid, '#' );
5240 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5241 return LDAP_INVALID_SYNTAX;
5244 sid.bv_len = ptr - sid.bv_val;
5245 if ( sid.bv_len != STRLENOF( "000" ) ) {
5246 return LDAP_INVALID_SYNTAX;
5249 mod.bv_val = ptr + 1;
5250 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5252 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5253 return LDAP_INVALID_SYNTAX;
5256 ber_dupbv_x( normalized, val, ctx );
5258 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5259 i < normalized->bv_len; i++ )
5261 /* assume it's already validated that's all hex digits */
5262 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5265 return LDAP_SUCCESS;
5275 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5278 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5279 /* slight optimization - does not need the start parameter */
5280 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5285 check_time_syntax (struct berval *val,
5288 struct berval *fraction)
5291 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5292 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5293 * GeneralizedTime supports leap seconds, UTCTime does not.
5295 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5296 static const int mdays[2][12] = {
5297 /* non-leap years */
5298 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5300 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5303 int part, c, c1, c2, tzoffset, leapyear = 0;
5306 e = p + val->bv_len;
5308 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5309 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5311 for (part = start; part < 7 && p < e; part++) {
5313 if (!ASCII_DIGIT(c1)) {
5318 return LDAP_INVALID_SYNTAX;
5321 if (!ASCII_DIGIT(c)) {
5322 return LDAP_INVALID_SYNTAX;
5324 c += c1 * 10 - '0' * 11;
5325 if ((part | 1) == 3) {
5328 return LDAP_INVALID_SYNTAX;
5331 if (c >= ceiling[part]) {
5332 if (! (c == 60 && part == 6 && start == 0))
5333 return LDAP_INVALID_SYNTAX;
5337 if (part < 5 + start) {
5338 return LDAP_INVALID_SYNTAX;
5340 for (; part < 9; part++) {
5344 /* leapyear check for the Gregorian calendar (year>1581) */
5345 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5349 if (parts[3] >= mdays[leapyear][parts[2]]) {
5350 return LDAP_INVALID_SYNTAX;
5354 fraction->bv_val = p;
5355 fraction->bv_len = 0;
5356 if (p < e && (*p == '.' || *p == ',')) {
5358 while (++p < e && ASCII_DIGIT(*p)) {
5361 if (p - fraction->bv_val == 1) {
5362 return LDAP_INVALID_SYNTAX;
5364 for (end_num = p; end_num[-1] == '0'; --end_num) {
5367 c = end_num - fraction->bv_val;
5368 if (c != 1) fraction->bv_len = c;
5374 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5380 return LDAP_INVALID_SYNTAX;
5386 for (part = 7; part < 9 && p < e; part++) {
5388 if (!ASCII_DIGIT(c1)) {
5393 return LDAP_INVALID_SYNTAX;
5396 if (!ASCII_DIGIT(c2)) {
5397 return LDAP_INVALID_SYNTAX;
5399 parts[part] = c1 * 10 + c2 - '0' * 11;
5400 if (parts[part] >= ceiling[part]) {
5401 return LDAP_INVALID_SYNTAX;
5404 if (part < 8 + start) {
5405 return LDAP_INVALID_SYNTAX;
5408 if (tzoffset == '-') {
5409 /* negative offset to UTC, ie west of Greenwich */
5410 parts[4] += parts[7];
5411 parts[5] += parts[8];
5412 /* offset is just hhmm, no seconds */
5413 for (part = 6; --part >= 0; ) {
5417 c = mdays[leapyear][parts[2]];
5419 if (parts[part] >= c) {
5421 return LDAP_INVALID_SYNTAX;
5426 } else if (part != 5) {
5431 /* positive offset to UTC, ie east of Greenwich */
5432 parts[4] -= parts[7];
5433 parts[5] -= parts[8];
5434 for (part = 6; --part >= 0; ) {
5435 if (parts[part] < 0) {
5437 return LDAP_INVALID_SYNTAX;
5442 /* make first arg to % non-negative */
5443 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5448 } else if (part != 5) {
5455 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5458 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5465 struct berval *normalized )
5469 rc = check_time_syntax(val, 1, parts, NULL);
5470 if (rc != LDAP_SUCCESS) {
5474 normalized->bv_val = ch_malloc( 14 );
5475 if ( normalized->bv_val == NULL ) {
5476 return LBER_ERROR_MEMORY;
5479 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5480 parts[1], parts[2] + 1, parts[3] + 1,
5481 parts[4], parts[5], parts[6] );
5482 normalized->bv_len = 13;
5484 return LDAP_SUCCESS;
5494 return check_time_syntax(in, 1, parts, NULL);
5497 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5500 generalizedTimeValidate(
5505 struct berval fraction;
5506 return check_time_syntax(in, 0, parts, &fraction);
5510 generalizedTimeNormalize(
5515 struct berval *normalized,
5520 struct berval fraction;
5522 rc = check_time_syntax(val, 0, parts, &fraction);
5523 if (rc != LDAP_SUCCESS) {
5527 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5528 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5529 if ( BER_BVISNULL( normalized ) ) {
5530 return LBER_ERROR_MEMORY;
5533 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5534 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5535 parts[4], parts[5], parts[6] );
5536 if ( !BER_BVISEMPTY( &fraction ) ) {
5537 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5538 fraction.bv_val, fraction.bv_len );
5539 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5541 strcpy( normalized->bv_val + len-1, "Z" );
5542 normalized->bv_len = len;
5544 return LDAP_SUCCESS;
5548 generalizedTimeOrderingMatch(
5553 struct berval *value,
5554 void *assertedValue )
5556 struct berval *asserted = (struct berval *) assertedValue;
5557 ber_len_t v_len = value->bv_len;
5558 ber_len_t av_len = asserted->bv_len;
5560 /* ignore trailing 'Z' when comparing */
5561 int match = memcmp( value->bv_val, asserted->bv_val,
5562 (v_len < av_len ? v_len : av_len) - 1 );
5563 if ( match == 0 ) match = v_len - av_len;
5566 return LDAP_SUCCESS;
5569 /* Index generation function */
5570 int generalizedTimeIndexer(
5575 struct berval *prefix,
5583 BerValue bvtmp; /* 40 bit index */
5585 struct lutil_timet tt;
5587 bvtmp.bv_len = sizeof(tmp);
5589 for( i=0; values[i].bv_val != NULL; i++ ) {
5590 /* just count them */
5593 /* we should have at least one value at this point */
5596 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5598 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5599 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5600 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5601 /* Use 40 bits of time for key */
5602 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5603 lutil_tm2time( &tm, &tt );
5604 tmp[0] = tt.tt_gsec & 0xff;
5605 tmp[4] = tt.tt_sec & 0xff;
5607 tmp[3] = tt.tt_sec & 0xff;
5609 tmp[2] = tt.tt_sec & 0xff;
5611 tmp[1] = tt.tt_sec & 0xff;
5613 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5617 keys[j].bv_val = NULL;
5622 return LDAP_SUCCESS;
5625 /* Index generation function */
5626 int generalizedTimeFilter(
5631 struct berval *prefix,
5632 void * assertedValue,
5638 BerValue bvtmp; /* 40 bit index */
5639 BerValue *value = (BerValue *) assertedValue;
5641 struct lutil_timet tt;
5643 bvtmp.bv_len = sizeof(tmp);
5645 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5646 /* Use 40 bits of time for key */
5647 if ( value->bv_val && value->bv_len >= 10 &&
5648 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5650 lutil_tm2time( &tm, &tt );
5651 tmp[0] = tt.tt_gsec & 0xff;
5652 tmp[4] = tt.tt_sec & 0xff;
5654 tmp[3] = tt.tt_sec & 0xff;
5656 tmp[2] = tt.tt_sec & 0xff;
5658 tmp[1] = tt.tt_sec & 0xff;
5660 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5661 ber_dupbv_x(keys, &bvtmp, ctx );
5662 keys[1].bv_val = NULL;
5670 return LDAP_SUCCESS;
5674 deliveryMethodValidate(
5676 struct berval *val )
5679 #define LENOF(s) (sizeof(s)-1)
5680 struct berval tmp = *val;
5682 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5683 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5684 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5687 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5689 switch( tmp.bv_val[0] ) {
5692 if(( tmp.bv_len >= LENOF("any") ) &&
5693 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5695 tmp.bv_len -= LENOF("any");
5696 tmp.bv_val += LENOF("any");
5699 return LDAP_INVALID_SYNTAX;
5703 if(( tmp.bv_len >= LENOF("mhs") ) &&
5704 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5706 tmp.bv_len -= LENOF("mhs");
5707 tmp.bv_val += LENOF("mhs");
5710 return LDAP_INVALID_SYNTAX;
5714 if(( tmp.bv_len >= LENOF("physical") ) &&
5715 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5717 tmp.bv_len -= LENOF("physical");
5718 tmp.bv_val += LENOF("physical");
5721 return LDAP_INVALID_SYNTAX;
5724 case 'T': /* telex or teletex or telephone */
5725 if(( tmp.bv_len >= LENOF("telex") ) &&
5726 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5728 tmp.bv_len -= LENOF("telex");
5729 tmp.bv_val += LENOF("telex");
5732 if(( tmp.bv_len >= LENOF("teletex") ) &&
5733 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5735 tmp.bv_len -= LENOF("teletex");
5736 tmp.bv_val += LENOF("teletex");
5739 if(( tmp.bv_len >= LENOF("telephone") ) &&
5740 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5742 tmp.bv_len -= LENOF("telephone");
5743 tmp.bv_val += LENOF("telephone");
5746 return LDAP_INVALID_SYNTAX;
5749 case 'G': /* g3fax or g4fax */
5750 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5751 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5752 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5754 tmp.bv_len -= LENOF("g3fax");
5755 tmp.bv_val += LENOF("g3fax");
5758 return LDAP_INVALID_SYNTAX;
5762 if(( tmp.bv_len >= LENOF("ia5") ) &&
5763 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5765 tmp.bv_len -= LENOF("ia5");
5766 tmp.bv_val += LENOF("ia5");
5769 return LDAP_INVALID_SYNTAX;
5773 if(( tmp.bv_len >= LENOF("videotex") ) &&
5774 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5776 tmp.bv_len -= LENOF("videotex");
5777 tmp.bv_val += LENOF("videotex");
5780 return LDAP_INVALID_SYNTAX;
5783 return LDAP_INVALID_SYNTAX;
5786 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5788 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5792 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5796 return LDAP_INVALID_SYNTAX;
5798 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5807 nisNetgroupTripleValidate(
5809 struct berval *val )
5814 if ( BER_BVISEMPTY( val ) ) {
5815 return LDAP_INVALID_SYNTAX;
5818 p = (char *)val->bv_val;
5819 e = p + val->bv_len;
5821 if ( *p != '(' /*')'*/ ) {
5822 return LDAP_INVALID_SYNTAX;
5825 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5829 return LDAP_INVALID_SYNTAX;
5832 } else if ( !AD_CHAR( *p ) ) {
5833 return LDAP_INVALID_SYNTAX;
5837 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5838 return LDAP_INVALID_SYNTAX;
5844 return LDAP_INVALID_SYNTAX;
5847 return LDAP_SUCCESS;
5851 bootParameterValidate(
5853 struct berval *val )
5857 if ( BER_BVISEMPTY( val ) ) {
5858 return LDAP_INVALID_SYNTAX;
5861 p = (char *)val->bv_val;
5862 e = p + val->bv_len;
5865 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5866 if ( !AD_CHAR( *p ) ) {
5867 return LDAP_INVALID_SYNTAX;
5872 return LDAP_INVALID_SYNTAX;
5876 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5877 if ( !AD_CHAR( *p ) ) {
5878 return LDAP_INVALID_SYNTAX;
5883 return LDAP_INVALID_SYNTAX;
5887 for ( p++; p < e; p++ ) {
5888 if ( !SLAP_PRINTABLE( *p ) ) {
5889 return LDAP_INVALID_SYNTAX;
5893 return LDAP_SUCCESS;
5897 firstComponentNormalize(
5902 struct berval *normalized,
5909 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5910 ber_dupbv_x( normalized, val, ctx );
5911 return LDAP_SUCCESS;
5914 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5916 if( ! ( val->bv_val[0] == '(' /*')'*/
5917 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5918 && ! ( val->bv_val[0] == '{' /*'}'*/
5919 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5921 return LDAP_INVALID_SYNTAX;
5924 /* trim leading white space */
5926 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5932 /* grab next word */
5933 comp.bv_val = &val->bv_val[len];
5934 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5935 for( comp.bv_len = 0;
5936 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5942 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5943 rc = numericoidValidate( NULL, &comp );
5944 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5945 rc = integerValidate( NULL, &comp );
5947 rc = LDAP_INVALID_SYNTAX;
5951 if( rc == LDAP_SUCCESS ) {
5952 ber_dupbv_x( normalized, &comp, ctx );
5958 static char *country_gen_syn[] = {
5959 "1.3.6.1.4.1.1466.115.121.1.15",
5960 "1.3.6.1.4.1.1466.115.121.1.26",
5961 "1.3.6.1.4.1.1466.115.121.1.44",
5965 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
5966 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
5968 static slap_syntax_defs_rec syntax_defs[] = {
5969 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
5970 X_BINARY X_NOT_H_R ")",
5971 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
5972 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
5973 0, NULL, NULL, NULL},
5974 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
5975 0, NULL, NULL, NULL},
5976 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
5978 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5979 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
5981 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5982 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
5983 0, NULL, bitStringValidate, NULL },
5984 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
5985 0, NULL, booleanValidate, NULL},
5986 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
5987 X_BINARY X_NOT_H_R ")",
5988 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5989 NULL, certificateValidate, NULL},
5990 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
5991 X_BINARY X_NOT_H_R ")",
5992 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5993 NULL, certificateListValidate, NULL},
5994 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
5995 X_BINARY X_NOT_H_R ")",
5996 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5997 NULL, sequenceValidate, NULL},
5998 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
5999 X_BINARY X_NOT_H_R ")",
6000 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6001 NULL, attributeCertificateValidate, NULL},
6002 #if 0 /* need to go __after__ printableString */
6003 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6004 0, "1.3.6.1.4.1.1466.115.121.1.44",
6005 countryStringValidate, NULL},
6007 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6008 0, NULL, dnValidate, dnPretty},
6009 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6010 0, NULL, rdnValidate, rdnPretty},
6011 #ifdef LDAP_COMP_MATCH
6012 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6013 0, NULL, allComponentsValidate, NULL},
6014 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6015 0, NULL, componentFilterValidate, NULL},
6017 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6018 0, NULL, NULL, NULL},
6019 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6020 0, NULL, deliveryMethodValidate, NULL},
6021 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6022 0, NULL, UTF8StringValidate, NULL},
6023 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6024 0, NULL, NULL, NULL},
6025 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6026 0, NULL, NULL, NULL},
6027 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6028 0, NULL, NULL, NULL},
6029 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6030 0, NULL, NULL, NULL},
6031 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6032 0, NULL, NULL, NULL},
6033 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6034 0, NULL, printablesStringValidate, NULL},
6035 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6036 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6037 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6038 0, NULL, generalizedTimeValidate, NULL},
6039 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6040 0, NULL, NULL, NULL},
6041 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6042 0, NULL, IA5StringValidate, NULL},
6043 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6044 0, NULL, integerValidate, NULL},
6045 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6046 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6047 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6048 0, NULL, NULL, NULL},
6049 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6050 0, NULL, NULL, NULL},
6051 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6052 0, NULL, NULL, NULL},
6053 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6054 0, NULL, NULL, NULL},
6055 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6056 0, NULL, NULL, NULL},
6057 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6058 0, NULL, nameUIDValidate, nameUIDPretty },
6059 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6060 0, NULL, NULL, NULL},
6061 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6062 0, NULL, numericStringValidate, NULL},
6063 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6064 0, NULL, NULL, NULL},
6065 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6066 0, NULL, numericoidValidate, NULL},
6067 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6068 0, NULL, IA5StringValidate, NULL},
6069 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6070 0, NULL, blobValidate, NULL},
6071 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6072 0, NULL, postalAddressValidate, NULL},
6073 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6074 0, NULL, NULL, NULL},
6075 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6076 0, NULL, NULL, NULL},
6077 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6078 0, NULL, printableStringValidate, NULL},
6079 /* moved here because now depends on Directory String, IA5 String
6080 * and Printable String */
6081 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6082 0, country_gen_syn, countryStringValidate, NULL},
6083 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6084 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6085 0, NULL, subtreeSpecificationValidate, NULL},
6086 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6087 X_BINARY X_NOT_H_R ")",
6088 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6089 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6090 0, NULL, printableStringValidate, NULL},
6091 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6092 0, NULL, NULL, NULL},
6093 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6094 0, NULL, printablesStringValidate, NULL},
6095 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6096 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6097 0, NULL, utcTimeValidate, NULL},
6099 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6100 0, NULL, NULL, NULL},
6101 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6102 0, NULL, NULL, NULL},
6103 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6104 0, NULL, NULL, NULL},
6105 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6106 0, NULL, NULL, NULL},
6107 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6108 0, NULL, NULL, NULL},
6110 /* RFC 2307 NIS Syntaxes */
6111 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6112 0, NULL, nisNetgroupTripleValidate, NULL},
6113 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6114 0, NULL, bootParameterValidate, NULL},
6116 /* draft-zeilenga-ldap-x509 */
6117 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6118 SLAP_SYNTAX_HIDE, NULL,
6119 serialNumberAndIssuerValidate,
6120 serialNumberAndIssuerPretty},
6121 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6122 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6123 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6124 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6125 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6126 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6127 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6128 SLAP_SYNTAX_HIDE, NULL,
6129 issuerAndThisUpdateValidate,
6130 issuerAndThisUpdatePretty},
6131 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6132 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6133 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6134 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6135 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6136 SLAP_SYNTAX_HIDE, NULL,
6137 serialNumberAndIssuerSerialValidate,
6138 serialNumberAndIssuerSerialPretty},
6139 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6140 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6142 #ifdef SLAPD_AUTHPASSWD
6143 /* needs updating */
6144 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6145 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6148 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6149 0, NULL, UUIDValidate, UUIDPretty},
6151 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6152 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6154 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6155 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6157 /* OpenLDAP Void Syntax */
6158 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6159 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6161 /* FIXME: OID is unused, but not registered yet */
6162 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6163 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6165 {NULL, 0, NULL, NULL, NULL}
6168 char *csnSIDMatchSyntaxes[] = {
6169 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6172 char *certificateExactMatchSyntaxes[] = {
6173 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6176 char *certificateListExactMatchSyntaxes[] = {
6177 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6180 char *attributeCertificateExactMatchSyntaxes[] = {
6181 attributeCertificateSyntaxOID /* attributeCertificate */,
6185 #ifdef LDAP_COMP_MATCH
6186 char *componentFilterMatchSyntaxes[] = {
6187 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6188 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6189 attributeCertificateSyntaxOID /* attributeCertificate */,
6194 char *directoryStringSyntaxes[] = {
6195 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6198 char *integerFirstComponentMatchSyntaxes[] = {
6199 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6200 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6203 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6204 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6205 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6206 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6207 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6208 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6209 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6210 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6211 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6216 * Other matching rules in X.520 that we do not use (yet):
6218 * 2.5.13.25 uTCTimeMatch
6219 * 2.5.13.26 uTCTimeOrderingMatch
6220 * 2.5.13.31* directoryStringFirstComponentMatch
6221 * 2.5.13.32* wordMatch
6222 * 2.5.13.33* keywordMatch
6223 * 2.5.13.36+ certificatePairExactMatch
6224 * 2.5.13.37+ certificatePairMatch
6225 * 2.5.13.40+ algorithmIdentifierMatch
6226 * 2.5.13.41* storedPrefixMatch
6227 * 2.5.13.42 attributeCertificateMatch
6228 * 2.5.13.43 readerAndKeyIDMatch
6229 * 2.5.13.44 attributeIntegrityMatch
6231 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6232 * (+) described in draft-zeilenga-ldap-x509
6234 static slap_mrule_defs_rec mrule_defs[] = {
6236 * EQUALITY matching rules must be listed after associated APPROX
6237 * matching rules. So, we list all APPROX matching rules first.
6239 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6240 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6241 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6242 NULL, NULL, directoryStringApproxMatch,
6243 directoryStringApproxIndexer, directoryStringApproxFilter,
6246 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6247 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6248 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6249 NULL, NULL, IA5StringApproxMatch,
6250 IA5StringApproxIndexer, IA5StringApproxFilter,
6254 * Other matching rules
6257 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6258 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6259 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6260 NULL, NULL, octetStringMatch,
6261 octetStringIndexer, octetStringFilter,
6264 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6265 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6266 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6267 NULL, dnNormalize, dnMatch,
6268 octetStringIndexer, octetStringFilter,
6271 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6272 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6273 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6274 NULL, dnNormalize, dnRelativeMatch,
6278 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6279 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6280 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6281 NULL, dnNormalize, dnRelativeMatch,
6285 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6286 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6287 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6288 NULL, dnNormalize, dnRelativeMatch,
6292 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6294 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6295 NULL, dnNormalize, dnRelativeMatch,
6299 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6300 "SYNTAX 1.2.36.79672281.1.5.0 )",
6301 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6302 NULL, rdnNormalize, rdnMatch,
6303 octetStringIndexer, octetStringFilter,
6306 #ifdef LDAP_COMP_MATCH
6307 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6308 "SYNTAX 1.2.36.79672281.1.5.2 )",
6309 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6310 NULL, NULL , componentFilterMatch,
6311 octetStringIndexer, octetStringFilter,
6314 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6315 "SYNTAX 1.2.36.79672281.1.5.3 )",
6316 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6317 NULL, NULL , allComponentsMatch,
6318 octetStringIndexer, octetStringFilter,
6321 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6322 "SYNTAX 1.2.36.79672281.1.5.3 )",
6323 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6324 NULL, NULL , directoryComponentsMatch,
6325 octetStringIndexer, octetStringFilter,
6329 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6330 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6331 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6332 NULL, UTF8StringNormalize, octetStringMatch,
6333 octetStringIndexer, octetStringFilter,
6334 directoryStringApproxMatchOID },
6336 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6337 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6338 SLAP_MR_ORDERING, directoryStringSyntaxes,
6339 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6341 "caseIgnoreMatch" },
6343 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6344 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6345 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6346 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6347 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6348 "caseIgnoreMatch" },
6350 {"( 2.5.13.5 NAME 'caseExactMatch' "
6351 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6352 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6353 NULL, UTF8StringNormalize, octetStringMatch,
6354 octetStringIndexer, octetStringFilter,
6355 directoryStringApproxMatchOID },
6357 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6358 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6359 SLAP_MR_ORDERING, directoryStringSyntaxes,
6360 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6364 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6365 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6366 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6367 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6368 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6371 {"( 2.5.13.8 NAME 'numericStringMatch' "
6372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6373 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6374 NULL, numericStringNormalize, octetStringMatch,
6375 octetStringIndexer, octetStringFilter,
6378 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6379 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6380 SLAP_MR_ORDERING, NULL,
6381 NULL, numericStringNormalize, octetStringOrderingMatch,
6383 "numericStringMatch" },
6385 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6386 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6387 SLAP_MR_SUBSTR, NULL,
6388 NULL, numericStringNormalize, octetStringSubstringsMatch,
6389 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6390 "numericStringMatch" },
6392 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6393 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6394 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6395 NULL, postalAddressNormalize, octetStringMatch,
6396 octetStringIndexer, octetStringFilter,
6399 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6400 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6401 SLAP_MR_SUBSTR, NULL,
6402 NULL, NULL, NULL, NULL, NULL,
6403 "caseIgnoreListMatch" },
6405 {"( 2.5.13.13 NAME 'booleanMatch' "
6406 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6407 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6408 NULL, NULL, booleanMatch,
6409 octetStringIndexer, octetStringFilter,
6412 {"( 2.5.13.14 NAME 'integerMatch' "
6413 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6414 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6415 NULL, NULL, integerMatch,
6416 integerIndexer, integerFilter,
6419 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6420 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6421 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6422 NULL, NULL, integerMatch,
6426 {"( 2.5.13.16 NAME 'bitStringMatch' "
6427 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6428 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6429 NULL, NULL, octetStringMatch,
6430 octetStringIndexer, octetStringFilter,
6433 {"( 2.5.13.17 NAME 'octetStringMatch' "
6434 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6435 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6436 NULL, NULL, octetStringMatch,
6437 octetStringIndexer, octetStringFilter,
6440 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6441 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6442 SLAP_MR_ORDERING, NULL,
6443 NULL, NULL, octetStringOrderingMatch,
6445 "octetStringMatch" },
6447 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6448 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6449 SLAP_MR_SUBSTR, NULL,
6450 NULL, NULL, octetStringSubstringsMatch,
6451 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6452 "octetStringMatch" },
6454 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6455 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6456 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6458 telephoneNumberNormalize, octetStringMatch,
6459 octetStringIndexer, octetStringFilter,
6462 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6463 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6464 SLAP_MR_SUBSTR, NULL,
6465 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6466 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6467 "telephoneNumberMatch" },
6469 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6470 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6471 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6472 NULL, NULL, NULL, NULL, NULL, NULL },
6474 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6475 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6476 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6477 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6478 uniqueMemberIndexer, uniqueMemberFilter,
6481 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6482 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6483 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6484 NULL, NULL, NULL, NULL, NULL, NULL },
6486 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6487 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6488 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6489 NULL, generalizedTimeNormalize, octetStringMatch,
6490 generalizedTimeIndexer, generalizedTimeFilter,
6493 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6495 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6496 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6498 "generalizedTimeMatch" },
6500 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6501 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6502 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6503 integerFirstComponentMatchSyntaxes,
6504 NULL, firstComponentNormalize, integerMatch,
6505 octetStringIndexer, octetStringFilter,
6508 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6510 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6511 objectIdentifierFirstComponentMatchSyntaxes,
6512 NULL, firstComponentNormalize, octetStringMatch,
6513 octetStringIndexer, octetStringFilter,
6516 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6517 "SYNTAX 1.3.6.1.1.15.1 )",
6518 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6519 NULL, certificateExactNormalize, octetStringMatch,
6520 octetStringIndexer, octetStringFilter,
6523 {"( 2.5.13.35 NAME 'certificateMatch' "
6524 "SYNTAX 1.3.6.1.1.15.2 )",
6525 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6526 NULL, NULL, NULL, NULL, NULL,
6529 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6530 "SYNTAX 1.3.6.1.1.15.5 )",
6531 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6532 NULL, certificateListExactNormalize, octetStringMatch,
6533 octetStringIndexer, octetStringFilter,
6536 {"( 2.5.13.39 NAME 'certificateListMatch' "
6537 "SYNTAX 1.3.6.1.1.15.6 )",
6538 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6539 NULL, NULL, NULL, NULL, NULL,
6542 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6543 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6544 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6545 NULL, attributeCertificateExactNormalize, octetStringMatch,
6546 octetStringIndexer, octetStringFilter,
6549 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6550 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6551 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6552 NULL, NULL, NULL, NULL, NULL,
6555 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6556 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6557 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6558 NULL, IA5StringNormalize, octetStringMatch,
6559 octetStringIndexer, octetStringFilter,
6560 IA5StringApproxMatchOID },
6562 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6563 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6564 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6565 NULL, IA5StringNormalize, octetStringMatch,
6566 octetStringIndexer, octetStringFilter,
6567 IA5StringApproxMatchOID },
6569 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6570 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6571 SLAP_MR_SUBSTR, NULL,
6572 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6573 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6574 "caseIgnoreIA5Match" },
6576 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6577 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6578 SLAP_MR_SUBSTR, NULL,
6579 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6580 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6581 "caseExactIA5Match" },
6583 #ifdef SLAPD_AUTHPASSWD
6584 /* needs updating */
6585 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6586 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6587 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6588 NULL, NULL, authPasswordMatch,
6593 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6594 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6596 NULL, NULL, integerBitAndMatch,
6600 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6601 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6603 NULL, NULL, integerBitOrMatch,
6607 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6608 "SYNTAX 1.3.6.1.1.16.1 )",
6609 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6610 NULL, UUIDNormalize, octetStringMatch,
6611 octetStringIndexer, octetStringFilter,
6614 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6615 "SYNTAX 1.3.6.1.1.16.1 )",
6616 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6617 NULL, UUIDNormalize, octetStringOrderingMatch,
6618 octetStringIndexer, octetStringFilter,
6621 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6622 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6623 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6624 NULL, csnNormalize, csnMatch,
6625 csnIndexer, csnFilter,
6628 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6629 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6630 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6631 NULL, csnNormalize, csnOrderingMatch,
6635 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6636 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6637 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6638 NULL, csnSidNormalize, octetStringMatch,
6639 octetStringIndexer, octetStringFilter,
6642 /* FIXME: OID is unused, but not registered yet */
6643 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6644 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6645 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6646 NULL, authzNormalize, authzMatch,
6650 {NULL, SLAP_MR_NONE, NULL,
6651 NULL, NULL, NULL, NULL, NULL,
6656 slap_schema_init( void )
6661 /* we should only be called once (from main) */
6662 assert( schema_init_done == 0 );
6664 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6665 res = register_syntax( &syntax_defs[i] );
6668 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6669 syntax_defs[i].sd_desc );
6674 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6675 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6676 mrule_defs[i].mrd_compat_syntaxes == NULL )
6679 "slap_schema_init: Ignoring unusable matching rule %s\n",
6680 mrule_defs[i].mrd_desc );
6684 res = register_matching_rule( &mrule_defs[i] );
6688 "slap_schema_init: Error registering matching rule %s\n",
6689 mrule_defs[i].mrd_desc );
6694 res = slap_schema_load();
6695 schema_init_done = 1;
6700 schema_destroy( void )
6709 if( schema_init_done ) {
6710 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6711 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );