1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2011 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>.
18 * Syntaxes - implementation notes:
20 * Validate function(syntax, value):
21 * Called before the other functions here to check if the value
22 * is valid according to the syntax.
24 * Pretty function(syntax, input value, output prettified...):
25 * If it exists, maps different notations of the same value to a
26 * unique representation which can be stored in the directory and
27 * possibly be passed to the Match/Indexer/Filter() functions.
29 * E.g. DN "2.5.4.3 = foo\,bar, o = BAZ" -> "cn=foo\2Cbar,o=BAZ",
30 * but unlike DN normalization, "BAZ" is not mapped to "baz".
34 * Matching rules - implementation notes:
36 * Matching rules match an attribute value (often from the directory)
37 * against an asserted value (e.g. from a filter).
39 * Invoked with validated and commonly pretty/normalized arguments, thus
40 * a number of matching rules can simply use the octetString functions.
42 * Normalize function(...input value, output normalized...):
43 * If it exists, maps matching values to a unique representation
44 * which is passed to the Match/Indexer/Filter() functions.
46 * Different matching rules can normalize values of the same syntax
47 * differently. E.g. caseIgnore rules normalize to lowercase,
48 * caseExact rules do not.
50 * Match function(*output matchp, ...value, asserted value):
51 * On success, set *matchp. 0 means match. For ORDERING/most EQUALITY,
52 * less/greater than 0 means value less/greater than asserted. However:
54 * In extensible match filters, ORDERING rules match if value<asserted.
56 * EQUALITY rules may order values differently than ORDERING rules for
57 * speed, since EQUALITY ordering is only used for SLAP_AT_SORTED_VAL.
58 * Some EQUALITY rules do not order values (ITS#6722).
60 * Indexer function(...attribute values, *output keysp,...):
61 * Generates index keys for the attribute values. Backends can store
62 * them in an index, a {key->entry ID set} mapping, for the attribute.
64 * A search can look up the DN/scope and asserted values in the
65 * indexes, if any, to narrow down the number of entires to check
66 * against the search criteria.
68 * Filter function(...asserted value, *output keysp,...):
69 * Generates index key(s) for the asserted value, to be looked up in
70 * the index from the Indexer function. *keysp is an array because
71 * substring matching rules can generate multiple lookup keys.
74 * A key is usually a hash of match type, attribute value and schema
75 * info, because one index can contain keys for many filtering types.
77 * Some indexes instead have EQUALITY keys ordered so that if
78 * key(val1) < key(val2), then val1 < val2 by the ORDERING rule.
79 * That way the ORDERING rule can use the EQUALITY index.
82 * This chops the attribute values up in small chunks and indexes all
83 * possible chunks of certain sizes. Substring filtering looks up
84 * SOME of the asserted value's chunks, and the caller uses the
85 * intersection of the resulting entry ID sets.
86 * See the index_substr_* keywords in slapd.conf(5).
98 #include <ac/string.h>
99 #include <ac/socket.h>
102 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
104 #include "ldap_utf8.h"
107 #include "lutil_hash.h"
108 #define HASH_BYTES LUTIL_HASH_BYTES
109 #define HASH_CONTEXT lutil_HASH_CTX
110 #define HASH_Init(c) lutil_HASHInit(c)
111 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
112 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
114 /* approx matching rules */
115 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
116 #define directoryStringApproxMatch approxMatch
117 #define directoryStringApproxIndexer approxIndexer
118 #define directoryStringApproxFilter approxFilter
119 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
120 #define IA5StringApproxMatch approxMatch
121 #define IA5StringApproxIndexer approxIndexer
122 #define IA5StringApproxFilter approxFilter
124 /* Change Sequence Number (CSN) - much of this will change */
125 #define csnMatch octetStringMatch
126 #define csnOrderingMatch octetStringOrderingMatch
127 #define csnIndexer generalizedTimeIndexer
128 #define csnFilter generalizedTimeFilter
130 #define authzMatch octetStringMatch
132 /* X.509 PMI ldapSyntaxes */
133 /* FIXME: need to create temporary OIDs under OpenLDAP's arc;
134 * these are currently hijacked
136 * 1.3.6.1.4.1.4203.666 OpenLDAP
137 * 1.3.6.1.4.1.4203.666.11 self-contained works
138 * 1.3.6.1.4.1.4203.666.11.10 X.509 PMI
139 * 1.3.6.1.4.1.4203.666.11.10.2 X.509 PMI ldapSyntaxes
140 * 1.3.6.1.4.1.4203.666.11.10.2.1 AttributeCertificate (supported)
141 * 1.3.6.1.4.1.4203.666.11.10.2.2 AttributeCertificateExactAssertion (supported)
142 * 1.3.6.1.4.1.4203.666.11.10.2.3 AttributeCertificateAssertion (not supported)
143 * 1.3.6.1.4.1.4203.666.11.10.2.4 AttCertPath (X-SUBST'ed right now in pmi.schema)
144 * 1.3.6.1.4.1.4203.666.11.10.2.5 PolicySyntax (X-SUBST'ed right now in pmi.schema)
145 * 1.3.6.1.4.1.4203.666.11.10.2.6 RoleSyntax (X-SUBST'ed right now in pmi.schema)
147 #if 0 /* from <draft-ietf-pkix-ldap-schema-02.txt> (expired) */
148 #define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5"
149 #define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6"
150 #define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7"
151 #else /* from OpenLDAP's experimental oid arc */
152 #define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2"
153 #define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1"
154 #define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2"
155 #define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3"
158 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
159 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
160 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
161 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
163 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
164 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
165 SLAP_INDEX_INTLEN_DEFAULT );
167 ldap_pvt_thread_mutex_t ad_undef_mutex;
168 ldap_pvt_thread_mutex_t oc_undef_mutex;
171 generalizedTimeValidate(
175 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
180 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
187 /* no value allowed */
188 return LDAP_INVALID_SYNTAX;
196 /* any value allowed */
200 #define berValidate blobValidate
207 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
208 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
213 /* X.509 related stuff */
222 SLAP_TAG_UTCTIME = 0x17U,
223 SLAP_TAG_GENERALIZEDTIME = 0x18U
227 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
230 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
231 SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1,
232 SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2,
233 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
237 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
241 GeneralName ::= CHOICE {
242 otherName [0] INSTANCE OF OTHER-NAME,
243 rfc822Name [1] IA5String,
244 dNSName [2] IA5String,
245 x400Address [3] ORAddress,
246 directoryName [4] Name,
247 ediPartyName [5] EDIPartyName,
248 uniformResourceIdentifier [6] IA5String,
249 iPAddress [7] OCTET STRING,
250 registeredID [8] OBJECT IDENTIFIER }
253 SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0,
254 SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1,
255 SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2,
256 SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3,
257 SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4,
258 SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5,
259 SLAP_X509_GN_URI = SLAP_X509_OPTION + 6,
260 SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7,
261 SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8
264 /* X.509 PMI related stuff */
271 SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0
274 /* X.509 certificate validation */
276 certificateValidate( Syntax *syntax, struct berval *in )
278 BerElementBuffer berbuf;
279 BerElement *ber = (BerElement *)&berbuf;
282 ber_int_t version = SLAP_X509_V1;
284 ber_init2( ber, in, LBER_USE_DER );
285 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
286 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
287 tag = ber_skip_tag( ber, &len ); /* Sequence */
288 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
289 tag = ber_peek_tag( ber, &len );
290 /* Optional version */
291 if ( tag == SLAP_X509_OPT_C_VERSION ) {
292 tag = ber_skip_tag( ber, &len );
293 tag = ber_get_int( ber, &version );
294 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
296 /* NOTE: don't try to parse Serial, because it might be longer
297 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
298 tag = ber_skip_tag( ber, &len ); /* Serial */
299 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
300 ber_skip_data( ber, len );
301 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
302 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
303 ber_skip_data( ber, len );
304 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
305 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
306 ber_skip_data( ber, len );
307 tag = ber_skip_tag( ber, &len ); /* Validity */
308 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
309 ber_skip_data( ber, len );
310 tag = ber_skip_tag( ber, &len ); /* Subject DN */
311 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
312 ber_skip_data( ber, len );
313 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
314 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
315 ber_skip_data( ber, len );
316 tag = ber_skip_tag( ber, &len );
317 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
318 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
319 ber_skip_data( ber, len );
320 tag = ber_skip_tag( ber, &len );
322 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
323 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
324 ber_skip_data( ber, len );
325 tag = ber_skip_tag( ber, &len );
327 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
328 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
329 tag = ber_skip_tag( ber, &len );
330 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
331 ber_skip_data( ber, len );
332 tag = ber_skip_tag( ber, &len );
334 /* signatureAlgorithm */
335 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
336 ber_skip_data( ber, len );
337 tag = ber_skip_tag( ber, &len );
339 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
340 ber_skip_data( ber, len );
341 tag = ber_skip_tag( ber, &len );
342 /* Must be at end now */
343 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
347 /* X.509 certificate list validation */
349 checkTime( struct berval *in, struct berval *out );
352 certificateListValidate( Syntax *syntax, struct berval *in )
354 BerElementBuffer berbuf;
355 BerElement *ber = (BerElement *)&berbuf;
357 ber_len_t len, wrapper_len;
360 ber_int_t version = SLAP_X509_V1;
361 struct berval bvdn, bvtu;
363 ber_init2( ber, in, LBER_USE_DER );
364 tag = ber_skip_tag( ber, &wrapper_len ); /* Signed wrapper */
365 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
366 wrapper_start = ber->ber_ptr;
367 tag = ber_skip_tag( ber, &len ); /* Sequence */
368 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
369 tag = ber_peek_tag( ber, &len );
370 /* Optional version */
371 if ( tag == LBER_INTEGER ) {
372 tag = ber_get_int( ber, &version );
373 assert( tag == LBER_INTEGER );
374 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
376 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
377 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
378 ber_skip_data( ber, len );
379 tag = ber_peek_tag( ber, &len ); /* Issuer DN */
380 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
381 len = ber_ptrlen( ber );
382 bvdn.bv_val = in->bv_val + len;
383 bvdn.bv_len = in->bv_len - len;
384 tag = ber_skip_tag( ber, &len );
385 ber_skip_data( ber, len );
386 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
387 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
388 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
389 bvtu.bv_val = (char *)ber->ber_ptr;
391 ber_skip_data( ber, len );
392 /* Optional nextUpdate */
393 tag = ber_skip_tag( ber, &len );
394 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
395 ber_skip_data( ber, len );
396 tag = ber_skip_tag( ber, &len );
398 /* revokedCertificates - Sequence of Sequence, Optional */
399 if ( tag == LBER_SEQUENCE ) {
402 stag = ber_peek_tag( ber, &seqlen );
403 if ( stag == LBER_SEQUENCE || !len ) {
404 /* RFC5280 requires non-empty, but X.509(2005) allows empty. */
406 ber_skip_data( ber, len );
407 tag = ber_skip_tag( ber, &len );
410 /* Optional Extensions - Sequence of Sequence */
411 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
413 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
414 tag = ber_peek_tag( ber, &seqlen );
415 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
416 ber_skip_data( ber, len );
417 tag = ber_skip_tag( ber, &len );
419 /* signatureAlgorithm */
420 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
421 ber_skip_data( ber, len );
422 tag = ber_skip_tag( ber, &len );
424 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
425 ber_skip_data( ber, len );
426 if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
427 tag = ber_skip_tag( ber, &len );
428 /* Must be at end now */
429 /* NOTE: OpenSSL tolerates CL with garbage past the end */
430 if ( len || tag != LBER_DEFAULT ) {
431 struct berval issuer_dn = BER_BVNULL, thisUpdate;
432 char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
435 if ( ! wrapper_ok ) {
436 return LDAP_INVALID_SYNTAX;
439 rc = dnX509normalize( &bvdn, &issuer_dn );
440 if ( rc != LDAP_SUCCESS ) {
441 rc = LDAP_INVALID_SYNTAX;
445 thisUpdate.bv_val = tubuf;
446 thisUpdate.bv_len = sizeof(tubuf);
447 if ( checkTime( &bvtu, &thisUpdate ) ) {
448 rc = LDAP_INVALID_SYNTAX;
452 Debug( LDAP_DEBUG_ANY,
453 "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
454 issuer_dn.bv_val, thisUpdate.bv_val, 0 );
457 if ( ! BER_BVISNULL( &issuer_dn ) ) {
458 ber_memfree( issuer_dn.bv_val );
467 /* X.509 PMI Attribute Certificate Validate */
469 attributeCertificateValidate( Syntax *syntax, struct berval *in )
471 BerElementBuffer berbuf;
472 BerElement *ber = (BerElement *)&berbuf;
478 ber_init2( ber, in, LBER_USE_DER );
480 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
481 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
483 tag = ber_skip_tag( ber, &len ); /* Sequence */
484 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
486 tag = ber_peek_tag( ber, &len ); /* Version */
487 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
488 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
489 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
491 tag = ber_skip_tag( ber, &len ); /* Holder */
492 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
493 ber_skip_data( ber, len );
495 tag = ber_skip_tag( ber, &len ); /* Issuer */
496 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
497 ber_skip_data( ber, len );
499 tag = ber_skip_tag( ber, &len ); /* Signature */
500 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
501 ber_skip_data( ber, len );
503 tag = ber_skip_tag( ber, &len ); /* Serial number */
504 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
505 ber_skip_data( ber, len );
507 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
508 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
509 ber_skip_data( ber, len );
511 tag = ber_skip_tag( ber, &len ); /* Attributes */
512 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
513 ber_skip_data( ber, len );
515 tag = ber_peek_tag( ber, &len );
517 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
518 tag = ber_skip_tag( ber, &len );
519 ber_skip_data( ber, len );
520 tag = ber_peek_tag( ber, &len );
523 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
524 tag = ber_skip_tag( ber, &len );
525 ber_skip_data( ber, len );
527 tag = ber_peek_tag( ber, &len );
530 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
531 tag = ber_skip_tag( ber, &len );
532 ber_skip_data( ber, len );
534 tag = ber_peek_tag( ber, &len );
537 if ( tag == LBER_BITSTRING ) { /* Signature */
538 tag = ber_skip_tag( ber, &len );
539 ber_skip_data( ber, len );
541 tag = ber_peek_tag( ber, &len );
544 /* Must be at end now */
545 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
556 struct berval *value,
557 void *assertedValue )
559 struct berval *asserted = (struct berval *) assertedValue;
560 ber_slen_t d = (ber_slen_t) value->bv_len - (ber_slen_t) asserted->bv_len;
562 /* For speed, order first by length, then by contents */
563 *matchp = d ? (sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1)
564 : memcmp( value->bv_val, asserted->bv_val, value->bv_len );
570 octetStringOrderingMatch(
575 struct berval *value,
576 void *assertedValue )
578 struct berval *asserted = (struct berval *) assertedValue;
579 ber_len_t v_len = value->bv_len;
580 ber_len_t av_len = asserted->bv_len;
582 int match = memcmp( value->bv_val, asserted->bv_val,
583 (v_len < av_len ? v_len : av_len) );
586 match = sizeof(v_len) == sizeof(int)
587 ? (int) v_len - (int) av_len
588 : v_len < av_len ? -1 : v_len > av_len;
590 /* If used in extensible match filter, match if value < asserted */
591 if ( flags & SLAP_MR_EXT )
592 match = (match >= 0);
598 /* Initialize HASHcontext from match type and schema info */
601 HASH_CONTEXT *HASHcontext,
602 struct berval *prefix,
607 HASH_Init(HASHcontext);
608 if(prefix && prefix->bv_len > 0) {
609 HASH_Update(HASHcontext,
610 (unsigned char *)prefix->bv_val, prefix->bv_len);
612 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
613 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
614 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
618 /* Set HASHdigest from HASHcontext and value:len */
621 HASH_CONTEXT *HASHcontext,
622 unsigned char *HASHdigest,
623 unsigned char *value,
626 HASH_CONTEXT ctx = *HASHcontext;
627 HASH_Update( &ctx, value, len );
628 HASH_Final( HASHdigest, &ctx );
631 /* Index generation function: Attribute values -> index hash keys */
632 int octetStringIndexer(
637 struct berval *prefix,
645 HASH_CONTEXT HASHcontext;
646 unsigned char HASHdigest[HASH_BYTES];
647 struct berval digest;
648 digest.bv_val = (char *)HASHdigest;
649 digest.bv_len = sizeof(HASHdigest);
651 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
652 /* just count them */
655 /* we should have at least one value at this point */
658 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
660 slen = syntax->ssyn_oidlen;
661 mlen = mr->smr_oidlen;
663 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
664 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
665 hashIter( &HASHcontext, HASHdigest,
666 (unsigned char *)values[i].bv_val, values[i].bv_len );
667 ber_dupbv_x( &keys[i], &digest, ctx );
670 BER_BVZERO( &keys[i] );
677 /* Index generation function: Asserted value -> index hash key */
678 int octetStringFilter(
683 struct berval *prefix,
684 void * assertedValue,
690 HASH_CONTEXT HASHcontext;
691 unsigned char HASHdigest[HASH_BYTES];
692 struct berval *value = (struct berval *) assertedValue;
693 struct berval digest;
694 digest.bv_val = (char *)HASHdigest;
695 digest.bv_len = sizeof(HASHdigest);
697 slen = syntax->ssyn_oidlen;
698 mlen = mr->smr_oidlen;
700 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
702 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
703 hashIter( &HASHcontext, HASHdigest,
704 (unsigned char *)value->bv_val, value->bv_len );
706 ber_dupbv_x( keys, &digest, ctx );
707 BER_BVZERO( &keys[1] );
715 octetStringSubstringsMatch(
720 struct berval *value,
721 void *assertedValue )
724 SubstringsAssertion *sub = assertedValue;
725 struct berval left = *value;
729 /* Add up asserted input length */
730 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
731 inlen += sub->sa_initial.bv_len;
734 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
735 inlen += sub->sa_any[i].bv_len;
738 if ( !BER_BVISNULL( &sub->sa_final ) ) {
739 inlen += sub->sa_final.bv_len;
742 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
743 if ( inlen > left.bv_len ) {
748 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
749 sub->sa_initial.bv_len );
755 left.bv_val += sub->sa_initial.bv_len;
756 left.bv_len -= sub->sa_initial.bv_len;
757 inlen -= sub->sa_initial.bv_len;
760 if ( !BER_BVISNULL( &sub->sa_final ) ) {
761 if ( inlen > left.bv_len ) {
766 match = memcmp( sub->sa_final.bv_val,
767 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
768 sub->sa_final.bv_len );
774 left.bv_len -= sub->sa_final.bv_len;
775 inlen -= sub->sa_final.bv_len;
779 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
784 if ( inlen > left.bv_len ) {
785 /* not enough length */
790 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
794 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
801 idx = p - left.bv_val;
803 if ( idx >= left.bv_len ) {
804 /* this shouldn't happen */
811 if ( sub->sa_any[i].bv_len > left.bv_len ) {
812 /* not enough left */
817 match = memcmp( left.bv_val,
818 sub->sa_any[i].bv_val,
819 sub->sa_any[i].bv_len );
827 left.bv_val += sub->sa_any[i].bv_len;
828 left.bv_len -= sub->sa_any[i].bv_len;
829 inlen -= sub->sa_any[i].bv_len;
838 /* Substring index generation function: Attribute values -> index hash keys */
840 octetStringSubstringsIndexer(
845 struct berval *prefix,
854 HASH_CONTEXT HCany, HCini, HCfin;
855 unsigned char HASHdigest[HASH_BYTES];
856 struct berval digest;
857 digest.bv_val = (char *)HASHdigest;
858 digest.bv_len = sizeof(HASHdigest);
862 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
863 /* count number of indices to generate */
864 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
865 if( values[i].bv_len >= index_substr_if_maxlen ) {
866 nkeys += index_substr_if_maxlen -
867 (index_substr_if_minlen - 1);
868 } else if( values[i].bv_len >= index_substr_if_minlen ) {
869 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
873 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
874 if( values[i].bv_len >= index_substr_any_len ) {
875 nkeys += values[i].bv_len - (index_substr_any_len - 1);
879 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
880 if( values[i].bv_len >= index_substr_if_maxlen ) {
881 nkeys += index_substr_if_maxlen -
882 (index_substr_if_minlen - 1);
883 } else if( values[i].bv_len >= index_substr_if_minlen ) {
884 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
890 /* no keys to generate */
895 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
897 slen = syntax->ssyn_oidlen;
898 mlen = mr->smr_oidlen;
900 if ( flags & SLAP_INDEX_SUBSTR_ANY )
901 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
902 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
903 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
904 if( flags & SLAP_INDEX_SUBSTR_FINAL )
905 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
908 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
911 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
912 ( values[i].bv_len >= index_substr_any_len ) )
914 max = values[i].bv_len - (index_substr_any_len - 1);
916 for( j=0; j<max; j++ ) {
917 hashIter( &HCany, HASHdigest,
918 (unsigned char *)&values[i].bv_val[j],
919 index_substr_any_len );
920 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
924 /* skip if too short */
925 if( values[i].bv_len < index_substr_if_minlen ) continue;
927 max = index_substr_if_maxlen < values[i].bv_len
928 ? index_substr_if_maxlen : values[i].bv_len;
930 for( j=index_substr_if_minlen; j<=max; j++ ) {
932 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
933 hashIter( &HCini, HASHdigest,
934 (unsigned char *)values[i].bv_val, j );
935 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
938 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
939 hashIter( &HCfin, HASHdigest,
940 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
941 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
948 BER_BVZERO( &keys[nkeys] );
958 /* Substring index generation function: Assertion value -> index hash keys */
960 octetStringSubstringsFilter (
965 struct berval *prefix,
966 void * assertedValue,
970 SubstringsAssertion *sa;
973 size_t slen, mlen, klen;
975 HASH_CONTEXT HASHcontext;
976 unsigned char HASHdigest[HASH_BYTES];
977 struct berval *value;
978 struct berval digest;
980 sa = (SubstringsAssertion *) assertedValue;
982 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
983 !BER_BVISNULL( &sa->sa_initial ) &&
984 sa->sa_initial.bv_len >= index_substr_if_minlen )
987 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
988 ( flags & SLAP_INDEX_SUBSTR_ANY ))
990 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
994 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
996 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
997 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
998 /* don't bother accounting with stepping */
999 nkeys += sa->sa_any[i].bv_len -
1000 ( index_substr_any_len - 1 );
1005 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1006 !BER_BVISNULL( &sa->sa_final ) &&
1007 sa->sa_final.bv_len >= index_substr_if_minlen )
1010 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
1011 ( flags & SLAP_INDEX_SUBSTR_ANY ))
1013 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
1019 return LDAP_SUCCESS;
1022 digest.bv_val = (char *)HASHdigest;
1023 digest.bv_len = sizeof(HASHdigest);
1025 slen = syntax->ssyn_oidlen;
1026 mlen = mr->smr_oidlen;
1028 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
1031 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
1032 !BER_BVISNULL( &sa->sa_initial ) &&
1033 sa->sa_initial.bv_len >= index_substr_if_minlen )
1035 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1036 value = &sa->sa_initial;
1038 klen = index_substr_if_maxlen < value->bv_len
1039 ? index_substr_if_maxlen : value->bv_len;
1041 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1042 hashIter( &HASHcontext, HASHdigest,
1043 (unsigned char *)value->bv_val, klen );
1044 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1046 /* If initial is too long and we have subany indexed, use it
1047 * to match the excess...
1049 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1052 pre = SLAP_INDEX_SUBSTR_PREFIX;
1053 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1054 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
1056 hashIter( &HASHcontext, HASHdigest,
1057 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1058 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1063 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1065 pre = SLAP_INDEX_SUBSTR_PREFIX;
1066 klen = index_substr_any_len;
1068 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
1069 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
1073 value = &sa->sa_any[i];
1075 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1077 j <= value->bv_len - index_substr_any_len;
1078 j += index_substr_any_step )
1080 hashIter( &HASHcontext, HASHdigest,
1081 (unsigned char *)&value->bv_val[j], klen );
1082 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1087 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1088 !BER_BVISNULL( &sa->sa_final ) &&
1089 sa->sa_final.bv_len >= index_substr_if_minlen )
1091 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1092 value = &sa->sa_final;
1094 klen = index_substr_if_maxlen < value->bv_len
1095 ? index_substr_if_maxlen : value->bv_len;
1097 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1098 hashIter( &HASHcontext, HASHdigest,
1099 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
1100 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1102 /* If final is too long and we have subany indexed, use it
1103 * to match the excess...
1105 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1108 pre = SLAP_INDEX_SUBSTR_PREFIX;
1109 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1110 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
1112 hashIter( &HASHcontext, HASHdigest,
1113 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1114 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1120 BER_BVZERO( &keys[nkeys] );
1127 return LDAP_SUCCESS;
1137 /* very unforgiving validation, requires no normalization
1138 * before simplistic matching
1140 if( in->bv_len < 3 ) {
1141 return LDAP_INVALID_SYNTAX;
1144 /* RFC 4517 Section 3.3.2 Bit String:
1145 * BitString = SQUOTE *binary-digit SQUOTE "B"
1146 * binary-digit = "0" / "1"
1148 * where SQUOTE [RFC4512] is
1149 * SQUOTE = %x27 ; single quote ("'")
1151 * Example: '0101111101'B
1154 if( in->bv_val[0] != '\'' ||
1155 in->bv_val[in->bv_len - 2] != '\'' ||
1156 in->bv_val[in->bv_len - 1] != 'B' )
1158 return LDAP_INVALID_SYNTAX;
1161 for( i = in->bv_len - 3; i > 0; i-- ) {
1162 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1163 return LDAP_INVALID_SYNTAX;
1167 return LDAP_SUCCESS;
1171 * Syntaxes from RFC 4517
1176 A value of the Bit String syntax is a sequence of binary digits. The
1177 LDAP-specific encoding of a value of this syntax is defined by the
1180 BitString = SQUOTE *binary-digit SQUOTE "B"
1182 binary-digit = "0" / "1"
1184 The <SQUOTE> rule is defined in [MODELS].
1189 The LDAP definition for the Bit String syntax is:
1191 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1193 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1197 3.3.21. Name and Optional UID
1199 A value of the Name and Optional UID syntax is the distinguished name
1200 [MODELS] of an entity optionally accompanied by a unique identifier
1201 that serves to differentiate the entity from others with an identical
1204 The LDAP-specific encoding of a value of this syntax is defined by
1207 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1209 The <BitString> rule is defined in Section 3.3.2. The
1210 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1211 defined in [MODELS].
1213 Note that although the '#' character may occur in the string
1214 representation of a distinguished name, no additional escaping of
1215 this character is performed when a <distinguishedName> is encoded in
1216 a <NameAndOptionalUID>.
1219 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1221 The LDAP definition for the Name and Optional UID syntax is:
1223 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1225 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1232 1.4. Common ABNF Productions
1235 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1237 SQUOTE = %x27 ; single quote ("'")
1242 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1243 * be escaped except when at the beginning of a value, the
1244 * definition of Name and Optional UID appears to be flawed,
1245 * because there is no clear means to determine whether the
1246 * UID part is present or not.
1250 * cn=Someone,dc=example,dc=com#'1'B
1252 * could be either a NameAndOptionalUID with trailing UID, i.e.
1254 * DN = "cn=Someone,dc=example,dc=com"
1257 * or a NameAndOptionalUID with no trailing UID, and the AVA
1258 * in the last RDN made of
1260 * attributeType = dc
1261 * attributeValue = com#'1'B
1263 * in fact "com#'1'B" is a valid IA5 string.
1265 * As a consequence, current slapd code takes the presence of
1266 * #<valid BitString> at the end of the string representation
1267 * of a NameAndOptionalUID to mean this is indeed a BitString.
1268 * This is quite arbitrary - it has changed the past and might
1269 * change in the future.
1279 struct berval dn, uid;
1281 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1283 ber_dupbv( &dn, in );
1284 if( !dn.bv_val ) return LDAP_OTHER;
1286 /* if there's a "#", try bitStringValidate()... */
1287 uid.bv_val = strrchr( dn.bv_val, '#' );
1288 if ( !BER_BVISNULL( &uid ) ) {
1290 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1292 rc = bitStringValidate( NULL, &uid );
1293 if ( rc == LDAP_SUCCESS ) {
1294 /* in case of success, trim the UID,
1295 * otherwise treat it as part of the DN */
1296 dn.bv_len -= uid.bv_len + 1;
1297 uid.bv_val[-1] = '\0';
1301 rc = dnValidate( NULL, &dn );
1303 ber_memfree( dn.bv_val );
1314 assert( val != NULL );
1315 assert( out != NULL );
1318 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1320 if( BER_BVISEMPTY( val ) ) {
1321 ber_dupbv_x( out, val, ctx );
1323 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1324 return LDAP_INVALID_SYNTAX;
1328 struct berval dnval = *val;
1329 struct berval uidval = BER_BVNULL;
1331 uidval.bv_val = strrchr( val->bv_val, '#' );
1332 if ( !BER_BVISNULL( &uidval ) ) {
1334 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1336 rc = bitStringValidate( NULL, &uidval );
1338 if ( rc == LDAP_SUCCESS ) {
1339 ber_dupbv_x( &dnval, val, ctx );
1341 dnval.bv_len -= ++uidval.bv_len;
1342 dnval.bv_val[dnval.bv_len] = '\0';
1345 BER_BVZERO( &uidval );
1349 rc = dnPretty( syntax, &dnval, out, ctx );
1350 if ( dnval.bv_val != val->bv_val ) {
1351 slap_sl_free( dnval.bv_val, ctx );
1353 if( rc != LDAP_SUCCESS ) {
1357 if( !BER_BVISNULL( &uidval ) ) {
1360 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1361 + uidval.bv_len + 1,
1364 ber_memfree_x( out->bv_val, ctx );
1368 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1369 out->bv_len += uidval.bv_len;
1370 out->bv_val[out->bv_len] = '\0';
1374 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1376 return LDAP_SUCCESS;
1380 uniqueMemberNormalize(
1385 struct berval *normalized,
1391 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1393 ber_dupbv_x( &out, val, ctx );
1394 if ( BER_BVISEMPTY( &out ) ) {
1398 struct berval uid = BER_BVNULL;
1400 uid.bv_val = strrchr( out.bv_val, '#' );
1401 if ( !BER_BVISNULL( &uid ) ) {
1403 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1405 rc = bitStringValidate( NULL, &uid );
1406 if ( rc == LDAP_SUCCESS ) {
1407 uid.bv_val[-1] = '\0';
1408 out.bv_len -= uid.bv_len + 1;
1414 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1416 if( rc != LDAP_SUCCESS ) {
1417 slap_sl_free( out.bv_val, ctx );
1418 return LDAP_INVALID_SYNTAX;
1421 if( !BER_BVISNULL( &uid ) ) {
1424 tmp = ch_realloc( normalized->bv_val,
1425 normalized->bv_len + uid.bv_len
1426 + STRLENOF("#") + 1 );
1427 if ( tmp == NULL ) {
1428 ber_memfree_x( normalized->bv_val, ctx );
1432 normalized->bv_val = tmp;
1434 /* insert the separator */
1435 normalized->bv_val[normalized->bv_len++] = '#';
1437 /* append the UID */
1438 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1439 uid.bv_val, uid.bv_len );
1440 normalized->bv_len += uid.bv_len;
1443 normalized->bv_val[normalized->bv_len] = '\0';
1446 slap_sl_free( out.bv_val, ctx );
1449 return LDAP_SUCCESS;
1458 struct berval *value,
1459 void *assertedValue )
1462 struct berval *asserted = (struct berval *) assertedValue;
1463 struct berval assertedDN = *asserted;
1464 struct berval assertedUID = BER_BVNULL;
1465 struct berval valueDN = *value;
1466 struct berval valueUID = BER_BVNULL;
1467 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1469 if ( !BER_BVISEMPTY( asserted ) ) {
1470 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1471 if ( !BER_BVISNULL( &assertedUID ) ) {
1472 assertedUID.bv_val++;
1473 assertedUID.bv_len = assertedDN.bv_len
1474 - ( assertedUID.bv_val - assertedDN.bv_val );
1476 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1477 assertedDN.bv_len -= assertedUID.bv_len + 1;
1480 BER_BVZERO( &assertedUID );
1485 if ( !BER_BVISEMPTY( value ) ) {
1487 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1488 if ( !BER_BVISNULL( &valueUID ) ) {
1490 valueUID.bv_len = valueDN.bv_len
1491 - ( valueUID.bv_val - valueDN.bv_val );
1493 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1494 valueDN.bv_len -= valueUID.bv_len + 1;
1497 BER_BVZERO( &valueUID );
1502 if( valueUID.bv_len && assertedUID.bv_len ) {
1504 d = (ber_slen_t) valueUID.bv_len - (ber_slen_t) assertedUID.bv_len;
1506 *matchp = sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1;
1507 return LDAP_SUCCESS;
1510 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1513 return LDAP_SUCCESS;
1516 } else if ( !approx && valueUID.bv_len ) {
1519 return LDAP_SUCCESS;
1521 } else if ( !approx && assertedUID.bv_len ) {
1524 return LDAP_SUCCESS;
1527 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1531 uniqueMemberIndexer(
1536 struct berval *prefix,
1544 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1545 /* just count them */
1549 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1551 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1552 struct berval assertedDN = values[i];
1553 struct berval assertedUID = BER_BVNULL;
1555 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1556 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1557 if ( !BER_BVISNULL( &assertedUID ) ) {
1558 assertedUID.bv_val++;
1559 assertedUID.bv_len = assertedDN.bv_len
1560 - ( assertedUID.bv_val - assertedDN.bv_val );
1562 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1563 assertedDN.bv_len -= assertedUID.bv_len + 1;
1566 BER_BVZERO( &assertedUID );
1571 dnvalues[i] = assertedDN;
1573 BER_BVZERO( &dnvalues[i] );
1575 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1576 dnvalues, keysp, ctx );
1578 slap_sl_free( dnvalues, ctx );
1588 struct berval *prefix,
1589 void * assertedValue,
1593 struct berval *asserted = (struct berval *) assertedValue;
1594 struct berval assertedDN = *asserted;
1595 struct berval assertedUID = BER_BVNULL;
1597 if ( !BER_BVISEMPTY( asserted ) ) {
1598 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1599 if ( !BER_BVISNULL( &assertedUID ) ) {
1600 assertedUID.bv_val++;
1601 assertedUID.bv_len = assertedDN.bv_len
1602 - ( assertedUID.bv_val - assertedDN.bv_val );
1604 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1605 assertedDN.bv_len -= assertedUID.bv_len + 1;
1608 BER_BVZERO( &assertedUID );
1613 return octetStringFilter( use, flags, syntax, mr, prefix,
1614 &assertedDN, keysp, ctx );
1619 * Handling boolean syntax and matching is quite rigid.
1620 * A more flexible approach would be to allow a variety
1621 * of strings to be normalized and prettied into TRUE
1629 /* very unforgiving validation, requires no normalization
1630 * before simplistic matching
1633 if( in->bv_len == 4 ) {
1634 if( bvmatch( in, &slap_true_bv ) ) {
1635 return LDAP_SUCCESS;
1637 } else if( in->bv_len == 5 ) {
1638 if( bvmatch( in, &slap_false_bv ) ) {
1639 return LDAP_SUCCESS;
1643 return LDAP_INVALID_SYNTAX;
1652 struct berval *value,
1653 void *assertedValue )
1655 /* simplistic matching allowed by rigid validation */
1656 struct berval *asserted = (struct berval *) assertedValue;
1657 *matchp = (int) asserted->bv_len - (int) value->bv_len;
1658 return LDAP_SUCCESS;
1661 /*-------------------------------------------------------------------
1662 LDAP/X.500 string syntax / matching rules have a few oddities. This
1663 comment attempts to detail how slapd(8) treats them.
1666 StringSyntax X.500 LDAP Matching/Comments
1667 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1668 PrintableString subset subset i/e + ignore insignificant spaces
1669 PrintableString subset subset i/e + ignore insignificant spaces
1670 NumericString subset subset ignore all spaces
1671 IA5String ASCII ASCII i/e + ignore insignificant spaces
1672 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1674 TelephoneNumber subset subset i + ignore all spaces and "-"
1676 See RFC 4518 for details.
1680 In X.500(93), a directory string can be either a PrintableString,
1681 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1682 In later versions, more CHOICEs were added. In all cases the string
1685 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1686 A directory string cannot be zero length.
1688 For matching, there are both case ignore and exact rules. Both
1689 also require that "insignificant" spaces be ignored.
1690 spaces before the first non-space are ignored;
1691 spaces after the last non-space are ignored;
1692 spaces after a space are ignored.
1693 Note: by these rules (and as clarified in X.520), a string of only
1694 spaces is to be treated as if held one space, not empty (which
1695 would be a syntax error).
1698 In ASN.1, numeric string is just a string of digits and spaces
1699 and could be empty. However, in X.500, all attribute values of
1700 numeric string carry a non-empty constraint. For example:
1702 internationalISDNNumber ATTRIBUTE ::= {
1703 WITH SYNTAX InternationalISDNNumber
1704 EQUALITY MATCHING RULE numericStringMatch
1705 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1706 ID id-at-internationalISDNNumber }
1707 InternationalISDNNumber ::=
1708 NumericString (SIZE(1..ub-international-isdn-number))
1710 Unforunately, some assertion values are don't carry the same
1711 constraint (but its unclear how such an assertion could ever
1712 be true). In LDAP, there is one syntax (numericString) not two
1713 (numericString with constraint, numericString without constraint).
1714 This should be treated as numericString with non-empty constraint.
1715 Note that while someone may have no ISDN number, there are no ISDN
1716 numbers which are zero length.
1718 In matching, spaces are ignored.
1721 In ASN.1, Printable string is just a string of printable characters
1722 and can be empty. In X.500, semantics much like NumericString (see
1723 serialNumber for a like example) excepting uses insignificant space
1724 handling instead of ignore all spaces. They must be non-empty.
1727 Basically same as PrintableString. There are no examples in X.500,
1728 but same logic applies. Empty strings are allowed.
1730 -------------------------------------------------------------------*/
1739 unsigned char *u = (unsigned char *)in->bv_val;
1741 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1742 /* directory strings cannot be empty */
1743 return LDAP_INVALID_SYNTAX;
1746 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1747 /* get the length indicated by the first byte */
1748 len = LDAP_UTF8_CHARLEN2( u, len );
1750 /* very basic checks */
1753 if( (u[5] & 0xC0) != 0x80 ) {
1754 return LDAP_INVALID_SYNTAX;
1757 if( (u[4] & 0xC0) != 0x80 ) {
1758 return LDAP_INVALID_SYNTAX;
1761 if( (u[3] & 0xC0) != 0x80 ) {
1762 return LDAP_INVALID_SYNTAX;
1765 if( (u[2] & 0xC0 )!= 0x80 ) {
1766 return LDAP_INVALID_SYNTAX;
1769 if( (u[1] & 0xC0) != 0x80 ) {
1770 return LDAP_INVALID_SYNTAX;
1773 /* CHARLEN already validated it */
1776 return LDAP_INVALID_SYNTAX;
1779 /* make sure len corresponds with the offset
1780 to the next character */
1781 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1785 return LDAP_INVALID_SYNTAX;
1788 return LDAP_SUCCESS;
1792 UTF8StringNormalize(
1797 struct berval *normalized,
1800 struct berval tmp, nvalue;
1801 int flags, wasspace;
1804 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1806 if( BER_BVISNULL( val ) ) {
1807 /* assume we're dealing with a syntax (e.g., UTF8String)
1808 * which allows empty strings
1810 BER_BVZERO( normalized );
1811 return LDAP_SUCCESS;
1814 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1815 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1816 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1817 ? LDAP_UTF8_APPROX : 0;
1819 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1820 /* out of memory or syntax error, the former is unlikely */
1822 return LDAP_INVALID_SYNTAX;
1825 /* collapse spaces (in place) */
1827 nvalue.bv_val = tmp.bv_val;
1829 /* trim leading spaces? */
1830 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1831 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1833 for( i = 0; i < tmp.bv_len; i++) {
1834 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1835 if( wasspace++ == 0 ) {
1836 /* trim repeated spaces */
1837 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1841 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1845 if( !BER_BVISEMPTY( &nvalue ) ) {
1846 /* trim trailing space? */
1848 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1849 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1853 nvalue.bv_val[nvalue.bv_len] = '\0';
1855 } else if ( tmp.bv_len ) {
1856 /* string of all spaces is treated as one space */
1857 nvalue.bv_val[0] = ' ';
1858 nvalue.bv_val[1] = '\0';
1860 } /* should never be entered with 0-length val */
1862 *normalized = nvalue;
1863 return LDAP_SUCCESS;
1867 directoryStringSubstringsMatch(
1872 struct berval *value,
1873 void *assertedValue )
1876 SubstringsAssertion *sub = assertedValue;
1877 struct berval left = *value;
1881 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1882 if ( sub->sa_initial.bv_len > left.bv_len ) {
1883 /* not enough left */
1888 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1889 sub->sa_initial.bv_len );
1895 left.bv_val += sub->sa_initial.bv_len;
1896 left.bv_len -= sub->sa_initial.bv_len;
1898 priorspace = ASCII_SPACE(
1899 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1902 if ( sub->sa_any ) {
1903 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1907 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1908 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1910 /* allow next space to match */
1917 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1921 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1922 /* not enough left */
1927 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1934 idx = p - left.bv_val;
1936 if ( idx >= left.bv_len ) {
1937 /* this shouldn't happen */
1944 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1945 /* not enough left */
1950 match = memcmp( left.bv_val,
1951 sub->sa_any[i].bv_val,
1952 sub->sa_any[i].bv_len );
1960 left.bv_val += sub->sa_any[i].bv_len;
1961 left.bv_len -= sub->sa_any[i].bv_len;
1963 priorspace = ASCII_SPACE(
1964 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1968 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1969 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1970 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1972 /* allow next space to match */
1977 if ( sub->sa_final.bv_len > left.bv_len ) {
1978 /* not enough left */
1983 match = memcmp( sub->sa_final.bv_val,
1984 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1985 sub->sa_final.bv_len );
1994 return LDAP_SUCCESS;
1997 #if defined(SLAPD_APPROX_INITIALS)
1998 # define SLAPD_APPROX_DELIMITER "._ "
1999 # define SLAPD_APPROX_WORDLEN 2
2001 # define SLAPD_APPROX_DELIMITER " "
2002 # define SLAPD_APPROX_WORDLEN 1
2011 struct berval *value,
2012 void *assertedValue )
2014 struct berval *nval, *assertv;
2015 char *val, **values, **words, *c;
2016 int i, count, len, nextchunk=0, nextavail=0;
2018 /* Yes, this is necessary */
2019 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
2020 if( nval == NULL ) {
2022 return LDAP_SUCCESS;
2025 /* Yes, this is necessary */
2026 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
2027 NULL, LDAP_UTF8_APPROX, NULL );
2028 if( assertv == NULL ) {
2031 return LDAP_SUCCESS;
2034 /* Isolate how many words there are */
2035 for ( c = nval->bv_val, count = 1; *c; c++ ) {
2036 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
2037 if ( c == NULL ) break;
2042 /* Get a phonetic copy of each word */
2043 words = (char **)ch_malloc( count * sizeof(char *) );
2044 values = (char **)ch_malloc( count * sizeof(char *) );
2045 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
2047 values[i] = phonetic(c);
2050 /* Work through the asserted value's words, to see if at least some
2051 * of the words are there, in the same order. */
2053 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
2054 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
2059 #if defined(SLAPD_APPROX_INITIALS)
2060 else if( len == 1 ) {
2061 /* Single letter words need to at least match one word's initial */
2062 for( i=nextavail; i<count; i++ )
2063 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
2070 /* Isolate the next word in the asserted value and phonetic it */
2071 assertv->bv_val[nextchunk+len] = '\0';
2072 val = phonetic( assertv->bv_val + nextchunk );
2074 /* See if this phonetic chunk is in the remaining words of *value */
2075 for( i=nextavail; i<count; i++ ){
2076 if( !strcmp( val, values[i] ) ){
2084 /* This chunk in the asserted value was NOT within the *value. */
2090 /* Go on to the next word in the asserted value */
2094 /* If some of the words were seen, call it a match */
2095 if( nextavail > 0 ) {
2102 /* Cleanup allocs */
2103 ber_bvfree( assertv );
2104 for( i=0; i<count; i++ ) {
2105 ch_free( values[i] );
2111 return LDAP_SUCCESS;
2120 struct berval *prefix,
2126 int i,j, len, wordcount, keycount=0;
2127 struct berval *newkeys;
2128 BerVarray keys=NULL;
2130 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2131 struct berval val = BER_BVNULL;
2132 /* Yes, this is necessary */
2133 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2134 assert( !BER_BVISNULL( &val ) );
2136 /* Isolate how many words there are. There will be a key for each */
2137 for( wordcount = 0, c = val.bv_val; *c; c++) {
2138 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2139 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2141 if (*c == '\0') break;
2145 /* Allocate/increase storage to account for new keys */
2146 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2147 * sizeof(struct berval) );
2148 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2149 if( keys ) ch_free( keys );
2152 /* Get a phonetic copy of each word */
2153 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2155 if( len < SLAPD_APPROX_WORDLEN ) continue;
2156 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2161 ber_memfree( val.bv_val );
2163 BER_BVZERO( &keys[keycount] );
2166 return LDAP_SUCCESS;
2175 struct berval *prefix,
2176 void * assertedValue,
2185 /* Yes, this is necessary */
2186 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2187 NULL, LDAP_UTF8_APPROX, NULL );
2188 if( val == NULL || BER_BVISNULL( val ) ) {
2189 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2190 BER_BVZERO( &keys[0] );
2193 return LDAP_SUCCESS;
2196 /* Isolate how many words there are. There will be a key for each */
2197 for( count = 0,c = val->bv_val; *c; c++) {
2198 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2199 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2201 if (*c == '\0') break;
2205 /* Allocate storage for new keys */
2206 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2208 /* Get a phonetic copy of each word */
2209 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2211 if( len < SLAPD_APPROX_WORDLEN ) continue;
2212 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2218 BER_BVZERO( &keys[count] );
2221 return LDAP_SUCCESS;
2224 /* Remove all spaces and '-' characters */
2226 telephoneNumberNormalize(
2231 struct berval *normalized,
2236 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2238 /* validator should have refused an empty string */
2239 assert( !BER_BVISEMPTY( val ) );
2241 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2243 for( p = val->bv_val; *p; p++ ) {
2244 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2250 normalized->bv_len = q - normalized->bv_val;
2252 if( BER_BVISEMPTY( normalized ) ) {
2253 slap_sl_free( normalized->bv_val, ctx );
2254 BER_BVZERO( normalized );
2255 return LDAP_INVALID_SYNTAX;
2258 return LDAP_SUCCESS;
2262 postalAddressValidate(
2266 struct berval bv = *in;
2269 for ( c = 0; c < in->bv_len; c++ ) {
2270 if ( in->bv_val[c] == '\\' ) {
2272 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2273 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2275 return LDAP_INVALID_SYNTAX;
2280 if ( in->bv_val[c] == '$' ) {
2281 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2282 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2283 return LDAP_INVALID_SYNTAX;
2285 bv.bv_val = &in->bv_val[c] + 1;
2289 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2290 return UTF8StringValidate( NULL, &bv );
2294 postalAddressNormalize(
2299 struct berval *normalized,
2302 BerVarray lines = NULL, nlines = NULL;
2304 int rc = LDAP_SUCCESS;
2305 MatchingRule *xmr = NULL;
2308 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2309 xmr = slap_schema.si_mr_caseIgnoreMatch;
2312 xmr = slap_schema.si_mr_caseExactMatch;
2315 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2316 if ( val->bv_val[c] == '$' ) {
2321 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2322 nlines = &lines[l + 2];
2324 lines[0].bv_val = val->bv_val;
2325 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2326 if ( val->bv_val[c] == '$' ) {
2327 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2329 lines[l].bv_val = &val->bv_val[c + 1];
2332 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2334 normalized->bv_len = c = l;
2336 for ( l = 0; l <= c; l++ ) {
2337 /* NOTE: we directly normalize each line,
2338 * without unescaping the values, since the special
2339 * values '\24' ('$') and '\5C' ('\') are not affected
2340 * by normalization */
2341 if ( !lines[l].bv_len ) {
2342 nlines[l].bv_len = 0;
2343 nlines[l].bv_val = NULL;
2346 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2347 if ( rc != LDAP_SUCCESS ) {
2348 rc = LDAP_INVALID_SYNTAX;
2352 normalized->bv_len += nlines[l].bv_len;
2355 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2357 p = normalized->bv_val;
2358 for ( l = 0; l <= c ; l++ ) {
2359 p = lutil_strbvcopy( p, &nlines[l] );
2364 assert( p == &normalized->bv_val[normalized->bv_len] );
2367 if ( nlines != NULL ) {
2368 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2369 slap_sl_free( nlines[l].bv_val, ctx );
2372 slap_sl_free( lines, ctx );
2383 struct berval val = *in;
2385 if( BER_BVISEMPTY( &val ) ) {
2386 /* disallow empty strings */
2387 return LDAP_INVALID_SYNTAX;
2390 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2391 if ( val.bv_len == 1 ) {
2392 return LDAP_SUCCESS;
2395 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2402 while ( OID_LEADCHAR( val.bv_val[0] )) {
2406 if ( val.bv_len == 0 ) {
2407 return LDAP_SUCCESS;
2411 if( !OID_SEPARATOR( val.bv_val[0] )) {
2419 return LDAP_INVALID_SYNTAX;
2428 struct berval val = *in;
2430 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2432 if ( val.bv_val[0] == '-' ) {
2436 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2437 return LDAP_INVALID_SYNTAX;
2440 if( val.bv_val[0] == '0' ) { /* "-0" */
2441 return LDAP_INVALID_SYNTAX;
2444 } else if ( val.bv_val[0] == '0' ) {
2445 if( val.bv_len > 1 ) { /* "0<more>" */
2446 return LDAP_INVALID_SYNTAX;
2449 return LDAP_SUCCESS;
2452 for( i=0; i < val.bv_len; i++ ) {
2453 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2454 return LDAP_INVALID_SYNTAX;
2458 return LDAP_SUCCESS;
2467 struct berval *value,
2468 void *assertedValue )
2470 struct berval *asserted = (struct berval *) assertedValue;
2471 int vsign = 1, asign = 1; /* default sign = '+' */
2476 if( v.bv_val[0] == '-' ) {
2482 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2485 if( a.bv_val[0] == '-' ) {
2491 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2493 match = vsign - asign;
2495 match = ( v.bv_len != a.bv_len
2496 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2497 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2498 if( vsign < 0 ) match = -match;
2501 /* Ordering rule used in extensible match filter? */
2502 if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
2503 match = (match >= 0);
2506 return LDAP_SUCCESS;
2509 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2510 #define INDEX_INTLEN_CHOP 7
2511 #define INDEX_INTLEN_CHOPBYTES 3
2520 /* Integer index key format, designed for memcmp to collate correctly:
2521 * if too large: one's complement sign*<approx exponent=chopped bytes>,
2522 * two's complement value (sign-extended or chopped as needed),
2523 * however in first byte above, the top <number of exponent-bytes + 1>
2524 * bits are the inverse sign and next bit is the sign as delimiter.
2526 ber_slen_t k = index_intlen_strlen;
2528 unsigned signmask = ~0x7fU;
2529 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2530 struct berval val = *in, itmp = *tmp;
2532 if ( val.bv_val[0] != '-' ) {
2537 /* Chop least significant digits, increase length instead */
2538 if ( val.bv_len > (ber_len_t) k ) {
2539 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2540 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2541 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2544 if ( lutil_str2bin( &val, &itmp, ctx )) {
2545 return LDAP_INVALID_SYNTAX;
2548 /* Omit leading sign byte */
2549 if ( itmp.bv_val[0] == neg ) {
2554 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2556 assert( chop == 0 );
2557 memset( key->bv_val, neg, k ); /* sign-extend */
2558 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2559 /* Got exponent -k, or no room for 2 sign bits */
2560 lenp = lenbuf + sizeof(lenbuf);
2561 chop = - (ber_len_t) k;
2563 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2565 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2566 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2567 * are 1, and the top n+2 bits of lenp[0] are the sign bit. */
2568 k = (lenbuf + sizeof(lenbuf)) - lenp;
2569 if ( k > (ber_slen_t) index_intlen )
2571 memcpy( key->bv_val, lenp, k );
2572 itmp.bv_len = index_intlen - k;
2574 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2575 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2579 /* Index generation function: Ordered index */
2586 struct berval *prefix,
2596 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2598 /* count the values and find max needed length */
2600 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2601 if ( vlen < values[i].bv_len )
2602 vlen = values[i].bv_len;
2604 if ( vlen > maxstrlen )
2607 /* we should have at least one value at this point */
2610 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2611 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2612 keys[i].bv_len = index_intlen;
2613 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2616 keys[i].bv_val = NULL;
2618 if ( vlen > sizeof(ibuf) ) {
2619 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2623 itmp.bv_len = sizeof(ibuf);
2625 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2626 if ( itmp.bv_val != ibuf ) {
2627 itmp.bv_len = values[i].bv_len;
2628 if ( itmp.bv_len <= sizeof(ibuf) )
2629 itmp.bv_len = sizeof(ibuf);
2630 else if ( itmp.bv_len > maxstrlen )
2631 itmp.bv_len = maxstrlen;
2633 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2639 if ( itmp.bv_val != ibuf ) {
2640 slap_sl_free( itmp.bv_val, ctx );
2645 /* Index generation function: Ordered index */
2652 struct berval *prefix,
2653 void * assertedValue,
2660 struct berval *value;
2663 value = (struct berval *) assertedValue;
2665 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2667 keys[0].bv_len = index_intlen;
2668 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2670 keys[1].bv_val = NULL;
2672 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2673 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2674 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2675 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2678 iv.bv_len = sizeof(ibuf);
2681 rc = integerVal2Key( value, keys, &iv, ctx );
2685 if ( iv.bv_val != ibuf ) {
2686 slap_sl_free( iv.bv_val, ctx );
2692 countryStringValidate(
2694 struct berval *val )
2696 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2698 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2699 return LDAP_INVALID_SYNTAX;
2701 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2702 return LDAP_INVALID_SYNTAX;
2705 return LDAP_SUCCESS;
2709 printableStringValidate(
2711 struct berval *val )
2715 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2717 for(i=0; i < val->bv_len; i++) {
2718 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2719 return LDAP_INVALID_SYNTAX;
2723 return LDAP_SUCCESS;
2727 printablesStringValidate(
2729 struct berval *val )
2733 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2735 for(i=0,len=0; i < val->bv_len; i++) {
2736 int c = val->bv_val[i];
2740 return LDAP_INVALID_SYNTAX;
2744 } else if ( SLAP_PRINTABLE(c) ) {
2747 return LDAP_INVALID_SYNTAX;
2752 return LDAP_INVALID_SYNTAX;
2755 return LDAP_SUCCESS;
2761 struct berval *val )
2765 for(i=0; i < val->bv_len; i++) {
2766 if( !LDAP_ASCII(val->bv_val[i]) ) {
2767 return LDAP_INVALID_SYNTAX;
2771 return LDAP_SUCCESS;
2780 struct berval *normalized,
2784 int casefold = !SLAP_MR_ASSOCIATED( mr,
2785 slap_schema.si_mr_caseExactIA5Match );
2787 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2791 /* Ignore initial whitespace */
2792 while ( ASCII_SPACE( *p ) ) p++;
2794 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2795 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2796 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2797 normalized->bv_val[normalized->bv_len] = '\0';
2799 p = q = normalized->bv_val;
2802 if ( ASCII_SPACE( *p ) ) {
2805 /* Ignore the extra whitespace */
2806 while ( ASCII_SPACE( *p ) ) {
2810 } else if ( casefold ) {
2811 /* Most IA5 rules require casefolding */
2812 *q++ = TOLOWER(*p); p++;
2819 assert( normalized->bv_val <= p );
2823 * If the string ended in space, backup the pointer one
2824 * position. One is enough because the above loop collapsed
2825 * all whitespace to a single space.
2827 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2829 /* null terminate */
2832 normalized->bv_len = q - normalized->bv_val;
2834 return LDAP_SUCCESS;
2843 if( in->bv_len != 36 ) {
2844 return LDAP_INVALID_SYNTAX;
2847 for( i=0; i<36; i++ ) {
2853 if( in->bv_val[i] != '-' ) {
2854 return LDAP_INVALID_SYNTAX;
2858 if( !ASCII_HEX( in->bv_val[i]) ) {
2859 return LDAP_INVALID_SYNTAX;
2864 return LDAP_SUCCESS;
2875 int rc=LDAP_INVALID_SYNTAX;
2877 assert( in != NULL );
2878 assert( out != NULL );
2880 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2883 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2885 for( i=0; i<36; i++ ) {
2891 if( in->bv_val[i] != '-' ) {
2894 out->bv_val[i] = '-';
2898 if( !ASCII_HEX( in->bv_val[i]) ) {
2901 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2906 out->bv_val[ out->bv_len ] = '\0';
2910 slap_sl_free( out->bv_val, ctx );
2923 struct berval *normalized,
2926 unsigned char octet = '\0';
2930 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2931 /* NOTE: must be a normalized UUID */
2932 assert( val->bv_len == 16 );
2934 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2935 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2936 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2937 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2939 return LDAP_SUCCESS;
2942 normalized->bv_len = 16;
2943 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2945 for( i=0, j=0; i<36; i++ ) {
2946 unsigned char nibble;
2947 if( val->bv_val[i] == '-' ) {
2950 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2951 nibble = val->bv_val[i] - '0';
2953 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2954 nibble = val->bv_val[i] - ('a'-10);
2956 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2957 nibble = val->bv_val[i] - ('A'-10);
2960 slap_sl_free( normalized->bv_val, ctx );
2961 BER_BVZERO( normalized );
2962 return LDAP_INVALID_SYNTAX;
2967 normalized->bv_val[j>>1] = octet;
2969 octet = nibble << 4;
2974 normalized->bv_val[normalized->bv_len] = 0;
2975 return LDAP_SUCCESS;
2981 numericStringValidate(
2987 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2989 for(i=0; i < in->bv_len; i++) {
2990 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2991 return LDAP_INVALID_SYNTAX;
2995 return LDAP_SUCCESS;
2999 numericStringNormalize(
3004 struct berval *normalized,
3007 /* removal all spaces */
3010 assert( !BER_BVISEMPTY( val ) );
3012 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
3015 q = normalized->bv_val;
3018 if ( ASCII_SPACE( *p ) ) {
3019 /* Ignore whitespace */
3026 /* we should have copied no more than is in val */
3027 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3029 /* null terminate */
3032 normalized->bv_len = q - normalized->bv_val;
3034 if( BER_BVISEMPTY( normalized ) ) {
3035 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
3036 normalized->bv_val[0] = ' ';
3037 normalized->bv_val[1] = '\0';
3038 normalized->bv_len = 1;
3041 return LDAP_SUCCESS;
3045 * Integer conversion macros that will use the largest available
3048 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
3049 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
3050 # define SLAP_LONG long long
3052 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
3053 # define SLAP_LONG long
3054 #endif /* HAVE_STRTOLL ... */
3062 struct berval *value,
3063 void *assertedValue )
3065 SLAP_LONG lValue, lAssertedValue;
3068 /* safe to assume integers are NUL terminated? */
3069 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3070 if( errno == ERANGE )
3072 return LDAP_CONSTRAINT_VIOLATION;
3075 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
3077 if( errno == ERANGE )
3079 return LDAP_CONSTRAINT_VIOLATION;
3082 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
3083 return LDAP_SUCCESS;
3092 struct berval *value,
3093 void *assertedValue )
3095 SLAP_LONG lValue, lAssertedValue;
3098 /* safe to assume integers are NUL terminated? */
3099 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3100 if( errno == ERANGE )
3102 return LDAP_CONSTRAINT_VIOLATION;
3105 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3107 if( errno == ERANGE )
3109 return LDAP_CONSTRAINT_VIOLATION;
3112 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3113 return LDAP_SUCCESS;
3117 checkNum( struct berval *in, struct berval *out )
3119 /* parse serialNumber */
3120 ber_len_t neg = 0, extra = 0;
3123 out->bv_val = in->bv_val;
3126 if ( out->bv_val[0] == '-' ) {
3131 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3132 first = out->bv_val[2];
3135 out->bv_len += STRLENOF("0x");
3136 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3137 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3140 } else if ( out->bv_val[0] == '\'' ) {
3141 first = out->bv_val[1];
3144 out->bv_len += STRLENOF("'");
3146 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3147 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3149 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3152 out->bv_len += STRLENOF("'H");
3155 first = out->bv_val[0];
3156 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3157 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3161 if ( !( out->bv_len > neg ) ) {
3165 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3173 serialNumberAndIssuerCheck(
3181 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3183 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3184 /* Parse old format */
3185 is->bv_val = ber_bvchr( in, '$' );
3186 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3188 sn->bv_val = in->bv_val;
3189 sn->bv_len = is->bv_val - in->bv_val;
3192 is->bv_len = in->bv_len - (sn->bv_len + 1);
3194 /* eat leading zeros */
3195 for( n=0; n < (sn->bv_len-1); n++ ) {
3196 if( sn->bv_val[n] != '0' ) break;
3201 for( n=0; n < sn->bv_len; n++ ) {
3202 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3206 /* Parse GSER format */
3211 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3215 struct berval x = *in;
3221 /* eat leading spaces */
3222 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3226 /* should be at issuer or serialNumber NamedValue */
3227 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3228 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3231 x.bv_val += STRLENOF("issuer");
3232 x.bv_len -= STRLENOF("issuer");
3234 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3238 /* eat leading spaces */
3239 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3243 /* For backward compatibility, this part is optional */
3244 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3245 x.bv_val += STRLENOF("rdnSequence:");
3246 x.bv_len -= STRLENOF("rdnSequence:");
3249 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3253 is->bv_val = x.bv_val;
3256 for ( ; is->bv_len < x.bv_len; ) {
3257 if ( is->bv_val[is->bv_len] != '"' ) {
3261 if ( is->bv_val[is->bv_len+1] == '"' ) {
3268 x.bv_val += is->bv_len + 1;
3269 x.bv_len -= is->bv_len + 1;
3271 have |= HAVE_ISSUER;
3273 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3275 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3277 /* parse serialNumber */
3278 x.bv_val += STRLENOF("serialNumber");
3279 x.bv_len -= STRLENOF("serialNumber");
3281 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3285 /* eat leading spaces */
3286 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3290 if ( checkNum( &x, sn ) ) {
3291 return LDAP_INVALID_SYNTAX;
3294 x.bv_val += sn->bv_len;
3295 x.bv_len -= sn->bv_len;
3300 return LDAP_INVALID_SYNTAX;
3303 /* eat leading spaces */
3304 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3308 if ( have == HAVE_ALL ) {
3312 if ( x.bv_val[0] != ',' ) {
3313 return LDAP_INVALID_SYNTAX;
3320 /* should have no characters left... */
3321 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3323 if ( numdquotes == 0 ) {
3324 ber_dupbv_x( &ni, is, ctx );
3329 ni.bv_len = is->bv_len - numdquotes;
3330 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3331 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3332 if ( is->bv_val[src] == '"' ) {
3335 ni.bv_val[dst] = is->bv_val[src];
3337 ni.bv_val[dst] = '\0';
3347 serialNumberAndIssuerValidate(
3352 struct berval sn, i;
3354 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3357 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3362 /* validate DN -- doesn't handle double dquote */
3363 rc = dnValidate( NULL, &i );
3365 rc = LDAP_INVALID_SYNTAX;
3368 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3369 slap_sl_free( i.bv_val, NULL );
3372 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3373 in->bv_val, rc, 0 );
3380 serialNumberAndIssuerPretty(
3387 struct berval sn, i, ni = BER_BVNULL;
3390 assert( in != NULL );
3391 assert( out != NULL );
3395 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3398 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3403 rc = dnPretty( syntax, &i, &ni, ctx );
3405 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3406 slap_sl_free( i.bv_val, ctx );
3410 rc = LDAP_INVALID_SYNTAX;
3414 /* make room from sn + "$" */
3415 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3416 + sn.bv_len + ni.bv_len;
3417 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3419 if ( out->bv_val == NULL ) {
3426 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3427 p = lutil_strbvcopy( p, &sn );
3428 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3429 p = lutil_strbvcopy( p, &ni );
3430 p = lutil_strcopy( p, /*{*/ "\" }" );
3432 assert( p == &out->bv_val[out->bv_len] );
3435 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3436 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3438 slap_sl_free( ni.bv_val, ctx );
3440 return LDAP_SUCCESS;
3450 /* Use hex format. '123456789abcdef'H */
3451 unsigned char *ptr, zero = '\0';
3454 ber_len_t i, len, nlen;
3456 assert( in != NULL );
3457 assert( !BER_BVISNULL( in ) );
3458 assert( out != NULL );
3459 assert( !BER_BVISNULL( out ) );
3461 ptr = (unsigned char *)in->bv_val;
3464 /* Check for minimal encodings */
3466 if ( ptr[0] & 0x80 ) {
3467 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3471 } else if ( ptr[0] == 0 ) {
3472 if ( !( ptr[1] & 0x80 ) ) {
3479 } else if ( len == 0 ) {
3480 /* FIXME: this should not be possible,
3481 * since a value of zero would have length 1 */
3486 first = !( ptr[0] & 0xf0U );
3487 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3488 if ( nlen >= out->bv_len ) {
3489 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3495 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3499 for ( ; i < len; i++ ) {
3500 sprintf( sptr, "%02X", ptr[i] );
3507 assert( sptr == &out->bv_val[nlen] );
3514 #define SLAP_SN_BUFLEN (64)
3517 * This routine is called by certificateExactNormalize when
3518 * certificateExactNormalize receives a search string instead of
3519 * a certificate. This routine checks if the search value is valid
3520 * and then returns the normalized value
3523 serialNumberAndIssuerNormalize(
3531 struct berval sn, sn2, sn3, i, ni;
3532 char sbuf2[SLAP_SN_BUFLEN];
3533 char sbuf3[SLAP_SN_BUFLEN];
3537 assert( in != NULL );
3538 assert( out != NULL );
3540 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3543 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3548 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3550 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3551 slap_sl_free( i.bv_val, ctx );
3555 return LDAP_INVALID_SYNTAX;
3558 /* Convert sn to canonical hex */
3560 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3561 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3563 sn2.bv_len = sn.bv_len;
3565 sn3.bv_len = sizeof(sbuf3);
3566 if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
3567 rc = LDAP_INVALID_SYNTAX;
3571 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3572 + sn3.bv_len + ni.bv_len;
3573 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3574 if ( out->bv_val == NULL ) {
3582 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3583 p = lutil_strbvcopy( p, &sn3 );
3584 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3585 p = lutil_strbvcopy( p, &ni );
3586 p = lutil_strcopy( p, /*{*/ "\" }" );
3588 assert( p == &out->bv_val[out->bv_len] );
3591 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3592 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3594 if ( sn2.bv_val != sbuf2 ) {
3595 slap_sl_free( sn2.bv_val, ctx );
3598 if ( sn3.bv_val != sbuf3 ) {
3599 slap_sl_free( sn3.bv_val, ctx );
3602 slap_sl_free( ni.bv_val, ctx );
3608 certificateExactNormalize(
3613 struct berval *normalized,
3616 BerElementBuffer berbuf;
3617 BerElement *ber = (BerElement *)&berbuf;
3621 char serialbuf2[SLAP_SN_BUFLEN];
3622 struct berval sn, sn2 = BER_BVNULL;
3623 struct berval issuer_dn = BER_BVNULL, bvdn;
3625 int rc = LDAP_INVALID_SYNTAX;
3627 assert( val != NULL );
3629 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3630 val->bv_val, val->bv_len, 0 );
3632 if ( BER_BVISEMPTY( val ) ) goto done;
3634 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3635 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3638 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3640 ber_init2( ber, val, LBER_USE_DER );
3641 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3642 tag = ber_skip_tag( ber, &len ); /* Sequence */
3643 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3644 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3645 tag = ber_skip_tag( ber, &len );
3646 tag = ber_get_int( ber, &i ); /* version */
3649 /* NOTE: move the test here from certificateValidate,
3650 * so that we can validate certs with serial longer
3651 * than sizeof(ber_int_t) */
3652 tag = ber_skip_tag( ber, &len ); /* serial */
3654 sn.bv_val = (char *)ber->ber_ptr;
3655 sn2.bv_val = serialbuf2;
3656 sn2.bv_len = sizeof(serialbuf2);
3657 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3658 rc = LDAP_INVALID_SYNTAX;
3661 ber_skip_data( ber, len );
3663 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3664 ber_skip_data( ber, len );
3665 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3666 len = ber_ptrlen( ber );
3667 bvdn.bv_val = val->bv_val + len;
3668 bvdn.bv_len = val->bv_len - len;
3670 rc = dnX509normalize( &bvdn, &issuer_dn );
3671 if ( rc != LDAP_SUCCESS ) goto done;
3673 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3674 + sn2.bv_len + issuer_dn.bv_len;
3675 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3677 p = normalized->bv_val;
3679 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3680 p = lutil_strbvcopy( p, &sn2 );
3681 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3682 p = lutil_strbvcopy( p, &issuer_dn );
3683 p = lutil_strcopy( p, /*{*/ "\" }" );
3688 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3689 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3691 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3692 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3697 /* X.509 PKI certificateList stuff */
3699 checkTime( struct berval *in, struct berval *out )
3703 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3706 assert( in != NULL );
3707 assert( !BER_BVISNULL( in ) );
3708 assert( !BER_BVISEMPTY( in ) );
3710 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3714 if ( out != NULL ) {
3715 assert( !BER_BVISNULL( out ) );
3716 assert( out->bv_len >= sizeof( buf ) );
3717 bv.bv_val = out->bv_val;
3723 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3724 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3727 if ( in->bv_val[i] != 'Z' ) {
3732 if ( i != in->bv_len ) {
3736 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3737 lutil_strncopy( bv.bv_val, in->bv_val, i );
3740 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3741 char *p = bv.bv_val;
3742 if ( in->bv_val[0] < '7' ) {
3743 p = lutil_strcopy( p, "20" );
3746 p = lutil_strcopy( p, "19" );
3748 lutil_strncopy( p, in->bv_val, i );
3755 rc = generalizedTimeValidate( NULL, &bv );
3756 if ( rc == LDAP_SUCCESS && out != NULL ) {
3757 if ( out->bv_len > bv.bv_len ) {
3758 out->bv_val[ bv.bv_len ] = '\0';
3760 out->bv_len = bv.bv_len;
3763 return rc != LDAP_SUCCESS;
3767 issuerAndThisUpdateCheck(
3774 struct berval x = *in;
3775 struct berval ni = BER_BVNULL;
3776 /* Parse GSER format */
3780 HAVE_THISUPDATE = 0x2,
3781 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3785 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3787 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3788 return LDAP_INVALID_SYNTAX;
3792 x.bv_len -= STRLENOF("{}");
3795 /* eat leading spaces */
3796 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3800 /* should be at issuer or thisUpdate */
3801 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3802 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3805 x.bv_val += STRLENOF("issuer");
3806 x.bv_len -= STRLENOF("issuer");
3808 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3812 /* eat leading spaces */
3813 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3817 /* For backward compatibility, this part is optional */
3818 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3819 return LDAP_INVALID_SYNTAX;
3821 x.bv_val += STRLENOF("rdnSequence:");
3822 x.bv_len -= STRLENOF("rdnSequence:");
3824 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3828 is->bv_val = x.bv_val;
3831 for ( ; is->bv_len < x.bv_len; ) {
3832 if ( is->bv_val[is->bv_len] != '"' ) {
3836 if ( is->bv_val[is->bv_len+1] == '"' ) {
3843 x.bv_val += is->bv_len + 1;
3844 x.bv_len -= is->bv_len + 1;
3846 have |= HAVE_ISSUER;
3848 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3850 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3852 /* parse thisUpdate */
3853 x.bv_val += STRLENOF("thisUpdate");
3854 x.bv_len -= STRLENOF("thisUpdate");
3856 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3860 /* eat leading spaces */
3861 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3865 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3869 tu->bv_val = x.bv_val;
3872 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3873 if ( tu->bv_val[tu->bv_len] == '"' ) {
3877 x.bv_val += tu->bv_len + 1;
3878 x.bv_len -= tu->bv_len + 1;
3880 have |= HAVE_THISUPDATE;
3883 return LDAP_INVALID_SYNTAX;
3886 /* eat leading spaces */
3887 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3891 if ( have == HAVE_ALL ) {
3895 if ( x.bv_val[0] != ',' ) {
3896 return LDAP_INVALID_SYNTAX;
3903 /* should have no characters left... */
3904 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3906 if ( numdquotes == 0 ) {
3907 ber_dupbv_x( &ni, is, ctx );
3912 ni.bv_len = is->bv_len - numdquotes;
3913 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3914 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3915 if ( is->bv_val[src] == '"' ) {
3918 ni.bv_val[dst] = is->bv_val[src];
3920 ni.bv_val[dst] = '\0';
3929 issuerAndThisUpdateValidate(
3934 struct berval i, tu;
3936 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3939 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3944 /* validate DN -- doesn't handle double dquote */
3945 rc = dnValidate( NULL, &i );
3947 rc = LDAP_INVALID_SYNTAX;
3949 } else if ( checkTime( &tu, NULL ) ) {
3950 rc = LDAP_INVALID_SYNTAX;
3953 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3954 slap_sl_free( i.bv_val, NULL );
3957 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3958 in->bv_val, rc, 0 );
3965 issuerAndThisUpdatePretty(
3972 struct berval i, tu, ni = BER_BVNULL;
3975 assert( in != NULL );
3976 assert( out != NULL );
3980 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3983 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3988 rc = dnPretty( syntax, &i, &ni, ctx );
3990 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3991 slap_sl_free( i.bv_val, ctx );
3994 if ( rc || checkTime( &tu, NULL ) ) {
3995 rc = LDAP_INVALID_SYNTAX;
4000 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
4001 + ni.bv_len + tu.bv_len;
4002 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4004 if ( out->bv_val == NULL ) {
4011 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4012 p = lutil_strbvcopy( p, &ni );
4013 p = lutil_strcopy( p, "\", thisUpdate \"" );
4014 p = lutil_strbvcopy( p, &tu );
4015 p = lutil_strcopy( p, /*{*/ "\" }" );
4017 assert( p == &out->bv_val[out->bv_len] );
4020 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
4021 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4023 slap_sl_free( ni.bv_val, ctx );
4029 issuerAndThisUpdateNormalize(
4037 struct berval i, ni, tu, tu2;
4038 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4042 assert( in != NULL );
4043 assert( out != NULL );
4045 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
4048 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4053 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4055 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4056 slap_sl_free( i.bv_val, ctx );
4060 tu2.bv_len = sizeof( sbuf );
4061 if ( rc || checkTime( &tu, &tu2 ) ) {
4062 return LDAP_INVALID_SYNTAX;
4065 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4066 + ni.bv_len + tu2.bv_len;
4067 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4069 if ( out->bv_val == NULL ) {
4077 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4078 p = lutil_strbvcopy( p, &ni );
4079 p = lutil_strcopy( p, "\", thisUpdate \"" );
4080 p = lutil_strbvcopy( p, &tu2 );
4081 p = lutil_strcopy( p, /*{*/ "\" }" );
4083 assert( p == &out->bv_val[out->bv_len] );
4086 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4087 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4089 slap_sl_free( ni.bv_val, ctx );
4095 certificateListExactNormalize(
4100 struct berval *normalized,
4103 BerElementBuffer berbuf;
4104 BerElement *ber = (BerElement *)&berbuf;
4108 struct berval issuer_dn = BER_BVNULL, bvdn,
4110 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4111 int rc = LDAP_INVALID_SYNTAX;
4113 assert( val != NULL );
4115 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4116 val->bv_val, val->bv_len, 0 );
4118 if ( BER_BVISEMPTY( val ) ) goto done;
4120 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4121 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4124 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4126 ber_init2( ber, val, LBER_USE_DER );
4127 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4128 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4129 tag = ber_skip_tag( ber, &len ); /* Sequence */
4130 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4131 tag = ber_peek_tag( ber, &len );
4132 /* Optional version */
4133 if ( tag == LBER_INTEGER ) {
4134 tag = ber_get_int( ber, &version );
4135 assert( tag == LBER_INTEGER );
4136 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4138 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4139 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4140 ber_skip_data( ber, len );
4142 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4143 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4144 len = ber_ptrlen( ber );
4145 bvdn.bv_val = val->bv_val + len;
4146 bvdn.bv_len = val->bv_len - len;
4147 tag = ber_skip_tag( ber, &len );
4148 ber_skip_data( ber, len );
4150 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4151 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4152 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4153 bvtu.bv_val = (char *)ber->ber_ptr;
4156 rc = dnX509normalize( &bvdn, &issuer_dn );
4157 if ( rc != LDAP_SUCCESS ) goto done;
4159 thisUpdate.bv_val = tubuf;
4160 thisUpdate.bv_len = sizeof(tubuf);
4161 if ( checkTime( &bvtu, &thisUpdate ) ) {
4162 rc = LDAP_INVALID_SYNTAX;
4166 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4167 + issuer_dn.bv_len + thisUpdate.bv_len;
4168 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4170 p = normalized->bv_val;
4172 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4173 p = lutil_strbvcopy( p, &issuer_dn );
4174 p = lutil_strcopy( p, "\", thisUpdate \"" );
4175 p = lutil_strbvcopy( p, &thisUpdate );
4176 p = lutil_strcopy( p, /*{*/ "\" }" );
4181 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4182 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4184 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4189 /* X.509 PMI serialNumberAndIssuerSerialCheck
4191 AttributeCertificateExactAssertion ::= SEQUENCE {
4192 serialNumber CertificateSerialNumber,
4193 issuer AttCertIssuer }
4195 CertificateSerialNumber ::= INTEGER
4197 AttCertIssuer ::= [0] SEQUENCE {
4198 issuerName GeneralNames OPTIONAL,
4199 baseCertificateID [0] IssuerSerial OPTIONAL,
4200 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4201 -- At least one component shall be present
4203 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4205 GeneralName ::= CHOICE {
4206 otherName [0] INSTANCE OF OTHER-NAME,
4207 rfc822Name [1] IA5String,
4208 dNSName [2] IA5String,
4209 x400Address [3] ORAddress,
4210 directoryName [4] Name,
4211 ediPartyName [5] EDIPartyName,
4212 uniformResourceIdentifier [6] IA5String,
4213 iPAddress [7] OCTET STRING,
4214 registeredID [8] OBJECT IDENTIFIER }
4216 IssuerSerial ::= SEQUENCE {
4217 issuer GeneralNames,
4218 serial CertificateSerialNumber,
4219 issuerUID UniqueIdentifier OPTIONAL }
4221 ObjectDigestInfo ::= SEQUENCE {
4222 digestedObjectType ENUMERATED {
4225 otherObjectTypes (2) },
4226 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4227 digestAlgorithm AlgorithmIdentifier,
4228 objectDigest BIT STRING }
4230 * The way I interpret it, an assertion should look like
4232 { serialNumber 'dd'H,
4233 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4234 baseCertificateID { serial '1d'H,
4235 issuer { directoryName:rdnSequence:"cn=zzz" },
4236 issuerUID <value> -- optional
4238 objectDigestInfo { ... } -- optional
4242 * with issuerName, baseCertificateID and objectDigestInfo optional,
4243 * at least one present; the way it's currently implemented, it is
4245 { serialNumber 'dd'H,
4246 issuer { baseCertificateID { serial '1d'H,
4247 issuer { directoryName:rdnSequence:"cn=zzz" }
4252 * with all the above parts mandatory.
4255 serialNumberAndIssuerSerialCheck(
4259 struct berval *i_sn, /* contain serial of baseCertificateID */
4262 /* Parse GSER format */
4267 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4268 } have = HAVE_NONE, have2 = HAVE_NONE;
4270 struct berval x = *in;
4273 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4276 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4283 /* eat leading spaces */
4284 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4288 /* should be at issuer or serialNumber NamedValue */
4289 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4290 if ( have & HAVE_ISSUER ) {
4291 return LDAP_INVALID_SYNTAX;
4294 /* parse IssuerSerial */
4295 x.bv_val += STRLENOF("issuer");
4296 x.bv_len -= STRLENOF("issuer");
4298 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4302 /* eat leading spaces */
4303 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4307 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4311 /* eat leading spaces */
4312 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4316 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4317 return LDAP_INVALID_SYNTAX;
4319 x.bv_val += STRLENOF("baseCertificateID ");
4320 x.bv_len -= STRLENOF("baseCertificateID ");
4322 /* eat leading spaces */
4323 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4327 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4332 /* eat leading spaces */
4333 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4337 /* parse issuer of baseCertificateID */
4338 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4339 if ( have2 & HAVE_ISSUER ) {
4340 return LDAP_INVALID_SYNTAX;
4343 x.bv_val += STRLENOF("issuer ");
4344 x.bv_len -= STRLENOF("issuer ");
4346 /* eat leading spaces */
4347 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4351 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4355 /* eat leading spaces */
4356 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4360 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4361 return LDAP_INVALID_SYNTAX;
4363 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4364 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4366 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4370 is->bv_val = x.bv_val;
4373 for ( ; is->bv_len < x.bv_len; ) {
4374 if ( is->bv_val[is->bv_len] != '"' ) {
4378 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4385 x.bv_val += is->bv_len + 1;
4386 x.bv_len -= is->bv_len + 1;
4388 /* eat leading spaces */
4389 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4393 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4397 have2 |= HAVE_ISSUER;
4399 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4400 if ( have2 & HAVE_SN ) {
4401 return LDAP_INVALID_SYNTAX;
4404 x.bv_val += STRLENOF("serial ");
4405 x.bv_len -= STRLENOF("serial ");
4407 /* eat leading spaces */
4408 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4412 if ( checkNum( &x, i_sn ) ) {
4413 return LDAP_INVALID_SYNTAX;
4416 x.bv_val += i_sn->bv_len;
4417 x.bv_len -= i_sn->bv_len;
4422 return LDAP_INVALID_SYNTAX;
4425 /* eat leading spaces */
4426 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4430 if ( have2 == HAVE_ALL ) {
4434 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4439 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4443 /* eat leading spaces */
4444 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4448 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4452 have |= HAVE_ISSUER;
4454 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4455 if ( have & HAVE_SN ) {
4456 return LDAP_INVALID_SYNTAX;
4459 /* parse serialNumber */
4460 x.bv_val += STRLENOF("serialNumber");
4461 x.bv_len -= STRLENOF("serialNumber");
4463 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4467 /* eat leading spaces */
4468 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4472 if ( checkNum( &x, sn ) ) {
4473 return LDAP_INVALID_SYNTAX;
4476 x.bv_val += sn->bv_len;
4477 x.bv_len -= sn->bv_len;
4482 return LDAP_INVALID_SYNTAX;
4486 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4490 if ( have == HAVE_ALL ) {
4494 if ( x.bv_val[0] != ',' ) {
4495 return LDAP_INVALID_SYNTAX;
4501 /* should have no characters left... */
4502 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4504 if ( numdquotes == 0 ) {
4505 ber_dupbv_x( &ni, is, ctx );
4510 ni.bv_len = is->bv_len - numdquotes;
4511 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4512 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4513 if ( is->bv_val[src] == '"' ) {
4516 ni.bv_val[dst] = is->bv_val[src];
4518 ni.bv_val[dst] = '\0';
4523 /* need to handle double dquotes here */
4527 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4529 serialNumberAndIssuerSerialValidate(
4534 struct berval sn, i, i_sn;
4536 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4539 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4544 /* validate DN -- doesn't handle double dquote */
4545 rc = dnValidate( NULL, &i );
4547 rc = LDAP_INVALID_SYNTAX;
4550 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4551 slap_sl_free( i.bv_val, NULL );
4555 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4556 in->bv_val, rc, 0 );
4561 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4563 serialNumberAndIssuerSerialPretty(
4569 struct berval sn, i, i_sn, ni = BER_BVNULL;
4573 assert( in != NULL );
4574 assert( out != NULL );
4576 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4579 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4584 rc = dnPretty( syntax, &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 /* make room from sn + "$" */
4596 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4597 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4598 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4600 if ( out->bv_val == NULL ) {
4607 p = lutil_strcopy( p, "{ serialNumber " );
4608 p = lutil_strbvcopy( p, &sn );
4609 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4610 p = lutil_strbvcopy( p, &ni );
4611 p = lutil_strcopy( p, "\" }, serial " );
4612 p = lutil_strbvcopy( p, &i_sn );
4613 p = lutil_strcopy( p, " } } }" );
4615 assert( p == &out->bv_val[out->bv_len] );
4618 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4619 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4621 slap_sl_free( ni.bv_val, ctx );
4626 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4628 * This routine is called by attributeCertificateExactNormalize
4629 * when attributeCertificateExactNormalize receives a search
4630 * string instead of a attribute certificate. This routine
4631 * checks if the search value is valid and then returns the
4635 serialNumberAndIssuerSerialNormalize(
4643 struct berval i, ni = BER_BVNULL,
4644 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4645 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4646 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4647 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4651 assert( in != NULL );
4652 assert( out != NULL );
4654 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4657 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4662 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4664 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4665 slap_sl_free( i.bv_val, ctx );
4669 rc = LDAP_INVALID_SYNTAX;
4673 /* Convert sn to canonical hex */
4675 sn2.bv_len = sn.bv_len;
4676 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4677 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4679 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4680 rc = LDAP_INVALID_SYNTAX;
4684 /* Convert i_sn to canonical hex */
4685 i_sn2.bv_val = i_sbuf2;
4686 i_sn2.bv_len = i_sn.bv_len;
4687 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4688 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4690 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4691 rc = LDAP_INVALID_SYNTAX;
4696 sn3.bv_len = sizeof(sbuf3);
4697 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4698 rc = LDAP_INVALID_SYNTAX;
4702 i_sn3.bv_val = i_sbuf3;
4703 i_sn3.bv_len = sizeof(i_sbuf3);
4704 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4705 rc = LDAP_INVALID_SYNTAX;
4709 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4710 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4711 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4713 if ( out->bv_val == NULL ) {
4721 p = lutil_strcopy( p, "{ serialNumber " );
4722 p = lutil_strbvcopy( p, &sn3 );
4723 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4724 p = lutil_strbvcopy( p, &ni );
4725 p = lutil_strcopy( p, "\" }, serial " );
4726 p = lutil_strbvcopy( p, &i_sn3 );
4727 p = lutil_strcopy( p, " } } }" );
4729 assert( p == &out->bv_val[out->bv_len] );
4732 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4733 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4735 if ( sn2.bv_val != sbuf2 ) {
4736 slap_sl_free( sn2.bv_val, ctx );
4739 if ( i_sn2.bv_val != i_sbuf2 ) {
4740 slap_sl_free( i_sn2.bv_val, ctx );
4743 if ( sn3.bv_val != sbuf3 ) {
4744 slap_sl_free( sn3.bv_val, ctx );
4747 if ( i_sn3.bv_val != i_sbuf3 ) {
4748 slap_sl_free( i_sn3.bv_val, ctx );
4751 slap_sl_free( ni.bv_val, ctx );
4756 /* X.509 PMI attributeCertificateExactNormalize */
4758 attributeCertificateExactNormalize(
4763 struct berval *normalized,
4766 BerElementBuffer berbuf;
4767 BerElement *ber = (BerElement *)&berbuf;
4770 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4771 struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
4772 struct berval issuer_dn = BER_BVNULL, bvdn;
4774 int rc = LDAP_INVALID_SYNTAX;
4776 if ( BER_BVISEMPTY( val ) ) {
4780 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4781 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4784 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4786 ber_init2( ber, val, LBER_USE_DER );
4787 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4788 tag = ber_skip_tag( ber, &len ); /* Sequence */
4789 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4790 ber_skip_data( ber, len );
4791 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4792 ber_skip_data( ber, len );
4795 tag = ber_skip_tag( ber, &len ); /* Sequence */
4796 /* issuerName (GeneralNames sequence; optional)? */
4797 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4798 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4799 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4800 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4801 return LDAP_INVALID_SYNTAX;
4803 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4804 len = ber_ptrlen( ber );
4805 bvdn.bv_val = val->bv_val + len;
4806 bvdn.bv_len = val->bv_len - len;
4807 rc = dnX509normalize( &bvdn, &issuer_dn );
4808 if ( rc != LDAP_SUCCESS ) goto done;
4810 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4811 ber_skip_data( ber, len );
4812 tag = ber_skip_tag( ber, &len ); /* serial number */
4813 if ( tag != LBER_INTEGER ) {
4814 rc = LDAP_INVALID_SYNTAX;
4817 i_sn.bv_val = (char *)ber->ber_ptr;
4819 i_sn2.bv_val = issuer_serialbuf;
4820 i_sn2.bv_len = sizeof(issuer_serialbuf);
4821 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4822 rc = LDAP_INVALID_SYNTAX;
4825 ber_skip_data( ber, len );
4827 /* issuerUID (bitstring; optional)? */
4828 /* objectDigestInfo (sequence; optional)? */
4830 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4831 ber_skip_data( ber, len );
4832 tag = ber_skip_tag( ber, &len ); /* serial number */
4833 if ( tag != LBER_INTEGER ) {
4834 rc = LDAP_INVALID_SYNTAX;
4837 sn.bv_val = (char *)ber->ber_ptr;
4839 sn2.bv_val = serialbuf;
4840 sn2.bv_len = sizeof(serialbuf);
4841 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4842 rc = LDAP_INVALID_SYNTAX;
4845 ber_skip_data( ber, len );
4847 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4848 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4849 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4851 p = normalized->bv_val;
4853 p = lutil_strcopy( p, "{ serialNumber " );
4854 p = lutil_strbvcopy( p, &sn2 );
4855 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4856 p = lutil_strbvcopy( p, &issuer_dn );
4857 p = lutil_strcopy( p, "\" }, serial " );
4858 p = lutil_strbvcopy( p, &i_sn2 );
4859 p = lutil_strcopy( p, " } } }" );
4861 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4862 normalized->bv_val, NULL, NULL );
4867 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4868 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4869 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4882 assert( in != NULL );
4883 assert( !BER_BVISNULL( in ) );
4885 for ( i = 0; i < in->bv_len; i++ ) {
4886 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4887 return LDAP_INVALID_SYNTAX;
4891 return LDAP_SUCCESS;
4894 /* Normalize a SID as used inside a CSN:
4895 * three-digit numeric string */
4902 struct berval *normalized,
4907 assert( val != NULL );
4908 assert( normalized != NULL );
4910 ber_dupbv_x( normalized, val, ctx );
4912 for ( i = 0; i < normalized->bv_len; i++ ) {
4913 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4914 ber_memfree_x( normalized->bv_val, ctx );
4915 BER_BVZERO( normalized );
4916 return LDAP_INVALID_SYNTAX;
4919 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4922 return LDAP_SUCCESS;
4930 assert( in != NULL );
4931 assert( !BER_BVISNULL( in ) );
4933 if ( in->bv_len != 3 ) {
4934 return LDAP_INVALID_SYNTAX;
4937 return hexValidate( NULL, in );
4940 /* Normalize a SID as used inside a CSN:
4941 * three-digit numeric string */
4948 struct berval *normalized,
4951 if ( val->bv_len != 3 ) {
4952 return LDAP_INVALID_SYNTAX;
4955 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4965 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4968 /* Normalize a SID as used inside a CSN, either as-is
4969 * (assertion value) or extracted from the CSN
4970 * (attribute value) */
4977 struct berval *normalized,
4985 if ( BER_BVISEMPTY( val ) ) {
4986 return LDAP_INVALID_SYNTAX;
4989 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4990 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4993 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4995 ptr = ber_bvchr( val, '#' );
4996 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4997 return LDAP_INVALID_SYNTAX;
5000 bv.bv_val = ptr + 1;
5001 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5003 ptr = ber_bvchr( &bv, '#' );
5004 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5005 return LDAP_INVALID_SYNTAX;
5008 bv.bv_val = ptr + 1;
5009 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5011 ptr = ber_bvchr( &bv, '#' );
5012 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5013 return LDAP_INVALID_SYNTAX;
5016 bv.bv_len = ptr - bv.bv_val;
5018 if ( bv.bv_len == 2 ) {
5019 /* OpenLDAP 2.3 SID */
5021 buf[ 1 ] = bv.bv_val[ 0 ];
5022 buf[ 2 ] = bv.bv_val[ 1 ];
5029 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
5041 assert( in != NULL );
5042 assert( !BER_BVISNULL( in ) );
5044 if ( BER_BVISEMPTY( in ) ) {
5045 return LDAP_INVALID_SYNTAX;
5050 ptr = ber_bvchr( &bv, '#' );
5051 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
5052 return LDAP_INVALID_SYNTAX;
5055 bv.bv_len = ptr - bv.bv_val;
5056 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
5057 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
5059 return LDAP_INVALID_SYNTAX;
5062 rc = generalizedTimeValidate( NULL, &bv );
5063 if ( rc != LDAP_SUCCESS ) {
5067 bv.bv_val = ptr + 1;
5068 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5070 ptr = ber_bvchr( &bv, '#' );
5071 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5072 return LDAP_INVALID_SYNTAX;
5075 bv.bv_len = ptr - bv.bv_val;
5076 if ( bv.bv_len != 6 ) {
5077 return LDAP_INVALID_SYNTAX;
5080 rc = hexValidate( NULL, &bv );
5081 if ( rc != LDAP_SUCCESS ) {
5085 bv.bv_val = ptr + 1;
5086 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5088 ptr = ber_bvchr( &bv, '#' );
5089 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5090 return LDAP_INVALID_SYNTAX;
5093 bv.bv_len = ptr - bv.bv_val;
5094 if ( bv.bv_len == 2 ) {
5095 /* tolerate old 2-digit replica-id */
5096 rc = hexValidate( NULL, &bv );
5099 rc = sidValidate( NULL, &bv );
5101 if ( rc != LDAP_SUCCESS ) {
5105 bv.bv_val = ptr + 1;
5106 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5108 if ( bv.bv_len != 6 ) {
5109 return LDAP_INVALID_SYNTAX;
5112 return hexValidate( NULL, &bv );
5115 /* Normalize a CSN in OpenLDAP 2.1 format */
5122 struct berval *normalized,
5125 struct berval gt, cnt, sid, mod;
5127 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5131 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5132 assert( !BER_BVISEMPTY( val ) );
5136 ptr = ber_bvchr( >, '#' );
5137 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5138 return LDAP_INVALID_SYNTAX;
5141 gt.bv_len = ptr - gt.bv_val;
5142 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5143 return LDAP_INVALID_SYNTAX;
5146 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5147 return LDAP_INVALID_SYNTAX;
5150 cnt.bv_val = ptr + 1;
5151 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5153 ptr = ber_bvchr( &cnt, '#' );
5154 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5155 return LDAP_INVALID_SYNTAX;
5158 cnt.bv_len = ptr - cnt.bv_val;
5159 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5160 return LDAP_INVALID_SYNTAX;
5163 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5164 return LDAP_INVALID_SYNTAX;
5167 cnt.bv_val += STRLENOF( "0x" );
5168 cnt.bv_len -= STRLENOF( "0x" );
5170 sid.bv_val = ptr + 1;
5171 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5173 ptr = ber_bvchr( &sid, '#' );
5174 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5175 return LDAP_INVALID_SYNTAX;
5178 sid.bv_len = ptr - sid.bv_val;
5179 if ( sid.bv_len != STRLENOF( "0" ) ) {
5180 return LDAP_INVALID_SYNTAX;
5183 mod.bv_val = ptr + 1;
5184 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5185 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5186 return LDAP_INVALID_SYNTAX;
5189 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5193 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5194 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5196 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5198 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5199 ptr = lutil_strbvcopy( ptr, &cnt );
5203 *ptr++ = sid.bv_val[ 0 ];
5207 for ( i = 0; i < mod.bv_len; i++ ) {
5208 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5212 assert( ptr == &bv.bv_val[bv.bv_len] );
5214 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5215 return LDAP_INVALID_SYNTAX;
5218 ber_dupbv_x( normalized, &bv, ctx );
5220 return LDAP_SUCCESS;
5223 /* Normalize a CSN in OpenLDAP 2.3 format */
5230 struct berval *normalized,
5233 struct berval gt, cnt, sid, mod;
5235 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5239 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5240 assert( !BER_BVISEMPTY( val ) );
5244 ptr = ber_bvchr( >, '#' );
5245 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5246 return LDAP_INVALID_SYNTAX;
5249 gt.bv_len = ptr - gt.bv_val;
5250 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5251 return LDAP_INVALID_SYNTAX;
5254 cnt.bv_val = ptr + 1;
5255 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5257 ptr = ber_bvchr( &cnt, '#' );
5258 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5259 return LDAP_INVALID_SYNTAX;
5262 cnt.bv_len = ptr - cnt.bv_val;
5263 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5264 return LDAP_INVALID_SYNTAX;
5267 sid.bv_val = ptr + 1;
5268 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5270 ptr = ber_bvchr( &sid, '#' );
5271 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5272 return LDAP_INVALID_SYNTAX;
5275 sid.bv_len = ptr - sid.bv_val;
5276 if ( sid.bv_len != STRLENOF( "00" ) ) {
5277 return LDAP_INVALID_SYNTAX;
5280 mod.bv_val = ptr + 1;
5281 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5282 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5283 return LDAP_INVALID_SYNTAX;
5286 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5290 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5291 ptr = lutil_strcopy( ptr, ".000000Z#" );
5292 ptr = lutil_strbvcopy( ptr, &cnt );
5295 for ( i = 0; i < sid.bv_len; i++ ) {
5296 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5299 for ( i = 0; i < mod.bv_len; i++ ) {
5300 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5304 assert( ptr == &bv.bv_val[bv.bv_len] );
5305 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5306 return LDAP_INVALID_SYNTAX;
5309 ber_dupbv_x( normalized, &bv, ctx );
5311 return LDAP_SUCCESS;
5314 /* Normalize a CSN */
5321 struct berval *normalized,
5324 struct berval cnt, sid, mod;
5328 assert( val != NULL );
5329 assert( normalized != NULL );
5331 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5333 if ( BER_BVISEMPTY( val ) ) {
5334 return LDAP_INVALID_SYNTAX;
5337 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5338 /* Openldap <= 2.3 */
5340 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5343 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5346 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5349 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5350 return LDAP_INVALID_SYNTAX;
5353 ptr = ber_bvchr( val, '#' );
5354 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5355 return LDAP_INVALID_SYNTAX;
5358 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5359 return LDAP_INVALID_SYNTAX;
5362 cnt.bv_val = ptr + 1;
5363 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5365 ptr = ber_bvchr( &cnt, '#' );
5366 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5367 return LDAP_INVALID_SYNTAX;
5370 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5371 return LDAP_INVALID_SYNTAX;
5374 sid.bv_val = ptr + 1;
5375 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5377 ptr = ber_bvchr( &sid, '#' );
5378 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5379 return LDAP_INVALID_SYNTAX;
5382 sid.bv_len = ptr - sid.bv_val;
5383 if ( sid.bv_len != STRLENOF( "000" ) ) {
5384 return LDAP_INVALID_SYNTAX;
5387 mod.bv_val = ptr + 1;
5388 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5390 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5391 return LDAP_INVALID_SYNTAX;
5394 ber_dupbv_x( normalized, val, ctx );
5396 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5397 i < normalized->bv_len; i++ )
5399 /* assume it's already validated that's all hex digits */
5400 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5403 return LDAP_SUCCESS;
5413 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5416 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5417 /* slight optimization - does not need the start parameter */
5418 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5423 check_time_syntax (struct berval *val,
5426 struct berval *fraction)
5429 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5430 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5431 * GeneralizedTime supports leap seconds, UTCTime does not.
5433 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5434 static const int mdays[2][12] = {
5435 /* non-leap years */
5436 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5438 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5441 int part, c, c1, c2, tzoffset, leapyear = 0;
5444 e = p + val->bv_len;
5446 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5447 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5449 for (part = start; part < 7 && p < e; part++) {
5451 if (!ASCII_DIGIT(c1)) {
5456 return LDAP_INVALID_SYNTAX;
5459 if (!ASCII_DIGIT(c)) {
5460 return LDAP_INVALID_SYNTAX;
5462 c += c1 * 10 - '0' * 11;
5463 if ((part | 1) == 3) {
5466 return LDAP_INVALID_SYNTAX;
5469 if (c >= ceiling[part]) {
5470 if (! (c == 60 && part == 6 && start == 0))
5471 return LDAP_INVALID_SYNTAX;
5475 if (part < 5 + start) {
5476 return LDAP_INVALID_SYNTAX;
5478 for (; part < 9; part++) {
5482 /* leapyear check for the Gregorian calendar (year>1581) */
5483 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5487 if (parts[3] >= mdays[leapyear][parts[2]]) {
5488 return LDAP_INVALID_SYNTAX;
5492 fraction->bv_val = p;
5493 fraction->bv_len = 0;
5494 if (p < e && (*p == '.' || *p == ',')) {
5496 while (++p < e && ASCII_DIGIT(*p)) {
5499 if (p - fraction->bv_val == 1) {
5500 return LDAP_INVALID_SYNTAX;
5502 for (end_num = p; end_num[-1] == '0'; --end_num) {
5505 c = end_num - fraction->bv_val;
5506 if (c != 1) fraction->bv_len = c;
5512 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5518 return LDAP_INVALID_SYNTAX;
5524 for (part = 7; part < 9 && p < e; part++) {
5526 if (!ASCII_DIGIT(c1)) {
5531 return LDAP_INVALID_SYNTAX;
5534 if (!ASCII_DIGIT(c2)) {
5535 return LDAP_INVALID_SYNTAX;
5537 parts[part] = c1 * 10 + c2 - '0' * 11;
5538 if (parts[part] >= ceiling[part]) {
5539 return LDAP_INVALID_SYNTAX;
5542 if (part < 8 + start) {
5543 return LDAP_INVALID_SYNTAX;
5546 if (tzoffset == '-') {
5547 /* negative offset to UTC, ie west of Greenwich */
5548 parts[4] += parts[7];
5549 parts[5] += parts[8];
5550 /* offset is just hhmm, no seconds */
5551 for (part = 6; --part >= 0; ) {
5555 c = mdays[leapyear][parts[2]];
5557 if (parts[part] >= c) {
5559 return LDAP_INVALID_SYNTAX;
5564 } else if (part != 5) {
5569 /* positive offset to UTC, ie east of Greenwich */
5570 parts[4] -= parts[7];
5571 parts[5] -= parts[8];
5572 for (part = 6; --part >= 0; ) {
5573 if (parts[part] < 0) {
5575 return LDAP_INVALID_SYNTAX;
5580 /* make first arg to % non-negative */
5581 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5586 } else if (part != 5) {
5593 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5596 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5603 struct berval *normalized )
5607 rc = check_time_syntax(val, 1, parts, NULL);
5608 if (rc != LDAP_SUCCESS) {
5612 normalized->bv_val = ch_malloc( 14 );
5613 if ( normalized->bv_val == NULL ) {
5614 return LBER_ERROR_MEMORY;
5617 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5618 parts[1], parts[2] + 1, parts[3] + 1,
5619 parts[4], parts[5], parts[6] );
5620 normalized->bv_len = 13;
5622 return LDAP_SUCCESS;
5632 return check_time_syntax(in, 1, parts, NULL);
5635 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5638 generalizedTimeValidate(
5643 struct berval fraction;
5644 return check_time_syntax(in, 0, parts, &fraction);
5648 generalizedTimeNormalize(
5653 struct berval *normalized,
5658 struct berval fraction;
5660 rc = check_time_syntax(val, 0, parts, &fraction);
5661 if (rc != LDAP_SUCCESS) {
5665 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5666 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5667 if ( BER_BVISNULL( normalized ) ) {
5668 return LBER_ERROR_MEMORY;
5671 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5672 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5673 parts[4], parts[5], parts[6] );
5674 if ( !BER_BVISEMPTY( &fraction ) ) {
5675 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5676 fraction.bv_val, fraction.bv_len );
5677 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5679 strcpy( normalized->bv_val + len-1, "Z" );
5680 normalized->bv_len = len;
5682 return LDAP_SUCCESS;
5686 generalizedTimeOrderingMatch(
5691 struct berval *value,
5692 void *assertedValue )
5694 struct berval *asserted = (struct berval *) assertedValue;
5695 ber_len_t v_len = value->bv_len;
5696 ber_len_t av_len = asserted->bv_len;
5698 /* ignore trailing 'Z' when comparing */
5699 int match = memcmp( value->bv_val, asserted->bv_val,
5700 (v_len < av_len ? v_len : av_len) - 1 );
5701 if ( match == 0 ) match = v_len - av_len;
5703 /* If used in extensible match filter, match if value < asserted */
5704 if ( flags & SLAP_MR_EXT )
5705 match = (match >= 0);
5708 return LDAP_SUCCESS;
5711 /* Index generation function: Ordered index */
5712 int generalizedTimeIndexer(
5717 struct berval *prefix,
5725 BerValue bvtmp; /* 40 bit index */
5727 struct lutil_timet tt;
5729 bvtmp.bv_len = sizeof(tmp);
5731 for( i=0; values[i].bv_val != NULL; i++ ) {
5732 /* just count them */
5735 /* we should have at least one value at this point */
5738 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5740 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5741 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5742 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5743 /* Use 40 bits of time for key */
5744 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5745 lutil_tm2time( &tm, &tt );
5746 tmp[0] = tt.tt_gsec & 0xff;
5747 tmp[4] = tt.tt_sec & 0xff;
5749 tmp[3] = tt.tt_sec & 0xff;
5751 tmp[2] = tt.tt_sec & 0xff;
5753 tmp[1] = tt.tt_sec & 0xff;
5755 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5759 keys[j].bv_val = NULL;
5764 return LDAP_SUCCESS;
5767 /* Index generation function: Ordered index */
5768 int generalizedTimeFilter(
5773 struct berval *prefix,
5774 void * assertedValue,
5780 BerValue bvtmp; /* 40 bit index */
5781 BerValue *value = (BerValue *) assertedValue;
5783 struct lutil_timet tt;
5785 bvtmp.bv_len = sizeof(tmp);
5787 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5788 /* Use 40 bits of time for key */
5789 if ( value->bv_val && value->bv_len >= 10 &&
5790 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5792 lutil_tm2time( &tm, &tt );
5793 tmp[0] = tt.tt_gsec & 0xff;
5794 tmp[4] = tt.tt_sec & 0xff;
5796 tmp[3] = tt.tt_sec & 0xff;
5798 tmp[2] = tt.tt_sec & 0xff;
5800 tmp[1] = tt.tt_sec & 0xff;
5802 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5803 ber_dupbv_x(keys, &bvtmp, ctx );
5804 keys[1].bv_val = NULL;
5812 return LDAP_SUCCESS;
5816 deliveryMethodValidate(
5818 struct berval *val )
5821 #define LENOF(s) (sizeof(s)-1)
5822 struct berval tmp = *val;
5824 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5825 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5826 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5829 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5831 switch( tmp.bv_val[0] ) {
5834 if(( tmp.bv_len >= LENOF("any") ) &&
5835 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5837 tmp.bv_len -= LENOF("any");
5838 tmp.bv_val += LENOF("any");
5841 return LDAP_INVALID_SYNTAX;
5845 if(( tmp.bv_len >= LENOF("mhs") ) &&
5846 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5848 tmp.bv_len -= LENOF("mhs");
5849 tmp.bv_val += LENOF("mhs");
5852 return LDAP_INVALID_SYNTAX;
5856 if(( tmp.bv_len >= LENOF("physical") ) &&
5857 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5859 tmp.bv_len -= LENOF("physical");
5860 tmp.bv_val += LENOF("physical");
5863 return LDAP_INVALID_SYNTAX;
5866 case 'T': /* telex or teletex or telephone */
5867 if(( tmp.bv_len >= LENOF("telex") ) &&
5868 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5870 tmp.bv_len -= LENOF("telex");
5871 tmp.bv_val += LENOF("telex");
5874 if(( tmp.bv_len >= LENOF("teletex") ) &&
5875 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5877 tmp.bv_len -= LENOF("teletex");
5878 tmp.bv_val += LENOF("teletex");
5881 if(( tmp.bv_len >= LENOF("telephone") ) &&
5882 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5884 tmp.bv_len -= LENOF("telephone");
5885 tmp.bv_val += LENOF("telephone");
5888 return LDAP_INVALID_SYNTAX;
5891 case 'G': /* g3fax or g4fax */
5892 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5893 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5894 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5896 tmp.bv_len -= LENOF("g3fax");
5897 tmp.bv_val += LENOF("g3fax");
5900 return LDAP_INVALID_SYNTAX;
5904 if(( tmp.bv_len >= LENOF("ia5") ) &&
5905 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5907 tmp.bv_len -= LENOF("ia5");
5908 tmp.bv_val += LENOF("ia5");
5911 return LDAP_INVALID_SYNTAX;
5915 if(( tmp.bv_len >= LENOF("videotex") ) &&
5916 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5918 tmp.bv_len -= LENOF("videotex");
5919 tmp.bv_val += LENOF("videotex");
5922 return LDAP_INVALID_SYNTAX;
5925 return LDAP_INVALID_SYNTAX;
5928 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5930 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5934 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5938 return LDAP_INVALID_SYNTAX;
5940 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5949 nisNetgroupTripleValidate(
5951 struct berval *val )
5956 if ( BER_BVISEMPTY( val ) ) {
5957 return LDAP_INVALID_SYNTAX;
5960 p = (char *)val->bv_val;
5961 e = p + val->bv_len;
5963 if ( *p != '(' /*')'*/ ) {
5964 return LDAP_INVALID_SYNTAX;
5967 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5971 return LDAP_INVALID_SYNTAX;
5974 } else if ( !AD_CHAR( *p ) ) {
5975 return LDAP_INVALID_SYNTAX;
5979 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5980 return LDAP_INVALID_SYNTAX;
5986 return LDAP_INVALID_SYNTAX;
5989 return LDAP_SUCCESS;
5993 bootParameterValidate(
5995 struct berval *val )
5999 if ( BER_BVISEMPTY( val ) ) {
6000 return LDAP_INVALID_SYNTAX;
6003 p = (char *)val->bv_val;
6004 e = p + val->bv_len;
6007 for (; ( p < e ) && ( *p != '=' ); p++ ) {
6008 if ( !AD_CHAR( *p ) ) {
6009 return LDAP_INVALID_SYNTAX;
6014 return LDAP_INVALID_SYNTAX;
6018 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
6019 if ( !AD_CHAR( *p ) ) {
6020 return LDAP_INVALID_SYNTAX;
6025 return LDAP_INVALID_SYNTAX;
6029 for ( p++; p < e; p++ ) {
6030 if ( !SLAP_PRINTABLE( *p ) ) {
6031 return LDAP_INVALID_SYNTAX;
6035 return LDAP_SUCCESS;
6039 firstComponentNormalize(
6044 struct berval *normalized,
6051 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
6052 ber_dupbv_x( normalized, val, ctx );
6053 return LDAP_SUCCESS;
6056 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
6058 if( ! ( val->bv_val[0] == '(' /*')'*/
6059 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
6060 && ! ( val->bv_val[0] == '{' /*'}'*/
6061 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
6063 return LDAP_INVALID_SYNTAX;
6066 /* trim leading white space */
6068 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
6074 /* grab next word */
6075 comp.bv_val = &val->bv_val[len];
6076 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
6077 for( comp.bv_len = 0;
6078 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
6084 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
6085 rc = numericoidValidate( NULL, &comp );
6086 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
6087 rc = integerValidate( NULL, &comp );
6089 rc = LDAP_INVALID_SYNTAX;
6093 if( rc == LDAP_SUCCESS ) {
6094 ber_dupbv_x( normalized, &comp, ctx );
6100 static char *country_gen_syn[] = {
6101 "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */
6102 "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */
6103 "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */
6107 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6108 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6110 static slap_syntax_defs_rec syntax_defs[] = {
6111 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6112 X_BINARY X_NOT_H_R ")",
6113 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6114 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6115 0, NULL, NULL, NULL},
6116 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6117 0, NULL, NULL, NULL},
6118 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6120 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6121 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6123 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6124 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6125 0, NULL, bitStringValidate, NULL },
6126 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6127 0, NULL, booleanValidate, NULL},
6128 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6129 X_BINARY X_NOT_H_R ")",
6130 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6131 NULL, certificateValidate, NULL},
6132 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6133 X_BINARY X_NOT_H_R ")",
6134 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6135 NULL, certificateListValidate, NULL},
6136 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6137 X_BINARY X_NOT_H_R ")",
6138 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6139 NULL, sequenceValidate, NULL},
6140 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6141 X_BINARY X_NOT_H_R ")",
6142 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6143 NULL, attributeCertificateValidate, NULL},
6144 #if 0 /* need to go __after__ printableString */
6145 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6146 0, "1.3.6.1.4.1.1466.115.121.1.44",
6147 countryStringValidate, NULL},
6149 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6150 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6151 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6152 0, NULL, rdnValidate, rdnPretty},
6153 #ifdef LDAP_COMP_MATCH
6154 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6155 0, NULL, allComponentsValidate, NULL},
6156 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6157 0, NULL, componentFilterValidate, NULL},
6159 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6160 0, NULL, NULL, NULL},
6161 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6162 0, NULL, deliveryMethodValidate, NULL},
6163 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6164 0, NULL, UTF8StringValidate, NULL},
6165 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6166 0, NULL, NULL, NULL},
6167 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6168 0, NULL, NULL, NULL},
6169 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6170 0, NULL, NULL, NULL},
6171 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6172 0, NULL, NULL, NULL},
6173 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6174 0, NULL, NULL, NULL},
6175 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6176 0, NULL, printablesStringValidate, NULL},
6177 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6178 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6179 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6180 0, NULL, generalizedTimeValidate, NULL},
6181 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6182 0, NULL, NULL, NULL},
6183 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6184 0, NULL, IA5StringValidate, NULL},
6185 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6186 0, NULL, integerValidate, NULL},
6187 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6188 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6189 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6190 0, NULL, NULL, NULL},
6191 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6192 0, NULL, NULL, NULL},
6193 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6194 0, NULL, NULL, NULL},
6195 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6196 0, NULL, NULL, NULL},
6197 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6198 0, NULL, NULL, NULL},
6199 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6200 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6201 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6202 0, NULL, NULL, NULL},
6203 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6204 0, NULL, numericStringValidate, NULL},
6205 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6206 0, NULL, NULL, NULL},
6207 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6208 0, NULL, numericoidValidate, NULL},
6209 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6210 0, NULL, IA5StringValidate, NULL},
6211 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6212 0, NULL, blobValidate, NULL},
6213 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6214 0, NULL, postalAddressValidate, NULL},
6215 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6216 0, NULL, NULL, NULL},
6217 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6218 0, NULL, NULL, NULL},
6219 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6220 0, NULL, printableStringValidate, NULL},
6221 /* moved here because now depends on Directory String, IA5 String
6222 * and Printable String */
6223 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6224 0, country_gen_syn, countryStringValidate, NULL},
6225 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6226 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6227 0, NULL, subtreeSpecificationValidate, NULL},
6228 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6229 X_BINARY X_NOT_H_R ")",
6230 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6231 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6232 0, NULL, printableStringValidate, NULL},
6233 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6234 0, NULL, NULL, NULL},
6235 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6236 0, NULL, printablesStringValidate, NULL},
6237 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6238 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6239 0, NULL, utcTimeValidate, NULL},
6241 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6242 0, NULL, NULL, NULL},
6243 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6244 0, NULL, NULL, NULL},
6245 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6246 0, NULL, NULL, NULL},
6247 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6248 0, NULL, NULL, NULL},
6249 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6250 0, NULL, NULL, NULL},
6252 /* RFC 2307 NIS Syntaxes */
6253 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6254 0, NULL, nisNetgroupTripleValidate, NULL},
6255 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6256 0, NULL, bootParameterValidate, NULL},
6258 /* draft-zeilenga-ldap-x509 */
6259 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6260 SLAP_SYNTAX_HIDE, NULL,
6261 serialNumberAndIssuerValidate,
6262 serialNumberAndIssuerPretty},
6263 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6264 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6265 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6266 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6267 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6268 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6269 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6270 SLAP_SYNTAX_HIDE, NULL,
6271 issuerAndThisUpdateValidate,
6272 issuerAndThisUpdatePretty},
6273 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6274 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6275 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6276 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6277 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6278 SLAP_SYNTAX_HIDE, NULL,
6279 serialNumberAndIssuerSerialValidate,
6280 serialNumberAndIssuerSerialPretty},
6281 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6282 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6284 #ifdef SLAPD_AUTHPASSWD
6285 /* needs updating */
6286 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6287 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6290 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6291 0, NULL, UUIDValidate, UUIDPretty},
6293 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6294 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6296 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6297 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6299 /* OpenLDAP Void Syntax */
6300 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6301 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6303 /* FIXME: OID is unused, but not registered yet */
6304 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6305 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6307 {NULL, 0, NULL, NULL, NULL}
6310 char *csnSIDMatchSyntaxes[] = {
6311 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6314 char *certificateExactMatchSyntaxes[] = {
6315 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6318 char *certificateListExactMatchSyntaxes[] = {
6319 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6322 char *attributeCertificateExactMatchSyntaxes[] = {
6323 attributeCertificateSyntaxOID /* attributeCertificate */,
6327 #ifdef LDAP_COMP_MATCH
6328 char *componentFilterMatchSyntaxes[] = {
6329 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6330 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6331 attributeCertificateSyntaxOID /* attributeCertificate */,
6336 char *directoryStringSyntaxes[] = {
6337 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6340 char *integerFirstComponentMatchSyntaxes[] = {
6341 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6342 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6345 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6346 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6347 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6348 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6349 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6350 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6351 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6352 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6353 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6358 * Other matching rules in X.520 that we do not use (yet):
6360 * 2.5.13.25 uTCTimeMatch
6361 * 2.5.13.26 uTCTimeOrderingMatch
6362 * 2.5.13.31* directoryStringFirstComponentMatch
6363 * 2.5.13.32* wordMatch
6364 * 2.5.13.33* keywordMatch
6365 * 2.5.13.36+ certificatePairExactMatch
6366 * 2.5.13.37+ certificatePairMatch
6367 * 2.5.13.40+ algorithmIdentifierMatch
6368 * 2.5.13.41* storedPrefixMatch
6369 * 2.5.13.42 attributeCertificateMatch
6370 * 2.5.13.43 readerAndKeyIDMatch
6371 * 2.5.13.44 attributeIntegrityMatch
6373 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6374 * (+) described in draft-zeilenga-ldap-x509
6376 static slap_mrule_defs_rec mrule_defs[] = {
6378 * EQUALITY matching rules must be listed after associated APPROX
6379 * matching rules. So, we list all APPROX matching rules first.
6381 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6382 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6383 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6384 NULL, NULL, directoryStringApproxMatch,
6385 directoryStringApproxIndexer, directoryStringApproxFilter,
6388 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6389 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6390 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6391 NULL, NULL, IA5StringApproxMatch,
6392 IA5StringApproxIndexer, IA5StringApproxFilter,
6396 * Other matching rules
6399 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6400 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6401 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6402 NULL, NULL, octetStringMatch,
6403 octetStringIndexer, octetStringFilter,
6406 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6407 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6408 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6409 NULL, dnNormalize, dnMatch,
6410 octetStringIndexer, octetStringFilter,
6413 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6414 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6415 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6416 NULL, dnNormalize, dnRelativeMatch,
6420 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6421 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6422 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6423 NULL, dnNormalize, dnRelativeMatch,
6427 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6428 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6429 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6430 NULL, dnNormalize, dnRelativeMatch,
6434 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6435 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6436 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6437 NULL, dnNormalize, dnRelativeMatch,
6441 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6442 "SYNTAX 1.2.36.79672281.1.5.0 )",
6443 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6444 NULL, rdnNormalize, rdnMatch,
6445 octetStringIndexer, octetStringFilter,
6448 #ifdef LDAP_COMP_MATCH
6449 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6450 "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */
6451 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6452 NULL, NULL , componentFilterMatch,
6453 octetStringIndexer, octetStringFilter,
6456 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6457 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6458 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6459 NULL, NULL , allComponentsMatch,
6460 octetStringIndexer, octetStringFilter,
6463 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6464 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6465 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6466 NULL, NULL , directoryComponentsMatch,
6467 octetStringIndexer, octetStringFilter,
6471 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6472 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6473 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6474 NULL, UTF8StringNormalize, octetStringMatch,
6475 octetStringIndexer, octetStringFilter,
6476 directoryStringApproxMatchOID },
6478 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6480 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6481 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6483 "caseIgnoreMatch" },
6485 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6486 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6487 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6488 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6489 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6490 "caseIgnoreMatch" },
6492 {"( 2.5.13.5 NAME 'caseExactMatch' "
6493 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6494 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6495 NULL, UTF8StringNormalize, octetStringMatch,
6496 octetStringIndexer, octetStringFilter,
6497 directoryStringApproxMatchOID },
6499 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6500 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6501 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6502 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6506 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6507 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6508 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6509 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6510 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6513 {"( 2.5.13.8 NAME 'numericStringMatch' "
6514 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6515 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6516 NULL, numericStringNormalize, octetStringMatch,
6517 octetStringIndexer, octetStringFilter,
6520 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6521 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6522 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6523 NULL, numericStringNormalize, octetStringOrderingMatch,
6525 "numericStringMatch" },
6527 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6528 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6529 SLAP_MR_SUBSTR, NULL,
6530 NULL, numericStringNormalize, octetStringSubstringsMatch,
6531 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6532 "numericStringMatch" },
6534 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6535 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */
6536 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6537 NULL, postalAddressNormalize, octetStringMatch,
6538 octetStringIndexer, octetStringFilter,
6541 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6542 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6543 SLAP_MR_SUBSTR, NULL,
6544 NULL, NULL, NULL, NULL, NULL,
6545 "caseIgnoreListMatch" },
6547 {"( 2.5.13.13 NAME 'booleanMatch' "
6548 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6549 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6550 NULL, NULL, booleanMatch,
6551 octetStringIndexer, octetStringFilter,
6554 {"( 2.5.13.14 NAME 'integerMatch' "
6555 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6556 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6557 NULL, NULL, integerMatch,
6558 integerIndexer, integerFilter,
6561 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6562 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6563 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6564 NULL, NULL, integerMatch,
6568 {"( 2.5.13.16 NAME 'bitStringMatch' "
6569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6570 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6571 NULL, NULL, octetStringMatch,
6572 octetStringIndexer, octetStringFilter,
6575 {"( 2.5.13.17 NAME 'octetStringMatch' "
6576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6577 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6578 NULL, NULL, octetStringMatch,
6579 octetStringIndexer, octetStringFilter,
6582 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6583 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6584 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6585 NULL, NULL, octetStringOrderingMatch,
6587 "octetStringMatch" },
6589 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6590 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6591 SLAP_MR_SUBSTR, NULL,
6592 NULL, NULL, octetStringSubstringsMatch,
6593 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6594 "octetStringMatch" },
6596 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6597 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6598 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6600 telephoneNumberNormalize, octetStringMatch,
6601 octetStringIndexer, octetStringFilter,
6604 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6605 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6606 SLAP_MR_SUBSTR, NULL,
6607 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6608 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6609 "telephoneNumberMatch" },
6611 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6612 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6613 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6614 NULL, NULL, NULL, NULL, NULL, NULL },
6616 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6617 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */
6618 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6619 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6620 uniqueMemberIndexer, uniqueMemberFilter,
6623 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6624 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6625 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6626 NULL, NULL, NULL, NULL, NULL, NULL },
6628 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6629 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6630 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6631 NULL, generalizedTimeNormalize, octetStringMatch,
6632 generalizedTimeIndexer, generalizedTimeFilter,
6635 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6636 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6637 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6638 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6640 "generalizedTimeMatch" },
6642 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6643 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6644 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6645 integerFirstComponentMatchSyntaxes,
6646 NULL, firstComponentNormalize, integerMatch,
6647 octetStringIndexer, octetStringFilter,
6650 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6651 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */
6652 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6653 objectIdentifierFirstComponentMatchSyntaxes,
6654 NULL, firstComponentNormalize, octetStringMatch,
6655 octetStringIndexer, octetStringFilter,
6658 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6659 "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */
6660 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6661 NULL, certificateExactNormalize, octetStringMatch,
6662 octetStringIndexer, octetStringFilter,
6665 {"( 2.5.13.35 NAME 'certificateMatch' "
6666 "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */
6667 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6668 NULL, NULL, NULL, NULL, NULL,
6671 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6672 "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */
6673 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6674 NULL, certificateListExactNormalize, octetStringMatch,
6675 octetStringIndexer, octetStringFilter,
6678 {"( 2.5.13.39 NAME 'certificateListMatch' "
6679 "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */
6680 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6681 NULL, NULL, NULL, NULL, NULL,
6684 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6685 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6686 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6687 NULL, attributeCertificateExactNormalize, octetStringMatch,
6688 octetStringIndexer, octetStringFilter,
6691 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6692 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6693 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6694 NULL, NULL, NULL, NULL, NULL,
6697 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6698 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6699 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6700 NULL, IA5StringNormalize, octetStringMatch,
6701 octetStringIndexer, octetStringFilter,
6702 IA5StringApproxMatchOID },
6704 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6705 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6706 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6707 NULL, IA5StringNormalize, octetStringMatch,
6708 octetStringIndexer, octetStringFilter,
6709 IA5StringApproxMatchOID },
6711 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6712 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6713 SLAP_MR_SUBSTR, NULL,
6714 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6715 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6716 "caseIgnoreIA5Match" },
6718 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6719 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6720 SLAP_MR_SUBSTR, NULL,
6721 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6722 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6723 "caseExactIA5Match" },
6725 #ifdef SLAPD_AUTHPASSWD
6726 /* needs updating */
6727 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6728 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */
6729 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6730 NULL, NULL, authPasswordMatch,
6735 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6736 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6738 NULL, NULL, integerBitAndMatch,
6742 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6743 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6745 NULL, NULL, integerBitOrMatch,
6749 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6750 "SYNTAX 1.3.6.1.1.16.1 )",
6751 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6752 NULL, UUIDNormalize, octetStringMatch,
6753 octetStringIndexer, octetStringFilter,
6756 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6757 "SYNTAX 1.3.6.1.1.16.1 )",
6758 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6759 NULL, UUIDNormalize, octetStringOrderingMatch,
6760 octetStringIndexer, octetStringFilter,
6763 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6764 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6765 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6766 NULL, csnNormalize, csnMatch,
6767 csnIndexer, csnFilter,
6770 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6771 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6772 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6773 NULL, csnNormalize, csnOrderingMatch,
6777 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6778 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6779 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6780 NULL, csnSidNormalize, octetStringMatch,
6781 octetStringIndexer, octetStringFilter,
6784 /* FIXME: OID is unused, but not registered yet */
6785 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6786 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */
6787 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6788 NULL, authzNormalize, authzMatch,
6792 {NULL, SLAP_MR_NONE, NULL,
6793 NULL, NULL, NULL, NULL, NULL,
6798 slap_schema_init( void )
6803 /* we should only be called once (from main) */
6804 assert( schema_init_done == 0 );
6806 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6807 res = register_syntax( &syntax_defs[i] );
6810 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6811 syntax_defs[i].sd_desc );
6816 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6817 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6818 mrule_defs[i].mrd_compat_syntaxes == NULL )
6821 "slap_schema_init: Ignoring unusable matching rule %s\n",
6822 mrule_defs[i].mrd_desc );
6826 res = register_matching_rule( &mrule_defs[i] );
6830 "slap_schema_init: Error registering matching rule %s\n",
6831 mrule_defs[i].mrd_desc );
6836 res = slap_schema_load();
6837 schema_init_done = 1;
6842 schema_destroy( void )
6851 if( schema_init_done ) {
6852 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6853 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );