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';
1856 /* string of all spaces is treated as one space */
1857 nvalue.bv_val[0] = ' ';
1858 nvalue.bv_val[1] = '\0';
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 = l;
2336 for ( l = 0; !BER_BVISNULL( &lines[l] ); 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 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2342 if ( rc != LDAP_SUCCESS ) {
2343 rc = LDAP_INVALID_SYNTAX;
2347 normalized->bv_len += nlines[l].bv_len;
2350 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2352 p = normalized->bv_val;
2353 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2354 p = lutil_strbvcopy( p, &nlines[l] );
2359 assert( p == &normalized->bv_val[normalized->bv_len] );
2362 if ( nlines != NULL ) {
2363 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2364 slap_sl_free( nlines[l].bv_val, ctx );
2367 slap_sl_free( lines, ctx );
2378 struct berval val = *in;
2380 if( BER_BVISEMPTY( &val ) ) {
2381 /* disallow empty strings */
2382 return LDAP_INVALID_SYNTAX;
2385 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2386 if ( val.bv_len == 1 ) {
2387 return LDAP_SUCCESS;
2390 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2397 while ( OID_LEADCHAR( val.bv_val[0] )) {
2401 if ( val.bv_len == 0 ) {
2402 return LDAP_SUCCESS;
2406 if( !OID_SEPARATOR( val.bv_val[0] )) {
2414 return LDAP_INVALID_SYNTAX;
2423 struct berval val = *in;
2425 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2427 if ( val.bv_val[0] == '-' ) {
2431 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2432 return LDAP_INVALID_SYNTAX;
2435 if( val.bv_val[0] == '0' ) { /* "-0" */
2436 return LDAP_INVALID_SYNTAX;
2439 } else if ( val.bv_val[0] == '0' ) {
2440 if( val.bv_len > 1 ) { /* "0<more>" */
2441 return LDAP_INVALID_SYNTAX;
2444 return LDAP_SUCCESS;
2447 for( i=0; i < val.bv_len; i++ ) {
2448 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2449 return LDAP_INVALID_SYNTAX;
2453 return LDAP_SUCCESS;
2462 struct berval *value,
2463 void *assertedValue )
2465 struct berval *asserted = (struct berval *) assertedValue;
2466 int vsign = 1, asign = 1; /* default sign = '+' */
2471 if( v.bv_val[0] == '-' ) {
2477 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2480 if( a.bv_val[0] == '-' ) {
2486 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2488 match = vsign - asign;
2490 match = ( v.bv_len != a.bv_len
2491 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2492 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2493 if( vsign < 0 ) match = -match;
2496 /* Ordering rule used in extensible match filter? */
2497 if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
2498 match = (match >= 0);
2501 return LDAP_SUCCESS;
2504 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2505 #define INDEX_INTLEN_CHOP 7
2506 #define INDEX_INTLEN_CHOPBYTES 3
2515 /* Integer index key format, designed for memcmp to collate correctly:
2516 * if too large: one's complement sign*<approx exponent=chopped bytes>,
2517 * two's complement value (sign-extended or chopped as needed),
2518 * however in first byte above, the top <number of exponent-bytes + 1>
2519 * bits are the inverse sign and next bit is the sign as delimiter.
2521 ber_slen_t k = index_intlen_strlen;
2523 unsigned signmask = ~0x7fU;
2524 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2525 struct berval val = *in, itmp = *tmp;
2527 if ( val.bv_val[0] != '-' ) {
2532 /* Chop least significant digits, increase length instead */
2533 if ( val.bv_len > (ber_len_t) k ) {
2534 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2535 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2536 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2539 if ( lutil_str2bin( &val, &itmp, ctx )) {
2540 return LDAP_INVALID_SYNTAX;
2543 /* Omit leading sign byte */
2544 if ( itmp.bv_val[0] == neg ) {
2549 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2551 assert( chop == 0 );
2552 memset( key->bv_val, neg, k ); /* sign-extend */
2553 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2554 /* Got exponent -k, or no room for 2 sign bits */
2555 lenp = lenbuf + sizeof(lenbuf);
2556 chop = - (ber_len_t) k;
2558 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2560 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2561 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2562 * are 1, and the top n+2 bits of lenp[0] are the sign bit. */
2563 k = (lenbuf + sizeof(lenbuf)) - lenp;
2564 if ( k > (ber_slen_t) index_intlen )
2566 memcpy( key->bv_val, lenp, k );
2567 itmp.bv_len = index_intlen - k;
2569 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2570 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2574 /* Index generation function: Ordered index */
2581 struct berval *prefix,
2591 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2593 /* count the values and find max needed length */
2595 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2596 if ( vlen < values[i].bv_len )
2597 vlen = values[i].bv_len;
2599 if ( vlen > maxstrlen )
2602 /* we should have at least one value at this point */
2605 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2606 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2607 keys[i].bv_len = index_intlen;
2608 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2611 keys[i].bv_val = NULL;
2613 if ( vlen > sizeof(ibuf) ) {
2614 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2618 itmp.bv_len = sizeof(ibuf);
2620 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2621 if ( itmp.bv_val != ibuf ) {
2622 itmp.bv_len = values[i].bv_len;
2623 if ( itmp.bv_len <= sizeof(ibuf) )
2624 itmp.bv_len = sizeof(ibuf);
2625 else if ( itmp.bv_len > maxstrlen )
2626 itmp.bv_len = maxstrlen;
2628 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2634 if ( itmp.bv_val != ibuf ) {
2635 slap_sl_free( itmp.bv_val, ctx );
2640 /* Index generation function: Ordered index */
2647 struct berval *prefix,
2648 void * assertedValue,
2655 struct berval *value;
2658 value = (struct berval *) assertedValue;
2660 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2662 keys[0].bv_len = index_intlen;
2663 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2665 keys[1].bv_val = NULL;
2667 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2668 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2669 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2670 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2673 iv.bv_len = sizeof(ibuf);
2676 rc = integerVal2Key( value, keys, &iv, ctx );
2680 if ( iv.bv_val != ibuf ) {
2681 slap_sl_free( iv.bv_val, ctx );
2687 countryStringValidate(
2689 struct berval *val )
2691 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2693 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2694 return LDAP_INVALID_SYNTAX;
2696 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2697 return LDAP_INVALID_SYNTAX;
2700 return LDAP_SUCCESS;
2704 printableStringValidate(
2706 struct berval *val )
2710 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2712 for(i=0; i < val->bv_len; i++) {
2713 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2714 return LDAP_INVALID_SYNTAX;
2718 return LDAP_SUCCESS;
2722 printablesStringValidate(
2724 struct berval *val )
2728 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2730 for(i=0,len=0; i < val->bv_len; i++) {
2731 int c = val->bv_val[i];
2735 return LDAP_INVALID_SYNTAX;
2739 } else if ( SLAP_PRINTABLE(c) ) {
2742 return LDAP_INVALID_SYNTAX;
2747 return LDAP_INVALID_SYNTAX;
2750 return LDAP_SUCCESS;
2756 struct berval *val )
2760 for(i=0; i < val->bv_len; i++) {
2761 if( !LDAP_ASCII(val->bv_val[i]) ) {
2762 return LDAP_INVALID_SYNTAX;
2766 return LDAP_SUCCESS;
2775 struct berval *normalized,
2779 int casefold = !SLAP_MR_ASSOCIATED( mr,
2780 slap_schema.si_mr_caseExactIA5Match );
2782 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2786 /* Ignore initial whitespace */
2787 while ( ASCII_SPACE( *p ) ) p++;
2789 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2790 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2791 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2792 normalized->bv_val[normalized->bv_len] = '\0';
2794 p = q = normalized->bv_val;
2797 if ( ASCII_SPACE( *p ) ) {
2800 /* Ignore the extra whitespace */
2801 while ( ASCII_SPACE( *p ) ) {
2805 } else if ( casefold ) {
2806 /* Most IA5 rules require casefolding */
2807 *q++ = TOLOWER(*p); p++;
2814 assert( normalized->bv_val <= p );
2818 * If the string ended in space, backup the pointer one
2819 * position. One is enough because the above loop collapsed
2820 * all whitespace to a single space.
2822 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2824 /* null terminate */
2827 normalized->bv_len = q - normalized->bv_val;
2829 return LDAP_SUCCESS;
2838 if( in->bv_len != 36 ) {
2839 return LDAP_INVALID_SYNTAX;
2842 for( i=0; i<36; i++ ) {
2848 if( in->bv_val[i] != '-' ) {
2849 return LDAP_INVALID_SYNTAX;
2853 if( !ASCII_HEX( in->bv_val[i]) ) {
2854 return LDAP_INVALID_SYNTAX;
2859 return LDAP_SUCCESS;
2870 int rc=LDAP_INVALID_SYNTAX;
2872 assert( in != NULL );
2873 assert( out != NULL );
2875 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2878 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2880 for( i=0; i<36; i++ ) {
2886 if( in->bv_val[i] != '-' ) {
2889 out->bv_val[i] = '-';
2893 if( !ASCII_HEX( in->bv_val[i]) ) {
2896 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2901 out->bv_val[ out->bv_len ] = '\0';
2905 slap_sl_free( out->bv_val, ctx );
2918 struct berval *normalized,
2921 unsigned char octet = '\0';
2925 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2926 /* NOTE: must be a normalized UUID */
2927 assert( val->bv_len == 16 );
2929 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2930 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2931 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2932 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2934 return LDAP_SUCCESS;
2937 normalized->bv_len = 16;
2938 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2940 for( i=0, j=0; i<36; i++ ) {
2941 unsigned char nibble;
2942 if( val->bv_val[i] == '-' ) {
2945 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2946 nibble = val->bv_val[i] - '0';
2948 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2949 nibble = val->bv_val[i] - ('a'-10);
2951 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2952 nibble = val->bv_val[i] - ('A'-10);
2955 slap_sl_free( normalized->bv_val, ctx );
2956 BER_BVZERO( normalized );
2957 return LDAP_INVALID_SYNTAX;
2962 normalized->bv_val[j>>1] = octet;
2964 octet = nibble << 4;
2969 normalized->bv_val[normalized->bv_len] = 0;
2970 return LDAP_SUCCESS;
2976 numericStringValidate(
2982 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2984 for(i=0; i < in->bv_len; i++) {
2985 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2986 return LDAP_INVALID_SYNTAX;
2990 return LDAP_SUCCESS;
2994 numericStringNormalize(
2999 struct berval *normalized,
3002 /* removal all spaces */
3005 assert( !BER_BVISEMPTY( val ) );
3007 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
3010 q = normalized->bv_val;
3013 if ( ASCII_SPACE( *p ) ) {
3014 /* Ignore whitespace */
3021 /* we should have copied no more than is in val */
3022 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3024 /* null terminate */
3027 normalized->bv_len = q - normalized->bv_val;
3029 if( BER_BVISEMPTY( normalized ) ) {
3030 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
3031 normalized->bv_val[0] = ' ';
3032 normalized->bv_val[1] = '\0';
3033 normalized->bv_len = 1;
3036 return LDAP_SUCCESS;
3040 * Integer conversion macros that will use the largest available
3043 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
3044 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
3045 # define SLAP_LONG long long
3047 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
3048 # define SLAP_LONG long
3049 #endif /* HAVE_STRTOLL ... */
3057 struct berval *value,
3058 void *assertedValue )
3060 SLAP_LONG lValue, lAssertedValue;
3063 /* safe to assume integers are NUL terminated? */
3064 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3065 if( errno == ERANGE )
3067 return LDAP_CONSTRAINT_VIOLATION;
3070 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
3072 if( errno == ERANGE )
3074 return LDAP_CONSTRAINT_VIOLATION;
3077 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
3078 return LDAP_SUCCESS;
3087 struct berval *value,
3088 void *assertedValue )
3090 SLAP_LONG lValue, lAssertedValue;
3093 /* safe to assume integers are NUL terminated? */
3094 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3095 if( errno == ERANGE )
3097 return LDAP_CONSTRAINT_VIOLATION;
3100 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3102 if( errno == ERANGE )
3104 return LDAP_CONSTRAINT_VIOLATION;
3107 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3108 return LDAP_SUCCESS;
3112 checkNum( struct berval *in, struct berval *out )
3114 /* parse serialNumber */
3115 ber_len_t neg = 0, extra = 0;
3118 out->bv_val = in->bv_val;
3121 if ( out->bv_val[0] == '-' ) {
3126 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3127 first = out->bv_val[2];
3130 out->bv_len += STRLENOF("0x");
3131 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3132 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3135 } else if ( out->bv_val[0] == '\'' ) {
3136 first = out->bv_val[1];
3139 out->bv_len += STRLENOF("'");
3141 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3142 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3144 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3147 out->bv_len += STRLENOF("'H");
3150 first = out->bv_val[0];
3151 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3152 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3156 if ( !( out->bv_len > neg ) ) {
3160 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3168 serialNumberAndIssuerCheck(
3176 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3178 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3179 /* Parse old format */
3180 is->bv_val = ber_bvchr( in, '$' );
3181 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3183 sn->bv_val = in->bv_val;
3184 sn->bv_len = is->bv_val - in->bv_val;
3187 is->bv_len = in->bv_len - (sn->bv_len + 1);
3189 /* eat leading zeros */
3190 for( n=0; n < (sn->bv_len-1); n++ ) {
3191 if( sn->bv_val[n] != '0' ) break;
3196 for( n=0; n < sn->bv_len; n++ ) {
3197 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3201 /* Parse GSER format */
3206 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3210 struct berval x = *in;
3216 /* eat leading spaces */
3217 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3221 /* should be at issuer or serialNumber NamedValue */
3222 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3223 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3226 x.bv_val += STRLENOF("issuer");
3227 x.bv_len -= STRLENOF("issuer");
3229 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3233 /* eat leading spaces */
3234 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3238 /* For backward compatibility, this part is optional */
3239 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3240 x.bv_val += STRLENOF("rdnSequence:");
3241 x.bv_len -= STRLENOF("rdnSequence:");
3244 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3248 is->bv_val = x.bv_val;
3251 for ( ; is->bv_len < x.bv_len; ) {
3252 if ( is->bv_val[is->bv_len] != '"' ) {
3256 if ( is->bv_val[is->bv_len+1] == '"' ) {
3263 x.bv_val += is->bv_len + 1;
3264 x.bv_len -= is->bv_len + 1;
3266 have |= HAVE_ISSUER;
3268 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3270 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3272 /* parse serialNumber */
3273 x.bv_val += STRLENOF("serialNumber");
3274 x.bv_len -= STRLENOF("serialNumber");
3276 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3280 /* eat leading spaces */
3281 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3285 if ( checkNum( &x, sn ) ) {
3286 return LDAP_INVALID_SYNTAX;
3289 x.bv_val += sn->bv_len;
3290 x.bv_len -= sn->bv_len;
3295 return LDAP_INVALID_SYNTAX;
3298 /* eat leading spaces */
3299 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3303 if ( have == HAVE_ALL ) {
3307 if ( x.bv_val[0] != ',' ) {
3308 return LDAP_INVALID_SYNTAX;
3315 /* should have no characters left... */
3316 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3318 if ( numdquotes == 0 ) {
3319 ber_dupbv_x( &ni, is, ctx );
3324 ni.bv_len = is->bv_len - numdquotes;
3325 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3326 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3327 if ( is->bv_val[src] == '"' ) {
3330 ni.bv_val[dst] = is->bv_val[src];
3332 ni.bv_val[dst] = '\0';
3342 serialNumberAndIssuerValidate(
3347 struct berval sn, i;
3349 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3352 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3357 /* validate DN -- doesn't handle double dquote */
3358 rc = dnValidate( NULL, &i );
3360 rc = LDAP_INVALID_SYNTAX;
3363 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3364 slap_sl_free( i.bv_val, NULL );
3367 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3368 in->bv_val, rc, 0 );
3375 serialNumberAndIssuerPretty(
3382 struct berval sn, i, ni = BER_BVNULL;
3385 assert( in != NULL );
3386 assert( out != NULL );
3390 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3393 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3398 rc = dnPretty( syntax, &i, &ni, ctx );
3400 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3401 slap_sl_free( i.bv_val, ctx );
3405 rc = LDAP_INVALID_SYNTAX;
3409 /* make room from sn + "$" */
3410 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3411 + sn.bv_len + ni.bv_len;
3412 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3414 if ( out->bv_val == NULL ) {
3421 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3422 p = lutil_strbvcopy( p, &sn );
3423 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3424 p = lutil_strbvcopy( p, &ni );
3425 p = lutil_strcopy( p, /*{*/ "\" }" );
3427 assert( p == &out->bv_val[out->bv_len] );
3430 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3431 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3433 slap_sl_free( ni.bv_val, ctx );
3435 return LDAP_SUCCESS;
3445 /* Use hex format. '123456789abcdef'H */
3446 unsigned char *ptr, zero = '\0';
3449 ber_len_t i, len, nlen;
3451 assert( in != NULL );
3452 assert( !BER_BVISNULL( in ) );
3453 assert( out != NULL );
3454 assert( !BER_BVISNULL( out ) );
3456 ptr = (unsigned char *)in->bv_val;
3459 /* Check for minimal encodings */
3461 if ( ptr[0] & 0x80 ) {
3462 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3466 } else if ( ptr[0] == 0 ) {
3467 if ( !( ptr[1] & 0x80 ) ) {
3474 } else if ( len == 0 ) {
3475 /* FIXME: this should not be possible,
3476 * since a value of zero would have length 1 */
3481 first = !( ptr[0] & 0xf0U );
3482 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3483 if ( nlen >= out->bv_len ) {
3484 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3490 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3494 for ( ; i < len; i++ ) {
3495 sprintf( sptr, "%02X", ptr[i] );
3502 assert( sptr == &out->bv_val[nlen] );
3509 #define SLAP_SN_BUFLEN (64)
3512 * This routine is called by certificateExactNormalize when
3513 * certificateExactNormalize receives a search string instead of
3514 * a certificate. This routine checks if the search value is valid
3515 * and then returns the normalized value
3518 serialNumberAndIssuerNormalize(
3526 struct berval sn, sn2, sn3, i, ni;
3527 char sbuf2[SLAP_SN_BUFLEN];
3528 char sbuf3[SLAP_SN_BUFLEN];
3532 assert( in != NULL );
3533 assert( out != NULL );
3535 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3538 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3543 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3545 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3546 slap_sl_free( i.bv_val, ctx );
3550 return LDAP_INVALID_SYNTAX;
3553 /* Convert sn to canonical hex */
3555 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3556 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3558 sn2.bv_len = sn.bv_len;
3560 sn3.bv_len = sizeof(sbuf3);
3561 if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
3562 rc = LDAP_INVALID_SYNTAX;
3566 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3567 + sn3.bv_len + ni.bv_len;
3568 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3569 if ( out->bv_val == NULL ) {
3577 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3578 p = lutil_strbvcopy( p, &sn3 );
3579 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3580 p = lutil_strbvcopy( p, &ni );
3581 p = lutil_strcopy( p, /*{*/ "\" }" );
3583 assert( p == &out->bv_val[out->bv_len] );
3586 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3587 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3589 if ( sn2.bv_val != sbuf2 ) {
3590 slap_sl_free( sn2.bv_val, ctx );
3593 if ( sn3.bv_val != sbuf3 ) {
3594 slap_sl_free( sn3.bv_val, ctx );
3597 slap_sl_free( ni.bv_val, ctx );
3603 certificateExactNormalize(
3608 struct berval *normalized,
3611 BerElementBuffer berbuf;
3612 BerElement *ber = (BerElement *)&berbuf;
3616 char serialbuf2[SLAP_SN_BUFLEN];
3617 struct berval sn, sn2 = BER_BVNULL;
3618 struct berval issuer_dn = BER_BVNULL, bvdn;
3620 int rc = LDAP_INVALID_SYNTAX;
3622 assert( val != NULL );
3624 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3625 val->bv_val, val->bv_len, 0 );
3627 if ( BER_BVISEMPTY( val ) ) goto done;
3629 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3630 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3633 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3635 ber_init2( ber, val, LBER_USE_DER );
3636 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3637 tag = ber_skip_tag( ber, &len ); /* Sequence */
3638 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3639 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3640 tag = ber_skip_tag( ber, &len );
3641 tag = ber_get_int( ber, &i ); /* version */
3644 /* NOTE: move the test here from certificateValidate,
3645 * so that we can validate certs with serial longer
3646 * than sizeof(ber_int_t) */
3647 tag = ber_skip_tag( ber, &len ); /* serial */
3649 sn.bv_val = (char *)ber->ber_ptr;
3650 sn2.bv_val = serialbuf2;
3651 sn2.bv_len = sizeof(serialbuf2);
3652 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3653 rc = LDAP_INVALID_SYNTAX;
3656 ber_skip_data( ber, len );
3658 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3659 ber_skip_data( ber, len );
3660 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3661 len = ber_ptrlen( ber );
3662 bvdn.bv_val = val->bv_val + len;
3663 bvdn.bv_len = val->bv_len - len;
3665 rc = dnX509normalize( &bvdn, &issuer_dn );
3666 if ( rc != LDAP_SUCCESS ) goto done;
3668 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3669 + sn2.bv_len + issuer_dn.bv_len;
3670 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3672 p = normalized->bv_val;
3674 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3675 p = lutil_strbvcopy( p, &sn2 );
3676 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3677 p = lutil_strbvcopy( p, &issuer_dn );
3678 p = lutil_strcopy( p, /*{*/ "\" }" );
3683 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3684 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3686 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3687 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3692 /* X.509 PKI certificateList stuff */
3694 checkTime( struct berval *in, struct berval *out )
3698 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3701 assert( in != NULL );
3702 assert( !BER_BVISNULL( in ) );
3703 assert( !BER_BVISEMPTY( in ) );
3705 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3709 if ( out != NULL ) {
3710 assert( !BER_BVISNULL( out ) );
3711 assert( out->bv_len >= sizeof( buf ) );
3712 bv.bv_val = out->bv_val;
3718 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3719 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3722 if ( in->bv_val[i] != 'Z' ) {
3727 if ( i != in->bv_len ) {
3731 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3732 lutil_strncopy( bv.bv_val, in->bv_val, i );
3735 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3736 char *p = bv.bv_val;
3737 if ( in->bv_val[0] < '7' ) {
3738 p = lutil_strcopy( p, "20" );
3741 p = lutil_strcopy( p, "19" );
3743 lutil_strncopy( p, in->bv_val, i );
3750 rc = generalizedTimeValidate( NULL, &bv );
3751 if ( rc == LDAP_SUCCESS && out != NULL ) {
3752 if ( out->bv_len > bv.bv_len ) {
3753 out->bv_val[ bv.bv_len ] = '\0';
3755 out->bv_len = bv.bv_len;
3758 return rc != LDAP_SUCCESS;
3762 issuerAndThisUpdateCheck(
3769 struct berval x = *in;
3770 struct berval ni = BER_BVNULL;
3771 /* Parse GSER format */
3775 HAVE_THISUPDATE = 0x2,
3776 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3780 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3782 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3783 return LDAP_INVALID_SYNTAX;
3787 x.bv_len -= STRLENOF("{}");
3790 /* eat leading spaces */
3791 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3795 /* should be at issuer or thisUpdate */
3796 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3797 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3800 x.bv_val += STRLENOF("issuer");
3801 x.bv_len -= STRLENOF("issuer");
3803 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3807 /* eat leading spaces */
3808 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3812 /* For backward compatibility, this part is optional */
3813 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3814 return LDAP_INVALID_SYNTAX;
3816 x.bv_val += STRLENOF("rdnSequence:");
3817 x.bv_len -= STRLENOF("rdnSequence:");
3819 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3823 is->bv_val = x.bv_val;
3826 for ( ; is->bv_len < x.bv_len; ) {
3827 if ( is->bv_val[is->bv_len] != '"' ) {
3831 if ( is->bv_val[is->bv_len+1] == '"' ) {
3838 x.bv_val += is->bv_len + 1;
3839 x.bv_len -= is->bv_len + 1;
3841 have |= HAVE_ISSUER;
3843 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3845 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3847 /* parse thisUpdate */
3848 x.bv_val += STRLENOF("thisUpdate");
3849 x.bv_len -= STRLENOF("thisUpdate");
3851 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3855 /* eat leading spaces */
3856 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3860 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3864 tu->bv_val = x.bv_val;
3867 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3868 if ( tu->bv_val[tu->bv_len] == '"' ) {
3872 x.bv_val += tu->bv_len + 1;
3873 x.bv_len -= tu->bv_len + 1;
3875 have |= HAVE_THISUPDATE;
3878 return LDAP_INVALID_SYNTAX;
3881 /* eat leading spaces */
3882 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3886 if ( have == HAVE_ALL ) {
3890 if ( x.bv_val[0] != ',' ) {
3891 return LDAP_INVALID_SYNTAX;
3898 /* should have no characters left... */
3899 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3901 if ( numdquotes == 0 ) {
3902 ber_dupbv_x( &ni, is, ctx );
3907 ni.bv_len = is->bv_len - numdquotes;
3908 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3909 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3910 if ( is->bv_val[src] == '"' ) {
3913 ni.bv_val[dst] = is->bv_val[src];
3915 ni.bv_val[dst] = '\0';
3924 issuerAndThisUpdateValidate(
3929 struct berval i, tu;
3931 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3934 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3939 /* validate DN -- doesn't handle double dquote */
3940 rc = dnValidate( NULL, &i );
3942 rc = LDAP_INVALID_SYNTAX;
3944 } else if ( checkTime( &tu, NULL ) ) {
3945 rc = LDAP_INVALID_SYNTAX;
3948 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3949 slap_sl_free( i.bv_val, NULL );
3952 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3953 in->bv_val, rc, 0 );
3960 issuerAndThisUpdatePretty(
3967 struct berval i, tu, ni = BER_BVNULL;
3970 assert( in != NULL );
3971 assert( out != NULL );
3975 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3978 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3983 rc = dnPretty( syntax, &i, &ni, ctx );
3985 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3986 slap_sl_free( i.bv_val, ctx );
3989 if ( rc || checkTime( &tu, NULL ) ) {
3990 rc = LDAP_INVALID_SYNTAX;
3995 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3996 + ni.bv_len + tu.bv_len;
3997 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3999 if ( out->bv_val == NULL ) {
4006 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4007 p = lutil_strbvcopy( p, &ni );
4008 p = lutil_strcopy( p, "\", thisUpdate \"" );
4009 p = lutil_strbvcopy( p, &tu );
4010 p = lutil_strcopy( p, /*{*/ "\" }" );
4012 assert( p == &out->bv_val[out->bv_len] );
4015 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
4016 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4018 slap_sl_free( ni.bv_val, ctx );
4024 issuerAndThisUpdateNormalize(
4032 struct berval i, ni, tu, tu2;
4033 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4037 assert( in != NULL );
4038 assert( out != NULL );
4040 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
4043 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4048 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4050 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4051 slap_sl_free( i.bv_val, ctx );
4055 tu2.bv_len = sizeof( sbuf );
4056 if ( rc || checkTime( &tu, &tu2 ) ) {
4057 return LDAP_INVALID_SYNTAX;
4060 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4061 + ni.bv_len + tu2.bv_len;
4062 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4064 if ( out->bv_val == NULL ) {
4072 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4073 p = lutil_strbvcopy( p, &ni );
4074 p = lutil_strcopy( p, "\", thisUpdate \"" );
4075 p = lutil_strbvcopy( p, &tu2 );
4076 p = lutil_strcopy( p, /*{*/ "\" }" );
4078 assert( p == &out->bv_val[out->bv_len] );
4081 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4082 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4084 slap_sl_free( ni.bv_val, ctx );
4090 certificateListExactNormalize(
4095 struct berval *normalized,
4098 BerElementBuffer berbuf;
4099 BerElement *ber = (BerElement *)&berbuf;
4103 struct berval issuer_dn = BER_BVNULL, bvdn,
4105 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4106 int rc = LDAP_INVALID_SYNTAX;
4108 assert( val != NULL );
4110 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4111 val->bv_val, val->bv_len, 0 );
4113 if ( BER_BVISEMPTY( val ) ) goto done;
4115 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4116 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4119 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4121 ber_init2( ber, val, LBER_USE_DER );
4122 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4123 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4124 tag = ber_skip_tag( ber, &len ); /* Sequence */
4125 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4126 tag = ber_peek_tag( ber, &len );
4127 /* Optional version */
4128 if ( tag == LBER_INTEGER ) {
4129 tag = ber_get_int( ber, &version );
4130 assert( tag == LBER_INTEGER );
4131 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4133 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4134 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4135 ber_skip_data( ber, len );
4137 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4138 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4139 len = ber_ptrlen( ber );
4140 bvdn.bv_val = val->bv_val + len;
4141 bvdn.bv_len = val->bv_len - len;
4142 tag = ber_skip_tag( ber, &len );
4143 ber_skip_data( ber, len );
4145 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4146 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4147 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4148 bvtu.bv_val = (char *)ber->ber_ptr;
4151 rc = dnX509normalize( &bvdn, &issuer_dn );
4152 if ( rc != LDAP_SUCCESS ) goto done;
4154 thisUpdate.bv_val = tubuf;
4155 thisUpdate.bv_len = sizeof(tubuf);
4156 if ( checkTime( &bvtu, &thisUpdate ) ) {
4157 rc = LDAP_INVALID_SYNTAX;
4161 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4162 + issuer_dn.bv_len + thisUpdate.bv_len;
4163 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4165 p = normalized->bv_val;
4167 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4168 p = lutil_strbvcopy( p, &issuer_dn );
4169 p = lutil_strcopy( p, "\", thisUpdate \"" );
4170 p = lutil_strbvcopy( p, &thisUpdate );
4171 p = lutil_strcopy( p, /*{*/ "\" }" );
4176 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4177 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4179 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4184 /* X.509 PMI serialNumberAndIssuerSerialCheck
4186 AttributeCertificateExactAssertion ::= SEQUENCE {
4187 serialNumber CertificateSerialNumber,
4188 issuer AttCertIssuer }
4190 CertificateSerialNumber ::= INTEGER
4192 AttCertIssuer ::= [0] SEQUENCE {
4193 issuerName GeneralNames OPTIONAL,
4194 baseCertificateID [0] IssuerSerial OPTIONAL,
4195 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4196 -- At least one component shall be present
4198 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4200 GeneralName ::= CHOICE {
4201 otherName [0] INSTANCE OF OTHER-NAME,
4202 rfc822Name [1] IA5String,
4203 dNSName [2] IA5String,
4204 x400Address [3] ORAddress,
4205 directoryName [4] Name,
4206 ediPartyName [5] EDIPartyName,
4207 uniformResourceIdentifier [6] IA5String,
4208 iPAddress [7] OCTET STRING,
4209 registeredID [8] OBJECT IDENTIFIER }
4211 IssuerSerial ::= SEQUENCE {
4212 issuer GeneralNames,
4213 serial CertificateSerialNumber,
4214 issuerUID UniqueIdentifier OPTIONAL }
4216 ObjectDigestInfo ::= SEQUENCE {
4217 digestedObjectType ENUMERATED {
4220 otherObjectTypes (2) },
4221 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4222 digestAlgorithm AlgorithmIdentifier,
4223 objectDigest BIT STRING }
4225 * The way I interpret it, an assertion should look like
4227 { serialNumber 'dd'H,
4228 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4229 baseCertificateID { serial '1d'H,
4230 issuer { directoryName:rdnSequence:"cn=zzz" },
4231 issuerUID <value> -- optional
4233 objectDigestInfo { ... } -- optional
4237 * with issuerName, baseCertificateID and objectDigestInfo optional,
4238 * at least one present; the way it's currently implemented, it is
4240 { serialNumber 'dd'H,
4241 issuer { baseCertificateID { serial '1d'H,
4242 issuer { directoryName:rdnSequence:"cn=zzz" }
4247 * with all the above parts mandatory.
4250 serialNumberAndIssuerSerialCheck(
4254 struct berval *i_sn, /* contain serial of baseCertificateID */
4257 /* Parse GSER format */
4262 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4263 } have = HAVE_NONE, have2 = HAVE_NONE;
4265 struct berval x = *in;
4268 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4271 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4278 /* eat leading spaces */
4279 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4283 /* should be at issuer or serialNumber NamedValue */
4284 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4285 if ( have & HAVE_ISSUER ) {
4286 return LDAP_INVALID_SYNTAX;
4289 /* parse IssuerSerial */
4290 x.bv_val += STRLENOF("issuer");
4291 x.bv_len -= STRLENOF("issuer");
4293 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4297 /* eat leading spaces */
4298 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4302 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4306 /* eat leading spaces */
4307 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4311 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4312 return LDAP_INVALID_SYNTAX;
4314 x.bv_val += STRLENOF("baseCertificateID ");
4315 x.bv_len -= STRLENOF("baseCertificateID ");
4317 /* eat leading spaces */
4318 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4322 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4327 /* eat leading spaces */
4328 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4332 /* parse issuer of baseCertificateID */
4333 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4334 if ( have2 & HAVE_ISSUER ) {
4335 return LDAP_INVALID_SYNTAX;
4338 x.bv_val += STRLENOF("issuer ");
4339 x.bv_len -= STRLENOF("issuer ");
4341 /* eat leading spaces */
4342 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4346 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4350 /* eat leading spaces */
4351 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4355 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4356 return LDAP_INVALID_SYNTAX;
4358 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4359 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4361 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4365 is->bv_val = x.bv_val;
4368 for ( ; is->bv_len < x.bv_len; ) {
4369 if ( is->bv_val[is->bv_len] != '"' ) {
4373 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4380 x.bv_val += is->bv_len + 1;
4381 x.bv_len -= is->bv_len + 1;
4383 /* eat leading spaces */
4384 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4388 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4392 have2 |= HAVE_ISSUER;
4394 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4395 if ( have2 & HAVE_SN ) {
4396 return LDAP_INVALID_SYNTAX;
4399 x.bv_val += STRLENOF("serial ");
4400 x.bv_len -= STRLENOF("serial ");
4402 /* eat leading spaces */
4403 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4407 if ( checkNum( &x, i_sn ) ) {
4408 return LDAP_INVALID_SYNTAX;
4411 x.bv_val += i_sn->bv_len;
4412 x.bv_len -= i_sn->bv_len;
4417 return LDAP_INVALID_SYNTAX;
4420 /* eat leading spaces */
4421 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4425 if ( have2 == HAVE_ALL ) {
4429 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4434 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4438 /* eat leading spaces */
4439 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4443 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4447 have |= HAVE_ISSUER;
4449 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4450 if ( have & HAVE_SN ) {
4451 return LDAP_INVALID_SYNTAX;
4454 /* parse serialNumber */
4455 x.bv_val += STRLENOF("serialNumber");
4456 x.bv_len -= STRLENOF("serialNumber");
4458 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4462 /* eat leading spaces */
4463 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4467 if ( checkNum( &x, sn ) ) {
4468 return LDAP_INVALID_SYNTAX;
4471 x.bv_val += sn->bv_len;
4472 x.bv_len -= sn->bv_len;
4477 return LDAP_INVALID_SYNTAX;
4481 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4485 if ( have == HAVE_ALL ) {
4489 if ( x.bv_val[0] != ',' ) {
4490 return LDAP_INVALID_SYNTAX;
4496 /* should have no characters left... */
4497 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4499 if ( numdquotes == 0 ) {
4500 ber_dupbv_x( &ni, is, ctx );
4505 ni.bv_len = is->bv_len - numdquotes;
4506 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4507 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4508 if ( is->bv_val[src] == '"' ) {
4511 ni.bv_val[dst] = is->bv_val[src];
4513 ni.bv_val[dst] = '\0';
4518 /* need to handle double dquotes here */
4522 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4524 serialNumberAndIssuerSerialValidate(
4529 struct berval sn, i, i_sn;
4531 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4534 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4539 /* validate DN -- doesn't handle double dquote */
4540 rc = dnValidate( NULL, &i );
4542 rc = LDAP_INVALID_SYNTAX;
4545 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4546 slap_sl_free( i.bv_val, NULL );
4550 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4551 in->bv_val, rc, 0 );
4556 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4558 serialNumberAndIssuerSerialPretty(
4564 struct berval sn, i, i_sn, ni = BER_BVNULL;
4568 assert( in != NULL );
4569 assert( out != NULL );
4571 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4574 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4579 rc = dnPretty( syntax, &i, &ni, ctx );
4581 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4582 slap_sl_free( i.bv_val, ctx );
4586 rc = LDAP_INVALID_SYNTAX;
4590 /* make room from sn + "$" */
4591 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4592 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4593 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4595 if ( out->bv_val == NULL ) {
4602 p = lutil_strcopy( p, "{ serialNumber " );
4603 p = lutil_strbvcopy( p, &sn );
4604 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4605 p = lutil_strbvcopy( p, &ni );
4606 p = lutil_strcopy( p, "\" }, serial " );
4607 p = lutil_strbvcopy( p, &i_sn );
4608 p = lutil_strcopy( p, " } } }" );
4610 assert( p == &out->bv_val[out->bv_len] );
4613 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4614 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4616 slap_sl_free( ni.bv_val, ctx );
4621 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4623 * This routine is called by attributeCertificateExactNormalize
4624 * when attributeCertificateExactNormalize receives a search
4625 * string instead of a attribute certificate. This routine
4626 * checks if the search value is valid and then returns the
4630 serialNumberAndIssuerSerialNormalize(
4638 struct berval i, ni = BER_BVNULL,
4639 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4640 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4641 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4642 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4646 assert( in != NULL );
4647 assert( out != NULL );
4649 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4652 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4657 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4659 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4660 slap_sl_free( i.bv_val, ctx );
4664 rc = LDAP_INVALID_SYNTAX;
4668 /* Convert sn to canonical hex */
4670 sn2.bv_len = sn.bv_len;
4671 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4672 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4674 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4675 rc = LDAP_INVALID_SYNTAX;
4679 /* Convert i_sn to canonical hex */
4680 i_sn2.bv_val = i_sbuf2;
4681 i_sn2.bv_len = i_sn.bv_len;
4682 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4683 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4685 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4686 rc = LDAP_INVALID_SYNTAX;
4691 sn3.bv_len = sizeof(sbuf3);
4692 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4693 rc = LDAP_INVALID_SYNTAX;
4697 i_sn3.bv_val = i_sbuf3;
4698 i_sn3.bv_len = sizeof(i_sbuf3);
4699 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4700 rc = LDAP_INVALID_SYNTAX;
4704 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4705 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4706 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4708 if ( out->bv_val == NULL ) {
4716 p = lutil_strcopy( p, "{ serialNumber " );
4717 p = lutil_strbvcopy( p, &sn3 );
4718 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4719 p = lutil_strbvcopy( p, &ni );
4720 p = lutil_strcopy( p, "\" }, serial " );
4721 p = lutil_strbvcopy( p, &i_sn3 );
4722 p = lutil_strcopy( p, " } } }" );
4724 assert( p == &out->bv_val[out->bv_len] );
4727 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4728 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4730 if ( sn2.bv_val != sbuf2 ) {
4731 slap_sl_free( sn2.bv_val, ctx );
4734 if ( i_sn2.bv_val != i_sbuf2 ) {
4735 slap_sl_free( i_sn2.bv_val, ctx );
4738 if ( sn3.bv_val != sbuf3 ) {
4739 slap_sl_free( sn3.bv_val, ctx );
4742 if ( i_sn3.bv_val != i_sbuf3 ) {
4743 slap_sl_free( i_sn3.bv_val, ctx );
4746 slap_sl_free( ni.bv_val, ctx );
4751 /* X.509 PMI attributeCertificateExactNormalize */
4753 attributeCertificateExactNormalize(
4758 struct berval *normalized,
4761 BerElementBuffer berbuf;
4762 BerElement *ber = (BerElement *)&berbuf;
4765 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4766 struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
4767 struct berval issuer_dn = BER_BVNULL, bvdn;
4769 int rc = LDAP_INVALID_SYNTAX;
4771 if ( BER_BVISEMPTY( val ) ) {
4775 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4776 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4779 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4781 ber_init2( ber, val, LBER_USE_DER );
4782 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4783 tag = ber_skip_tag( ber, &len ); /* Sequence */
4784 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4785 ber_skip_data( ber, len );
4786 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4787 ber_skip_data( ber, len );
4790 tag = ber_skip_tag( ber, &len ); /* Sequence */
4791 /* issuerName (GeneralNames sequence; optional)? */
4792 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4793 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4794 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4795 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4796 return LDAP_INVALID_SYNTAX;
4798 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4799 len = ber_ptrlen( ber );
4800 bvdn.bv_val = val->bv_val + len;
4801 bvdn.bv_len = val->bv_len - len;
4802 rc = dnX509normalize( &bvdn, &issuer_dn );
4803 if ( rc != LDAP_SUCCESS ) goto done;
4805 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4806 ber_skip_data( ber, len );
4807 tag = ber_skip_tag( ber, &len ); /* serial number */
4808 if ( tag != LBER_INTEGER ) {
4809 rc = LDAP_INVALID_SYNTAX;
4812 i_sn.bv_val = (char *)ber->ber_ptr;
4814 i_sn2.bv_val = issuer_serialbuf;
4815 i_sn2.bv_len = sizeof(issuer_serialbuf);
4816 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4817 rc = LDAP_INVALID_SYNTAX;
4820 ber_skip_data( ber, len );
4822 /* issuerUID (bitstring; optional)? */
4823 /* objectDigestInfo (sequence; optional)? */
4825 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4826 ber_skip_data( ber, len );
4827 tag = ber_skip_tag( ber, &len ); /* serial number */
4828 if ( tag != LBER_INTEGER ) {
4829 rc = LDAP_INVALID_SYNTAX;
4832 sn.bv_val = (char *)ber->ber_ptr;
4834 sn2.bv_val = serialbuf;
4835 sn2.bv_len = sizeof(serialbuf);
4836 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4837 rc = LDAP_INVALID_SYNTAX;
4840 ber_skip_data( ber, len );
4842 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4843 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4844 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4846 p = normalized->bv_val;
4848 p = lutil_strcopy( p, "{ serialNumber " );
4849 p = lutil_strbvcopy( p, &sn2 );
4850 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4851 p = lutil_strbvcopy( p, &issuer_dn );
4852 p = lutil_strcopy( p, "\" }, serial " );
4853 p = lutil_strbvcopy( p, &i_sn2 );
4854 p = lutil_strcopy( p, " } } }" );
4856 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4857 normalized->bv_val, NULL, NULL );
4862 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4863 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4864 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4877 assert( in != NULL );
4878 assert( !BER_BVISNULL( in ) );
4880 for ( i = 0; i < in->bv_len; i++ ) {
4881 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4882 return LDAP_INVALID_SYNTAX;
4886 return LDAP_SUCCESS;
4889 /* Normalize a SID as used inside a CSN:
4890 * three-digit numeric string */
4897 struct berval *normalized,
4902 assert( val != NULL );
4903 assert( normalized != NULL );
4905 ber_dupbv_x( normalized, val, ctx );
4907 for ( i = 0; i < normalized->bv_len; i++ ) {
4908 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4909 ber_memfree_x( normalized->bv_val, ctx );
4910 BER_BVZERO( normalized );
4911 return LDAP_INVALID_SYNTAX;
4914 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4917 return LDAP_SUCCESS;
4925 assert( in != NULL );
4926 assert( !BER_BVISNULL( in ) );
4928 if ( in->bv_len != 3 ) {
4929 return LDAP_INVALID_SYNTAX;
4932 return hexValidate( NULL, in );
4935 /* Normalize a SID as used inside a CSN:
4936 * three-digit numeric string */
4943 struct berval *normalized,
4946 if ( val->bv_len != 3 ) {
4947 return LDAP_INVALID_SYNTAX;
4950 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4960 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4963 /* Normalize a SID as used inside a CSN, either as-is
4964 * (assertion value) or extracted from the CSN
4965 * (attribute value) */
4972 struct berval *normalized,
4980 if ( BER_BVISEMPTY( val ) ) {
4981 return LDAP_INVALID_SYNTAX;
4984 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4985 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4988 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4990 ptr = ber_bvchr( val, '#' );
4991 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4992 return LDAP_INVALID_SYNTAX;
4995 bv.bv_val = ptr + 1;
4996 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4998 ptr = ber_bvchr( &bv, '#' );
4999 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5000 return LDAP_INVALID_SYNTAX;
5003 bv.bv_val = ptr + 1;
5004 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5006 ptr = ber_bvchr( &bv, '#' );
5007 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5008 return LDAP_INVALID_SYNTAX;
5011 bv.bv_len = ptr - bv.bv_val;
5013 if ( bv.bv_len == 2 ) {
5014 /* OpenLDAP 2.3 SID */
5016 buf[ 1 ] = bv.bv_val[ 0 ];
5017 buf[ 2 ] = bv.bv_val[ 1 ];
5024 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
5036 assert( in != NULL );
5037 assert( !BER_BVISNULL( in ) );
5039 if ( BER_BVISEMPTY( in ) ) {
5040 return LDAP_INVALID_SYNTAX;
5045 ptr = ber_bvchr( &bv, '#' );
5046 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
5047 return LDAP_INVALID_SYNTAX;
5050 bv.bv_len = ptr - bv.bv_val;
5051 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
5052 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
5054 return LDAP_INVALID_SYNTAX;
5057 rc = generalizedTimeValidate( NULL, &bv );
5058 if ( rc != LDAP_SUCCESS ) {
5062 bv.bv_val = ptr + 1;
5063 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5065 ptr = ber_bvchr( &bv, '#' );
5066 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5067 return LDAP_INVALID_SYNTAX;
5070 bv.bv_len = ptr - bv.bv_val;
5071 if ( bv.bv_len != 6 ) {
5072 return LDAP_INVALID_SYNTAX;
5075 rc = hexValidate( NULL, &bv );
5076 if ( rc != LDAP_SUCCESS ) {
5080 bv.bv_val = ptr + 1;
5081 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5083 ptr = ber_bvchr( &bv, '#' );
5084 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5085 return LDAP_INVALID_SYNTAX;
5088 bv.bv_len = ptr - bv.bv_val;
5089 if ( bv.bv_len == 2 ) {
5090 /* tolerate old 2-digit replica-id */
5091 rc = hexValidate( NULL, &bv );
5094 rc = sidValidate( NULL, &bv );
5096 if ( rc != LDAP_SUCCESS ) {
5100 bv.bv_val = ptr + 1;
5101 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5103 if ( bv.bv_len != 6 ) {
5104 return LDAP_INVALID_SYNTAX;
5107 return hexValidate( NULL, &bv );
5110 /* Normalize a CSN in OpenLDAP 2.1 format */
5117 struct berval *normalized,
5120 struct berval gt, cnt, sid, mod;
5122 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5126 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5127 assert( !BER_BVISEMPTY( val ) );
5131 ptr = ber_bvchr( >, '#' );
5132 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5133 return LDAP_INVALID_SYNTAX;
5136 gt.bv_len = ptr - gt.bv_val;
5137 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5138 return LDAP_INVALID_SYNTAX;
5141 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5142 return LDAP_INVALID_SYNTAX;
5145 cnt.bv_val = ptr + 1;
5146 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5148 ptr = ber_bvchr( &cnt, '#' );
5149 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5150 return LDAP_INVALID_SYNTAX;
5153 cnt.bv_len = ptr - cnt.bv_val;
5154 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5155 return LDAP_INVALID_SYNTAX;
5158 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5159 return LDAP_INVALID_SYNTAX;
5162 cnt.bv_val += STRLENOF( "0x" );
5163 cnt.bv_len -= STRLENOF( "0x" );
5165 sid.bv_val = ptr + 1;
5166 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5168 ptr = ber_bvchr( &sid, '#' );
5169 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5170 return LDAP_INVALID_SYNTAX;
5173 sid.bv_len = ptr - sid.bv_val;
5174 if ( sid.bv_len != STRLENOF( "0" ) ) {
5175 return LDAP_INVALID_SYNTAX;
5178 mod.bv_val = ptr + 1;
5179 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5180 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5181 return LDAP_INVALID_SYNTAX;
5184 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5188 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5189 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5191 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5193 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5194 ptr = lutil_strbvcopy( ptr, &cnt );
5198 *ptr++ = sid.bv_val[ 0 ];
5202 for ( i = 0; i < mod.bv_len; i++ ) {
5203 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5207 assert( ptr == &bv.bv_val[bv.bv_len] );
5209 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5210 return LDAP_INVALID_SYNTAX;
5213 ber_dupbv_x( normalized, &bv, ctx );
5215 return LDAP_SUCCESS;
5218 /* Normalize a CSN in OpenLDAP 2.3 format */
5225 struct berval *normalized,
5228 struct berval gt, cnt, sid, mod;
5230 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5234 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5235 assert( !BER_BVISEMPTY( val ) );
5239 ptr = ber_bvchr( >, '#' );
5240 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5241 return LDAP_INVALID_SYNTAX;
5244 gt.bv_len = ptr - gt.bv_val;
5245 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5246 return LDAP_INVALID_SYNTAX;
5249 cnt.bv_val = ptr + 1;
5250 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5252 ptr = ber_bvchr( &cnt, '#' );
5253 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5254 return LDAP_INVALID_SYNTAX;
5257 cnt.bv_len = ptr - cnt.bv_val;
5258 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5259 return LDAP_INVALID_SYNTAX;
5262 sid.bv_val = ptr + 1;
5263 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5265 ptr = ber_bvchr( &sid, '#' );
5266 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5267 return LDAP_INVALID_SYNTAX;
5270 sid.bv_len = ptr - sid.bv_val;
5271 if ( sid.bv_len != STRLENOF( "00" ) ) {
5272 return LDAP_INVALID_SYNTAX;
5275 mod.bv_val = ptr + 1;
5276 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5277 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5278 return LDAP_INVALID_SYNTAX;
5281 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5285 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5286 ptr = lutil_strcopy( ptr, ".000000Z#" );
5287 ptr = lutil_strbvcopy( ptr, &cnt );
5290 for ( i = 0; i < sid.bv_len; i++ ) {
5291 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5294 for ( i = 0; i < mod.bv_len; i++ ) {
5295 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5299 assert( ptr == &bv.bv_val[bv.bv_len] );
5300 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5301 return LDAP_INVALID_SYNTAX;
5304 ber_dupbv_x( normalized, &bv, ctx );
5306 return LDAP_SUCCESS;
5309 /* Normalize a CSN */
5316 struct berval *normalized,
5319 struct berval cnt, sid, mod;
5323 assert( val != NULL );
5324 assert( normalized != NULL );
5326 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5328 if ( BER_BVISEMPTY( val ) ) {
5329 return LDAP_INVALID_SYNTAX;
5332 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5333 /* Openldap <= 2.3 */
5335 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5338 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5341 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5344 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5345 return LDAP_INVALID_SYNTAX;
5348 ptr = ber_bvchr( val, '#' );
5349 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5350 return LDAP_INVALID_SYNTAX;
5353 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5354 return LDAP_INVALID_SYNTAX;
5357 cnt.bv_val = ptr + 1;
5358 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5360 ptr = ber_bvchr( &cnt, '#' );
5361 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5362 return LDAP_INVALID_SYNTAX;
5365 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5366 return LDAP_INVALID_SYNTAX;
5369 sid.bv_val = ptr + 1;
5370 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5372 ptr = ber_bvchr( &sid, '#' );
5373 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5374 return LDAP_INVALID_SYNTAX;
5377 sid.bv_len = ptr - sid.bv_val;
5378 if ( sid.bv_len != STRLENOF( "000" ) ) {
5379 return LDAP_INVALID_SYNTAX;
5382 mod.bv_val = ptr + 1;
5383 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5385 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5386 return LDAP_INVALID_SYNTAX;
5389 ber_dupbv_x( normalized, val, ctx );
5391 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5392 i < normalized->bv_len; i++ )
5394 /* assume it's already validated that's all hex digits */
5395 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5398 return LDAP_SUCCESS;
5408 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5411 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5412 /* slight optimization - does not need the start parameter */
5413 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5418 check_time_syntax (struct berval *val,
5421 struct berval *fraction)
5424 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5425 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5426 * GeneralizedTime supports leap seconds, UTCTime does not.
5428 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5429 static const int mdays[2][12] = {
5430 /* non-leap years */
5431 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5433 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5436 int part, c, c1, c2, tzoffset, leapyear = 0;
5439 e = p + val->bv_len;
5441 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5442 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5444 for (part = start; part < 7 && p < e; part++) {
5446 if (!ASCII_DIGIT(c1)) {
5451 return LDAP_INVALID_SYNTAX;
5454 if (!ASCII_DIGIT(c)) {
5455 return LDAP_INVALID_SYNTAX;
5457 c += c1 * 10 - '0' * 11;
5458 if ((part | 1) == 3) {
5461 return LDAP_INVALID_SYNTAX;
5464 if (c >= ceiling[part]) {
5465 if (! (c == 60 && part == 6 && start == 0))
5466 return LDAP_INVALID_SYNTAX;
5470 if (part < 5 + start) {
5471 return LDAP_INVALID_SYNTAX;
5473 for (; part < 9; part++) {
5477 /* leapyear check for the Gregorian calendar (year>1581) */
5478 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5482 if (parts[3] >= mdays[leapyear][parts[2]]) {
5483 return LDAP_INVALID_SYNTAX;
5487 fraction->bv_val = p;
5488 fraction->bv_len = 0;
5489 if (p < e && (*p == '.' || *p == ',')) {
5491 while (++p < e && ASCII_DIGIT(*p)) {
5494 if (p - fraction->bv_val == 1) {
5495 return LDAP_INVALID_SYNTAX;
5497 for (end_num = p; end_num[-1] == '0'; --end_num) {
5500 c = end_num - fraction->bv_val;
5501 if (c != 1) fraction->bv_len = c;
5507 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5513 return LDAP_INVALID_SYNTAX;
5519 for (part = 7; part < 9 && p < e; part++) {
5521 if (!ASCII_DIGIT(c1)) {
5526 return LDAP_INVALID_SYNTAX;
5529 if (!ASCII_DIGIT(c2)) {
5530 return LDAP_INVALID_SYNTAX;
5532 parts[part] = c1 * 10 + c2 - '0' * 11;
5533 if (parts[part] >= ceiling[part]) {
5534 return LDAP_INVALID_SYNTAX;
5537 if (part < 8 + start) {
5538 return LDAP_INVALID_SYNTAX;
5541 if (tzoffset == '-') {
5542 /* negative offset to UTC, ie west of Greenwich */
5543 parts[4] += parts[7];
5544 parts[5] += parts[8];
5545 /* offset is just hhmm, no seconds */
5546 for (part = 6; --part >= 0; ) {
5550 c = mdays[leapyear][parts[2]];
5552 if (parts[part] >= c) {
5554 return LDAP_INVALID_SYNTAX;
5559 } else if (part != 5) {
5564 /* positive offset to UTC, ie east of Greenwich */
5565 parts[4] -= parts[7];
5566 parts[5] -= parts[8];
5567 for (part = 6; --part >= 0; ) {
5568 if (parts[part] < 0) {
5570 return LDAP_INVALID_SYNTAX;
5575 /* make first arg to % non-negative */
5576 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5581 } else if (part != 5) {
5588 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5591 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5598 struct berval *normalized )
5602 rc = check_time_syntax(val, 1, parts, NULL);
5603 if (rc != LDAP_SUCCESS) {
5607 normalized->bv_val = ch_malloc( 14 );
5608 if ( normalized->bv_val == NULL ) {
5609 return LBER_ERROR_MEMORY;
5612 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5613 parts[1], parts[2] + 1, parts[3] + 1,
5614 parts[4], parts[5], parts[6] );
5615 normalized->bv_len = 13;
5617 return LDAP_SUCCESS;
5627 return check_time_syntax(in, 1, parts, NULL);
5630 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5633 generalizedTimeValidate(
5638 struct berval fraction;
5639 return check_time_syntax(in, 0, parts, &fraction);
5643 generalizedTimeNormalize(
5648 struct berval *normalized,
5653 struct berval fraction;
5655 rc = check_time_syntax(val, 0, parts, &fraction);
5656 if (rc != LDAP_SUCCESS) {
5660 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5661 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5662 if ( BER_BVISNULL( normalized ) ) {
5663 return LBER_ERROR_MEMORY;
5666 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5667 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5668 parts[4], parts[5], parts[6] );
5669 if ( !BER_BVISEMPTY( &fraction ) ) {
5670 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5671 fraction.bv_val, fraction.bv_len );
5672 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5674 strcpy( normalized->bv_val + len-1, "Z" );
5675 normalized->bv_len = len;
5677 return LDAP_SUCCESS;
5681 generalizedTimeOrderingMatch(
5686 struct berval *value,
5687 void *assertedValue )
5689 struct berval *asserted = (struct berval *) assertedValue;
5690 ber_len_t v_len = value->bv_len;
5691 ber_len_t av_len = asserted->bv_len;
5693 /* ignore trailing 'Z' when comparing */
5694 int match = memcmp( value->bv_val, asserted->bv_val,
5695 (v_len < av_len ? v_len : av_len) - 1 );
5696 if ( match == 0 ) match = v_len - av_len;
5698 /* If used in extensible match filter, match if value < asserted */
5699 if ( flags & SLAP_MR_EXT )
5700 match = (match >= 0);
5703 return LDAP_SUCCESS;
5706 /* Index generation function: Ordered index */
5707 int generalizedTimeIndexer(
5712 struct berval *prefix,
5720 BerValue bvtmp; /* 40 bit index */
5722 struct lutil_timet tt;
5724 bvtmp.bv_len = sizeof(tmp);
5726 for( i=0; values[i].bv_val != NULL; i++ ) {
5727 /* just count them */
5730 /* we should have at least one value at this point */
5733 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5735 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5736 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5737 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5738 /* Use 40 bits of time for key */
5739 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5740 lutil_tm2time( &tm, &tt );
5741 tmp[0] = tt.tt_gsec & 0xff;
5742 tmp[4] = tt.tt_sec & 0xff;
5744 tmp[3] = tt.tt_sec & 0xff;
5746 tmp[2] = tt.tt_sec & 0xff;
5748 tmp[1] = tt.tt_sec & 0xff;
5750 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5754 keys[j].bv_val = NULL;
5759 return LDAP_SUCCESS;
5762 /* Index generation function: Ordered index */
5763 int generalizedTimeFilter(
5768 struct berval *prefix,
5769 void * assertedValue,
5775 BerValue bvtmp; /* 40 bit index */
5776 BerValue *value = (BerValue *) assertedValue;
5778 struct lutil_timet tt;
5780 bvtmp.bv_len = sizeof(tmp);
5782 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5783 /* Use 40 bits of time for key */
5784 if ( value->bv_val && value->bv_len >= 10 &&
5785 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5787 lutil_tm2time( &tm, &tt );
5788 tmp[0] = tt.tt_gsec & 0xff;
5789 tmp[4] = tt.tt_sec & 0xff;
5791 tmp[3] = tt.tt_sec & 0xff;
5793 tmp[2] = tt.tt_sec & 0xff;
5795 tmp[1] = tt.tt_sec & 0xff;
5797 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5798 ber_dupbv_x(keys, &bvtmp, ctx );
5799 keys[1].bv_val = NULL;
5807 return LDAP_SUCCESS;
5811 deliveryMethodValidate(
5813 struct berval *val )
5816 #define LENOF(s) (sizeof(s)-1)
5817 struct berval tmp = *val;
5819 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5820 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5821 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5824 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5826 switch( tmp.bv_val[0] ) {
5829 if(( tmp.bv_len >= LENOF("any") ) &&
5830 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5832 tmp.bv_len -= LENOF("any");
5833 tmp.bv_val += LENOF("any");
5836 return LDAP_INVALID_SYNTAX;
5840 if(( tmp.bv_len >= LENOF("mhs") ) &&
5841 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5843 tmp.bv_len -= LENOF("mhs");
5844 tmp.bv_val += LENOF("mhs");
5847 return LDAP_INVALID_SYNTAX;
5851 if(( tmp.bv_len >= LENOF("physical") ) &&
5852 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5854 tmp.bv_len -= LENOF("physical");
5855 tmp.bv_val += LENOF("physical");
5858 return LDAP_INVALID_SYNTAX;
5861 case 'T': /* telex or teletex or telephone */
5862 if(( tmp.bv_len >= LENOF("telex") ) &&
5863 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5865 tmp.bv_len -= LENOF("telex");
5866 tmp.bv_val += LENOF("telex");
5869 if(( tmp.bv_len >= LENOF("teletex") ) &&
5870 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5872 tmp.bv_len -= LENOF("teletex");
5873 tmp.bv_val += LENOF("teletex");
5876 if(( tmp.bv_len >= LENOF("telephone") ) &&
5877 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5879 tmp.bv_len -= LENOF("telephone");
5880 tmp.bv_val += LENOF("telephone");
5883 return LDAP_INVALID_SYNTAX;
5886 case 'G': /* g3fax or g4fax */
5887 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5888 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5889 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5891 tmp.bv_len -= LENOF("g3fax");
5892 tmp.bv_val += LENOF("g3fax");
5895 return LDAP_INVALID_SYNTAX;
5899 if(( tmp.bv_len >= LENOF("ia5") ) &&
5900 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5902 tmp.bv_len -= LENOF("ia5");
5903 tmp.bv_val += LENOF("ia5");
5906 return LDAP_INVALID_SYNTAX;
5910 if(( tmp.bv_len >= LENOF("videotex") ) &&
5911 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5913 tmp.bv_len -= LENOF("videotex");
5914 tmp.bv_val += LENOF("videotex");
5917 return LDAP_INVALID_SYNTAX;
5920 return LDAP_INVALID_SYNTAX;
5923 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5925 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5929 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5933 return LDAP_INVALID_SYNTAX;
5935 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5944 nisNetgroupTripleValidate(
5946 struct berval *val )
5951 if ( BER_BVISEMPTY( val ) ) {
5952 return LDAP_INVALID_SYNTAX;
5955 p = (char *)val->bv_val;
5956 e = p + val->bv_len;
5958 if ( *p != '(' /*')'*/ ) {
5959 return LDAP_INVALID_SYNTAX;
5962 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5966 return LDAP_INVALID_SYNTAX;
5969 } else if ( !AD_CHAR( *p ) ) {
5970 return LDAP_INVALID_SYNTAX;
5974 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5975 return LDAP_INVALID_SYNTAX;
5981 return LDAP_INVALID_SYNTAX;
5984 return LDAP_SUCCESS;
5988 bootParameterValidate(
5990 struct berval *val )
5994 if ( BER_BVISEMPTY( val ) ) {
5995 return LDAP_INVALID_SYNTAX;
5998 p = (char *)val->bv_val;
5999 e = p + val->bv_len;
6002 for (; ( p < e ) && ( *p != '=' ); p++ ) {
6003 if ( !AD_CHAR( *p ) ) {
6004 return LDAP_INVALID_SYNTAX;
6009 return LDAP_INVALID_SYNTAX;
6013 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
6014 if ( !AD_CHAR( *p ) ) {
6015 return LDAP_INVALID_SYNTAX;
6020 return LDAP_INVALID_SYNTAX;
6024 for ( p++; p < e; p++ ) {
6025 if ( !SLAP_PRINTABLE( *p ) ) {
6026 return LDAP_INVALID_SYNTAX;
6030 return LDAP_SUCCESS;
6034 firstComponentNormalize(
6039 struct berval *normalized,
6046 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
6047 ber_dupbv_x( normalized, val, ctx );
6048 return LDAP_SUCCESS;
6051 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
6053 if( ! ( val->bv_val[0] == '(' /*')'*/
6054 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
6055 && ! ( val->bv_val[0] == '{' /*'}'*/
6056 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
6058 return LDAP_INVALID_SYNTAX;
6061 /* trim leading white space */
6063 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
6069 /* grab next word */
6070 comp.bv_val = &val->bv_val[len];
6071 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
6072 for( comp.bv_len = 0;
6073 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
6079 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
6080 rc = numericoidValidate( NULL, &comp );
6081 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
6082 rc = integerValidate( NULL, &comp );
6084 rc = LDAP_INVALID_SYNTAX;
6088 if( rc == LDAP_SUCCESS ) {
6089 ber_dupbv_x( normalized, &comp, ctx );
6095 static char *country_gen_syn[] = {
6096 "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */
6097 "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */
6098 "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */
6102 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6103 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6105 static slap_syntax_defs_rec syntax_defs[] = {
6106 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6107 X_BINARY X_NOT_H_R ")",
6108 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6109 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6110 0, NULL, NULL, NULL},
6111 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6112 0, NULL, NULL, NULL},
6113 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6115 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6116 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6118 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6119 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6120 0, NULL, bitStringValidate, NULL },
6121 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6122 0, NULL, booleanValidate, NULL},
6123 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6124 X_BINARY X_NOT_H_R ")",
6125 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6126 NULL, certificateValidate, NULL},
6127 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6128 X_BINARY X_NOT_H_R ")",
6129 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6130 NULL, certificateListValidate, NULL},
6131 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6132 X_BINARY X_NOT_H_R ")",
6133 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6134 NULL, sequenceValidate, NULL},
6135 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6136 X_BINARY X_NOT_H_R ")",
6137 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6138 NULL, attributeCertificateValidate, NULL},
6139 #if 0 /* need to go __after__ printableString */
6140 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6141 0, "1.3.6.1.4.1.1466.115.121.1.44",
6142 countryStringValidate, NULL},
6144 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6145 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6146 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6147 0, NULL, rdnValidate, rdnPretty},
6148 #ifdef LDAP_COMP_MATCH
6149 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6150 0, NULL, allComponentsValidate, NULL},
6151 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6152 0, NULL, componentFilterValidate, NULL},
6154 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6155 0, NULL, NULL, NULL},
6156 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6157 0, NULL, deliveryMethodValidate, NULL},
6158 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6159 0, NULL, UTF8StringValidate, NULL},
6160 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6161 0, NULL, NULL, NULL},
6162 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6163 0, NULL, NULL, NULL},
6164 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6165 0, NULL, NULL, NULL},
6166 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6167 0, NULL, NULL, NULL},
6168 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6169 0, NULL, NULL, NULL},
6170 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6171 0, NULL, printablesStringValidate, NULL},
6172 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6173 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6174 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6175 0, NULL, generalizedTimeValidate, NULL},
6176 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6177 0, NULL, NULL, NULL},
6178 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6179 0, NULL, IA5StringValidate, NULL},
6180 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6181 0, NULL, integerValidate, NULL},
6182 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6183 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6184 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6185 0, NULL, NULL, NULL},
6186 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6187 0, NULL, NULL, NULL},
6188 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6189 0, NULL, NULL, NULL},
6190 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6191 0, NULL, NULL, NULL},
6192 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6193 0, NULL, NULL, NULL},
6194 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6195 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6196 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6197 0, NULL, NULL, NULL},
6198 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6199 0, NULL, numericStringValidate, NULL},
6200 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6201 0, NULL, NULL, NULL},
6202 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6203 0, NULL, numericoidValidate, NULL},
6204 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6205 0, NULL, IA5StringValidate, NULL},
6206 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6207 0, NULL, blobValidate, NULL},
6208 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6209 0, NULL, postalAddressValidate, NULL},
6210 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6211 0, NULL, NULL, NULL},
6212 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6213 0, NULL, NULL, NULL},
6214 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6215 0, NULL, printableStringValidate, NULL},
6216 /* moved here because now depends on Directory String, IA5 String
6217 * and Printable String */
6218 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6219 0, country_gen_syn, countryStringValidate, NULL},
6220 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6221 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6222 0, NULL, subtreeSpecificationValidate, NULL},
6223 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6224 X_BINARY X_NOT_H_R ")",
6225 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6226 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6227 0, NULL, printableStringValidate, NULL},
6228 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6229 0, NULL, NULL, NULL},
6230 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6231 0, NULL, printablesStringValidate, NULL},
6232 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6233 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6234 0, NULL, utcTimeValidate, NULL},
6236 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6237 0, NULL, NULL, NULL},
6238 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6239 0, NULL, NULL, NULL},
6240 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6241 0, NULL, NULL, NULL},
6242 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6243 0, NULL, NULL, NULL},
6244 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6245 0, NULL, NULL, NULL},
6247 /* RFC 2307 NIS Syntaxes */
6248 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6249 0, NULL, nisNetgroupTripleValidate, NULL},
6250 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6251 0, NULL, bootParameterValidate, NULL},
6253 /* draft-zeilenga-ldap-x509 */
6254 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6255 SLAP_SYNTAX_HIDE, NULL,
6256 serialNumberAndIssuerValidate,
6257 serialNumberAndIssuerPretty},
6258 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6259 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6260 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6261 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6262 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6263 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6264 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6265 SLAP_SYNTAX_HIDE, NULL,
6266 issuerAndThisUpdateValidate,
6267 issuerAndThisUpdatePretty},
6268 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6269 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6270 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6271 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6272 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6273 SLAP_SYNTAX_HIDE, NULL,
6274 serialNumberAndIssuerSerialValidate,
6275 serialNumberAndIssuerSerialPretty},
6276 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6277 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6279 #ifdef SLAPD_AUTHPASSWD
6280 /* needs updating */
6281 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6282 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6285 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6286 0, NULL, UUIDValidate, UUIDPretty},
6288 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6289 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6291 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6292 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6294 /* OpenLDAP Void Syntax */
6295 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6296 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6298 /* FIXME: OID is unused, but not registered yet */
6299 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6300 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6302 {NULL, 0, NULL, NULL, NULL}
6305 char *csnSIDMatchSyntaxes[] = {
6306 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6309 char *certificateExactMatchSyntaxes[] = {
6310 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6313 char *certificateListExactMatchSyntaxes[] = {
6314 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6317 char *attributeCertificateExactMatchSyntaxes[] = {
6318 attributeCertificateSyntaxOID /* attributeCertificate */,
6322 #ifdef LDAP_COMP_MATCH
6323 char *componentFilterMatchSyntaxes[] = {
6324 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6325 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6326 attributeCertificateSyntaxOID /* attributeCertificate */,
6331 char *directoryStringSyntaxes[] = {
6332 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6335 char *integerFirstComponentMatchSyntaxes[] = {
6336 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6337 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6340 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6341 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6342 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6343 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6344 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6345 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6346 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6347 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6348 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6353 * Other matching rules in X.520 that we do not use (yet):
6355 * 2.5.13.25 uTCTimeMatch
6356 * 2.5.13.26 uTCTimeOrderingMatch
6357 * 2.5.13.31* directoryStringFirstComponentMatch
6358 * 2.5.13.32* wordMatch
6359 * 2.5.13.33* keywordMatch
6360 * 2.5.13.36+ certificatePairExactMatch
6361 * 2.5.13.37+ certificatePairMatch
6362 * 2.5.13.40+ algorithmIdentifierMatch
6363 * 2.5.13.41* storedPrefixMatch
6364 * 2.5.13.42 attributeCertificateMatch
6365 * 2.5.13.43 readerAndKeyIDMatch
6366 * 2.5.13.44 attributeIntegrityMatch
6368 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6369 * (+) described in draft-zeilenga-ldap-x509
6371 static slap_mrule_defs_rec mrule_defs[] = {
6373 * EQUALITY matching rules must be listed after associated APPROX
6374 * matching rules. So, we list all APPROX matching rules first.
6376 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6377 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6378 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6379 NULL, NULL, directoryStringApproxMatch,
6380 directoryStringApproxIndexer, directoryStringApproxFilter,
6383 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6384 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6385 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6386 NULL, NULL, IA5StringApproxMatch,
6387 IA5StringApproxIndexer, IA5StringApproxFilter,
6391 * Other matching rules
6394 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6395 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6396 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6397 NULL, NULL, octetStringMatch,
6398 octetStringIndexer, octetStringFilter,
6401 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6402 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6403 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6404 NULL, dnNormalize, dnMatch,
6405 octetStringIndexer, octetStringFilter,
6408 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6409 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6410 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6411 NULL, dnNormalize, dnRelativeMatch,
6415 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6416 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6417 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6418 NULL, dnNormalize, dnRelativeMatch,
6422 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6423 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6424 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6425 NULL, dnNormalize, dnRelativeMatch,
6429 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6430 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6431 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6432 NULL, dnNormalize, dnRelativeMatch,
6436 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6437 "SYNTAX 1.2.36.79672281.1.5.0 )",
6438 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6439 NULL, rdnNormalize, rdnMatch,
6440 octetStringIndexer, octetStringFilter,
6443 #ifdef LDAP_COMP_MATCH
6444 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6445 "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */
6446 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6447 NULL, NULL , componentFilterMatch,
6448 octetStringIndexer, octetStringFilter,
6451 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6452 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6453 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6454 NULL, NULL , allComponentsMatch,
6455 octetStringIndexer, octetStringFilter,
6458 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6459 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6460 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6461 NULL, NULL , directoryComponentsMatch,
6462 octetStringIndexer, octetStringFilter,
6466 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6468 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6469 NULL, UTF8StringNormalize, octetStringMatch,
6470 octetStringIndexer, octetStringFilter,
6471 directoryStringApproxMatchOID },
6473 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6475 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6476 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6478 "caseIgnoreMatch" },
6480 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6481 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6482 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6483 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6484 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6485 "caseIgnoreMatch" },
6487 {"( 2.5.13.5 NAME 'caseExactMatch' "
6488 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6489 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6490 NULL, UTF8StringNormalize, octetStringMatch,
6491 octetStringIndexer, octetStringFilter,
6492 directoryStringApproxMatchOID },
6494 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6495 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6496 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6497 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6501 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6503 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6504 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6505 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6508 {"( 2.5.13.8 NAME 'numericStringMatch' "
6509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6510 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6511 NULL, numericStringNormalize, octetStringMatch,
6512 octetStringIndexer, octetStringFilter,
6515 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6517 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6518 NULL, numericStringNormalize, octetStringOrderingMatch,
6520 "numericStringMatch" },
6522 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6524 SLAP_MR_SUBSTR, NULL,
6525 NULL, numericStringNormalize, octetStringSubstringsMatch,
6526 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6527 "numericStringMatch" },
6529 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6530 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */
6531 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6532 NULL, postalAddressNormalize, octetStringMatch,
6533 octetStringIndexer, octetStringFilter,
6536 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6538 SLAP_MR_SUBSTR, NULL,
6539 NULL, NULL, NULL, NULL, NULL,
6540 "caseIgnoreListMatch" },
6542 {"( 2.5.13.13 NAME 'booleanMatch' "
6543 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6544 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6545 NULL, NULL, booleanMatch,
6546 octetStringIndexer, octetStringFilter,
6549 {"( 2.5.13.14 NAME 'integerMatch' "
6550 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6551 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6552 NULL, NULL, integerMatch,
6553 integerIndexer, integerFilter,
6556 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6557 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6558 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6559 NULL, NULL, integerMatch,
6563 {"( 2.5.13.16 NAME 'bitStringMatch' "
6564 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6565 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6566 NULL, NULL, octetStringMatch,
6567 octetStringIndexer, octetStringFilter,
6570 {"( 2.5.13.17 NAME 'octetStringMatch' "
6571 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6572 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6573 NULL, NULL, octetStringMatch,
6574 octetStringIndexer, octetStringFilter,
6577 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6578 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6579 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6580 NULL, NULL, octetStringOrderingMatch,
6582 "octetStringMatch" },
6584 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6585 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6586 SLAP_MR_SUBSTR, NULL,
6587 NULL, NULL, octetStringSubstringsMatch,
6588 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6589 "octetStringMatch" },
6591 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6592 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6593 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6595 telephoneNumberNormalize, octetStringMatch,
6596 octetStringIndexer, octetStringFilter,
6599 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6600 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6601 SLAP_MR_SUBSTR, NULL,
6602 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6603 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6604 "telephoneNumberMatch" },
6606 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6607 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6608 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6609 NULL, NULL, NULL, NULL, NULL, NULL },
6611 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6612 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */
6613 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6614 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6615 uniqueMemberIndexer, uniqueMemberFilter,
6618 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6619 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6620 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6621 NULL, NULL, NULL, NULL, NULL, NULL },
6623 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6624 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6625 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6626 NULL, generalizedTimeNormalize, octetStringMatch,
6627 generalizedTimeIndexer, generalizedTimeFilter,
6630 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6631 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6632 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6633 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6635 "generalizedTimeMatch" },
6637 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6638 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6639 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6640 integerFirstComponentMatchSyntaxes,
6641 NULL, firstComponentNormalize, integerMatch,
6642 octetStringIndexer, octetStringFilter,
6645 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6646 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */
6647 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6648 objectIdentifierFirstComponentMatchSyntaxes,
6649 NULL, firstComponentNormalize, octetStringMatch,
6650 octetStringIndexer, octetStringFilter,
6653 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6654 "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */
6655 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6656 NULL, certificateExactNormalize, octetStringMatch,
6657 octetStringIndexer, octetStringFilter,
6660 {"( 2.5.13.35 NAME 'certificateMatch' "
6661 "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */
6662 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6663 NULL, NULL, NULL, NULL, NULL,
6666 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6667 "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */
6668 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6669 NULL, certificateListExactNormalize, octetStringMatch,
6670 octetStringIndexer, octetStringFilter,
6673 {"( 2.5.13.39 NAME 'certificateListMatch' "
6674 "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */
6675 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6676 NULL, NULL, NULL, NULL, NULL,
6679 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6680 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6681 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6682 NULL, attributeCertificateExactNormalize, octetStringMatch,
6683 octetStringIndexer, octetStringFilter,
6686 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6687 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6688 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6689 NULL, NULL, NULL, NULL, NULL,
6692 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6693 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6694 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6695 NULL, IA5StringNormalize, octetStringMatch,
6696 octetStringIndexer, octetStringFilter,
6697 IA5StringApproxMatchOID },
6699 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6700 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6701 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6702 NULL, IA5StringNormalize, octetStringMatch,
6703 octetStringIndexer, octetStringFilter,
6704 IA5StringApproxMatchOID },
6706 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6707 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6708 SLAP_MR_SUBSTR, NULL,
6709 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6710 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6711 "caseIgnoreIA5Match" },
6713 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6714 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6715 SLAP_MR_SUBSTR, NULL,
6716 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6717 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6718 "caseExactIA5Match" },
6720 #ifdef SLAPD_AUTHPASSWD
6721 /* needs updating */
6722 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6723 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */
6724 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6725 NULL, NULL, authPasswordMatch,
6730 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6731 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6733 NULL, NULL, integerBitAndMatch,
6737 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6738 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6740 NULL, NULL, integerBitOrMatch,
6744 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6745 "SYNTAX 1.3.6.1.1.16.1 )",
6746 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6747 NULL, UUIDNormalize, octetStringMatch,
6748 octetStringIndexer, octetStringFilter,
6751 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6752 "SYNTAX 1.3.6.1.1.16.1 )",
6753 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6754 NULL, UUIDNormalize, octetStringOrderingMatch,
6755 octetStringIndexer, octetStringFilter,
6758 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6759 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6760 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6761 NULL, csnNormalize, csnMatch,
6762 csnIndexer, csnFilter,
6765 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6766 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6767 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6768 NULL, csnNormalize, csnOrderingMatch,
6772 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6773 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6774 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6775 NULL, csnSidNormalize, octetStringMatch,
6776 octetStringIndexer, octetStringFilter,
6779 /* FIXME: OID is unused, but not registered yet */
6780 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6781 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */
6782 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6783 NULL, authzNormalize, authzMatch,
6787 {NULL, SLAP_MR_NONE, NULL,
6788 NULL, NULL, NULL, NULL, NULL,
6793 slap_schema_init( void )
6798 /* we should only be called once (from main) */
6799 assert( schema_init_done == 0 );
6801 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6802 res = register_syntax( &syntax_defs[i] );
6805 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6806 syntax_defs[i].sd_desc );
6811 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6812 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6813 mrule_defs[i].mrd_compat_syntaxes == NULL )
6816 "slap_schema_init: Ignoring unusable matching rule %s\n",
6817 mrule_defs[i].mrd_desc );
6821 res = register_matching_rule( &mrule_defs[i] );
6825 "slap_schema_init: Error registering matching rule %s\n",
6826 mrule_defs[i].mrd_desc );
6831 res = slap_schema_load();
6832 schema_init_done = 1;
6837 schema_destroy( void )
6846 if( schema_init_done ) {
6847 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6848 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );