1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2010 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 checkTime( struct berval *in, struct berval *out );
280 certificateListValidate( Syntax *syntax, struct berval *in )
282 BerElementBuffer berbuf;
283 BerElement *ber = (BerElement *)&berbuf;
285 ber_len_t len, wrapper_len;
288 ber_int_t version = SLAP_X509_V1;
289 struct berval bvdn, bvtu;
291 ber_init2( ber, in, LBER_USE_DER );
292 tag = ber_skip_tag( ber, &wrapper_len ); /* Signed wrapper */
293 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
294 wrapper_start = ber->ber_ptr;
295 tag = ber_skip_tag( ber, &len ); /* Sequence */
296 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
297 tag = ber_peek_tag( ber, &len );
298 /* Optional version */
299 if ( tag == LBER_INTEGER ) {
300 tag = ber_get_int( ber, &version );
301 assert( tag == LBER_INTEGER );
302 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
304 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
305 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
306 ber_skip_data( ber, len );
307 tag = ber_peek_tag( ber, &len ); /* Issuer DN */
308 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
309 len = ber_ptrlen( ber );
310 bvdn.bv_val = in->bv_val + len;
311 bvdn.bv_len = in->bv_len - len;
312 tag = ber_skip_tag( ber, &len );
313 ber_skip_data( ber, len );
314 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
315 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
316 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
317 bvtu.bv_val = (char *)ber->ber_ptr;
319 ber_skip_data( ber, len );
320 /* Optional nextUpdate */
321 tag = ber_skip_tag( ber, &len );
322 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
323 ber_skip_data( ber, len );
324 tag = ber_skip_tag( ber, &len );
326 /* revokedCertificates - Sequence of Sequence, Optional */
327 if ( tag == LBER_SEQUENCE ) {
330 stag = ber_peek_tag( ber, &seqlen );
331 if ( stag == LBER_SEQUENCE || !len ) {
332 /* RFC5280 requires non-empty, but X.509(2005) allows empty. */
334 ber_skip_data( ber, len );
335 tag = ber_skip_tag( ber, &len );
338 /* Optional Extensions - Sequence of Sequence */
339 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
341 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
342 tag = ber_peek_tag( ber, &seqlen );
343 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
344 ber_skip_data( ber, len );
345 tag = ber_skip_tag( ber, &len );
347 /* signatureAlgorithm */
348 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
349 ber_skip_data( ber, len );
350 tag = ber_skip_tag( ber, &len );
352 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
353 ber_skip_data( ber, len );
354 if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
355 tag = ber_skip_tag( ber, &len );
356 /* Must be at end now */
357 /* NOTE: OpenSSL tolerates CL with garbage past the end */
358 if ( len || tag != LBER_DEFAULT ) {
359 struct berval issuer_dn = BER_BVNULL, thisUpdate;
360 char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
363 if ( ! wrapper_ok ) {
364 return LDAP_INVALID_SYNTAX;
367 rc = dnX509normalize( &bvdn, &issuer_dn );
368 if ( rc != LDAP_SUCCESS ) {
369 rc = LDAP_INVALID_SYNTAX;
373 thisUpdate.bv_val = tubuf;
374 thisUpdate.bv_len = sizeof(tubuf);
375 if ( checkTime( &bvtu, &thisUpdate ) ) {
376 rc = LDAP_INVALID_SYNTAX;
380 Debug( LDAP_DEBUG_ANY,
381 "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
382 issuer_dn.bv_val, thisUpdate.bv_val, 0 );
385 if ( ! BER_BVISNULL( &issuer_dn ) ) {
386 ber_memfree( issuer_dn.bv_val );
395 /* X.509 PMI Attribute Certificate Validate */
397 attributeCertificateValidate( Syntax *syntax, struct berval *in )
399 BerElementBuffer berbuf;
400 BerElement *ber = (BerElement *)&berbuf;
406 ber_init2( ber, in, LBER_USE_DER );
408 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
409 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
411 tag = ber_skip_tag( ber, &len ); /* Sequence */
412 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
414 tag = ber_peek_tag( ber, &len ); /* Version */
415 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
416 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
417 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
419 tag = ber_skip_tag( ber, &len ); /* Holder */
420 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
421 ber_skip_data( ber, len );
423 tag = ber_skip_tag( ber, &len ); /* Issuer */
424 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
425 ber_skip_data( ber, len );
427 tag = ber_skip_tag( ber, &len ); /* Signature */
428 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
429 ber_skip_data( ber, len );
431 tag = ber_skip_tag( ber, &len ); /* Serial number */
432 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
433 ber_skip_data( ber, len );
435 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
436 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
437 ber_skip_data( ber, len );
439 tag = ber_skip_tag( ber, &len ); /* Attributes */
440 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
441 ber_skip_data( ber, len );
443 tag = ber_peek_tag( ber, &len );
445 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
446 tag = ber_skip_tag( ber, &len );
447 ber_skip_data( ber, len );
448 tag = ber_peek_tag( ber, &len );
451 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
452 tag = ber_skip_tag( ber, &len );
453 ber_skip_data( ber, len );
455 tag = ber_peek_tag( ber, &len );
458 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
459 tag = ber_skip_tag( ber, &len );
460 ber_skip_data( ber, len );
462 tag = ber_peek_tag( ber, &len );
465 if ( tag == LBER_BITSTRING ) { /* Signature */
466 tag = ber_skip_tag( ber, &len );
467 ber_skip_data( ber, len );
469 tag = ber_peek_tag( ber, &len );
472 /* Must be at end now */
473 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
484 struct berval *value,
485 void *assertedValue )
487 struct berval *asserted = (struct berval *) assertedValue;
488 ber_slen_t d = (ber_slen_t) value->bv_len - (ber_slen_t) asserted->bv_len;
490 *matchp = d ? (sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1)
491 : memcmp( value->bv_val, asserted->bv_val, value->bv_len );
497 octetStringOrderingMatch(
502 struct berval *value,
503 void *assertedValue )
505 struct berval *asserted = (struct berval *) assertedValue;
506 ber_len_t v_len = value->bv_len;
507 ber_len_t av_len = asserted->bv_len;
509 int match = memcmp( value->bv_val, asserted->bv_val,
510 (v_len < av_len ? v_len : av_len) );
513 match = sizeof(v_len) == sizeof(int)
514 ? (int) v_len - (int) av_len
515 : v_len < av_len ? -1 : v_len > av_len;
517 if ( flags & SLAP_MR_EXT )
518 match = (match >= 0);
526 HASH_CONTEXT *HASHcontext,
527 struct berval *prefix,
532 HASH_Init(HASHcontext);
533 if(prefix && prefix->bv_len > 0) {
534 HASH_Update(HASHcontext,
535 (unsigned char *)prefix->bv_val, prefix->bv_len);
537 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
538 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
539 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
545 HASH_CONTEXT *HASHcontext,
546 unsigned char *HASHdigest,
547 unsigned char *value,
550 HASH_CONTEXT ctx = *HASHcontext;
551 HASH_Update( &ctx, value, len );
552 HASH_Final( HASHdigest, &ctx );
555 /* Index generation function */
556 int octetStringIndexer(
561 struct berval *prefix,
569 HASH_CONTEXT HASHcontext;
570 unsigned char HASHdigest[HASH_BYTES];
571 struct berval digest;
572 digest.bv_val = (char *)HASHdigest;
573 digest.bv_len = sizeof(HASHdigest);
575 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
576 /* just count them */
579 /* we should have at least one value at this point */
582 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
584 slen = syntax->ssyn_oidlen;
585 mlen = mr->smr_oidlen;
587 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
588 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
589 hashIter( &HASHcontext, HASHdigest,
590 (unsigned char *)values[i].bv_val, values[i].bv_len );
591 ber_dupbv_x( &keys[i], &digest, ctx );
594 BER_BVZERO( &keys[i] );
601 /* Index generation function */
602 int octetStringFilter(
607 struct berval *prefix,
608 void * assertedValue,
614 HASH_CONTEXT HASHcontext;
615 unsigned char HASHdigest[HASH_BYTES];
616 struct berval *value = (struct berval *) assertedValue;
617 struct berval digest;
618 digest.bv_val = (char *)HASHdigest;
619 digest.bv_len = sizeof(HASHdigest);
621 slen = syntax->ssyn_oidlen;
622 mlen = mr->smr_oidlen;
624 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
626 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
627 hashIter( &HASHcontext, HASHdigest,
628 (unsigned char *)value->bv_val, value->bv_len );
630 ber_dupbv_x( keys, &digest, ctx );
631 BER_BVZERO( &keys[1] );
639 octetStringSubstringsMatch(
644 struct berval *value,
645 void *assertedValue )
648 SubstringsAssertion *sub = assertedValue;
649 struct berval left = *value;
653 /* Add up asserted input length */
654 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
655 inlen += sub->sa_initial.bv_len;
658 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
659 inlen += sub->sa_any[i].bv_len;
662 if ( !BER_BVISNULL( &sub->sa_final ) ) {
663 inlen += sub->sa_final.bv_len;
666 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
667 if ( inlen > left.bv_len ) {
672 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
673 sub->sa_initial.bv_len );
679 left.bv_val += sub->sa_initial.bv_len;
680 left.bv_len -= sub->sa_initial.bv_len;
681 inlen -= sub->sa_initial.bv_len;
684 if ( !BER_BVISNULL( &sub->sa_final ) ) {
685 if ( inlen > left.bv_len ) {
690 match = memcmp( sub->sa_final.bv_val,
691 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
692 sub->sa_final.bv_len );
698 left.bv_len -= sub->sa_final.bv_len;
699 inlen -= sub->sa_final.bv_len;
703 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
708 if ( inlen > left.bv_len ) {
709 /* not enough length */
714 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
718 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
725 idx = p - left.bv_val;
727 if ( idx >= left.bv_len ) {
728 /* this shouldn't happen */
735 if ( sub->sa_any[i].bv_len > left.bv_len ) {
736 /* not enough left */
741 match = memcmp( left.bv_val,
742 sub->sa_any[i].bv_val,
743 sub->sa_any[i].bv_len );
751 left.bv_val += sub->sa_any[i].bv_len;
752 left.bv_len -= sub->sa_any[i].bv_len;
753 inlen -= sub->sa_any[i].bv_len;
762 /* Substrings Index generation function */
764 octetStringSubstringsIndexer(
769 struct berval *prefix,
778 HASH_CONTEXT HCany, HCini, HCfin;
779 unsigned char HASHdigest[HASH_BYTES];
780 struct berval digest;
781 digest.bv_val = (char *)HASHdigest;
782 digest.bv_len = sizeof(HASHdigest);
786 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
787 /* count number of indices to generate */
788 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
789 if( values[i].bv_len >= index_substr_if_maxlen ) {
790 nkeys += index_substr_if_maxlen -
791 (index_substr_if_minlen - 1);
792 } else if( values[i].bv_len >= index_substr_if_minlen ) {
793 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
797 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
798 if( values[i].bv_len >= index_substr_any_len ) {
799 nkeys += values[i].bv_len - (index_substr_any_len - 1);
803 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
804 if( values[i].bv_len >= index_substr_if_maxlen ) {
805 nkeys += index_substr_if_maxlen -
806 (index_substr_if_minlen - 1);
807 } else if( values[i].bv_len >= index_substr_if_minlen ) {
808 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
814 /* no keys to generate */
819 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
821 slen = syntax->ssyn_oidlen;
822 mlen = mr->smr_oidlen;
824 if ( flags & SLAP_INDEX_SUBSTR_ANY )
825 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
826 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
827 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
828 if( flags & SLAP_INDEX_SUBSTR_FINAL )
829 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
832 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
835 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
836 ( values[i].bv_len >= index_substr_any_len ) )
838 max = values[i].bv_len - (index_substr_any_len - 1);
840 for( j=0; j<max; j++ ) {
841 hashIter( &HCany, HASHdigest,
842 (unsigned char *)&values[i].bv_val[j],
843 index_substr_any_len );
844 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
848 /* skip if too short */
849 if( values[i].bv_len < index_substr_if_minlen ) continue;
851 max = index_substr_if_maxlen < values[i].bv_len
852 ? index_substr_if_maxlen : values[i].bv_len;
854 for( j=index_substr_if_minlen; j<=max; j++ ) {
856 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
857 hashIter( &HCini, HASHdigest,
858 (unsigned char *)values[i].bv_val, j );
859 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
862 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
863 hashIter( &HCfin, HASHdigest,
864 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
865 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
872 BER_BVZERO( &keys[nkeys] );
883 octetStringSubstringsFilter (
888 struct berval *prefix,
889 void * assertedValue,
893 SubstringsAssertion *sa;
896 size_t slen, mlen, klen;
898 HASH_CONTEXT HASHcontext;
899 unsigned char HASHdigest[HASH_BYTES];
900 struct berval *value;
901 struct berval digest;
903 sa = (SubstringsAssertion *) assertedValue;
905 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
906 !BER_BVISNULL( &sa->sa_initial ) &&
907 sa->sa_initial.bv_len >= index_substr_if_minlen )
910 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
911 ( flags & SLAP_INDEX_SUBSTR_ANY ))
913 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
917 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
919 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
920 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
921 /* don't bother accounting with stepping */
922 nkeys += sa->sa_any[i].bv_len -
923 ( index_substr_any_len - 1 );
928 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
929 !BER_BVISNULL( &sa->sa_final ) &&
930 sa->sa_final.bv_len >= index_substr_if_minlen )
933 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
934 ( flags & SLAP_INDEX_SUBSTR_ANY ))
936 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
945 digest.bv_val = (char *)HASHdigest;
946 digest.bv_len = sizeof(HASHdigest);
948 slen = syntax->ssyn_oidlen;
949 mlen = mr->smr_oidlen;
951 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
954 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
955 !BER_BVISNULL( &sa->sa_initial ) &&
956 sa->sa_initial.bv_len >= index_substr_if_minlen )
958 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
959 value = &sa->sa_initial;
961 klen = index_substr_if_maxlen < value->bv_len
962 ? index_substr_if_maxlen : value->bv_len;
964 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
965 hashIter( &HASHcontext, HASHdigest,
966 (unsigned char *)value->bv_val, klen );
967 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
969 /* If initial is too long and we have subany indexed, use it
970 * to match the excess...
972 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
975 pre = SLAP_INDEX_SUBSTR_PREFIX;
976 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
977 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
979 hashIter( &HASHcontext, HASHdigest,
980 (unsigned char *)&value->bv_val[j], index_substr_any_len );
981 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
986 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
988 pre = SLAP_INDEX_SUBSTR_PREFIX;
989 klen = index_substr_any_len;
991 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
992 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
996 value = &sa->sa_any[i];
998 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1000 j <= value->bv_len - index_substr_any_len;
1001 j += index_substr_any_step )
1003 hashIter( &HASHcontext, HASHdigest,
1004 (unsigned char *)&value->bv_val[j], klen );
1005 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1010 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1011 !BER_BVISNULL( &sa->sa_final ) &&
1012 sa->sa_final.bv_len >= index_substr_if_minlen )
1014 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1015 value = &sa->sa_final;
1017 klen = index_substr_if_maxlen < value->bv_len
1018 ? index_substr_if_maxlen : value->bv_len;
1020 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1021 hashIter( &HASHcontext, HASHdigest,
1022 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
1023 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1025 /* If final is too long and we have subany indexed, use it
1026 * to match the excess...
1028 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1031 pre = SLAP_INDEX_SUBSTR_PREFIX;
1032 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1033 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
1035 hashIter( &HASHcontext, HASHdigest,
1036 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1037 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1043 BER_BVZERO( &keys[nkeys] );
1050 return LDAP_SUCCESS;
1060 /* very unforgiving validation, requires no normalization
1061 * before simplistic matching
1063 if( in->bv_len < 3 ) {
1064 return LDAP_INVALID_SYNTAX;
1067 /* RFC 4517 Section 3.3.2 Bit String:
1068 * BitString = SQUOTE *binary-digit SQUOTE "B"
1069 * binary-digit = "0" / "1"
1071 * where SQUOTE [RFC4512] is
1072 * SQUOTE = %x27 ; single quote ("'")
1074 * Example: '0101111101'B
1077 if( in->bv_val[0] != '\'' ||
1078 in->bv_val[in->bv_len - 2] != '\'' ||
1079 in->bv_val[in->bv_len - 1] != 'B' )
1081 return LDAP_INVALID_SYNTAX;
1084 for( i = in->bv_len - 3; i > 0; i-- ) {
1085 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1086 return LDAP_INVALID_SYNTAX;
1090 return LDAP_SUCCESS;
1094 * Syntaxes from RFC 4517
1099 A value of the Bit String syntax is a sequence of binary digits. The
1100 LDAP-specific encoding of a value of this syntax is defined by the
1103 BitString = SQUOTE *binary-digit SQUOTE "B"
1105 binary-digit = "0" / "1"
1107 The <SQUOTE> rule is defined in [MODELS].
1112 The LDAP definition for the Bit String syntax is:
1114 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1116 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1120 3.3.21. Name and Optional UID
1122 A value of the Name and Optional UID syntax is the distinguished name
1123 [MODELS] of an entity optionally accompanied by a unique identifier
1124 that serves to differentiate the entity from others with an identical
1127 The LDAP-specific encoding of a value of this syntax is defined by
1130 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1132 The <BitString> rule is defined in Section 3.3.2. The
1133 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1134 defined in [MODELS].
1136 Note that although the '#' character may occur in the string
1137 representation of a distinguished name, no additional escaping of
1138 this character is performed when a <distinguishedName> is encoded in
1139 a <NameAndOptionalUID>.
1142 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1144 The LDAP definition for the Name and Optional UID syntax is:
1146 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1148 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1155 1.4. Common ABNF Productions
1158 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1160 SQUOTE = %x27 ; single quote ("'")
1165 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1166 * be escaped except when at the beginning of a value, the
1167 * definition of Name and Optional UID appears to be flawed,
1168 * because there is no clear means to determine whether the
1169 * UID part is present or not.
1173 * cn=Someone,dc=example,dc=com#'1'B
1175 * could be either a NameAndOptionalUID with trailing UID, i.e.
1177 * DN = "cn=Someone,dc=example,dc=com"
1180 * or a NameAndOptionalUID with no trailing UID, and the AVA
1181 * in the last RDN made of
1183 * attributeType = dc
1184 * attributeValue = com#'1'B
1186 * in fact "com#'1'B" is a valid IA5 string.
1188 * As a consequence, current slapd code takes the presence of
1189 * #<valid BitString> at the end of the string representation
1190 * of a NameAndOptionalUID to mean this is indeed a BitString.
1191 * This is quite arbitrary - it has changed the past and might
1192 * change in the future.
1202 struct berval dn, uid;
1204 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1206 ber_dupbv( &dn, in );
1207 if( !dn.bv_val ) return LDAP_OTHER;
1209 /* if there's a "#", try bitStringValidate()... */
1210 uid.bv_val = strrchr( dn.bv_val, '#' );
1211 if ( !BER_BVISNULL( &uid ) ) {
1213 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1215 rc = bitStringValidate( NULL, &uid );
1216 if ( rc == LDAP_SUCCESS ) {
1217 /* in case of success, trim the UID,
1218 * otherwise treat it as part of the DN */
1219 dn.bv_len -= uid.bv_len + 1;
1220 uid.bv_val[-1] = '\0';
1224 rc = dnValidate( NULL, &dn );
1226 ber_memfree( dn.bv_val );
1237 assert( val != NULL );
1238 assert( out != NULL );
1241 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1243 if( BER_BVISEMPTY( val ) ) {
1244 ber_dupbv_x( out, val, ctx );
1246 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1247 return LDAP_INVALID_SYNTAX;
1251 struct berval dnval = *val;
1252 struct berval uidval = BER_BVNULL;
1254 uidval.bv_val = strrchr( val->bv_val, '#' );
1255 if ( !BER_BVISNULL( &uidval ) ) {
1257 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1259 rc = bitStringValidate( NULL, &uidval );
1261 if ( rc == LDAP_SUCCESS ) {
1262 ber_dupbv_x( &dnval, val, ctx );
1264 dnval.bv_len -= ++uidval.bv_len;
1265 dnval.bv_val[dnval.bv_len] = '\0';
1268 BER_BVZERO( &uidval );
1272 rc = dnPretty( syntax, &dnval, out, ctx );
1273 if ( dnval.bv_val != val->bv_val ) {
1274 slap_sl_free( dnval.bv_val, ctx );
1276 if( rc != LDAP_SUCCESS ) {
1280 if( !BER_BVISNULL( &uidval ) ) {
1283 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1284 + uidval.bv_len + 1,
1287 ber_memfree_x( out->bv_val, ctx );
1291 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1292 out->bv_len += uidval.bv_len;
1293 out->bv_val[out->bv_len] = '\0';
1297 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1299 return LDAP_SUCCESS;
1303 uniqueMemberNormalize(
1308 struct berval *normalized,
1314 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1316 ber_dupbv_x( &out, val, ctx );
1317 if ( BER_BVISEMPTY( &out ) ) {
1321 struct berval uid = BER_BVNULL;
1323 uid.bv_val = strrchr( out.bv_val, '#' );
1324 if ( !BER_BVISNULL( &uid ) ) {
1326 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1328 rc = bitStringValidate( NULL, &uid );
1329 if ( rc == LDAP_SUCCESS ) {
1330 uid.bv_val[-1] = '\0';
1331 out.bv_len -= uid.bv_len + 1;
1337 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1339 if( rc != LDAP_SUCCESS ) {
1340 slap_sl_free( out.bv_val, ctx );
1341 return LDAP_INVALID_SYNTAX;
1344 if( !BER_BVISNULL( &uid ) ) {
1347 tmp = ch_realloc( normalized->bv_val,
1348 normalized->bv_len + uid.bv_len
1349 + STRLENOF("#") + 1 );
1350 if ( tmp == NULL ) {
1351 ber_memfree_x( normalized->bv_val, ctx );
1355 normalized->bv_val = tmp;
1357 /* insert the separator */
1358 normalized->bv_val[normalized->bv_len++] = '#';
1360 /* append the UID */
1361 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1362 uid.bv_val, uid.bv_len );
1363 normalized->bv_len += uid.bv_len;
1366 normalized->bv_val[normalized->bv_len] = '\0';
1369 slap_sl_free( out.bv_val, ctx );
1372 return LDAP_SUCCESS;
1381 struct berval *value,
1382 void *assertedValue )
1385 struct berval *asserted = (struct berval *) assertedValue;
1386 struct berval assertedDN = *asserted;
1387 struct berval assertedUID = BER_BVNULL;
1388 struct berval valueDN = *value;
1389 struct berval valueUID = BER_BVNULL;
1390 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1392 if ( !BER_BVISEMPTY( asserted ) ) {
1393 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1394 if ( !BER_BVISNULL( &assertedUID ) ) {
1395 assertedUID.bv_val++;
1396 assertedUID.bv_len = assertedDN.bv_len
1397 - ( assertedUID.bv_val - assertedDN.bv_val );
1399 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1400 assertedDN.bv_len -= assertedUID.bv_len + 1;
1403 BER_BVZERO( &assertedUID );
1408 if ( !BER_BVISEMPTY( value ) ) {
1410 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1411 if ( !BER_BVISNULL( &valueUID ) ) {
1413 valueUID.bv_len = valueDN.bv_len
1414 - ( valueUID.bv_val - valueDN.bv_val );
1416 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1417 valueDN.bv_len -= valueUID.bv_len + 1;
1420 BER_BVZERO( &valueUID );
1425 if( valueUID.bv_len && assertedUID.bv_len ) {
1427 d = (ber_slen_t) valueUID.bv_len - (ber_slen_t) assertedUID.bv_len;
1429 *matchp = sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1;
1430 return LDAP_SUCCESS;
1433 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1436 return LDAP_SUCCESS;
1439 } else if ( !approx && valueUID.bv_len ) {
1442 return LDAP_SUCCESS;
1444 } else if ( !approx && assertedUID.bv_len ) {
1447 return LDAP_SUCCESS;
1450 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1454 uniqueMemberIndexer(
1459 struct berval *prefix,
1467 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1468 /* just count them */
1472 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1474 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1475 struct berval assertedDN = values[i];
1476 struct berval assertedUID = BER_BVNULL;
1478 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1479 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1480 if ( !BER_BVISNULL( &assertedUID ) ) {
1481 assertedUID.bv_val++;
1482 assertedUID.bv_len = assertedDN.bv_len
1483 - ( assertedUID.bv_val - assertedDN.bv_val );
1485 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1486 assertedDN.bv_len -= assertedUID.bv_len + 1;
1489 BER_BVZERO( &assertedUID );
1494 dnvalues[i] = assertedDN;
1496 BER_BVZERO( &dnvalues[i] );
1498 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1499 dnvalues, keysp, ctx );
1501 slap_sl_free( dnvalues, ctx );
1511 struct berval *prefix,
1512 void * assertedValue,
1516 struct berval *asserted = (struct berval *) assertedValue;
1517 struct berval assertedDN = *asserted;
1518 struct berval assertedUID = BER_BVNULL;
1520 if ( !BER_BVISEMPTY( asserted ) ) {
1521 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1522 if ( !BER_BVISNULL( &assertedUID ) ) {
1523 assertedUID.bv_val++;
1524 assertedUID.bv_len = assertedDN.bv_len
1525 - ( assertedUID.bv_val - assertedDN.bv_val );
1527 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1528 assertedDN.bv_len -= assertedUID.bv_len + 1;
1531 BER_BVZERO( &assertedUID );
1536 return octetStringFilter( use, flags, syntax, mr, prefix,
1537 &assertedDN, keysp, ctx );
1542 * Handling boolean syntax and matching is quite rigid.
1543 * A more flexible approach would be to allow a variety
1544 * of strings to be normalized and prettied into TRUE
1552 /* very unforgiving validation, requires no normalization
1553 * before simplistic matching
1556 if( in->bv_len == 4 ) {
1557 if( bvmatch( in, &slap_true_bv ) ) {
1558 return LDAP_SUCCESS;
1560 } else if( in->bv_len == 5 ) {
1561 if( bvmatch( in, &slap_false_bv ) ) {
1562 return LDAP_SUCCESS;
1566 return LDAP_INVALID_SYNTAX;
1575 struct berval *value,
1576 void *assertedValue )
1578 /* simplistic matching allowed by rigid validation */
1579 struct berval *asserted = (struct berval *) assertedValue;
1580 *matchp = (int) asserted->bv_len - (int) value->bv_len;
1581 return LDAP_SUCCESS;
1584 /*-------------------------------------------------------------------
1585 LDAP/X.500 string syntax / matching rules have a few oddities. This
1586 comment attempts to detail how slapd(8) treats them.
1589 StringSyntax X.500 LDAP Matching/Comments
1590 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1591 PrintableString subset subset i/e + ignore insignificant spaces
1592 PrintableString subset subset i/e + ignore insignificant spaces
1593 NumericString subset subset ignore all spaces
1594 IA5String ASCII ASCII i/e + ignore insignificant spaces
1595 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1597 TelephoneNumber subset subset i + ignore all spaces and "-"
1599 See RFC 4518 for details.
1603 In X.500(93), a directory string can be either a PrintableString,
1604 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1605 In later versions, more CHOICEs were added. In all cases the string
1608 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1609 A directory string cannot be zero length.
1611 For matching, there are both case ignore and exact rules. Both
1612 also require that "insignificant" spaces be ignored.
1613 spaces before the first non-space are ignored;
1614 spaces after the last non-space are ignored;
1615 spaces after a space are ignored.
1616 Note: by these rules (and as clarified in X.520), a string of only
1617 spaces is to be treated as if held one space, not empty (which
1618 would be a syntax error).
1621 In ASN.1, numeric string is just a string of digits and spaces
1622 and could be empty. However, in X.500, all attribute values of
1623 numeric string carry a non-empty constraint. For example:
1625 internationalISDNNumber ATTRIBUTE ::= {
1626 WITH SYNTAX InternationalISDNNumber
1627 EQUALITY MATCHING RULE numericStringMatch
1628 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1629 ID id-at-internationalISDNNumber }
1630 InternationalISDNNumber ::=
1631 NumericString (SIZE(1..ub-international-isdn-number))
1633 Unforunately, some assertion values are don't carry the same
1634 constraint (but its unclear how such an assertion could ever
1635 be true). In LDAP, there is one syntax (numericString) not two
1636 (numericString with constraint, numericString without constraint).
1637 This should be treated as numericString with non-empty constraint.
1638 Note that while someone may have no ISDN number, there are no ISDN
1639 numbers which are zero length.
1641 In matching, spaces are ignored.
1644 In ASN.1, Printable string is just a string of printable characters
1645 and can be empty. In X.500, semantics much like NumericString (see
1646 serialNumber for a like example) excepting uses insignificant space
1647 handling instead of ignore all spaces. They must be non-empty.
1650 Basically same as PrintableString. There are no examples in X.500,
1651 but same logic applies. Empty strings are allowed.
1653 -------------------------------------------------------------------*/
1662 unsigned char *u = (unsigned char *)in->bv_val;
1664 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1665 /* directory strings cannot be empty */
1666 return LDAP_INVALID_SYNTAX;
1669 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1670 /* get the length indicated by the first byte */
1671 len = LDAP_UTF8_CHARLEN2( u, len );
1673 /* very basic checks */
1676 if( (u[5] & 0xC0) != 0x80 ) {
1677 return LDAP_INVALID_SYNTAX;
1680 if( (u[4] & 0xC0) != 0x80 ) {
1681 return LDAP_INVALID_SYNTAX;
1684 if( (u[3] & 0xC0) != 0x80 ) {
1685 return LDAP_INVALID_SYNTAX;
1688 if( (u[2] & 0xC0 )!= 0x80 ) {
1689 return LDAP_INVALID_SYNTAX;
1692 if( (u[1] & 0xC0) != 0x80 ) {
1693 return LDAP_INVALID_SYNTAX;
1696 /* CHARLEN already validated it */
1699 return LDAP_INVALID_SYNTAX;
1702 /* make sure len corresponds with the offset
1703 to the next character */
1704 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1708 return LDAP_INVALID_SYNTAX;
1711 return LDAP_SUCCESS;
1715 UTF8StringNormalize(
1720 struct berval *normalized,
1723 struct berval tmp, nvalue;
1724 int flags, wasspace;
1727 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1729 if( BER_BVISNULL( val ) ) {
1730 /* assume we're dealing with a syntax (e.g., UTF8String)
1731 * which allows empty strings
1733 BER_BVZERO( normalized );
1734 return LDAP_SUCCESS;
1737 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1738 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1739 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1740 ? LDAP_UTF8_APPROX : 0;
1742 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1743 /* out of memory or syntax error, the former is unlikely */
1745 return LDAP_INVALID_SYNTAX;
1748 /* collapse spaces (in place) */
1750 nvalue.bv_val = tmp.bv_val;
1752 /* trim leading spaces? */
1753 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1754 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1756 for( i = 0; i < tmp.bv_len; i++) {
1757 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1758 if( wasspace++ == 0 ) {
1759 /* trim repeated spaces */
1760 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1764 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1768 if( !BER_BVISEMPTY( &nvalue ) ) {
1769 /* trim trailing space? */
1771 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1772 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1776 nvalue.bv_val[nvalue.bv_len] = '\0';
1779 /* string of all spaces is treated as one space */
1780 nvalue.bv_val[0] = ' ';
1781 nvalue.bv_val[1] = '\0';
1785 *normalized = nvalue;
1786 return LDAP_SUCCESS;
1790 directoryStringSubstringsMatch(
1795 struct berval *value,
1796 void *assertedValue )
1799 SubstringsAssertion *sub = assertedValue;
1800 struct berval left = *value;
1804 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1805 if ( sub->sa_initial.bv_len > left.bv_len ) {
1806 /* not enough left */
1811 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1812 sub->sa_initial.bv_len );
1818 left.bv_val += sub->sa_initial.bv_len;
1819 left.bv_len -= sub->sa_initial.bv_len;
1821 priorspace = ASCII_SPACE(
1822 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1825 if ( sub->sa_any ) {
1826 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1830 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1831 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1833 /* allow next space to match */
1840 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1844 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1845 /* not enough left */
1850 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1857 idx = p - left.bv_val;
1859 if ( idx >= left.bv_len ) {
1860 /* this shouldn't happen */
1867 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1868 /* not enough left */
1873 match = memcmp( left.bv_val,
1874 sub->sa_any[i].bv_val,
1875 sub->sa_any[i].bv_len );
1883 left.bv_val += sub->sa_any[i].bv_len;
1884 left.bv_len -= sub->sa_any[i].bv_len;
1886 priorspace = ASCII_SPACE(
1887 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1891 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1892 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1893 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1895 /* allow next space to match */
1900 if ( sub->sa_final.bv_len > left.bv_len ) {
1901 /* not enough left */
1906 match = memcmp( sub->sa_final.bv_val,
1907 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1908 sub->sa_final.bv_len );
1917 return LDAP_SUCCESS;
1920 #if defined(SLAPD_APPROX_INITIALS)
1921 # define SLAPD_APPROX_DELIMITER "._ "
1922 # define SLAPD_APPROX_WORDLEN 2
1924 # define SLAPD_APPROX_DELIMITER " "
1925 # define SLAPD_APPROX_WORDLEN 1
1934 struct berval *value,
1935 void *assertedValue )
1937 struct berval *nval, *assertv;
1938 char *val, **values, **words, *c;
1939 int i, count, len, nextchunk=0, nextavail=0;
1941 /* Yes, this is necessary */
1942 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1943 if( nval == NULL ) {
1945 return LDAP_SUCCESS;
1948 /* Yes, this is necessary */
1949 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1950 NULL, LDAP_UTF8_APPROX, NULL );
1951 if( assertv == NULL ) {
1954 return LDAP_SUCCESS;
1957 /* Isolate how many words there are */
1958 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1959 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1960 if ( c == NULL ) break;
1965 /* Get a phonetic copy of each word */
1966 words = (char **)ch_malloc( count * sizeof(char *) );
1967 values = (char **)ch_malloc( count * sizeof(char *) );
1968 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1970 values[i] = phonetic(c);
1973 /* Work through the asserted value's words, to see if at least some
1974 * of the words are there, in the same order. */
1976 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1977 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1982 #if defined(SLAPD_APPROX_INITIALS)
1983 else if( len == 1 ) {
1984 /* Single letter words need to at least match one word's initial */
1985 for( i=nextavail; i<count; i++ )
1986 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1993 /* Isolate the next word in the asserted value and phonetic it */
1994 assertv->bv_val[nextchunk+len] = '\0';
1995 val = phonetic( assertv->bv_val + nextchunk );
1997 /* See if this phonetic chunk is in the remaining words of *value */
1998 for( i=nextavail; i<count; i++ ){
1999 if( !strcmp( val, values[i] ) ){
2007 /* This chunk in the asserted value was NOT within the *value. */
2013 /* Go on to the next word in the asserted value */
2017 /* If some of the words were seen, call it a match */
2018 if( nextavail > 0 ) {
2025 /* Cleanup allocs */
2026 ber_bvfree( assertv );
2027 for( i=0; i<count; i++ ) {
2028 ch_free( values[i] );
2034 return LDAP_SUCCESS;
2043 struct berval *prefix,
2049 int i,j, len, wordcount, keycount=0;
2050 struct berval *newkeys;
2051 BerVarray keys=NULL;
2053 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2054 struct berval val = BER_BVNULL;
2055 /* Yes, this is necessary */
2056 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2057 assert( !BER_BVISNULL( &val ) );
2059 /* Isolate how many words there are. There will be a key for each */
2060 for( wordcount = 0, c = val.bv_val; *c; c++) {
2061 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2062 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2064 if (*c == '\0') break;
2068 /* Allocate/increase storage to account for new keys */
2069 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2070 * sizeof(struct berval) );
2071 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2072 if( keys ) ch_free( keys );
2075 /* Get a phonetic copy of each word */
2076 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2078 if( len < SLAPD_APPROX_WORDLEN ) continue;
2079 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2084 ber_memfree( val.bv_val );
2086 BER_BVZERO( &keys[keycount] );
2089 return LDAP_SUCCESS;
2098 struct berval *prefix,
2099 void * assertedValue,
2108 /* Yes, this is necessary */
2109 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2110 NULL, LDAP_UTF8_APPROX, NULL );
2111 if( val == NULL || BER_BVISNULL( val ) ) {
2112 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2113 BER_BVZERO( &keys[0] );
2116 return LDAP_SUCCESS;
2119 /* Isolate how many words there are. There will be a key for each */
2120 for( count = 0,c = val->bv_val; *c; c++) {
2121 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2122 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2124 if (*c == '\0') break;
2128 /* Allocate storage for new keys */
2129 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2131 /* Get a phonetic copy of each word */
2132 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2134 if( len < SLAPD_APPROX_WORDLEN ) continue;
2135 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2141 BER_BVZERO( &keys[count] );
2144 return LDAP_SUCCESS;
2147 /* Remove all spaces and '-' characters */
2149 telephoneNumberNormalize(
2154 struct berval *normalized,
2159 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2161 /* validator should have refused an empty string */
2162 assert( !BER_BVISEMPTY( val ) );
2164 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2166 for( p = val->bv_val; *p; p++ ) {
2167 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2173 normalized->bv_len = q - normalized->bv_val;
2175 if( BER_BVISEMPTY( normalized ) ) {
2176 slap_sl_free( normalized->bv_val, ctx );
2177 BER_BVZERO( normalized );
2178 return LDAP_INVALID_SYNTAX;
2181 return LDAP_SUCCESS;
2185 postalAddressValidate(
2189 struct berval bv = *in;
2192 for ( c = 0; c < in->bv_len; c++ ) {
2193 if ( in->bv_val[c] == '\\' ) {
2195 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2196 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2198 return LDAP_INVALID_SYNTAX;
2203 if ( in->bv_val[c] == '$' ) {
2204 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2205 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2206 return LDAP_INVALID_SYNTAX;
2208 bv.bv_val = &in->bv_val[c] + 1;
2212 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2213 return UTF8StringValidate( NULL, &bv );
2217 postalAddressNormalize(
2222 struct berval *normalized,
2225 BerVarray lines = NULL, nlines = NULL;
2227 int rc = LDAP_SUCCESS;
2228 MatchingRule *xmr = NULL;
2231 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2232 xmr = slap_schema.si_mr_caseIgnoreMatch;
2235 xmr = slap_schema.si_mr_caseExactMatch;
2238 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2239 if ( val->bv_val[c] == '$' ) {
2244 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2245 nlines = &lines[l + 2];
2247 lines[0].bv_val = val->bv_val;
2248 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2249 if ( val->bv_val[c] == '$' ) {
2250 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2252 lines[l].bv_val = &val->bv_val[c + 1];
2255 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2257 normalized->bv_len = l;
2259 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2260 /* NOTE: we directly normalize each line,
2261 * without unescaping the values, since the special
2262 * values '\24' ('$') and '\5C' ('\') are not affected
2263 * by normalization */
2264 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2265 if ( rc != LDAP_SUCCESS ) {
2266 rc = LDAP_INVALID_SYNTAX;
2270 normalized->bv_len += nlines[l].bv_len;
2273 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2275 p = normalized->bv_val;
2276 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2277 p = lutil_strbvcopy( p, &nlines[l] );
2282 assert( p == &normalized->bv_val[normalized->bv_len] );
2285 if ( nlines != NULL ) {
2286 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2287 slap_sl_free( nlines[l].bv_val, ctx );
2290 slap_sl_free( lines, ctx );
2301 struct berval val = *in;
2303 if( BER_BVISEMPTY( &val ) ) {
2304 /* disallow empty strings */
2305 return LDAP_INVALID_SYNTAX;
2308 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2309 if ( val.bv_len == 1 ) {
2310 return LDAP_SUCCESS;
2313 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2320 while ( OID_LEADCHAR( val.bv_val[0] )) {
2324 if ( val.bv_len == 0 ) {
2325 return LDAP_SUCCESS;
2329 if( !OID_SEPARATOR( val.bv_val[0] )) {
2337 return LDAP_INVALID_SYNTAX;
2346 struct berval val = *in;
2348 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2350 if ( val.bv_val[0] == '-' ) {
2354 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2355 return LDAP_INVALID_SYNTAX;
2358 if( val.bv_val[0] == '0' ) { /* "-0" */
2359 return LDAP_INVALID_SYNTAX;
2362 } else if ( val.bv_val[0] == '0' ) {
2363 if( val.bv_len > 1 ) { /* "0<more>" */
2364 return LDAP_INVALID_SYNTAX;
2367 return LDAP_SUCCESS;
2370 for( i=0; i < val.bv_len; i++ ) {
2371 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2372 return LDAP_INVALID_SYNTAX;
2376 return LDAP_SUCCESS;
2385 struct berval *value,
2386 void *assertedValue )
2388 struct berval *asserted = (struct berval *) assertedValue;
2389 int vsign = 1, asign = 1; /* default sign = '+' */
2394 if( v.bv_val[0] == '-' ) {
2400 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2403 if( a.bv_val[0] == '-' ) {
2409 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2411 match = vsign - asign;
2413 match = ( v.bv_len != a.bv_len
2414 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2415 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2416 if( vsign < 0 ) match = -match;
2419 if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
2420 match = (match >= 0);
2423 return LDAP_SUCCESS;
2426 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2427 #define INDEX_INTLEN_CHOP 7
2428 #define INDEX_INTLEN_CHOPBYTES 3
2438 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2439 * two's complement value (sign-extended or chopped as needed),
2440 * however the top <number of exponent-bytes + 1> bits of first byte
2441 * above is the inverse sign. The next bit is the sign as delimiter.
2443 ber_slen_t k = index_intlen_strlen;
2445 unsigned signmask = ~0x7fU;
2446 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2447 struct berval val = *in, itmp = *tmp;
2449 if ( val.bv_val[0] != '-' ) {
2454 /* Chop least significant digits, increase length instead */
2455 if ( val.bv_len > (ber_len_t) k ) {
2456 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2457 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2458 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2461 if ( lutil_str2bin( &val, &itmp, ctx )) {
2462 return LDAP_INVALID_SYNTAX;
2465 /* Omit leading sign byte */
2466 if ( itmp.bv_val[0] == neg ) {
2471 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2473 assert( chop == 0 );
2474 memset( key->bv_val, neg, k ); /* sign-extend */
2475 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2476 lenp = lenbuf + sizeof(lenbuf);
2477 chop = - (ber_len_t) k;
2479 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2481 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2482 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2483 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2484 k = (lenbuf + sizeof(lenbuf)) - lenp;
2485 if ( k > (ber_slen_t) index_intlen )
2487 memcpy( key->bv_val, lenp, k );
2488 itmp.bv_len = index_intlen - k;
2490 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2491 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2495 /* Index generation function */
2502 struct berval *prefix,
2512 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2514 /* count the values and find max needed length */
2516 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2517 if ( vlen < values[i].bv_len )
2518 vlen = values[i].bv_len;
2520 if ( vlen > maxstrlen )
2523 /* we should have at least one value at this point */
2526 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2527 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2528 keys[i].bv_len = index_intlen;
2529 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2532 keys[i].bv_val = NULL;
2534 if ( vlen > sizeof(ibuf) ) {
2535 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2539 itmp.bv_len = sizeof(ibuf);
2541 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2542 if ( itmp.bv_val != ibuf ) {
2543 itmp.bv_len = values[i].bv_len;
2544 if ( itmp.bv_len <= sizeof(ibuf) )
2545 itmp.bv_len = sizeof(ibuf);
2546 else if ( itmp.bv_len > maxstrlen )
2547 itmp.bv_len = maxstrlen;
2549 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2555 if ( itmp.bv_val != ibuf ) {
2556 slap_sl_free( itmp.bv_val, ctx );
2561 /* Index generation function */
2568 struct berval *prefix,
2569 void * assertedValue,
2576 struct berval *value;
2579 value = (struct berval *) assertedValue;
2581 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2583 keys[0].bv_len = index_intlen;
2584 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2586 keys[1].bv_val = NULL;
2588 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2589 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2590 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2591 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2594 iv.bv_len = sizeof(ibuf);
2597 rc = integerVal2Key( value, keys, &iv, ctx );
2601 if ( iv.bv_val != ibuf ) {
2602 slap_sl_free( iv.bv_val, ctx );
2608 countryStringValidate(
2610 struct berval *val )
2612 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2614 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2615 return LDAP_INVALID_SYNTAX;
2617 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2618 return LDAP_INVALID_SYNTAX;
2621 return LDAP_SUCCESS;
2625 printableStringValidate(
2627 struct berval *val )
2631 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2633 for(i=0; i < val->bv_len; i++) {
2634 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2635 return LDAP_INVALID_SYNTAX;
2639 return LDAP_SUCCESS;
2643 printablesStringValidate(
2645 struct berval *val )
2649 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2651 for(i=0,len=0; i < val->bv_len; i++) {
2652 int c = val->bv_val[i];
2656 return LDAP_INVALID_SYNTAX;
2660 } else if ( SLAP_PRINTABLE(c) ) {
2663 return LDAP_INVALID_SYNTAX;
2668 return LDAP_INVALID_SYNTAX;
2671 return LDAP_SUCCESS;
2677 struct berval *val )
2681 for(i=0; i < val->bv_len; i++) {
2682 if( !LDAP_ASCII(val->bv_val[i]) ) {
2683 return LDAP_INVALID_SYNTAX;
2687 return LDAP_SUCCESS;
2696 struct berval *normalized,
2700 int casefold = !SLAP_MR_ASSOCIATED( mr,
2701 slap_schema.si_mr_caseExactIA5Match );
2703 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2707 /* Ignore initial whitespace */
2708 while ( ASCII_SPACE( *p ) ) p++;
2710 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2711 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2712 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2713 normalized->bv_val[normalized->bv_len] = '\0';
2715 p = q = normalized->bv_val;
2718 if ( ASCII_SPACE( *p ) ) {
2721 /* Ignore the extra whitespace */
2722 while ( ASCII_SPACE( *p ) ) {
2726 } else if ( casefold ) {
2727 /* Most IA5 rules require casefolding */
2728 *q++ = TOLOWER(*p); p++;
2735 assert( normalized->bv_val <= p );
2739 * If the string ended in space, backup the pointer one
2740 * position. One is enough because the above loop collapsed
2741 * all whitespace to a single space.
2743 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2745 /* null terminate */
2748 normalized->bv_len = q - normalized->bv_val;
2750 return LDAP_SUCCESS;
2759 if( in->bv_len != 36 ) {
2760 return LDAP_INVALID_SYNTAX;
2763 for( i=0; i<36; i++ ) {
2769 if( in->bv_val[i] != '-' ) {
2770 return LDAP_INVALID_SYNTAX;
2774 if( !ASCII_HEX( in->bv_val[i]) ) {
2775 return LDAP_INVALID_SYNTAX;
2780 return LDAP_SUCCESS;
2791 int rc=LDAP_INVALID_SYNTAX;
2793 assert( in != NULL );
2794 assert( out != NULL );
2796 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2799 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2801 for( i=0; i<36; i++ ) {
2807 if( in->bv_val[i] != '-' ) {
2810 out->bv_val[i] = '-';
2814 if( !ASCII_HEX( in->bv_val[i]) ) {
2817 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2822 out->bv_val[ out->bv_len ] = '\0';
2826 slap_sl_free( out->bv_val, ctx );
2839 struct berval *normalized,
2842 unsigned char octet = '\0';
2846 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2847 /* NOTE: must be a normalized UUID */
2848 assert( val->bv_len == 16 );
2850 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2851 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2852 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2853 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2855 return LDAP_SUCCESS;
2858 normalized->bv_len = 16;
2859 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2861 for( i=0, j=0; i<36; i++ ) {
2862 unsigned char nibble;
2863 if( val->bv_val[i] == '-' ) {
2866 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2867 nibble = val->bv_val[i] - '0';
2869 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2870 nibble = val->bv_val[i] - ('a'-10);
2872 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2873 nibble = val->bv_val[i] - ('A'-10);
2876 slap_sl_free( normalized->bv_val, ctx );
2877 BER_BVZERO( normalized );
2878 return LDAP_INVALID_SYNTAX;
2883 normalized->bv_val[j>>1] = octet;
2885 octet = nibble << 4;
2890 normalized->bv_val[normalized->bv_len] = 0;
2891 return LDAP_SUCCESS;
2897 numericStringValidate(
2903 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2905 for(i=0; i < in->bv_len; i++) {
2906 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2907 return LDAP_INVALID_SYNTAX;
2911 return LDAP_SUCCESS;
2915 numericStringNormalize(
2920 struct berval *normalized,
2923 /* removal all spaces */
2926 assert( !BER_BVISEMPTY( val ) );
2928 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2931 q = normalized->bv_val;
2934 if ( ASCII_SPACE( *p ) ) {
2935 /* Ignore whitespace */
2942 /* we should have copied no more than is in val */
2943 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2945 /* null terminate */
2948 normalized->bv_len = q - normalized->bv_val;
2950 if( BER_BVISEMPTY( normalized ) ) {
2951 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2952 normalized->bv_val[0] = ' ';
2953 normalized->bv_val[1] = '\0';
2954 normalized->bv_len = 1;
2957 return LDAP_SUCCESS;
2961 * Integer conversion macros that will use the largest available
2964 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2965 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2966 # define SLAP_LONG long long
2968 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2969 # define SLAP_LONG long
2970 #endif /* HAVE_STRTOLL ... */
2978 struct berval *value,
2979 void *assertedValue )
2981 SLAP_LONG lValue, lAssertedValue;
2984 /* safe to assume integers are NUL terminated? */
2985 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2986 if( errno == ERANGE )
2988 return LDAP_CONSTRAINT_VIOLATION;
2991 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2993 if( errno == ERANGE )
2995 return LDAP_CONSTRAINT_VIOLATION;
2998 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2999 return LDAP_SUCCESS;
3008 struct berval *value,
3009 void *assertedValue )
3011 SLAP_LONG lValue, lAssertedValue;
3014 /* safe to assume integers are NUL terminated? */
3015 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3016 if( errno == ERANGE )
3018 return LDAP_CONSTRAINT_VIOLATION;
3021 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3023 if( errno == ERANGE )
3025 return LDAP_CONSTRAINT_VIOLATION;
3028 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3029 return LDAP_SUCCESS;
3033 checkNum( struct berval *in, struct berval *out )
3035 /* parse serialNumber */
3036 ber_len_t neg = 0, extra = 0;
3039 out->bv_val = in->bv_val;
3042 if ( out->bv_val[0] == '-' ) {
3047 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3048 first = out->bv_val[2];
3051 out->bv_len += STRLENOF("0x");
3052 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3053 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3056 } else if ( out->bv_val[0] == '\'' ) {
3057 first = out->bv_val[1];
3060 out->bv_len += STRLENOF("'");
3062 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3063 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3065 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3068 out->bv_len += STRLENOF("'H");
3071 first = out->bv_val[0];
3072 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3073 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3077 if ( !( out->bv_len > neg ) ) {
3081 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3089 serialNumberAndIssuerCheck(
3097 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3099 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3100 /* Parse old format */
3101 is->bv_val = ber_bvchr( in, '$' );
3102 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3104 sn->bv_val = in->bv_val;
3105 sn->bv_len = is->bv_val - in->bv_val;
3108 is->bv_len = in->bv_len - (sn->bv_len + 1);
3110 /* eat leading zeros */
3111 for( n=0; n < (sn->bv_len-1); n++ ) {
3112 if( sn->bv_val[n] != '0' ) break;
3117 for( n=0; n < sn->bv_len; n++ ) {
3118 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3122 /* Parse GSER format */
3127 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3131 struct berval x = *in;
3137 /* eat leading spaces */
3138 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3142 /* should be at issuer or serialNumber NamedValue */
3143 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3144 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3147 x.bv_val += STRLENOF("issuer");
3148 x.bv_len -= STRLENOF("issuer");
3150 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3154 /* eat leading spaces */
3155 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3159 /* For backward compatibility, this part is optional */
3160 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3161 x.bv_val += STRLENOF("rdnSequence:");
3162 x.bv_len -= STRLENOF("rdnSequence:");
3165 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3169 is->bv_val = x.bv_val;
3172 for ( ; is->bv_len < x.bv_len; ) {
3173 if ( is->bv_val[is->bv_len] != '"' ) {
3177 if ( is->bv_val[is->bv_len+1] == '"' ) {
3184 x.bv_val += is->bv_len + 1;
3185 x.bv_len -= is->bv_len + 1;
3187 have |= HAVE_ISSUER;
3189 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3191 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3193 /* parse serialNumber */
3194 x.bv_val += STRLENOF("serialNumber");
3195 x.bv_len -= STRLENOF("serialNumber");
3197 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3201 /* eat leading spaces */
3202 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3206 if ( checkNum( &x, sn ) ) {
3207 return LDAP_INVALID_SYNTAX;
3210 x.bv_val += sn->bv_len;
3211 x.bv_len -= sn->bv_len;
3216 return LDAP_INVALID_SYNTAX;
3219 /* eat leading spaces */
3220 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3224 if ( have == HAVE_ALL ) {
3228 if ( x.bv_val[0] != ',' ) {
3229 return LDAP_INVALID_SYNTAX;
3236 /* should have no characters left... */
3237 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3239 if ( numdquotes == 0 ) {
3240 ber_dupbv_x( &ni, is, ctx );
3245 ni.bv_len = is->bv_len - numdquotes;
3246 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3247 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3248 if ( is->bv_val[src] == '"' ) {
3251 ni.bv_val[dst] = is->bv_val[src];
3253 ni.bv_val[dst] = '\0';
3263 serialNumberAndIssuerValidate(
3268 struct berval sn, i;
3270 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3273 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3278 /* validate DN -- doesn't handle double dquote */
3279 rc = dnValidate( NULL, &i );
3281 rc = LDAP_INVALID_SYNTAX;
3284 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3285 slap_sl_free( i.bv_val, NULL );
3288 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3289 in->bv_val, rc, 0 );
3296 serialNumberAndIssuerPretty(
3303 struct berval sn, i, ni = BER_BVNULL;
3306 assert( in != NULL );
3307 assert( out != NULL );
3311 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3314 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3319 rc = dnPretty( syntax, &i, &ni, ctx );
3321 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3322 slap_sl_free( i.bv_val, ctx );
3326 rc = LDAP_INVALID_SYNTAX;
3330 /* make room from sn + "$" */
3331 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3332 + sn.bv_len + ni.bv_len;
3333 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3335 if ( out->bv_val == NULL ) {
3342 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3343 p = lutil_strbvcopy( p, &sn );
3344 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3345 p = lutil_strbvcopy( p, &ni );
3346 p = lutil_strcopy( p, /*{*/ "\" }" );
3348 assert( p == &out->bv_val[out->bv_len] );
3351 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3352 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3354 slap_sl_free( ni.bv_val, ctx );
3356 return LDAP_SUCCESS;
3366 /* Use hex format. '123456789abcdef'H */
3367 unsigned char *ptr, zero = '\0';
3370 ber_len_t i, len, nlen;
3372 assert( in != NULL );
3373 assert( !BER_BVISNULL( in ) );
3374 assert( out != NULL );
3375 assert( !BER_BVISNULL( out ) );
3377 ptr = (unsigned char *)in->bv_val;
3380 /* Check for minimal encodings */
3382 if ( ptr[0] & 0x80 ) {
3383 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3387 } else if ( ptr[0] == 0 ) {
3388 if ( !( ptr[1] & 0x80 ) ) {
3395 } else if ( len == 0 ) {
3396 /* FIXME: this should not be possible,
3397 * since a value of zero would have length 1 */
3402 first = !( ptr[0] & 0xf0U );
3403 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3404 if ( nlen >= out->bv_len ) {
3405 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3411 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3415 for ( ; i < len; i++ ) {
3416 sprintf( sptr, "%02X", ptr[i] );
3423 assert( sptr == &out->bv_val[nlen] );
3430 #define SLAP_SN_BUFLEN (64)
3433 * This routine is called by certificateExactNormalize when
3434 * certificateExactNormalize receives a search string instead of
3435 * a certificate. This routine checks if the search value is valid
3436 * and then returns the normalized value
3439 serialNumberAndIssuerNormalize(
3447 struct berval sn, sn2, sn3, i, ni;
3448 char sbuf2[SLAP_SN_BUFLEN];
3449 char sbuf3[SLAP_SN_BUFLEN];
3453 assert( in != NULL );
3454 assert( out != NULL );
3456 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3459 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3464 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3466 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3467 slap_sl_free( i.bv_val, ctx );
3471 return LDAP_INVALID_SYNTAX;
3474 /* Convert sn to canonical hex */
3476 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3477 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3479 sn2.bv_len = sn.bv_len;
3480 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3481 rc = LDAP_INVALID_SYNTAX;
3486 sn3.bv_len = sizeof(sbuf3);
3487 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3488 rc = LDAP_INVALID_SYNTAX;
3492 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3493 + sn3.bv_len + ni.bv_len;
3494 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3496 if ( out->bv_val == NULL ) {
3504 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3505 p = lutil_strbvcopy( p, &sn3 );
3506 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3507 p = lutil_strbvcopy( p, &ni );
3508 p = lutil_strcopy( p, /*{*/ "\" }" );
3510 assert( p == &out->bv_val[out->bv_len] );
3513 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3514 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3516 if ( sn2.bv_val != sbuf2 ) {
3517 slap_sl_free( sn2.bv_val, ctx );
3520 if ( sn3.bv_val != sbuf3 ) {
3521 slap_sl_free( sn3.bv_val, ctx );
3524 slap_sl_free( ni.bv_val, ctx );
3530 certificateExactNormalize(
3535 struct berval *normalized,
3538 BerElementBuffer berbuf;
3539 BerElement *ber = (BerElement *)&berbuf;
3543 char serialbuf2[SLAP_SN_BUFLEN];
3544 struct berval sn, sn2 = BER_BVNULL;
3545 struct berval issuer_dn = BER_BVNULL, bvdn;
3547 int rc = LDAP_INVALID_SYNTAX;
3549 assert( val != NULL );
3551 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3552 val->bv_val, val->bv_len, 0 );
3554 if ( BER_BVISEMPTY( val ) ) goto done;
3556 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3557 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3560 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3562 ber_init2( ber, val, LBER_USE_DER );
3563 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3564 tag = ber_skip_tag( ber, &len ); /* Sequence */
3565 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3566 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3567 tag = ber_skip_tag( ber, &len );
3568 tag = ber_get_int( ber, &i ); /* version */
3571 /* NOTE: move the test here from certificateValidate,
3572 * so that we can validate certs with serial longer
3573 * than sizeof(ber_int_t) */
3574 tag = ber_skip_tag( ber, &len ); /* serial */
3576 sn.bv_val = (char *)ber->ber_ptr;
3577 sn2.bv_val = serialbuf2;
3578 sn2.bv_len = sizeof(serialbuf2);
3579 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3580 rc = LDAP_INVALID_SYNTAX;
3583 ber_skip_data( ber, len );
3585 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3586 ber_skip_data( ber, len );
3587 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3588 len = ber_ptrlen( ber );
3589 bvdn.bv_val = val->bv_val + len;
3590 bvdn.bv_len = val->bv_len - len;
3592 rc = dnX509normalize( &bvdn, &issuer_dn );
3593 if ( rc != LDAP_SUCCESS ) goto done;
3595 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3596 + sn2.bv_len + issuer_dn.bv_len;
3597 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3599 p = normalized->bv_val;
3601 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3602 p = lutil_strbvcopy( p, &sn2 );
3603 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3604 p = lutil_strbvcopy( p, &issuer_dn );
3605 p = lutil_strcopy( p, /*{*/ "\" }" );
3610 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3611 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3613 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3614 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3619 /* X.509 PKI certificateList stuff */
3621 checkTime( struct berval *in, struct berval *out )
3625 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3628 assert( in != NULL );
3629 assert( !BER_BVISNULL( in ) );
3630 assert( !BER_BVISEMPTY( in ) );
3632 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3636 if ( out != NULL ) {
3637 assert( !BER_BVISNULL( out ) );
3638 assert( out->bv_len >= sizeof( buf ) );
3639 bv.bv_val = out->bv_val;
3645 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3646 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3649 if ( in->bv_val[i] != 'Z' ) {
3654 if ( i != in->bv_len ) {
3658 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3659 lutil_strncopy( bv.bv_val, in->bv_val, i );
3662 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3663 char *p = bv.bv_val;
3664 if ( in->bv_val[0] < '7' ) {
3665 p = lutil_strcopy( p, "20" );
3668 p = lutil_strcopy( p, "19" );
3670 lutil_strncopy( p, in->bv_val, i );
3677 rc = generalizedTimeValidate( NULL, &bv );
3678 if ( rc == LDAP_SUCCESS && out != NULL ) {
3679 if ( out->bv_len > bv.bv_len ) {
3680 out->bv_val[ bv.bv_len ] = '\0';
3682 out->bv_len = bv.bv_len;
3685 return rc != LDAP_SUCCESS;
3689 issuerAndThisUpdateCheck(
3696 struct berval x = *in;
3697 struct berval ni = BER_BVNULL;
3698 /* Parse GSER format */
3702 HAVE_THISUPDATE = 0x2,
3703 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3707 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3709 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3710 return LDAP_INVALID_SYNTAX;
3714 x.bv_len -= STRLENOF("{}");
3717 /* eat leading spaces */
3718 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3722 /* should be at issuer or thisUpdate */
3723 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3724 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3727 x.bv_val += STRLENOF("issuer");
3728 x.bv_len -= STRLENOF("issuer");
3730 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3734 /* eat leading spaces */
3735 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3739 /* For backward compatibility, this part is optional */
3740 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3741 return LDAP_INVALID_SYNTAX;
3743 x.bv_val += STRLENOF("rdnSequence:");
3744 x.bv_len -= STRLENOF("rdnSequence:");
3746 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3750 is->bv_val = x.bv_val;
3753 for ( ; is->bv_len < x.bv_len; ) {
3754 if ( is->bv_val[is->bv_len] != '"' ) {
3758 if ( is->bv_val[is->bv_len+1] == '"' ) {
3765 x.bv_val += is->bv_len + 1;
3766 x.bv_len -= is->bv_len + 1;
3768 have |= HAVE_ISSUER;
3770 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3772 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3774 /* parse thisUpdate */
3775 x.bv_val += STRLENOF("thisUpdate");
3776 x.bv_len -= STRLENOF("thisUpdate");
3778 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3782 /* eat leading spaces */
3783 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3787 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3791 tu->bv_val = x.bv_val;
3794 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3795 if ( tu->bv_val[tu->bv_len] == '"' ) {
3799 x.bv_val += tu->bv_len + 1;
3800 x.bv_len -= tu->bv_len + 1;
3802 have |= HAVE_THISUPDATE;
3805 return LDAP_INVALID_SYNTAX;
3808 /* eat leading spaces */
3809 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3813 if ( have == HAVE_ALL ) {
3817 if ( x.bv_val[0] != ',' ) {
3818 return LDAP_INVALID_SYNTAX;
3825 /* should have no characters left... */
3826 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3828 if ( numdquotes == 0 ) {
3829 ber_dupbv_x( &ni, is, ctx );
3834 ni.bv_len = is->bv_len - numdquotes;
3835 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3836 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3837 if ( is->bv_val[src] == '"' ) {
3840 ni.bv_val[dst] = is->bv_val[src];
3842 ni.bv_val[dst] = '\0';
3851 issuerAndThisUpdateValidate(
3856 struct berval i, tu;
3858 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3861 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3866 /* validate DN -- doesn't handle double dquote */
3867 rc = dnValidate( NULL, &i );
3869 rc = LDAP_INVALID_SYNTAX;
3871 } else if ( checkTime( &tu, NULL ) ) {
3872 rc = LDAP_INVALID_SYNTAX;
3875 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3876 slap_sl_free( i.bv_val, NULL );
3879 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3880 in->bv_val, rc, 0 );
3887 issuerAndThisUpdatePretty(
3894 struct berval i, tu, ni = BER_BVNULL;
3897 assert( in != NULL );
3898 assert( out != NULL );
3902 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3905 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3910 rc = dnPretty( syntax, &i, &ni, ctx );
3912 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3913 slap_sl_free( i.bv_val, ctx );
3916 if ( rc || checkTime( &tu, NULL ) ) {
3917 rc = LDAP_INVALID_SYNTAX;
3922 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3923 + ni.bv_len + tu.bv_len;
3924 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3926 if ( out->bv_val == NULL ) {
3933 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3934 p = lutil_strbvcopy( p, &ni );
3935 p = lutil_strcopy( p, "\", thisUpdate \"" );
3936 p = lutil_strbvcopy( p, &tu );
3937 p = lutil_strcopy( p, /*{*/ "\" }" );
3939 assert( p == &out->bv_val[out->bv_len] );
3942 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3943 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3945 slap_sl_free( ni.bv_val, ctx );
3951 issuerAndThisUpdateNormalize(
3959 struct berval i, ni, tu, tu2;
3960 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3964 assert( in != NULL );
3965 assert( out != NULL );
3967 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3970 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3975 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3977 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3978 slap_sl_free( i.bv_val, ctx );
3982 tu2.bv_len = sizeof( sbuf );
3983 if ( rc || checkTime( &tu, &tu2 ) ) {
3984 return LDAP_INVALID_SYNTAX;
3987 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3988 + ni.bv_len + tu2.bv_len;
3989 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3991 if ( out->bv_val == NULL ) {
3999 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4000 p = lutil_strbvcopy( p, &ni );
4001 p = lutil_strcopy( p, "\", thisUpdate \"" );
4002 p = lutil_strbvcopy( p, &tu2 );
4003 p = lutil_strcopy( p, /*{*/ "\" }" );
4005 assert( p == &out->bv_val[out->bv_len] );
4008 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4009 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4011 slap_sl_free( ni.bv_val, ctx );
4017 certificateListExactNormalize(
4022 struct berval *normalized,
4025 BerElementBuffer berbuf;
4026 BerElement *ber = (BerElement *)&berbuf;
4030 struct berval issuer_dn = BER_BVNULL, bvdn,
4032 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4033 int rc = LDAP_INVALID_SYNTAX;
4035 assert( val != NULL );
4037 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4038 val->bv_val, val->bv_len, 0 );
4040 if ( BER_BVISEMPTY( val ) ) goto done;
4042 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4043 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4046 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4048 ber_init2( ber, val, LBER_USE_DER );
4049 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4050 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4051 tag = ber_skip_tag( ber, &len ); /* Sequence */
4052 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4053 tag = ber_peek_tag( ber, &len );
4054 /* Optional version */
4055 if ( tag == LBER_INTEGER ) {
4056 tag = ber_get_int( ber, &version );
4057 assert( tag == LBER_INTEGER );
4058 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4060 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4061 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4062 ber_skip_data( ber, len );
4064 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4065 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4066 len = ber_ptrlen( ber );
4067 bvdn.bv_val = val->bv_val + len;
4068 bvdn.bv_len = val->bv_len - len;
4069 tag = ber_skip_tag( ber, &len );
4070 ber_skip_data( ber, len );
4072 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4073 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4074 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4075 bvtu.bv_val = (char *)ber->ber_ptr;
4078 rc = dnX509normalize( &bvdn, &issuer_dn );
4079 if ( rc != LDAP_SUCCESS ) goto done;
4081 thisUpdate.bv_val = tubuf;
4082 thisUpdate.bv_len = sizeof(tubuf);
4083 if ( checkTime( &bvtu, &thisUpdate ) ) {
4084 rc = LDAP_INVALID_SYNTAX;
4088 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4089 + issuer_dn.bv_len + thisUpdate.bv_len;
4090 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4092 p = normalized->bv_val;
4094 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4095 p = lutil_strbvcopy( p, &issuer_dn );
4096 p = lutil_strcopy( p, "\", thisUpdate \"" );
4097 p = lutil_strbvcopy( p, &thisUpdate );
4098 p = lutil_strcopy( p, /*{*/ "\" }" );
4103 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4104 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4106 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4111 /* X.509 PMI serialNumberAndIssuerSerialCheck
4113 AttributeCertificateExactAssertion ::= SEQUENCE {
4114 serialNumber CertificateSerialNumber,
4115 issuer AttCertIssuer }
4117 CertificateSerialNumber ::= INTEGER
4119 AttCertIssuer ::= [0] SEQUENCE {
4120 issuerName GeneralNames OPTIONAL,
4121 baseCertificateID [0] IssuerSerial OPTIONAL,
4122 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4123 -- At least one component shall be present
4125 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4127 GeneralName ::= CHOICE {
4128 otherName [0] INSTANCE OF OTHER-NAME,
4129 rfc822Name [1] IA5String,
4130 dNSName [2] IA5String,
4131 x400Address [3] ORAddress,
4132 directoryName [4] Name,
4133 ediPartyName [5] EDIPartyName,
4134 uniformResourceIdentifier [6] IA5String,
4135 iPAddress [7] OCTET STRING,
4136 registeredID [8] OBJECT IDENTIFIER }
4138 IssuerSerial ::= SEQUENCE {
4139 issuer GeneralNames,
4140 serial CertificateSerialNumber,
4141 issuerUID UniqueIdentifier OPTIONAL }
4143 ObjectDigestInfo ::= SEQUENCE {
4144 digestedObjectType ENUMERATED {
4147 otherObjectTypes (2) },
4148 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4149 digestAlgorithm AlgorithmIdentifier,
4150 objectDigest BIT STRING }
4152 * The way I interpret it, an assertion should look like
4154 { serialNumber 'dd'H,
4155 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4156 baseCertificateID { serial '1d'H,
4157 issuer { directoryName:rdnSequence:"cn=zzz" },
4158 issuerUID <value> -- optional
4160 objectDigestInfo { ... } -- optional
4164 * with issuerName, baseCertificateID and objectDigestInfo optional,
4165 * at least one present; the way it's currently implemented, it is
4167 { serialNumber 'dd'H,
4168 issuer { baseCertificateID { serial '1d'H,
4169 issuer { directoryName:rdnSequence:"cn=zzz" }
4174 * with all the above parts mandatory.
4177 serialNumberAndIssuerSerialCheck(
4181 struct berval *i_sn, /* contain serial of baseCertificateID */
4184 /* Parse GSER format */
4189 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4190 } have = HAVE_NONE, have2 = HAVE_NONE;
4192 struct berval x = *in;
4195 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4198 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4205 /* eat leading spaces */
4206 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4210 /* should be at issuer or serialNumber NamedValue */
4211 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4212 if ( have & HAVE_ISSUER ) {
4213 return LDAP_INVALID_SYNTAX;
4216 /* parse IssuerSerial */
4217 x.bv_val += STRLENOF("issuer");
4218 x.bv_len -= STRLENOF("issuer");
4220 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4224 /* eat leading spaces */
4225 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4229 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4233 /* eat leading spaces */
4234 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4238 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4239 return LDAP_INVALID_SYNTAX;
4241 x.bv_val += STRLENOF("baseCertificateID ");
4242 x.bv_len -= STRLENOF("baseCertificateID ");
4244 /* eat leading spaces */
4245 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4249 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4254 /* eat leading spaces */
4255 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4259 /* parse issuer of baseCertificateID */
4260 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4261 if ( have2 & HAVE_ISSUER ) {
4262 return LDAP_INVALID_SYNTAX;
4265 x.bv_val += STRLENOF("issuer ");
4266 x.bv_len -= STRLENOF("issuer ");
4268 /* eat leading spaces */
4269 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4273 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4277 /* eat leading spaces */
4278 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4282 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4283 return LDAP_INVALID_SYNTAX;
4285 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4286 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4288 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4292 is->bv_val = x.bv_val;
4295 for ( ; is->bv_len < x.bv_len; ) {
4296 if ( is->bv_val[is->bv_len] != '"' ) {
4300 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4307 x.bv_val += is->bv_len + 1;
4308 x.bv_len -= is->bv_len + 1;
4310 /* eat leading spaces */
4311 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4315 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4319 have2 |= HAVE_ISSUER;
4321 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4322 if ( have2 & HAVE_SN ) {
4323 return LDAP_INVALID_SYNTAX;
4326 x.bv_val += STRLENOF("serial ");
4327 x.bv_len -= STRLENOF("serial ");
4329 /* eat leading spaces */
4330 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4334 if ( checkNum( &x, i_sn ) ) {
4335 return LDAP_INVALID_SYNTAX;
4338 x.bv_val += i_sn->bv_len;
4339 x.bv_len -= i_sn->bv_len;
4344 return LDAP_INVALID_SYNTAX;
4347 /* eat leading spaces */
4348 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4352 if ( have2 == HAVE_ALL ) {
4356 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4361 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4365 /* eat leading spaces */
4366 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4370 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4374 have |= HAVE_ISSUER;
4376 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4377 if ( have & HAVE_SN ) {
4378 return LDAP_INVALID_SYNTAX;
4381 /* parse serialNumber */
4382 x.bv_val += STRLENOF("serialNumber");
4383 x.bv_len -= STRLENOF("serialNumber");
4385 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4389 /* eat leading spaces */
4390 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4394 if ( checkNum( &x, sn ) ) {
4395 return LDAP_INVALID_SYNTAX;
4398 x.bv_val += sn->bv_len;
4399 x.bv_len -= sn->bv_len;
4404 return LDAP_INVALID_SYNTAX;
4408 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4412 if ( have == HAVE_ALL ) {
4416 if ( x.bv_val[0] != ',' ) {
4417 return LDAP_INVALID_SYNTAX;
4423 /* should have no characters left... */
4424 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4426 if ( numdquotes == 0 ) {
4427 ber_dupbv_x( &ni, is, ctx );
4432 ni.bv_len = is->bv_len - numdquotes;
4433 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4434 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4435 if ( is->bv_val[src] == '"' ) {
4438 ni.bv_val[dst] = is->bv_val[src];
4440 ni.bv_val[dst] = '\0';
4445 /* need to handle double dquotes here */
4449 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4451 serialNumberAndIssuerSerialValidate(
4456 struct berval sn, i, i_sn;
4458 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4461 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4466 /* validate DN -- doesn't handle double dquote */
4467 rc = dnValidate( NULL, &i );
4469 rc = LDAP_INVALID_SYNTAX;
4472 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4473 slap_sl_free( i.bv_val, NULL );
4477 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4478 in->bv_val, rc, 0 );
4483 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4485 serialNumberAndIssuerSerialPretty(
4491 struct berval sn, i, i_sn, ni = BER_BVNULL;
4495 assert( in != NULL );
4496 assert( out != NULL );
4498 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4501 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4506 rc = dnPretty( syntax, &i, &ni, ctx );
4508 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4509 slap_sl_free( i.bv_val, ctx );
4513 rc = LDAP_INVALID_SYNTAX;
4517 /* make room from sn + "$" */
4518 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4519 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4520 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4522 if ( out->bv_val == NULL ) {
4529 p = lutil_strcopy( p, "{ serialNumber " );
4530 p = lutil_strbvcopy( p, &sn );
4531 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4532 p = lutil_strbvcopy( p, &ni );
4533 p = lutil_strcopy( p, "\" }, serial " );
4534 p = lutil_strbvcopy( p, &i_sn );
4535 p = lutil_strcopy( p, " } } }" );
4537 assert( p == &out->bv_val[out->bv_len] );
4540 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4541 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4543 slap_sl_free( ni.bv_val, ctx );
4548 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4550 * This routine is called by attributeCertificateExactNormalize
4551 * when attributeCertificateExactNormalize receives a search
4552 * string instead of a attribute certificate. This routine
4553 * checks if the search value is valid and then returns the
4557 serialNumberAndIssuerSerialNormalize(
4565 struct berval i, ni = BER_BVNULL,
4566 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4567 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4568 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4569 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4573 assert( in != NULL );
4574 assert( out != NULL );
4576 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4579 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4584 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4586 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4587 slap_sl_free( i.bv_val, ctx );
4591 rc = LDAP_INVALID_SYNTAX;
4595 /* Convert sn to canonical hex */
4597 sn2.bv_len = sn.bv_len;
4598 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4599 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4601 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4602 rc = LDAP_INVALID_SYNTAX;
4606 /* Convert i_sn to canonical hex */
4607 i_sn2.bv_val = i_sbuf2;
4608 i_sn2.bv_len = i_sn.bv_len;
4609 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4610 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4612 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4613 rc = LDAP_INVALID_SYNTAX;
4618 sn3.bv_len = sizeof(sbuf3);
4619 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4620 rc = LDAP_INVALID_SYNTAX;
4624 i_sn3.bv_val = i_sbuf3;
4625 i_sn3.bv_len = sizeof(i_sbuf3);
4626 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4627 rc = LDAP_INVALID_SYNTAX;
4631 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4632 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4633 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4635 if ( out->bv_val == NULL ) {
4643 p = lutil_strcopy( p, "{ serialNumber " );
4644 p = lutil_strbvcopy( p, &sn3 );
4645 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4646 p = lutil_strbvcopy( p, &ni );
4647 p = lutil_strcopy( p, "\" }, serial " );
4648 p = lutil_strbvcopy( p, &i_sn3 );
4649 p = lutil_strcopy( p, " } } }" );
4651 assert( p == &out->bv_val[out->bv_len] );
4654 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4655 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4657 if ( sn2.bv_val != sbuf2 ) {
4658 slap_sl_free( sn2.bv_val, ctx );
4661 if ( i_sn2.bv_val != i_sbuf2 ) {
4662 slap_sl_free( i_sn2.bv_val, ctx );
4665 if ( sn3.bv_val != sbuf3 ) {
4666 slap_sl_free( sn3.bv_val, ctx );
4669 if ( i_sn3.bv_val != i_sbuf3 ) {
4670 slap_sl_free( i_sn3.bv_val, ctx );
4673 slap_sl_free( ni.bv_val, ctx );
4678 /* X.509 PMI attributeCertificateExactNormalize */
4680 attributeCertificateExactNormalize(
4685 struct berval *normalized,
4688 BerElementBuffer berbuf;
4689 BerElement *ber = (BerElement *)&berbuf;
4692 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4693 struct berval sn, i_sn, sn2, i_sn2;
4694 struct berval issuer_dn = BER_BVNULL, bvdn;
4696 int rc = LDAP_INVALID_SYNTAX;
4698 if ( BER_BVISEMPTY( val ) ) {
4702 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4703 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4706 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4708 ber_init2( ber, val, LBER_USE_DER );
4709 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4710 tag = ber_skip_tag( ber, &len ); /* Sequence */
4711 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4712 ber_skip_data( ber, len );
4713 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4714 ber_skip_data( ber, len );
4717 tag = ber_skip_tag( ber, &len ); /* Sequence */
4718 /* issuerName (GeneralNames sequence; optional)? */
4719 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4720 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4721 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4722 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4723 rc = LDAP_INVALID_SYNTAX;
4726 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4727 len = ber_ptrlen( ber );
4728 bvdn.bv_val = val->bv_val + len;
4729 bvdn.bv_len = val->bv_len - len;
4730 rc = dnX509normalize( &bvdn, &issuer_dn );
4731 if ( rc != LDAP_SUCCESS ) goto done;
4733 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4734 ber_skip_data( ber, len );
4735 tag = ber_skip_tag( ber, &len ); /* serial number */
4736 if ( tag != LBER_INTEGER ) {
4737 rc = LDAP_INVALID_SYNTAX;
4740 i_sn.bv_val = (char *)ber->ber_ptr;
4742 i_sn2.bv_val = issuer_serialbuf;
4743 i_sn2.bv_len = sizeof(issuer_serialbuf);
4744 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4745 rc = LDAP_INVALID_SYNTAX;
4748 ber_skip_data( ber, len );
4750 /* issuerUID (bitstring; optional)? */
4751 /* objectDigestInfo (sequence; optional)? */
4753 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4754 ber_skip_data( ber, len );
4755 tag = ber_skip_tag( ber, &len ); /* serial number */
4756 if ( tag != LBER_INTEGER ) {
4757 rc = LDAP_INVALID_SYNTAX;
4760 sn.bv_val = (char *)ber->ber_ptr;
4762 sn2.bv_val = serialbuf;
4763 sn2.bv_len = sizeof(serialbuf);
4764 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4765 rc = LDAP_INVALID_SYNTAX;
4768 ber_skip_data( ber, len );
4770 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4771 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4772 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4774 p = normalized->bv_val;
4776 p = lutil_strcopy( p, "{ serialNumber " );
4777 p = lutil_strbvcopy( p, &sn2 );
4778 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4779 p = lutil_strbvcopy( p, &issuer_dn );
4780 p = lutil_strcopy( p, "\" }, serial " );
4781 p = lutil_strbvcopy( p, &i_sn2 );
4782 p = lutil_strcopy( p, " } } }" );
4784 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4785 normalized->bv_val, NULL, NULL );
4790 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4791 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4792 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4805 assert( in != NULL );
4806 assert( !BER_BVISNULL( in ) );
4808 for ( i = 0; i < in->bv_len; i++ ) {
4809 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4810 return LDAP_INVALID_SYNTAX;
4814 return LDAP_SUCCESS;
4817 /* Normalize a SID as used inside a CSN:
4818 * three-digit numeric string */
4825 struct berval *normalized,
4830 assert( val != NULL );
4831 assert( normalized != NULL );
4833 ber_dupbv_x( normalized, val, ctx );
4835 for ( i = 0; i < normalized->bv_len; i++ ) {
4836 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4837 ber_memfree_x( normalized->bv_val, ctx );
4838 BER_BVZERO( normalized );
4839 return LDAP_INVALID_SYNTAX;
4842 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4845 return LDAP_SUCCESS;
4853 assert( in != NULL );
4854 assert( !BER_BVISNULL( in ) );
4856 if ( in->bv_len != 3 ) {
4857 return LDAP_INVALID_SYNTAX;
4860 return hexValidate( NULL, in );
4863 /* Normalize a SID as used inside a CSN:
4864 * three-digit numeric string */
4871 struct berval *normalized,
4874 if ( val->bv_len != 3 ) {
4875 return LDAP_INVALID_SYNTAX;
4878 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4888 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4891 /* Normalize a SID as used inside a CSN, either as-is
4892 * (assertion value) or extracted from the CSN
4893 * (attribute value) */
4900 struct berval *normalized,
4908 if ( BER_BVISEMPTY( val ) ) {
4909 return LDAP_INVALID_SYNTAX;
4912 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4913 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4916 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4918 ptr = ber_bvchr( val, '#' );
4919 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4920 return LDAP_INVALID_SYNTAX;
4923 bv.bv_val = ptr + 1;
4924 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4926 ptr = ber_bvchr( &bv, '#' );
4927 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4928 return LDAP_INVALID_SYNTAX;
4931 bv.bv_val = ptr + 1;
4932 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4934 ptr = ber_bvchr( &bv, '#' );
4935 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4936 return LDAP_INVALID_SYNTAX;
4939 bv.bv_len = ptr - bv.bv_val;
4941 if ( bv.bv_len == 2 ) {
4942 /* OpenLDAP 2.3 SID */
4944 buf[ 1 ] = bv.bv_val[ 0 ];
4945 buf[ 2 ] = bv.bv_val[ 1 ];
4952 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4964 assert( in != NULL );
4965 assert( !BER_BVISNULL( in ) );
4967 if ( BER_BVISEMPTY( in ) ) {
4968 return LDAP_INVALID_SYNTAX;
4973 ptr = ber_bvchr( &bv, '#' );
4974 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4975 return LDAP_INVALID_SYNTAX;
4978 bv.bv_len = ptr - bv.bv_val;
4979 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4980 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4982 return LDAP_INVALID_SYNTAX;
4985 rc = generalizedTimeValidate( NULL, &bv );
4986 if ( rc != LDAP_SUCCESS ) {
4990 bv.bv_val = ptr + 1;
4991 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4993 ptr = ber_bvchr( &bv, '#' );
4994 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4995 return LDAP_INVALID_SYNTAX;
4998 bv.bv_len = ptr - bv.bv_val;
4999 if ( bv.bv_len != 6 ) {
5000 return LDAP_INVALID_SYNTAX;
5003 rc = hexValidate( NULL, &bv );
5004 if ( rc != LDAP_SUCCESS ) {
5008 bv.bv_val = ptr + 1;
5009 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5011 ptr = ber_bvchr( &bv, '#' );
5012 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5013 return LDAP_INVALID_SYNTAX;
5016 bv.bv_len = ptr - bv.bv_val;
5017 if ( bv.bv_len == 2 ) {
5018 /* tolerate old 2-digit replica-id */
5019 rc = hexValidate( NULL, &bv );
5022 rc = sidValidate( NULL, &bv );
5024 if ( rc != LDAP_SUCCESS ) {
5028 bv.bv_val = ptr + 1;
5029 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5031 if ( bv.bv_len != 6 ) {
5032 return LDAP_INVALID_SYNTAX;
5035 return hexValidate( NULL, &bv );
5038 /* Normalize a CSN in OpenLDAP 2.1 format */
5045 struct berval *normalized,
5048 struct berval gt, cnt, sid, mod;
5050 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5054 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5055 assert( !BER_BVISEMPTY( val ) );
5059 ptr = ber_bvchr( >, '#' );
5060 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5061 return LDAP_INVALID_SYNTAX;
5064 gt.bv_len = ptr - gt.bv_val;
5065 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5066 return LDAP_INVALID_SYNTAX;
5069 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5070 return LDAP_INVALID_SYNTAX;
5073 cnt.bv_val = ptr + 1;
5074 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5076 ptr = ber_bvchr( &cnt, '#' );
5077 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5078 return LDAP_INVALID_SYNTAX;
5081 cnt.bv_len = ptr - cnt.bv_val;
5082 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5083 return LDAP_INVALID_SYNTAX;
5086 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5087 return LDAP_INVALID_SYNTAX;
5090 cnt.bv_val += STRLENOF( "0x" );
5091 cnt.bv_len -= STRLENOF( "0x" );
5093 sid.bv_val = ptr + 1;
5094 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5096 ptr = ber_bvchr( &sid, '#' );
5097 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5098 return LDAP_INVALID_SYNTAX;
5101 sid.bv_len = ptr - sid.bv_val;
5102 if ( sid.bv_len != STRLENOF( "0" ) ) {
5103 return LDAP_INVALID_SYNTAX;
5106 mod.bv_val = ptr + 1;
5107 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5108 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5109 return LDAP_INVALID_SYNTAX;
5112 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5116 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5117 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5119 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5121 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5122 ptr = lutil_strbvcopy( ptr, &cnt );
5126 *ptr++ = sid.bv_val[ 0 ];
5130 for ( i = 0; i < mod.bv_len; i++ ) {
5131 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5135 assert( ptr == &bv.bv_val[bv.bv_len] );
5137 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5138 return LDAP_INVALID_SYNTAX;
5141 ber_dupbv_x( normalized, &bv, ctx );
5143 return LDAP_SUCCESS;
5146 /* Normalize a CSN in OpenLDAP 2.3 format */
5153 struct berval *normalized,
5156 struct berval gt, cnt, sid, mod;
5158 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5162 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5163 assert( !BER_BVISEMPTY( val ) );
5167 ptr = ber_bvchr( >, '#' );
5168 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5169 return LDAP_INVALID_SYNTAX;
5172 gt.bv_len = ptr - gt.bv_val;
5173 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5174 return LDAP_INVALID_SYNTAX;
5177 cnt.bv_val = ptr + 1;
5178 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5180 ptr = ber_bvchr( &cnt, '#' );
5181 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5182 return LDAP_INVALID_SYNTAX;
5185 cnt.bv_len = ptr - cnt.bv_val;
5186 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5187 return LDAP_INVALID_SYNTAX;
5190 sid.bv_val = ptr + 1;
5191 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5193 ptr = ber_bvchr( &sid, '#' );
5194 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5195 return LDAP_INVALID_SYNTAX;
5198 sid.bv_len = ptr - sid.bv_val;
5199 if ( sid.bv_len != STRLENOF( "00" ) ) {
5200 return LDAP_INVALID_SYNTAX;
5203 mod.bv_val = ptr + 1;
5204 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5205 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5206 return LDAP_INVALID_SYNTAX;
5209 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5213 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5214 ptr = lutil_strcopy( ptr, ".000000Z#" );
5215 ptr = lutil_strbvcopy( ptr, &cnt );
5218 for ( i = 0; i < sid.bv_len; i++ ) {
5219 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5222 for ( i = 0; i < mod.bv_len; i++ ) {
5223 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5227 assert( ptr == &bv.bv_val[bv.bv_len] );
5228 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5229 return LDAP_INVALID_SYNTAX;
5232 ber_dupbv_x( normalized, &bv, ctx );
5234 return LDAP_SUCCESS;
5237 /* Normalize a CSN */
5244 struct berval *normalized,
5247 struct berval cnt, sid, mod;
5251 assert( val != NULL );
5252 assert( normalized != NULL );
5254 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5256 if ( BER_BVISEMPTY( val ) ) {
5257 return LDAP_INVALID_SYNTAX;
5260 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5261 /* Openldap <= 2.3 */
5263 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5266 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5269 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5272 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5273 return LDAP_INVALID_SYNTAX;
5276 ptr = ber_bvchr( val, '#' );
5277 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5278 return LDAP_INVALID_SYNTAX;
5281 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5282 return LDAP_INVALID_SYNTAX;
5285 cnt.bv_val = ptr + 1;
5286 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5288 ptr = ber_bvchr( &cnt, '#' );
5289 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5290 return LDAP_INVALID_SYNTAX;
5293 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5294 return LDAP_INVALID_SYNTAX;
5297 sid.bv_val = ptr + 1;
5298 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5300 ptr = ber_bvchr( &sid, '#' );
5301 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5302 return LDAP_INVALID_SYNTAX;
5305 sid.bv_len = ptr - sid.bv_val;
5306 if ( sid.bv_len != STRLENOF( "000" ) ) {
5307 return LDAP_INVALID_SYNTAX;
5310 mod.bv_val = ptr + 1;
5311 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5313 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5314 return LDAP_INVALID_SYNTAX;
5317 ber_dupbv_x( normalized, val, ctx );
5319 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5320 i < normalized->bv_len; i++ )
5322 /* assume it's already validated that's all hex digits */
5323 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5326 return LDAP_SUCCESS;
5336 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5339 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5340 /* slight optimization - does not need the start parameter */
5341 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5346 check_time_syntax (struct berval *val,
5349 struct berval *fraction)
5352 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5353 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5354 * GeneralizedTime supports leap seconds, UTCTime does not.
5356 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5357 static const int mdays[2][12] = {
5358 /* non-leap years */
5359 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5361 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5364 int part, c, c1, c2, tzoffset, leapyear = 0;
5367 e = p + val->bv_len;
5369 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5370 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5372 for (part = start; part < 7 && p < e; part++) {
5374 if (!ASCII_DIGIT(c1)) {
5379 return LDAP_INVALID_SYNTAX;
5382 if (!ASCII_DIGIT(c)) {
5383 return LDAP_INVALID_SYNTAX;
5385 c += c1 * 10 - '0' * 11;
5386 if ((part | 1) == 3) {
5389 return LDAP_INVALID_SYNTAX;
5392 if (c >= ceiling[part]) {
5393 if (! (c == 60 && part == 6 && start == 0))
5394 return LDAP_INVALID_SYNTAX;
5398 if (part < 5 + start) {
5399 return LDAP_INVALID_SYNTAX;
5401 for (; part < 9; part++) {
5405 /* leapyear check for the Gregorian calendar (year>1581) */
5406 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5410 if (parts[3] >= mdays[leapyear][parts[2]]) {
5411 return LDAP_INVALID_SYNTAX;
5415 fraction->bv_val = p;
5416 fraction->bv_len = 0;
5417 if (p < e && (*p == '.' || *p == ',')) {
5419 while (++p < e && ASCII_DIGIT(*p)) {
5422 if (p - fraction->bv_val == 1) {
5423 return LDAP_INVALID_SYNTAX;
5425 for (end_num = p; end_num[-1] == '0'; --end_num) {
5428 c = end_num - fraction->bv_val;
5429 if (c != 1) fraction->bv_len = c;
5435 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5441 return LDAP_INVALID_SYNTAX;
5447 for (part = 7; part < 9 && p < e; part++) {
5449 if (!ASCII_DIGIT(c1)) {
5454 return LDAP_INVALID_SYNTAX;
5457 if (!ASCII_DIGIT(c2)) {
5458 return LDAP_INVALID_SYNTAX;
5460 parts[part] = c1 * 10 + c2 - '0' * 11;
5461 if (parts[part] >= ceiling[part]) {
5462 return LDAP_INVALID_SYNTAX;
5465 if (part < 8 + start) {
5466 return LDAP_INVALID_SYNTAX;
5469 if (tzoffset == '-') {
5470 /* negative offset to UTC, ie west of Greenwich */
5471 parts[4] += parts[7];
5472 parts[5] += parts[8];
5473 /* offset is just hhmm, no seconds */
5474 for (part = 6; --part >= 0; ) {
5478 c = mdays[leapyear][parts[2]];
5480 if (parts[part] >= c) {
5482 return LDAP_INVALID_SYNTAX;
5487 } else if (part != 5) {
5492 /* positive offset to UTC, ie east of Greenwich */
5493 parts[4] -= parts[7];
5494 parts[5] -= parts[8];
5495 for (part = 6; --part >= 0; ) {
5496 if (parts[part] < 0) {
5498 return LDAP_INVALID_SYNTAX;
5503 /* make first arg to % non-negative */
5504 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5509 } else if (part != 5) {
5516 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5519 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5526 struct berval *normalized )
5530 rc = check_time_syntax(val, 1, parts, NULL);
5531 if (rc != LDAP_SUCCESS) {
5535 normalized->bv_val = ch_malloc( 14 );
5536 if ( normalized->bv_val == NULL ) {
5537 return LBER_ERROR_MEMORY;
5540 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5541 parts[1], parts[2] + 1, parts[3] + 1,
5542 parts[4], parts[5], parts[6] );
5543 normalized->bv_len = 13;
5545 return LDAP_SUCCESS;
5555 return check_time_syntax(in, 1, parts, NULL);
5558 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5561 generalizedTimeValidate(
5566 struct berval fraction;
5567 return check_time_syntax(in, 0, parts, &fraction);
5571 generalizedTimeNormalize(
5576 struct berval *normalized,
5581 struct berval fraction;
5583 rc = check_time_syntax(val, 0, parts, &fraction);
5584 if (rc != LDAP_SUCCESS) {
5588 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5589 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5590 if ( BER_BVISNULL( normalized ) ) {
5591 return LBER_ERROR_MEMORY;
5594 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5595 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5596 parts[4], parts[5], parts[6] );
5597 if ( !BER_BVISEMPTY( &fraction ) ) {
5598 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5599 fraction.bv_val, fraction.bv_len );
5600 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5602 strcpy( normalized->bv_val + len-1, "Z" );
5603 normalized->bv_len = len;
5605 return LDAP_SUCCESS;
5609 generalizedTimeOrderingMatch(
5614 struct berval *value,
5615 void *assertedValue )
5617 struct berval *asserted = (struct berval *) assertedValue;
5618 ber_len_t v_len = value->bv_len;
5619 ber_len_t av_len = asserted->bv_len;
5621 /* ignore trailing 'Z' when comparing */
5622 int match = memcmp( value->bv_val, asserted->bv_val,
5623 (v_len < av_len ? v_len : av_len) - 1 );
5624 if ( match == 0 ) match = v_len - av_len;
5626 if ( flags & SLAP_MR_EXT )
5627 match = (match >= 0);
5630 return LDAP_SUCCESS;
5633 /* Index generation function */
5634 int generalizedTimeIndexer(
5639 struct berval *prefix,
5647 BerValue bvtmp; /* 40 bit index */
5649 struct lutil_timet tt;
5651 bvtmp.bv_len = sizeof(tmp);
5653 for( i=0; values[i].bv_val != NULL; i++ ) {
5654 /* just count them */
5657 /* we should have at least one value at this point */
5660 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5662 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5663 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5664 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5665 /* Use 40 bits of time for key */
5666 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5667 lutil_tm2time( &tm, &tt );
5668 tmp[0] = tt.tt_gsec & 0xff;
5669 tmp[4] = tt.tt_sec & 0xff;
5671 tmp[3] = tt.tt_sec & 0xff;
5673 tmp[2] = tt.tt_sec & 0xff;
5675 tmp[1] = tt.tt_sec & 0xff;
5677 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5681 keys[j].bv_val = NULL;
5686 return LDAP_SUCCESS;
5689 /* Index generation function */
5690 int generalizedTimeFilter(
5695 struct berval *prefix,
5696 void * assertedValue,
5702 BerValue bvtmp; /* 40 bit index */
5703 BerValue *value = (BerValue *) assertedValue;
5705 struct lutil_timet tt;
5707 bvtmp.bv_len = sizeof(tmp);
5709 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5710 /* Use 40 bits of time for key */
5711 if ( value->bv_val && value->bv_len >= 10 &&
5712 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5714 lutil_tm2time( &tm, &tt );
5715 tmp[0] = tt.tt_gsec & 0xff;
5716 tmp[4] = tt.tt_sec & 0xff;
5718 tmp[3] = tt.tt_sec & 0xff;
5720 tmp[2] = tt.tt_sec & 0xff;
5722 tmp[1] = tt.tt_sec & 0xff;
5724 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5725 ber_dupbv_x(keys, &bvtmp, ctx );
5726 keys[1].bv_val = NULL;
5734 return LDAP_SUCCESS;
5738 deliveryMethodValidate(
5740 struct berval *val )
5743 #define LENOF(s) (sizeof(s)-1)
5744 struct berval tmp = *val;
5746 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5747 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5748 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5751 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5753 switch( tmp.bv_val[0] ) {
5756 if(( tmp.bv_len >= LENOF("any") ) &&
5757 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5759 tmp.bv_len -= LENOF("any");
5760 tmp.bv_val += LENOF("any");
5763 return LDAP_INVALID_SYNTAX;
5767 if(( tmp.bv_len >= LENOF("mhs") ) &&
5768 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5770 tmp.bv_len -= LENOF("mhs");
5771 tmp.bv_val += LENOF("mhs");
5774 return LDAP_INVALID_SYNTAX;
5778 if(( tmp.bv_len >= LENOF("physical") ) &&
5779 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5781 tmp.bv_len -= LENOF("physical");
5782 tmp.bv_val += LENOF("physical");
5785 return LDAP_INVALID_SYNTAX;
5788 case 'T': /* telex or teletex or telephone */
5789 if(( tmp.bv_len >= LENOF("telex") ) &&
5790 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5792 tmp.bv_len -= LENOF("telex");
5793 tmp.bv_val += LENOF("telex");
5796 if(( tmp.bv_len >= LENOF("teletex") ) &&
5797 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5799 tmp.bv_len -= LENOF("teletex");
5800 tmp.bv_val += LENOF("teletex");
5803 if(( tmp.bv_len >= LENOF("telephone") ) &&
5804 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5806 tmp.bv_len -= LENOF("telephone");
5807 tmp.bv_val += LENOF("telephone");
5810 return LDAP_INVALID_SYNTAX;
5813 case 'G': /* g3fax or g4fax */
5814 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5815 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5816 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5818 tmp.bv_len -= LENOF("g3fax");
5819 tmp.bv_val += LENOF("g3fax");
5822 return LDAP_INVALID_SYNTAX;
5826 if(( tmp.bv_len >= LENOF("ia5") ) &&
5827 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5829 tmp.bv_len -= LENOF("ia5");
5830 tmp.bv_val += LENOF("ia5");
5833 return LDAP_INVALID_SYNTAX;
5837 if(( tmp.bv_len >= LENOF("videotex") ) &&
5838 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5840 tmp.bv_len -= LENOF("videotex");
5841 tmp.bv_val += LENOF("videotex");
5844 return LDAP_INVALID_SYNTAX;
5847 return LDAP_INVALID_SYNTAX;
5850 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5852 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5856 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5860 return LDAP_INVALID_SYNTAX;
5862 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5871 nisNetgroupTripleValidate(
5873 struct berval *val )
5878 if ( BER_BVISEMPTY( val ) ) {
5879 return LDAP_INVALID_SYNTAX;
5882 p = (char *)val->bv_val;
5883 e = p + val->bv_len;
5885 if ( *p != '(' /*')'*/ ) {
5886 return LDAP_INVALID_SYNTAX;
5889 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5893 return LDAP_INVALID_SYNTAX;
5896 } else if ( !AD_CHAR( *p ) ) {
5897 return LDAP_INVALID_SYNTAX;
5901 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5902 return LDAP_INVALID_SYNTAX;
5908 return LDAP_INVALID_SYNTAX;
5911 return LDAP_SUCCESS;
5915 bootParameterValidate(
5917 struct berval *val )
5921 if ( BER_BVISEMPTY( val ) ) {
5922 return LDAP_INVALID_SYNTAX;
5925 p = (char *)val->bv_val;
5926 e = p + val->bv_len;
5929 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5930 if ( !AD_CHAR( *p ) ) {
5931 return LDAP_INVALID_SYNTAX;
5936 return LDAP_INVALID_SYNTAX;
5940 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5941 if ( !AD_CHAR( *p ) ) {
5942 return LDAP_INVALID_SYNTAX;
5947 return LDAP_INVALID_SYNTAX;
5951 for ( p++; p < e; p++ ) {
5952 if ( !SLAP_PRINTABLE( *p ) ) {
5953 return LDAP_INVALID_SYNTAX;
5957 return LDAP_SUCCESS;
5961 firstComponentNormalize(
5966 struct berval *normalized,
5973 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5974 ber_dupbv_x( normalized, val, ctx );
5975 return LDAP_SUCCESS;
5978 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5980 if( ! ( val->bv_val[0] == '(' /*')'*/
5981 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5982 && ! ( val->bv_val[0] == '{' /*'}'*/
5983 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5985 return LDAP_INVALID_SYNTAX;
5988 /* trim leading white space */
5990 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5996 /* grab next word */
5997 comp.bv_val = &val->bv_val[len];
5998 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5999 for( comp.bv_len = 0;
6000 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
6006 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
6007 rc = numericoidValidate( NULL, &comp );
6008 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
6009 rc = integerValidate( NULL, &comp );
6011 rc = LDAP_INVALID_SYNTAX;
6015 if( rc == LDAP_SUCCESS ) {
6016 ber_dupbv_x( normalized, &comp, ctx );
6022 static char *country_gen_syn[] = {
6023 "1.3.6.1.4.1.1466.115.121.1.15",
6024 "1.3.6.1.4.1.1466.115.121.1.26",
6025 "1.3.6.1.4.1.1466.115.121.1.44",
6029 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6030 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6032 static slap_syntax_defs_rec syntax_defs[] = {
6033 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6034 X_BINARY X_NOT_H_R ")",
6035 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6036 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6037 0, NULL, NULL, NULL},
6038 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6039 0, NULL, NULL, NULL},
6040 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6042 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6043 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6045 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6046 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6047 0, NULL, bitStringValidate, NULL },
6048 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6049 0, NULL, booleanValidate, NULL},
6050 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6051 X_BINARY X_NOT_H_R ")",
6052 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6053 NULL, certificateValidate, NULL},
6054 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6055 X_BINARY X_NOT_H_R ")",
6056 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6057 NULL, certificateListValidate, NULL},
6058 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6059 X_BINARY X_NOT_H_R ")",
6060 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6061 NULL, sequenceValidate, NULL},
6062 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6063 X_BINARY X_NOT_H_R ")",
6064 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6065 NULL, attributeCertificateValidate, NULL},
6066 #if 0 /* need to go __after__ printableString */
6067 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6068 0, "1.3.6.1.4.1.1466.115.121.1.44",
6069 countryStringValidate, NULL},
6071 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6072 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6073 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6074 0, NULL, rdnValidate, rdnPretty},
6075 #ifdef LDAP_COMP_MATCH
6076 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6077 0, NULL, allComponentsValidate, NULL},
6078 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6079 0, NULL, componentFilterValidate, NULL},
6081 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6082 0, NULL, NULL, NULL},
6083 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6084 0, NULL, deliveryMethodValidate, NULL},
6085 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6086 0, NULL, UTF8StringValidate, NULL},
6087 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6088 0, NULL, NULL, NULL},
6089 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6090 0, NULL, NULL, NULL},
6091 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6092 0, NULL, NULL, NULL},
6093 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6094 0, NULL, NULL, NULL},
6095 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6096 0, NULL, NULL, NULL},
6097 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6098 0, NULL, printablesStringValidate, NULL},
6099 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6100 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6101 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6102 0, NULL, generalizedTimeValidate, NULL},
6103 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6104 0, NULL, NULL, NULL},
6105 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6106 0, NULL, IA5StringValidate, NULL},
6107 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6108 0, NULL, integerValidate, NULL},
6109 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6110 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6111 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6112 0, NULL, NULL, NULL},
6113 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6114 0, NULL, NULL, NULL},
6115 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6116 0, NULL, NULL, NULL},
6117 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6118 0, NULL, NULL, NULL},
6119 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6120 0, NULL, NULL, NULL},
6121 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6122 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6123 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6124 0, NULL, NULL, NULL},
6125 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6126 0, NULL, numericStringValidate, NULL},
6127 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6128 0, NULL, NULL, NULL},
6129 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6130 0, NULL, numericoidValidate, NULL},
6131 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6132 0, NULL, IA5StringValidate, NULL},
6133 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6134 0, NULL, blobValidate, NULL},
6135 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6136 0, NULL, postalAddressValidate, NULL},
6137 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6138 0, NULL, NULL, NULL},
6139 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6140 0, NULL, NULL, NULL},
6141 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6142 0, NULL, printableStringValidate, NULL},
6143 /* moved here because now depends on Directory String, IA5 String
6144 * and Printable String */
6145 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6146 0, country_gen_syn, countryStringValidate, NULL},
6147 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6148 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6149 0, NULL, subtreeSpecificationValidate, NULL},
6150 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6151 X_BINARY X_NOT_H_R ")",
6152 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6153 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6154 0, NULL, printableStringValidate, NULL},
6155 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6156 0, NULL, NULL, NULL},
6157 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6158 0, NULL, printablesStringValidate, NULL},
6159 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6160 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6161 0, NULL, utcTimeValidate, NULL},
6163 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6164 0, NULL, NULL, NULL},
6165 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6166 0, NULL, NULL, NULL},
6167 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6168 0, NULL, NULL, NULL},
6169 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6170 0, NULL, NULL, NULL},
6171 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6172 0, NULL, NULL, NULL},
6174 /* RFC 2307 NIS Syntaxes */
6175 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6176 0, NULL, nisNetgroupTripleValidate, NULL},
6177 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6178 0, NULL, bootParameterValidate, NULL},
6180 /* draft-zeilenga-ldap-x509 */
6181 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6182 SLAP_SYNTAX_HIDE, NULL,
6183 serialNumberAndIssuerValidate,
6184 serialNumberAndIssuerPretty},
6185 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6186 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6187 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6188 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6189 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6190 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6191 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6192 SLAP_SYNTAX_HIDE, NULL,
6193 issuerAndThisUpdateValidate,
6194 issuerAndThisUpdatePretty},
6195 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6196 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6197 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6198 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6199 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6200 SLAP_SYNTAX_HIDE, NULL,
6201 serialNumberAndIssuerSerialValidate,
6202 serialNumberAndIssuerSerialPretty},
6203 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6204 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6206 #ifdef SLAPD_AUTHPASSWD
6207 /* needs updating */
6208 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6209 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6212 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6213 0, NULL, UUIDValidate, UUIDPretty},
6215 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6216 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6218 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6219 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6221 /* OpenLDAP Void Syntax */
6222 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6223 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6225 /* FIXME: OID is unused, but not registered yet */
6226 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6227 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6229 {NULL, 0, NULL, NULL, NULL}
6232 char *csnSIDMatchSyntaxes[] = {
6233 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6236 char *certificateExactMatchSyntaxes[] = {
6237 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6240 char *certificateListExactMatchSyntaxes[] = {
6241 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6244 char *attributeCertificateExactMatchSyntaxes[] = {
6245 attributeCertificateSyntaxOID /* attributeCertificate */,
6249 #ifdef LDAP_COMP_MATCH
6250 char *componentFilterMatchSyntaxes[] = {
6251 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6252 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6253 attributeCertificateSyntaxOID /* attributeCertificate */,
6258 char *directoryStringSyntaxes[] = {
6259 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6262 char *integerFirstComponentMatchSyntaxes[] = {
6263 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6264 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6267 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6268 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6269 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6270 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6271 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6272 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6273 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6274 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6275 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6280 * Other matching rules in X.520 that we do not use (yet):
6282 * 2.5.13.25 uTCTimeMatch
6283 * 2.5.13.26 uTCTimeOrderingMatch
6284 * 2.5.13.31* directoryStringFirstComponentMatch
6285 * 2.5.13.32* wordMatch
6286 * 2.5.13.33* keywordMatch
6287 * 2.5.13.36+ certificatePairExactMatch
6288 * 2.5.13.37+ certificatePairMatch
6289 * 2.5.13.40+ algorithmIdentifierMatch
6290 * 2.5.13.41* storedPrefixMatch
6291 * 2.5.13.42 attributeCertificateMatch
6292 * 2.5.13.43 readerAndKeyIDMatch
6293 * 2.5.13.44 attributeIntegrityMatch
6295 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6296 * (+) described in draft-zeilenga-ldap-x509
6298 static slap_mrule_defs_rec mrule_defs[] = {
6300 * EQUALITY matching rules must be listed after associated APPROX
6301 * matching rules. So, we list all APPROX matching rules first.
6303 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6304 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6305 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6306 NULL, NULL, directoryStringApproxMatch,
6307 directoryStringApproxIndexer, directoryStringApproxFilter,
6310 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6311 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6312 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6313 NULL, NULL, IA5StringApproxMatch,
6314 IA5StringApproxIndexer, IA5StringApproxFilter,
6318 * Other matching rules
6321 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6322 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6323 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6324 NULL, NULL, octetStringMatch,
6325 octetStringIndexer, octetStringFilter,
6328 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6329 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6330 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6331 NULL, dnNormalize, dnMatch,
6332 octetStringIndexer, octetStringFilter,
6335 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6336 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6337 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6338 NULL, dnNormalize, dnRelativeMatch,
6342 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6343 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6344 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6345 NULL, dnNormalize, dnRelativeMatch,
6349 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6350 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6351 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6352 NULL, dnNormalize, dnRelativeMatch,
6356 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6357 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6358 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6359 NULL, dnNormalize, dnRelativeMatch,
6363 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6364 "SYNTAX 1.2.36.79672281.1.5.0 )",
6365 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6366 NULL, rdnNormalize, rdnMatch,
6367 octetStringIndexer, octetStringFilter,
6370 #ifdef LDAP_COMP_MATCH
6371 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6372 "SYNTAX 1.2.36.79672281.1.5.2 )",
6373 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6374 NULL, NULL , componentFilterMatch,
6375 octetStringIndexer, octetStringFilter,
6378 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6379 "SYNTAX 1.2.36.79672281.1.5.3 )",
6380 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6381 NULL, NULL , allComponentsMatch,
6382 octetStringIndexer, octetStringFilter,
6385 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6386 "SYNTAX 1.2.36.79672281.1.5.3 )",
6387 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6388 NULL, NULL , directoryComponentsMatch,
6389 octetStringIndexer, octetStringFilter,
6393 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6394 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6395 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6396 NULL, UTF8StringNormalize, octetStringMatch,
6397 octetStringIndexer, octetStringFilter,
6398 directoryStringApproxMatchOID },
6400 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6401 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6402 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6403 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6405 "caseIgnoreMatch" },
6407 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6408 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6409 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6410 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6411 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6412 "caseIgnoreMatch" },
6414 {"( 2.5.13.5 NAME 'caseExactMatch' "
6415 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6416 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6417 NULL, UTF8StringNormalize, octetStringMatch,
6418 octetStringIndexer, octetStringFilter,
6419 directoryStringApproxMatchOID },
6421 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6422 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6423 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6424 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6428 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6429 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6430 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6431 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6432 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6435 {"( 2.5.13.8 NAME 'numericStringMatch' "
6436 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6437 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6438 NULL, numericStringNormalize, octetStringMatch,
6439 octetStringIndexer, octetStringFilter,
6442 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6443 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6444 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6445 NULL, numericStringNormalize, octetStringOrderingMatch,
6447 "numericStringMatch" },
6449 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6450 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6451 SLAP_MR_SUBSTR, NULL,
6452 NULL, numericStringNormalize, octetStringSubstringsMatch,
6453 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6454 "numericStringMatch" },
6456 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6457 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6458 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6459 NULL, postalAddressNormalize, octetStringMatch,
6460 octetStringIndexer, octetStringFilter,
6463 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6464 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6465 SLAP_MR_SUBSTR, NULL,
6466 NULL, NULL, NULL, NULL, NULL,
6467 "caseIgnoreListMatch" },
6469 {"( 2.5.13.13 NAME 'booleanMatch' "
6470 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6471 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6472 NULL, NULL, booleanMatch,
6473 octetStringIndexer, octetStringFilter,
6476 {"( 2.5.13.14 NAME 'integerMatch' "
6477 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6478 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6479 NULL, NULL, integerMatch,
6480 integerIndexer, integerFilter,
6483 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6484 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6485 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6486 NULL, NULL, integerMatch,
6490 {"( 2.5.13.16 NAME 'bitStringMatch' "
6491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6492 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6493 NULL, NULL, octetStringMatch,
6494 octetStringIndexer, octetStringFilter,
6497 {"( 2.5.13.17 NAME 'octetStringMatch' "
6498 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6499 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6500 NULL, NULL, octetStringMatch,
6501 octetStringIndexer, octetStringFilter,
6504 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6505 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6506 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6507 NULL, NULL, octetStringOrderingMatch,
6509 "octetStringMatch" },
6511 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6512 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6513 SLAP_MR_SUBSTR, NULL,
6514 NULL, NULL, octetStringSubstringsMatch,
6515 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6516 "octetStringMatch" },
6518 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6519 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6520 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6522 telephoneNumberNormalize, octetStringMatch,
6523 octetStringIndexer, octetStringFilter,
6526 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6527 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6528 SLAP_MR_SUBSTR, NULL,
6529 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6530 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6531 "telephoneNumberMatch" },
6533 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6534 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6535 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6536 NULL, NULL, NULL, NULL, NULL, NULL },
6538 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6539 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6540 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6541 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6542 uniqueMemberIndexer, uniqueMemberFilter,
6545 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6546 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6547 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6548 NULL, NULL, NULL, NULL, NULL, NULL },
6550 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6552 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6553 NULL, generalizedTimeNormalize, octetStringMatch,
6554 generalizedTimeIndexer, generalizedTimeFilter,
6557 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6559 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6560 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6562 "generalizedTimeMatch" },
6564 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6566 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6567 integerFirstComponentMatchSyntaxes,
6568 NULL, firstComponentNormalize, integerMatch,
6569 octetStringIndexer, octetStringFilter,
6572 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6573 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6574 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6575 objectIdentifierFirstComponentMatchSyntaxes,
6576 NULL, firstComponentNormalize, octetStringMatch,
6577 octetStringIndexer, octetStringFilter,
6580 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6581 "SYNTAX 1.3.6.1.1.15.1 )",
6582 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6583 NULL, certificateExactNormalize, octetStringMatch,
6584 octetStringIndexer, octetStringFilter,
6587 {"( 2.5.13.35 NAME 'certificateMatch' "
6588 "SYNTAX 1.3.6.1.1.15.2 )",
6589 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6590 NULL, NULL, NULL, NULL, NULL,
6593 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6594 "SYNTAX 1.3.6.1.1.15.5 )",
6595 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6596 NULL, certificateListExactNormalize, octetStringMatch,
6597 octetStringIndexer, octetStringFilter,
6600 {"( 2.5.13.39 NAME 'certificateListMatch' "
6601 "SYNTAX 1.3.6.1.1.15.6 )",
6602 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6603 NULL, NULL, NULL, NULL, NULL,
6606 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6607 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6608 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6609 NULL, attributeCertificateExactNormalize, octetStringMatch,
6610 octetStringIndexer, octetStringFilter,
6613 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6614 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6615 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6616 NULL, NULL, NULL, NULL, NULL,
6619 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6621 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6622 NULL, IA5StringNormalize, octetStringMatch,
6623 octetStringIndexer, octetStringFilter,
6624 IA5StringApproxMatchOID },
6626 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6628 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6629 NULL, IA5StringNormalize, octetStringMatch,
6630 octetStringIndexer, octetStringFilter,
6631 IA5StringApproxMatchOID },
6633 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6634 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6635 SLAP_MR_SUBSTR, NULL,
6636 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6637 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6638 "caseIgnoreIA5Match" },
6640 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6641 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6642 SLAP_MR_SUBSTR, NULL,
6643 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6644 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6645 "caseExactIA5Match" },
6647 #ifdef SLAPD_AUTHPASSWD
6648 /* needs updating */
6649 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6651 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6652 NULL, NULL, authPasswordMatch,
6657 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6658 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6660 NULL, NULL, integerBitAndMatch,
6664 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6665 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6667 NULL, NULL, integerBitOrMatch,
6671 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6672 "SYNTAX 1.3.6.1.1.16.1 )",
6673 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6674 NULL, UUIDNormalize, octetStringMatch,
6675 octetStringIndexer, octetStringFilter,
6678 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6679 "SYNTAX 1.3.6.1.1.16.1 )",
6680 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6681 NULL, UUIDNormalize, octetStringOrderingMatch,
6682 octetStringIndexer, octetStringFilter,
6685 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6686 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6687 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6688 NULL, csnNormalize, csnMatch,
6689 csnIndexer, csnFilter,
6692 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6693 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6694 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6695 NULL, csnNormalize, csnOrderingMatch,
6699 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6700 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6701 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6702 NULL, csnSidNormalize, octetStringMatch,
6703 octetStringIndexer, octetStringFilter,
6706 /* FIXME: OID is unused, but not registered yet */
6707 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6708 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6709 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6710 NULL, authzNormalize, authzMatch,
6714 {NULL, SLAP_MR_NONE, NULL,
6715 NULL, NULL, NULL, NULL, NULL,
6720 slap_schema_init( void )
6725 /* we should only be called once (from main) */
6726 assert( schema_init_done == 0 );
6728 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6729 res = register_syntax( &syntax_defs[i] );
6732 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6733 syntax_defs[i].sd_desc );
6738 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6739 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6740 mrule_defs[i].mrd_compat_syntaxes == NULL )
6743 "slap_schema_init: Ignoring unusable matching rule %s\n",
6744 mrule_defs[i].mrd_desc );
6748 res = register_matching_rule( &mrule_defs[i] );
6752 "slap_schema_init: Error registering matching rule %s\n",
6753 mrule_defs[i].mrd_desc );
6758 res = slap_schema_load();
6759 schema_init_done = 1;
6764 schema_destroy( void )
6773 if( schema_init_done ) {
6774 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6775 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );