1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2014 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"
109 #ifdef LUTIL_HASH64_BYTES
110 #define HASH_BYTES LUTIL_HASH64_BYTES
111 #define HASH_LEN hashlen
112 static void (*hashinit)(lutil_HASH_CTX *ctx) = lutil_HASHInit;
113 static void (*hashupdate)(lutil_HASH_CTX *ctx,unsigned char const *buf, ber_len_t len) = lutil_HASHUpdate;
114 static void (*hashfinal)(unsigned char digest[HASH_BYTES], lutil_HASH_CTX *ctx) = lutil_HASHFinal;
115 static int hashlen = LUTIL_HASH_BYTES;
116 #define HASH_Init(c) hashinit(c)
117 #define HASH_Update(c,buf,len) hashupdate(c,buf,len)
118 #define HASH_Final(d,c) hashfinal(d,c)
120 /* Toggle between 32 and 64 bit hashing, default to 32 for compatibility
121 -1 to query, returns 1 if 64 bit, 0 if 32.
122 0/1 to set 32/64, returns 0 on success, -1 on failure */
123 int slap_hash64( int onoff )
126 return hashlen == LUTIL_HASH64_BYTES;
127 } else if ( onoff ) {
128 hashinit = lutil_HASH64Init;
129 hashupdate = lutil_HASH64Update;
130 hashfinal = lutil_HASH64Final;
131 hashlen = LUTIL_HASH64_BYTES;
133 hashinit = lutil_HASHInit;
134 hashupdate = lutil_HASHUpdate;
135 hashfinal = lutil_HASHFinal;
136 hashlen = LUTIL_HASH_BYTES;
142 #define HASH_BYTES LUTIL_HASH_BYTES
143 #define HASH_LEN HASH_BYTES
144 #define HASH_Init(c) lutil_HASHInit(c)
145 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
146 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
148 int slap_has64( int onoff )
153 return onoff ? -1 : 0;
157 #define HASH_CONTEXT lutil_HASH_CTX
159 /* approx matching rules */
160 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
161 #define directoryStringApproxMatch approxMatch
162 #define directoryStringApproxIndexer approxIndexer
163 #define directoryStringApproxFilter approxFilter
164 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
165 #define IA5StringApproxMatch approxMatch
166 #define IA5StringApproxIndexer approxIndexer
167 #define IA5StringApproxFilter approxFilter
169 /* Change Sequence Number (CSN) - much of this will change */
170 #define csnMatch octetStringMatch
171 #define csnOrderingMatch octetStringOrderingMatch
172 #define csnIndexer generalizedTimeIndexer
173 #define csnFilter generalizedTimeFilter
175 #define authzMatch octetStringMatch
177 /* X.509 PMI ldapSyntaxes */
178 /* FIXME: need to create temporary OIDs under OpenLDAP's arc;
179 * these are currently hijacked
181 * 1.3.6.1.4.1.4203.666 OpenLDAP
182 * 1.3.6.1.4.1.4203.666.11 self-contained works
183 * 1.3.6.1.4.1.4203.666.11.10 X.509 PMI
184 * 1.3.6.1.4.1.4203.666.11.10.2 X.509 PMI ldapSyntaxes
185 * 1.3.6.1.4.1.4203.666.11.10.2.1 AttributeCertificate (supported)
186 * 1.3.6.1.4.1.4203.666.11.10.2.2 AttributeCertificateExactAssertion (supported)
187 * 1.3.6.1.4.1.4203.666.11.10.2.3 AttributeCertificateAssertion (not supported)
188 * 1.3.6.1.4.1.4203.666.11.10.2.4 AttCertPath (X-SUBST'ed right now in pmi.schema)
189 * 1.3.6.1.4.1.4203.666.11.10.2.5 PolicySyntax (X-SUBST'ed right now in pmi.schema)
190 * 1.3.6.1.4.1.4203.666.11.10.2.6 RoleSyntax (X-SUBST'ed right now in pmi.schema)
192 #if 0 /* from <draft-ietf-pkix-ldap-schema-02.txt> (expired) */
193 #define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5"
194 #define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6"
195 #define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7"
196 #else /* from OpenLDAP's experimental oid arc */
197 #define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2"
198 #define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1"
199 #define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2"
200 #define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3"
203 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
204 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
205 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
206 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
208 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
209 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
210 SLAP_INDEX_INTLEN_DEFAULT );
212 ldap_pvt_thread_mutex_t ad_index_mutex;
213 ldap_pvt_thread_mutex_t ad_undef_mutex;
214 ldap_pvt_thread_mutex_t oc_undef_mutex;
217 generalizedTimeValidate(
221 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
226 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
233 /* no value allowed */
234 return LDAP_INVALID_SYNTAX;
242 /* any value allowed */
246 #define berValidate blobValidate
253 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
254 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
259 /* X.509 related stuff */
268 SLAP_TAG_UTCTIME = 0x17U,
269 SLAP_TAG_GENERALIZEDTIME = 0x18U
273 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
276 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
277 SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1,
278 SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2,
279 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
283 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
287 GeneralName ::= CHOICE {
288 otherName [0] INSTANCE OF OTHER-NAME,
289 rfc822Name [1] IA5String,
290 dNSName [2] IA5String,
291 x400Address [3] ORAddress,
292 directoryName [4] Name,
293 ediPartyName [5] EDIPartyName,
294 uniformResourceIdentifier [6] IA5String,
295 iPAddress [7] OCTET STRING,
296 registeredID [8] OBJECT IDENTIFIER }
299 SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0,
300 SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1,
301 SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2,
302 SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3,
303 SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4,
304 SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5,
305 SLAP_X509_GN_URI = SLAP_X509_OPTION + 6,
306 SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7,
307 SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8
310 /* X.509 PMI related stuff */
317 SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0
320 /* X.509 certificate validation */
322 certificateValidate( Syntax *syntax, struct berval *in )
324 BerElementBuffer berbuf;
325 BerElement *ber = (BerElement *)&berbuf;
328 ber_int_t version = SLAP_X509_V1;
330 ber_init2( ber, in, LBER_USE_DER );
331 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
332 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
333 tag = ber_skip_tag( ber, &len ); /* Sequence */
334 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
335 tag = ber_peek_tag( ber, &len );
336 /* Optional version */
337 if ( tag == SLAP_X509_OPT_C_VERSION ) {
338 tag = ber_skip_tag( ber, &len );
339 tag = ber_get_int( ber, &version );
340 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
342 /* NOTE: don't try to parse Serial, because it might be longer
343 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
344 tag = ber_skip_tag( ber, &len ); /* Serial */
345 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
346 ber_skip_data( ber, len );
347 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
348 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
349 ber_skip_data( ber, len );
350 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
351 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
352 ber_skip_data( ber, len );
353 tag = ber_skip_tag( ber, &len ); /* Validity */
354 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
355 ber_skip_data( ber, len );
356 tag = ber_skip_tag( ber, &len ); /* Subject DN */
357 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
358 ber_skip_data( ber, len );
359 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
360 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
361 ber_skip_data( ber, len );
362 tag = ber_skip_tag( ber, &len );
363 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
364 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
365 ber_skip_data( ber, len );
366 tag = ber_skip_tag( ber, &len );
368 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
369 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
370 ber_skip_data( ber, len );
371 tag = ber_skip_tag( ber, &len );
373 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
374 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
375 tag = ber_skip_tag( ber, &len );
376 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
377 ber_skip_data( ber, len );
378 tag = ber_skip_tag( ber, &len );
380 /* signatureAlgorithm */
381 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
382 ber_skip_data( ber, len );
383 tag = ber_skip_tag( ber, &len );
385 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
386 ber_skip_data( ber, len );
387 tag = ber_skip_tag( ber, &len );
388 /* Must be at end now */
389 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
393 /* X.509 certificate list validation */
395 checkTime( struct berval *in, struct berval *out );
398 certificateListValidate( Syntax *syntax, struct berval *in )
400 BerElementBuffer berbuf;
401 BerElement *ber = (BerElement *)&berbuf;
403 ber_len_t len, wrapper_len;
406 ber_int_t version = SLAP_X509_V1;
407 struct berval bvdn, bvtu;
409 ber_init2( ber, in, LBER_USE_DER );
410 tag = ber_skip_tag( ber, &wrapper_len ); /* Signed wrapper */
411 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
412 wrapper_start = ber->ber_ptr;
413 tag = ber_skip_tag( ber, &len ); /* Sequence */
414 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
415 tag = ber_peek_tag( ber, &len );
416 /* Optional version */
417 if ( tag == LBER_INTEGER ) {
418 tag = ber_get_int( ber, &version );
419 assert( tag == LBER_INTEGER );
420 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
422 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
423 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
424 ber_skip_data( ber, len );
425 tag = ber_peek_tag( ber, &len ); /* Issuer DN */
426 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
427 len = ber_ptrlen( ber );
428 bvdn.bv_val = in->bv_val + len;
429 bvdn.bv_len = in->bv_len - len;
430 tag = ber_skip_tag( ber, &len );
431 ber_skip_data( ber, len );
432 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
433 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
434 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
435 bvtu.bv_val = (char *)ber->ber_ptr;
437 ber_skip_data( ber, len );
438 /* Optional nextUpdate */
439 tag = ber_skip_tag( ber, &len );
440 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
441 ber_skip_data( ber, len );
442 tag = ber_skip_tag( ber, &len );
444 /* revokedCertificates - Sequence of Sequence, Optional */
445 if ( tag == LBER_SEQUENCE ) {
448 stag = ber_peek_tag( ber, &seqlen );
449 if ( stag == LBER_SEQUENCE || !len ) {
450 /* RFC5280 requires non-empty, but X.509(2005) allows empty. */
452 ber_skip_data( ber, len );
453 tag = ber_skip_tag( ber, &len );
456 /* Optional Extensions - Sequence of Sequence */
457 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
459 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
460 tag = ber_peek_tag( ber, &seqlen );
461 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
462 ber_skip_data( ber, len );
463 tag = ber_skip_tag( ber, &len );
465 /* signatureAlgorithm */
466 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
467 ber_skip_data( ber, len );
468 tag = ber_skip_tag( ber, &len );
470 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
471 ber_skip_data( ber, len );
472 if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
473 tag = ber_skip_tag( ber, &len );
474 /* Must be at end now */
475 /* NOTE: OpenSSL tolerates CL with garbage past the end */
476 if ( len || tag != LBER_DEFAULT ) {
477 struct berval issuer_dn = BER_BVNULL, thisUpdate;
478 char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
481 if ( ! wrapper_ok ) {
482 return LDAP_INVALID_SYNTAX;
485 rc = dnX509normalize( &bvdn, &issuer_dn );
486 if ( rc != LDAP_SUCCESS ) {
487 rc = LDAP_INVALID_SYNTAX;
491 thisUpdate.bv_val = tubuf;
492 thisUpdate.bv_len = sizeof(tubuf);
493 if ( checkTime( &bvtu, &thisUpdate ) ) {
494 rc = LDAP_INVALID_SYNTAX;
498 Debug( LDAP_DEBUG_ANY,
499 "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
500 issuer_dn.bv_val, thisUpdate.bv_val, 0 );
503 if ( ! BER_BVISNULL( &issuer_dn ) ) {
504 ber_memfree( issuer_dn.bv_val );
513 /* X.509 PMI Attribute Certificate Validate */
515 attributeCertificateValidate( Syntax *syntax, struct berval *in )
517 BerElementBuffer berbuf;
518 BerElement *ber = (BerElement *)&berbuf;
524 ber_init2( ber, in, LBER_USE_DER );
526 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
527 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
529 tag = ber_skip_tag( ber, &len ); /* Sequence */
530 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
532 tag = ber_peek_tag( ber, &len ); /* Version */
533 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
534 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
535 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
537 tag = ber_skip_tag( ber, &len ); /* Holder */
538 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
539 ber_skip_data( ber, len );
541 tag = ber_skip_tag( ber, &len ); /* Issuer */
542 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
543 ber_skip_data( ber, len );
545 tag = ber_skip_tag( ber, &len ); /* Signature */
546 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
547 ber_skip_data( ber, len );
549 tag = ber_skip_tag( ber, &len ); /* Serial number */
550 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
551 ber_skip_data( ber, len );
553 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
554 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
555 ber_skip_data( ber, len );
557 tag = ber_skip_tag( ber, &len ); /* Attributes */
558 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
559 ber_skip_data( ber, len );
561 tag = ber_peek_tag( ber, &len );
563 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
564 tag = ber_skip_tag( ber, &len );
565 ber_skip_data( ber, len );
566 tag = ber_peek_tag( ber, &len );
569 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
570 tag = ber_skip_tag( ber, &len );
571 ber_skip_data( ber, len );
573 tag = ber_peek_tag( ber, &len );
576 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
577 tag = ber_skip_tag( ber, &len );
578 ber_skip_data( ber, len );
580 tag = ber_peek_tag( ber, &len );
583 if ( tag == LBER_BITSTRING ) { /* Signature */
584 tag = ber_skip_tag( ber, &len );
585 ber_skip_data( ber, len );
587 tag = ber_peek_tag( ber, &len );
590 /* Must be at end now */
591 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
602 struct berval *value,
603 void *assertedValue )
605 struct berval *asserted = (struct berval *) assertedValue;
606 ber_slen_t d = (ber_slen_t) value->bv_len - (ber_slen_t) asserted->bv_len;
608 /* For speed, order first by length, then by contents */
609 *matchp = d ? (sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1)
610 : memcmp( value->bv_val, asserted->bv_val, value->bv_len );
616 octetStringOrderingMatch(
621 struct berval *value,
622 void *assertedValue )
624 struct berval *asserted = (struct berval *) assertedValue;
625 ber_len_t v_len = value->bv_len;
626 ber_len_t av_len = asserted->bv_len;
628 int match = memcmp( value->bv_val, asserted->bv_val,
629 (v_len < av_len ? v_len : av_len) );
632 match = sizeof(v_len) == sizeof(int)
633 ? (int) v_len - (int) av_len
634 : v_len < av_len ? -1 : v_len > av_len;
636 /* If used in extensible match filter, match if value < asserted */
637 if ( flags & SLAP_MR_EXT )
638 match = (match >= 0);
644 /* Initialize HASHcontext from match type and schema info */
647 HASH_CONTEXT *HASHcontext,
648 struct berval *prefix,
653 HASH_Init(HASHcontext);
654 if(prefix && prefix->bv_len > 0) {
655 HASH_Update(HASHcontext,
656 (unsigned char *)prefix->bv_val, prefix->bv_len);
658 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
659 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
660 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
664 /* Set HASHdigest from HASHcontext and value:len */
667 HASH_CONTEXT *HASHcontext,
668 unsigned char *HASHdigest,
669 unsigned char *value,
672 HASH_CONTEXT ctx = *HASHcontext;
673 HASH_Update( &ctx, value, len );
674 HASH_Final( HASHdigest, &ctx );
677 /* Index generation function: Attribute values -> index hash keys */
678 int octetStringIndexer(
683 struct berval *prefix,
691 HASH_CONTEXT HASHcontext;
692 unsigned char HASHdigest[HASH_BYTES];
693 struct berval digest;
694 digest.bv_val = (char *)HASHdigest;
695 digest.bv_len = HASH_LEN;
697 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
698 /* just count them */
701 /* we should have at least one value at this point */
704 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
706 slen = syntax->ssyn_oidlen;
707 mlen = mr->smr_oidlen;
709 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
710 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
711 hashIter( &HASHcontext, HASHdigest,
712 (unsigned char *)values[i].bv_val, values[i].bv_len );
713 ber_dupbv_x( &keys[i], &digest, ctx );
716 BER_BVZERO( &keys[i] );
723 /* Index generation function: Asserted value -> index hash key */
724 int octetStringFilter(
729 struct berval *prefix,
730 void * assertedValue,
736 HASH_CONTEXT HASHcontext;
737 unsigned char HASHdigest[HASH_BYTES];
738 struct berval *value = (struct berval *) assertedValue;
739 struct berval digest;
740 digest.bv_val = (char *)HASHdigest;
741 digest.bv_len = HASH_LEN;
743 slen = syntax->ssyn_oidlen;
744 mlen = mr->smr_oidlen;
746 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
748 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
749 hashIter( &HASHcontext, HASHdigest,
750 (unsigned char *)value->bv_val, value->bv_len );
752 ber_dupbv_x( keys, &digest, ctx );
753 BER_BVZERO( &keys[1] );
761 octetStringSubstringsMatch(
766 struct berval *value,
767 void *assertedValue )
770 SubstringsAssertion *sub = assertedValue;
771 struct berval left = *value;
775 /* Add up asserted input length */
776 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
777 inlen += sub->sa_initial.bv_len;
780 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
781 inlen += sub->sa_any[i].bv_len;
784 if ( !BER_BVISNULL( &sub->sa_final ) ) {
785 inlen += sub->sa_final.bv_len;
788 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
789 if ( inlen > left.bv_len ) {
794 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
795 sub->sa_initial.bv_len );
801 left.bv_val += sub->sa_initial.bv_len;
802 left.bv_len -= sub->sa_initial.bv_len;
803 inlen -= sub->sa_initial.bv_len;
806 if ( !BER_BVISNULL( &sub->sa_final ) ) {
807 if ( inlen > left.bv_len ) {
812 match = memcmp( sub->sa_final.bv_val,
813 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
814 sub->sa_final.bv_len );
820 left.bv_len -= sub->sa_final.bv_len;
821 inlen -= sub->sa_final.bv_len;
825 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
830 if ( inlen > left.bv_len ) {
831 /* not enough length */
836 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
840 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
847 idx = p - left.bv_val;
849 if ( idx >= left.bv_len ) {
850 /* this shouldn't happen */
857 if ( sub->sa_any[i].bv_len > left.bv_len ) {
858 /* not enough left */
863 match = memcmp( left.bv_val,
864 sub->sa_any[i].bv_val,
865 sub->sa_any[i].bv_len );
873 left.bv_val += sub->sa_any[i].bv_len;
874 left.bv_len -= sub->sa_any[i].bv_len;
875 inlen -= sub->sa_any[i].bv_len;
884 /* Substring index generation function: Attribute values -> index hash keys */
886 octetStringSubstringsIndexer(
891 struct berval *prefix,
900 HASH_CONTEXT HCany, HCini, HCfin;
901 unsigned char HASHdigest[HASH_BYTES];
902 struct berval digest;
903 digest.bv_val = (char *)HASHdigest;
904 digest.bv_len = HASH_LEN;
908 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
909 /* count number of indices to generate */
910 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
911 if( values[i].bv_len >= index_substr_if_maxlen ) {
912 nkeys += index_substr_if_maxlen -
913 (index_substr_if_minlen - 1);
914 } else if( values[i].bv_len >= index_substr_if_minlen ) {
915 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
919 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
920 if( values[i].bv_len >= index_substr_any_len ) {
921 nkeys += values[i].bv_len - (index_substr_any_len - 1);
925 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
926 if( values[i].bv_len >= index_substr_if_maxlen ) {
927 nkeys += index_substr_if_maxlen -
928 (index_substr_if_minlen - 1);
929 } else if( values[i].bv_len >= index_substr_if_minlen ) {
930 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
936 /* no keys to generate */
941 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
943 slen = syntax->ssyn_oidlen;
944 mlen = mr->smr_oidlen;
946 if ( flags & SLAP_INDEX_SUBSTR_ANY )
947 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
948 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
949 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
950 if( flags & SLAP_INDEX_SUBSTR_FINAL )
951 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
954 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
957 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
958 ( values[i].bv_len >= index_substr_any_len ) )
960 max = values[i].bv_len - (index_substr_any_len - 1);
962 for( j=0; j<max; j++ ) {
963 hashIter( &HCany, HASHdigest,
964 (unsigned char *)&values[i].bv_val[j],
965 index_substr_any_len );
966 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
970 /* skip if too short */
971 if( values[i].bv_len < index_substr_if_minlen ) continue;
973 max = index_substr_if_maxlen < values[i].bv_len
974 ? index_substr_if_maxlen : values[i].bv_len;
976 for( j=index_substr_if_minlen; j<=max; j++ ) {
978 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
979 hashIter( &HCini, HASHdigest,
980 (unsigned char *)values[i].bv_val, j );
981 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
984 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
985 hashIter( &HCfin, HASHdigest,
986 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
987 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
994 BER_BVZERO( &keys[nkeys] );
1001 return LDAP_SUCCESS;
1004 /* Substring index generation function: Assertion value -> index hash keys */
1006 octetStringSubstringsFilter (
1011 struct berval *prefix,
1012 void * assertedValue,
1016 SubstringsAssertion *sa;
1018 ber_len_t nkeys = 0;
1019 size_t slen, mlen, klen;
1021 HASH_CONTEXT HASHcontext;
1022 unsigned char HASHdigest[HASH_BYTES];
1023 struct berval *value;
1024 struct berval digest;
1026 sa = (SubstringsAssertion *) assertedValue;
1028 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
1029 !BER_BVISNULL( &sa->sa_initial ) &&
1030 sa->sa_initial.bv_len >= index_substr_if_minlen )
1033 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
1034 ( flags & SLAP_INDEX_SUBSTR_ANY ))
1036 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
1040 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1042 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
1043 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
1044 /* don't bother accounting with stepping */
1045 nkeys += sa->sa_any[i].bv_len -
1046 ( index_substr_any_len - 1 );
1051 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1052 !BER_BVISNULL( &sa->sa_final ) &&
1053 sa->sa_final.bv_len >= index_substr_if_minlen )
1056 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
1057 ( flags & SLAP_INDEX_SUBSTR_ANY ))
1059 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
1065 return LDAP_SUCCESS;
1068 digest.bv_val = (char *)HASHdigest;
1069 digest.bv_len = HASH_LEN;
1071 slen = syntax->ssyn_oidlen;
1072 mlen = mr->smr_oidlen;
1074 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
1077 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
1078 !BER_BVISNULL( &sa->sa_initial ) &&
1079 sa->sa_initial.bv_len >= index_substr_if_minlen )
1081 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1082 value = &sa->sa_initial;
1084 klen = index_substr_if_maxlen < value->bv_len
1085 ? index_substr_if_maxlen : value->bv_len;
1087 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1088 hashIter( &HASHcontext, HASHdigest,
1089 (unsigned char *)value->bv_val, klen );
1090 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1092 /* If initial is too long and we have subany indexed, use it
1093 * to match the excess...
1095 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1098 pre = SLAP_INDEX_SUBSTR_PREFIX;
1099 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1100 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
1102 hashIter( &HASHcontext, HASHdigest,
1103 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1104 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1109 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1111 pre = SLAP_INDEX_SUBSTR_PREFIX;
1112 klen = index_substr_any_len;
1114 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
1115 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
1119 value = &sa->sa_any[i];
1121 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1123 j <= value->bv_len - index_substr_any_len;
1124 j += index_substr_any_step )
1126 hashIter( &HASHcontext, HASHdigest,
1127 (unsigned char *)&value->bv_val[j], klen );
1128 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1133 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1134 !BER_BVISNULL( &sa->sa_final ) &&
1135 sa->sa_final.bv_len >= index_substr_if_minlen )
1137 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1138 value = &sa->sa_final;
1140 klen = index_substr_if_maxlen < value->bv_len
1141 ? index_substr_if_maxlen : value->bv_len;
1143 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1144 hashIter( &HASHcontext, HASHdigest,
1145 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
1146 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1148 /* If final is too long and we have subany indexed, use it
1149 * to match the excess...
1151 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1154 pre = SLAP_INDEX_SUBSTR_PREFIX;
1155 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1156 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
1158 hashIter( &HASHcontext, HASHdigest,
1159 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1160 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1166 BER_BVZERO( &keys[nkeys] );
1173 return LDAP_SUCCESS;
1183 /* very unforgiving validation, requires no normalization
1184 * before simplistic matching
1186 if( in->bv_len < 3 ) {
1187 return LDAP_INVALID_SYNTAX;
1190 /* RFC 4517 Section 3.3.2 Bit String:
1191 * BitString = SQUOTE *binary-digit SQUOTE "B"
1192 * binary-digit = "0" / "1"
1194 * where SQUOTE [RFC4512] is
1195 * SQUOTE = %x27 ; single quote ("'")
1197 * Example: '0101111101'B
1200 if( in->bv_val[0] != '\'' ||
1201 in->bv_val[in->bv_len - 2] != '\'' ||
1202 in->bv_val[in->bv_len - 1] != 'B' )
1204 return LDAP_INVALID_SYNTAX;
1207 for( i = in->bv_len - 3; i > 0; i-- ) {
1208 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1209 return LDAP_INVALID_SYNTAX;
1213 return LDAP_SUCCESS;
1217 * Syntaxes from RFC 4517
1222 A value of the Bit String syntax is a sequence of binary digits. The
1223 LDAP-specific encoding of a value of this syntax is defined by the
1226 BitString = SQUOTE *binary-digit SQUOTE "B"
1228 binary-digit = "0" / "1"
1230 The <SQUOTE> rule is defined in [MODELS].
1235 The LDAP definition for the Bit String syntax is:
1237 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1239 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1243 3.3.21. Name and Optional UID
1245 A value of the Name and Optional UID syntax is the distinguished name
1246 [MODELS] of an entity optionally accompanied by a unique identifier
1247 that serves to differentiate the entity from others with an identical
1250 The LDAP-specific encoding of a value of this syntax is defined by
1253 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1255 The <BitString> rule is defined in Section 3.3.2. The
1256 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1257 defined in [MODELS].
1259 Note that although the '#' character may occur in the string
1260 representation of a distinguished name, no additional escaping of
1261 this character is performed when a <distinguishedName> is encoded in
1262 a <NameAndOptionalUID>.
1265 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1267 The LDAP definition for the Name and Optional UID syntax is:
1269 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1271 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1278 1.4. Common ABNF Productions
1281 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1283 SQUOTE = %x27 ; single quote ("'")
1288 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1289 * be escaped except when at the beginning of a value, the
1290 * definition of Name and Optional UID appears to be flawed,
1291 * because there is no clear means to determine whether the
1292 * UID part is present or not.
1296 * cn=Someone,dc=example,dc=com#'1'B
1298 * could be either a NameAndOptionalUID with trailing UID, i.e.
1300 * DN = "cn=Someone,dc=example,dc=com"
1303 * or a NameAndOptionalUID with no trailing UID, and the AVA
1304 * in the last RDN made of
1306 * attributeType = dc
1307 * attributeValue = com#'1'B
1309 * in fact "com#'1'B" is a valid IA5 string.
1311 * As a consequence, current slapd code takes the presence of
1312 * #<valid BitString> at the end of the string representation
1313 * of a NameAndOptionalUID to mean this is indeed a BitString.
1314 * This is quite arbitrary - it has changed the past and might
1315 * change in the future.
1325 struct berval dn, uid;
1327 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1329 ber_dupbv( &dn, in );
1330 if( !dn.bv_val ) return LDAP_OTHER;
1332 /* if there's a "#", try bitStringValidate()... */
1333 uid.bv_val = strrchr( dn.bv_val, '#' );
1334 if ( !BER_BVISNULL( &uid ) ) {
1336 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1338 rc = bitStringValidate( NULL, &uid );
1339 if ( rc == LDAP_SUCCESS ) {
1340 /* in case of success, trim the UID,
1341 * otherwise treat it as part of the DN */
1342 dn.bv_len -= uid.bv_len + 1;
1343 uid.bv_val[-1] = '\0';
1347 rc = dnValidate( NULL, &dn );
1349 ber_memfree( dn.bv_val );
1360 assert( val != NULL );
1361 assert( out != NULL );
1364 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1366 if( BER_BVISEMPTY( val ) ) {
1367 ber_dupbv_x( out, val, ctx );
1369 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1370 return LDAP_INVALID_SYNTAX;
1374 struct berval dnval = *val;
1375 struct berval uidval = BER_BVNULL;
1377 uidval.bv_val = strrchr( val->bv_val, '#' );
1378 if ( !BER_BVISNULL( &uidval ) ) {
1380 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1382 rc = bitStringValidate( NULL, &uidval );
1384 if ( rc == LDAP_SUCCESS ) {
1385 ber_dupbv_x( &dnval, val, ctx );
1387 dnval.bv_len -= ++uidval.bv_len;
1388 dnval.bv_val[dnval.bv_len] = '\0';
1391 BER_BVZERO( &uidval );
1395 rc = dnPretty( syntax, &dnval, out, ctx );
1396 if ( dnval.bv_val != val->bv_val ) {
1397 slap_sl_free( dnval.bv_val, ctx );
1399 if( rc != LDAP_SUCCESS ) {
1403 if( !BER_BVISNULL( &uidval ) ) {
1406 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1407 + uidval.bv_len + 1,
1410 ber_memfree_x( out->bv_val, ctx );
1414 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1415 out->bv_len += uidval.bv_len;
1416 out->bv_val[out->bv_len] = '\0';
1420 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1422 return LDAP_SUCCESS;
1426 uniqueMemberNormalize(
1431 struct berval *normalized,
1437 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1439 ber_dupbv_x( &out, val, ctx );
1440 if ( BER_BVISEMPTY( &out ) ) {
1444 struct berval uid = BER_BVNULL;
1446 uid.bv_val = strrchr( out.bv_val, '#' );
1447 if ( !BER_BVISNULL( &uid ) ) {
1449 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1451 rc = bitStringValidate( NULL, &uid );
1452 if ( rc == LDAP_SUCCESS ) {
1453 uid.bv_val[-1] = '\0';
1454 out.bv_len -= uid.bv_len + 1;
1460 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1462 if( rc != LDAP_SUCCESS ) {
1463 slap_sl_free( out.bv_val, ctx );
1464 return LDAP_INVALID_SYNTAX;
1467 if( !BER_BVISNULL( &uid ) ) {
1470 tmp = ch_realloc( normalized->bv_val,
1471 normalized->bv_len + uid.bv_len
1472 + STRLENOF("#") + 1 );
1473 if ( tmp == NULL ) {
1474 ber_memfree_x( normalized->bv_val, ctx );
1478 normalized->bv_val = tmp;
1480 /* insert the separator */
1481 normalized->bv_val[normalized->bv_len++] = '#';
1483 /* append the UID */
1484 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1485 uid.bv_val, uid.bv_len );
1486 normalized->bv_len += uid.bv_len;
1489 normalized->bv_val[normalized->bv_len] = '\0';
1492 slap_sl_free( out.bv_val, ctx );
1495 return LDAP_SUCCESS;
1504 struct berval *value,
1505 void *assertedValue )
1508 struct berval *asserted = (struct berval *) assertedValue;
1509 struct berval assertedDN = *asserted;
1510 struct berval assertedUID = BER_BVNULL;
1511 struct berval valueDN = *value;
1512 struct berval valueUID = BER_BVNULL;
1513 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1515 if ( !BER_BVISEMPTY( asserted ) ) {
1516 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1517 if ( !BER_BVISNULL( &assertedUID ) ) {
1518 assertedUID.bv_val++;
1519 assertedUID.bv_len = assertedDN.bv_len
1520 - ( assertedUID.bv_val - assertedDN.bv_val );
1522 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1523 assertedDN.bv_len -= assertedUID.bv_len + 1;
1526 BER_BVZERO( &assertedUID );
1531 if ( !BER_BVISEMPTY( value ) ) {
1533 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1534 if ( !BER_BVISNULL( &valueUID ) ) {
1536 valueUID.bv_len = valueDN.bv_len
1537 - ( valueUID.bv_val - valueDN.bv_val );
1539 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1540 valueDN.bv_len -= valueUID.bv_len + 1;
1543 BER_BVZERO( &valueUID );
1548 if( valueUID.bv_len && assertedUID.bv_len ) {
1550 d = (ber_slen_t) valueUID.bv_len - (ber_slen_t) assertedUID.bv_len;
1552 *matchp = sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1;
1553 return LDAP_SUCCESS;
1556 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1559 return LDAP_SUCCESS;
1562 } else if ( !approx && valueUID.bv_len ) {
1565 return LDAP_SUCCESS;
1567 } else if ( !approx && assertedUID.bv_len ) {
1570 return LDAP_SUCCESS;
1573 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1577 uniqueMemberIndexer(
1582 struct berval *prefix,
1590 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1591 /* just count them */
1595 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1597 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1598 struct berval assertedDN = values[i];
1599 struct berval assertedUID = BER_BVNULL;
1601 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1602 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1603 if ( !BER_BVISNULL( &assertedUID ) ) {
1604 assertedUID.bv_val++;
1605 assertedUID.bv_len = assertedDN.bv_len
1606 - ( assertedUID.bv_val - assertedDN.bv_val );
1608 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1609 assertedDN.bv_len -= assertedUID.bv_len + 1;
1612 BER_BVZERO( &assertedUID );
1617 dnvalues[i] = assertedDN;
1619 BER_BVZERO( &dnvalues[i] );
1621 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1622 dnvalues, keysp, ctx );
1624 slap_sl_free( dnvalues, ctx );
1634 struct berval *prefix,
1635 void * assertedValue,
1639 struct berval *asserted = (struct berval *) assertedValue;
1640 struct berval assertedDN = *asserted;
1641 struct berval assertedUID = BER_BVNULL;
1643 if ( !BER_BVISEMPTY( asserted ) ) {
1644 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1645 if ( !BER_BVISNULL( &assertedUID ) ) {
1646 assertedUID.bv_val++;
1647 assertedUID.bv_len = assertedDN.bv_len
1648 - ( assertedUID.bv_val - assertedDN.bv_val );
1650 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1651 assertedDN.bv_len -= assertedUID.bv_len + 1;
1654 BER_BVZERO( &assertedUID );
1659 return octetStringFilter( use, flags, syntax, mr, prefix,
1660 &assertedDN, keysp, ctx );
1665 * Handling boolean syntax and matching is quite rigid.
1666 * A more flexible approach would be to allow a variety
1667 * of strings to be normalized and prettied into TRUE
1675 /* very unforgiving validation, requires no normalization
1676 * before simplistic matching
1679 if( in->bv_len == 4 ) {
1680 if( bvmatch( in, &slap_true_bv ) ) {
1681 return LDAP_SUCCESS;
1683 } else if( in->bv_len == 5 ) {
1684 if( bvmatch( in, &slap_false_bv ) ) {
1685 return LDAP_SUCCESS;
1689 return LDAP_INVALID_SYNTAX;
1698 struct berval *value,
1699 void *assertedValue )
1701 /* simplistic matching allowed by rigid validation */
1702 struct berval *asserted = (struct berval *) assertedValue;
1703 *matchp = (int) asserted->bv_len - (int) value->bv_len;
1704 return LDAP_SUCCESS;
1707 /*-------------------------------------------------------------------
1708 LDAP/X.500 string syntax / matching rules have a few oddities. This
1709 comment attempts to detail how slapd(8) treats them.
1712 StringSyntax X.500 LDAP Matching/Comments
1713 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1714 PrintableString subset subset i/e + ignore insignificant spaces
1715 PrintableString subset subset i/e + ignore insignificant spaces
1716 NumericString subset subset ignore all spaces
1717 IA5String ASCII ASCII i/e + ignore insignificant spaces
1718 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1720 TelephoneNumber subset subset i + ignore all spaces and "-"
1722 See RFC 4518 for details.
1726 In X.500(93), a directory string can be either a PrintableString,
1727 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1728 In later versions, more CHOICEs were added. In all cases the string
1731 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1732 A directory string cannot be zero length.
1734 For matching, there are both case ignore and exact rules. Both
1735 also require that "insignificant" spaces be ignored.
1736 spaces before the first non-space are ignored;
1737 spaces after the last non-space are ignored;
1738 spaces after a space are ignored.
1739 Note: by these rules (and as clarified in X.520), a string of only
1740 spaces is to be treated as if held one space, not empty (which
1741 would be a syntax error).
1744 In ASN.1, numeric string is just a string of digits and spaces
1745 and could be empty. However, in X.500, all attribute values of
1746 numeric string carry a non-empty constraint. For example:
1748 internationalISDNNumber ATTRIBUTE ::= {
1749 WITH SYNTAX InternationalISDNNumber
1750 EQUALITY MATCHING RULE numericStringMatch
1751 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1752 ID id-at-internationalISDNNumber }
1753 InternationalISDNNumber ::=
1754 NumericString (SIZE(1..ub-international-isdn-number))
1756 Unforunately, some assertion values are don't carry the same
1757 constraint (but its unclear how such an assertion could ever
1758 be true). In LDAP, there is one syntax (numericString) not two
1759 (numericString with constraint, numericString without constraint).
1760 This should be treated as numericString with non-empty constraint.
1761 Note that while someone may have no ISDN number, there are no ISDN
1762 numbers which are zero length.
1764 In matching, spaces are ignored.
1767 In ASN.1, Printable string is just a string of printable characters
1768 and can be empty. In X.500, semantics much like NumericString (see
1769 serialNumber for a like example) excepting uses insignificant space
1770 handling instead of ignore all spaces. They must be non-empty.
1773 Basically same as PrintableString. There are no examples in X.500,
1774 but same logic applies. Empty strings are allowed.
1776 -------------------------------------------------------------------*/
1785 unsigned char *u = (unsigned char *)in->bv_val;
1787 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1788 /* directory strings cannot be empty */
1789 return LDAP_INVALID_SYNTAX;
1792 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1793 /* get the length indicated by the first byte */
1794 len = LDAP_UTF8_CHARLEN2( u, len );
1796 /* very basic checks */
1799 if( (u[5] & 0xC0) != 0x80 ) {
1800 return LDAP_INVALID_SYNTAX;
1803 if( (u[4] & 0xC0) != 0x80 ) {
1804 return LDAP_INVALID_SYNTAX;
1807 if( (u[3] & 0xC0) != 0x80 ) {
1808 return LDAP_INVALID_SYNTAX;
1811 if( (u[2] & 0xC0 )!= 0x80 ) {
1812 return LDAP_INVALID_SYNTAX;
1815 if( (u[1] & 0xC0) != 0x80 ) {
1816 return LDAP_INVALID_SYNTAX;
1819 /* CHARLEN already validated it */
1822 return LDAP_INVALID_SYNTAX;
1825 /* make sure len corresponds with the offset
1826 to the next character */
1827 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1831 return LDAP_INVALID_SYNTAX;
1834 return LDAP_SUCCESS;
1838 UTF8StringNormalize(
1843 struct berval *normalized,
1846 struct berval tmp, nvalue;
1847 int flags, wasspace;
1850 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1852 if( BER_BVISNULL( val ) ) {
1853 /* assume we're dealing with a syntax (e.g., UTF8String)
1854 * which allows empty strings
1856 BER_BVZERO( normalized );
1857 return LDAP_SUCCESS;
1860 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1861 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1862 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1863 ? LDAP_UTF8_APPROX : 0;
1865 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1866 /* out of memory or syntax error, the former is unlikely */
1868 return LDAP_INVALID_SYNTAX;
1871 /* collapse spaces (in place) */
1873 nvalue.bv_val = tmp.bv_val;
1875 /* trim leading spaces? */
1876 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1877 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1879 for( i = 0; i < tmp.bv_len; i++) {
1880 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1881 if( wasspace++ == 0 ) {
1882 /* trim repeated spaces */
1883 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1887 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1891 if( !BER_BVISEMPTY( &nvalue ) ) {
1892 /* trim trailing space? */
1894 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1895 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1899 nvalue.bv_val[nvalue.bv_len] = '\0';
1901 } else if ( tmp.bv_len ) {
1902 /* string of all spaces is treated as one space */
1903 nvalue.bv_val[0] = ' ';
1904 nvalue.bv_val[1] = '\0';
1906 } /* should never be entered with 0-length val */
1908 *normalized = nvalue;
1909 return LDAP_SUCCESS;
1913 directoryStringSubstringsMatch(
1918 struct berval *value,
1919 void *assertedValue )
1922 SubstringsAssertion *sub = assertedValue;
1923 struct berval left = *value;
1927 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1928 if ( sub->sa_initial.bv_len > left.bv_len ) {
1929 /* not enough left */
1934 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1935 sub->sa_initial.bv_len );
1941 left.bv_val += sub->sa_initial.bv_len;
1942 left.bv_len -= sub->sa_initial.bv_len;
1944 priorspace = ASCII_SPACE(
1945 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1948 if ( sub->sa_any ) {
1949 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1953 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1954 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1956 /* allow next space to match */
1963 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1967 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1968 /* not enough left */
1973 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1980 idx = p - left.bv_val;
1982 if ( idx >= left.bv_len ) {
1983 /* this shouldn't happen */
1990 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1991 /* not enough left */
1996 match = memcmp( left.bv_val,
1997 sub->sa_any[i].bv_val,
1998 sub->sa_any[i].bv_len );
2006 left.bv_val += sub->sa_any[i].bv_len;
2007 left.bv_len -= sub->sa_any[i].bv_len;
2009 priorspace = ASCII_SPACE(
2010 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
2014 if ( !BER_BVISNULL( &sub->sa_final ) ) {
2015 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
2016 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
2018 /* allow next space to match */
2023 if ( sub->sa_final.bv_len > left.bv_len ) {
2024 /* not enough left */
2029 match = memcmp( sub->sa_final.bv_val,
2030 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2031 sub->sa_final.bv_len );
2040 return LDAP_SUCCESS;
2043 #if defined(SLAPD_APPROX_INITIALS)
2044 # define SLAPD_APPROX_DELIMITER "._ "
2045 # define SLAPD_APPROX_WORDLEN 2
2047 # define SLAPD_APPROX_DELIMITER " "
2048 # define SLAPD_APPROX_WORDLEN 1
2057 struct berval *value,
2058 void *assertedValue )
2060 struct berval *nval, *assertv;
2061 char *val, **values, **words, *c;
2062 int i, count, len, nextchunk=0, nextavail=0;
2064 /* Yes, this is necessary */
2065 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
2066 if( nval == NULL ) {
2068 return LDAP_SUCCESS;
2071 /* Yes, this is necessary */
2072 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
2073 NULL, LDAP_UTF8_APPROX, NULL );
2074 if( assertv == NULL ) {
2077 return LDAP_SUCCESS;
2080 /* Isolate how many words there are */
2081 for ( c = nval->bv_val, count = 1; *c; c++ ) {
2082 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
2083 if ( c == NULL ) break;
2088 /* Get a phonetic copy of each word */
2089 words = (char **)ch_malloc( count * sizeof(char *) );
2090 values = (char **)ch_malloc( count * sizeof(char *) );
2091 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
2093 values[i] = phonetic(c);
2096 /* Work through the asserted value's words, to see if at least some
2097 * of the words are there, in the same order. */
2099 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
2100 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
2105 #if defined(SLAPD_APPROX_INITIALS)
2106 else if( len == 1 ) {
2107 /* Single letter words need to at least match one word's initial */
2108 for( i=nextavail; i<count; i++ )
2109 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
2116 /* Isolate the next word in the asserted value and phonetic it */
2117 assertv->bv_val[nextchunk+len] = '\0';
2118 val = phonetic( assertv->bv_val + nextchunk );
2120 /* See if this phonetic chunk is in the remaining words of *value */
2121 for( i=nextavail; i<count; i++ ){
2122 if( !strcmp( val, values[i] ) ){
2130 /* This chunk in the asserted value was NOT within the *value. */
2136 /* Go on to the next word in the asserted value */
2140 /* If some of the words were seen, call it a match */
2141 if( nextavail > 0 ) {
2148 /* Cleanup allocs */
2149 ber_bvfree( assertv );
2150 for( i=0; i<count; i++ ) {
2151 ch_free( values[i] );
2157 return LDAP_SUCCESS;
2166 struct berval *prefix,
2172 int i,j, len, wordcount, keycount=0;
2173 struct berval *newkeys;
2174 BerVarray keys=NULL;
2176 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2177 struct berval val = BER_BVNULL;
2178 /* Yes, this is necessary */
2179 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2180 assert( !BER_BVISNULL( &val ) );
2182 /* Isolate how many words there are. There will be a key for each */
2183 for( wordcount = 0, c = val.bv_val; *c; c++) {
2184 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2185 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2187 if (*c == '\0') break;
2191 /* Allocate/increase storage to account for new keys */
2192 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2193 * sizeof(struct berval) );
2194 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2195 if( keys ) ch_free( keys );
2198 /* Get a phonetic copy of each word */
2199 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2201 if( len < SLAPD_APPROX_WORDLEN ) continue;
2202 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2203 if( keys[keycount].bv_len ) {
2206 ch_free( keys[keycount].bv_val );
2211 ber_memfree( val.bv_val );
2213 BER_BVZERO( &keys[keycount] );
2216 return LDAP_SUCCESS;
2225 struct berval *prefix,
2226 void * assertedValue,
2235 /* Yes, this is necessary */
2236 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2237 NULL, LDAP_UTF8_APPROX, NULL );
2238 if( val == NULL || BER_BVISNULL( val ) ) {
2239 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2240 BER_BVZERO( &keys[0] );
2243 return LDAP_SUCCESS;
2246 /* Isolate how many words there are. There will be a key for each */
2247 for( count = 0,c = val->bv_val; *c; c++) {
2248 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2249 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2251 if (*c == '\0') break;
2255 /* Allocate storage for new keys */
2256 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2258 /* Get a phonetic copy of each word */
2259 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2261 if( len < SLAPD_APPROX_WORDLEN ) continue;
2262 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2268 BER_BVZERO( &keys[count] );
2271 return LDAP_SUCCESS;
2274 /* Remove all spaces and '-' characters */
2276 telephoneNumberNormalize(
2281 struct berval *normalized,
2286 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2288 /* validator should have refused an empty string */
2289 assert( !BER_BVISEMPTY( val ) );
2291 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2293 for( p = val->bv_val; *p; p++ ) {
2294 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2300 normalized->bv_len = q - normalized->bv_val;
2302 if( BER_BVISEMPTY( normalized ) ) {
2303 slap_sl_free( normalized->bv_val, ctx );
2304 BER_BVZERO( normalized );
2305 return LDAP_INVALID_SYNTAX;
2308 return LDAP_SUCCESS;
2312 postalAddressValidate(
2316 struct berval bv = *in;
2319 for ( c = 0; c < in->bv_len; c++ ) {
2320 if ( in->bv_val[c] == '\\' ) {
2322 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2323 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2325 return LDAP_INVALID_SYNTAX;
2330 if ( in->bv_val[c] == '$' ) {
2331 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2332 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2333 return LDAP_INVALID_SYNTAX;
2335 bv.bv_val = &in->bv_val[c] + 1;
2339 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2340 return UTF8StringValidate( NULL, &bv );
2344 postalAddressNormalize(
2349 struct berval *normalized,
2352 BerVarray lines = NULL, nlines = NULL;
2354 int rc = LDAP_SUCCESS;
2355 MatchingRule *xmr = NULL;
2358 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2359 xmr = slap_schema.si_mr_caseIgnoreMatch;
2362 xmr = slap_schema.si_mr_caseExactMatch;
2365 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2366 if ( val->bv_val[c] == '$' ) {
2371 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2372 nlines = &lines[l + 2];
2374 lines[0].bv_val = val->bv_val;
2375 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2376 if ( val->bv_val[c] == '$' ) {
2377 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2379 lines[l].bv_val = &val->bv_val[c + 1];
2382 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2384 normalized->bv_len = c = l;
2386 for ( l = 0; l <= c; l++ ) {
2387 /* NOTE: we directly normalize each line,
2388 * without unescaping the values, since the special
2389 * values '\24' ('$') and '\5C' ('\') are not affected
2390 * by normalization */
2391 if ( !lines[l].bv_len ) {
2392 nlines[l].bv_len = 0;
2393 nlines[l].bv_val = NULL;
2396 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2397 if ( rc != LDAP_SUCCESS ) {
2398 rc = LDAP_INVALID_SYNTAX;
2402 normalized->bv_len += nlines[l].bv_len;
2405 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2407 p = normalized->bv_val;
2408 for ( l = 0; l <= c ; l++ ) {
2409 p = lutil_strbvcopy( p, &nlines[l] );
2414 assert( p == &normalized->bv_val[normalized->bv_len] );
2417 if ( nlines != NULL ) {
2418 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2419 slap_sl_free( nlines[l].bv_val, ctx );
2422 slap_sl_free( lines, ctx );
2433 struct berval val = *in;
2435 if( BER_BVISEMPTY( &val ) ) {
2436 /* disallow empty strings */
2437 return LDAP_INVALID_SYNTAX;
2440 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2441 if ( val.bv_len == 1 ) {
2442 return LDAP_SUCCESS;
2445 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2452 while ( OID_LEADCHAR( val.bv_val[0] )) {
2456 if ( val.bv_len == 0 ) {
2457 return LDAP_SUCCESS;
2461 if( !OID_SEPARATOR( val.bv_val[0] )) {
2469 return LDAP_INVALID_SYNTAX;
2478 struct berval val = *in;
2480 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2482 if ( val.bv_val[0] == '-' ) {
2486 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2487 return LDAP_INVALID_SYNTAX;
2490 if( val.bv_val[0] == '0' ) { /* "-0" */
2491 return LDAP_INVALID_SYNTAX;
2494 } else if ( val.bv_val[0] == '0' ) {
2495 if( val.bv_len > 1 ) { /* "0<more>" */
2496 return LDAP_INVALID_SYNTAX;
2499 return LDAP_SUCCESS;
2502 for( i=0; i < val.bv_len; i++ ) {
2503 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2504 return LDAP_INVALID_SYNTAX;
2508 return LDAP_SUCCESS;
2517 struct berval *value,
2518 void *assertedValue )
2520 struct berval *asserted = (struct berval *) assertedValue;
2521 int vsign = 1, asign = 1; /* default sign = '+' */
2526 if( v.bv_val[0] == '-' ) {
2532 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2535 if( a.bv_val[0] == '-' ) {
2541 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2543 match = vsign - asign;
2545 match = ( v.bv_len != a.bv_len
2546 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2547 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2548 if( vsign < 0 ) match = -match;
2551 /* Ordering rule used in extensible match filter? */
2552 if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
2553 match = (match >= 0);
2556 return LDAP_SUCCESS;
2559 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2560 #define INDEX_INTLEN_CHOP 7
2561 #define INDEX_INTLEN_CHOPBYTES 3
2570 /* Integer index key format, designed for memcmp to collate correctly:
2571 * if too large: one's complement sign*<approx exponent=chopped bytes>,
2572 * two's complement value (sign-extended or chopped as needed),
2573 * however in first byte above, the top <number of exponent-bytes + 1>
2574 * bits are the inverse sign and next bit is the sign as delimiter.
2576 ber_slen_t k = index_intlen_strlen;
2578 unsigned signmask = ~0x7fU;
2579 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2580 struct berval val = *in, itmp = *tmp;
2582 if ( val.bv_val[0] != '-' ) {
2587 /* Chop least significant digits, increase length instead */
2588 if ( val.bv_len > (ber_len_t) k ) {
2589 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2590 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2591 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2594 if ( lutil_str2bin( &val, &itmp, ctx )) {
2595 return LDAP_INVALID_SYNTAX;
2598 /* Omit leading sign byte */
2599 if ( itmp.bv_val[0] == neg ) {
2604 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2606 assert( chop == 0 );
2607 memset( key->bv_val, neg, k ); /* sign-extend */
2608 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2609 /* Got exponent -k, or no room for 2 sign bits */
2610 lenp = lenbuf + sizeof(lenbuf);
2611 chop = - (ber_len_t) k;
2613 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2615 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2616 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2617 * are 1, and the top n+2 bits of lenp[0] are the sign bit. */
2618 k = (lenbuf + sizeof(lenbuf)) - lenp;
2619 if ( k > (ber_slen_t) index_intlen )
2621 memcpy( key->bv_val, lenp, k );
2622 itmp.bv_len = index_intlen - k;
2624 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2625 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2629 /* Index generation function: Ordered index */
2636 struct berval *prefix,
2646 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2648 /* count the values and find max needed length */
2650 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2651 if ( vlen < values[i].bv_len )
2652 vlen = values[i].bv_len;
2654 if ( vlen > maxstrlen )
2657 /* we should have at least one value at this point */
2660 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2661 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2662 keys[i].bv_len = index_intlen;
2663 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2666 keys[i].bv_val = NULL;
2668 if ( vlen > sizeof(ibuf) ) {
2669 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2673 itmp.bv_len = sizeof(ibuf);
2675 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2676 if ( itmp.bv_val != ibuf ) {
2677 itmp.bv_len = values[i].bv_len;
2678 if ( itmp.bv_len <= sizeof(ibuf) )
2679 itmp.bv_len = sizeof(ibuf);
2680 else if ( itmp.bv_len > maxstrlen )
2681 itmp.bv_len = maxstrlen;
2683 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2689 if ( itmp.bv_val != ibuf ) {
2690 slap_sl_free( itmp.bv_val, ctx );
2695 /* Index generation function: Ordered index */
2702 struct berval *prefix,
2703 void * assertedValue,
2710 struct berval *value;
2713 value = (struct berval *) assertedValue;
2715 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2717 keys[0].bv_len = index_intlen;
2718 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2720 keys[1].bv_val = NULL;
2722 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2723 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2724 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2725 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2728 iv.bv_len = sizeof(ibuf);
2731 rc = integerVal2Key( value, keys, &iv, ctx );
2735 if ( iv.bv_val != ibuf ) {
2736 slap_sl_free( iv.bv_val, ctx );
2742 countryStringValidate(
2744 struct berval *val )
2746 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2748 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2749 return LDAP_INVALID_SYNTAX;
2751 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2752 return LDAP_INVALID_SYNTAX;
2755 return LDAP_SUCCESS;
2759 printableStringValidate(
2761 struct berval *val )
2765 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2767 for(i=0; i < val->bv_len; i++) {
2768 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2769 return LDAP_INVALID_SYNTAX;
2773 return LDAP_SUCCESS;
2777 printablesStringValidate(
2779 struct berval *val )
2783 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2785 for(i=0,len=0; i < val->bv_len; i++) {
2786 int c = val->bv_val[i];
2790 return LDAP_INVALID_SYNTAX;
2794 } else if ( SLAP_PRINTABLE(c) ) {
2797 return LDAP_INVALID_SYNTAX;
2802 return LDAP_INVALID_SYNTAX;
2805 return LDAP_SUCCESS;
2811 struct berval *val )
2815 for(i=0; i < val->bv_len; i++) {
2816 if( !LDAP_ASCII(val->bv_val[i]) ) {
2817 return LDAP_INVALID_SYNTAX;
2821 return LDAP_SUCCESS;
2830 struct berval *normalized,
2834 int casefold = !SLAP_MR_ASSOCIATED( mr,
2835 slap_schema.si_mr_caseExactIA5Match );
2837 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2841 /* Ignore initial whitespace */
2842 while ( ASCII_SPACE( *p ) ) p++;
2844 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2845 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2846 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2847 normalized->bv_val[normalized->bv_len] = '\0';
2849 p = q = normalized->bv_val;
2852 if ( ASCII_SPACE( *p ) ) {
2855 /* Ignore the extra whitespace */
2856 while ( ASCII_SPACE( *p ) ) {
2860 } else if ( casefold ) {
2861 /* Most IA5 rules require casefolding */
2862 *q++ = TOLOWER(*p); p++;
2869 assert( normalized->bv_val <= p );
2873 * If the string ended in space, backup the pointer one
2874 * position. One is enough because the above loop collapsed
2875 * all whitespace to a single space.
2877 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2879 /* null terminate */
2882 normalized->bv_len = q - normalized->bv_val;
2884 return LDAP_SUCCESS;
2893 if( in->bv_len != 36 ) {
2894 return LDAP_INVALID_SYNTAX;
2897 for( i=0; i<36; i++ ) {
2903 if( in->bv_val[i] != '-' ) {
2904 return LDAP_INVALID_SYNTAX;
2908 if( !ASCII_HEX( in->bv_val[i]) ) {
2909 return LDAP_INVALID_SYNTAX;
2914 return LDAP_SUCCESS;
2925 int rc=LDAP_INVALID_SYNTAX;
2927 assert( in != NULL );
2928 assert( out != NULL );
2930 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2933 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2935 for( i=0; i<36; i++ ) {
2941 if( in->bv_val[i] != '-' ) {
2944 out->bv_val[i] = '-';
2948 if( !ASCII_HEX( in->bv_val[i]) ) {
2951 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2956 out->bv_val[ out->bv_len ] = '\0';
2960 slap_sl_free( out->bv_val, ctx );
2973 struct berval *normalized,
2976 unsigned char octet = '\0';
2980 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2981 /* NOTE: must be a normalized UUID */
2982 assert( val->bv_len == 16 );
2984 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2985 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2986 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2987 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2989 return LDAP_SUCCESS;
2992 normalized->bv_len = 16;
2993 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2995 for( i=0, j=0; i<36; i++ ) {
2996 unsigned char nibble;
2997 if( val->bv_val[i] == '-' ) {
3000 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
3001 nibble = val->bv_val[i] - '0';
3003 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
3004 nibble = val->bv_val[i] - ('a'-10);
3006 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
3007 nibble = val->bv_val[i] - ('A'-10);
3010 slap_sl_free( normalized->bv_val, ctx );
3011 BER_BVZERO( normalized );
3012 return LDAP_INVALID_SYNTAX;
3017 normalized->bv_val[j>>1] = octet;
3019 octet = nibble << 4;
3024 normalized->bv_val[normalized->bv_len] = 0;
3025 return LDAP_SUCCESS;
3031 numericStringValidate(
3037 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
3039 for(i=0; i < in->bv_len; i++) {
3040 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3041 return LDAP_INVALID_SYNTAX;
3045 return LDAP_SUCCESS;
3049 numericStringNormalize(
3054 struct berval *normalized,
3057 /* removal all spaces */
3060 assert( !BER_BVISEMPTY( val ) );
3062 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
3065 q = normalized->bv_val;
3068 if ( ASCII_SPACE( *p ) ) {
3069 /* Ignore whitespace */
3076 /* we should have copied no more than is in val */
3077 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3079 /* null terminate */
3082 normalized->bv_len = q - normalized->bv_val;
3084 if( BER_BVISEMPTY( normalized ) ) {
3085 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
3086 normalized->bv_val[0] = ' ';
3087 normalized->bv_val[1] = '\0';
3088 normalized->bv_len = 1;
3091 return LDAP_SUCCESS;
3095 * Integer conversion macros that will use the largest available
3098 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
3099 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
3100 # define SLAP_LONG long long
3102 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
3103 # define SLAP_LONG long
3104 #endif /* HAVE_STRTOLL ... */
3112 struct berval *value,
3113 void *assertedValue )
3115 SLAP_LONG lValue, lAssertedValue;
3118 /* safe to assume integers are NUL terminated? */
3119 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3120 if( errno == ERANGE )
3122 return LDAP_CONSTRAINT_VIOLATION;
3125 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
3127 if( errno == ERANGE )
3129 return LDAP_CONSTRAINT_VIOLATION;
3132 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
3133 return LDAP_SUCCESS;
3142 struct berval *value,
3143 void *assertedValue )
3145 SLAP_LONG lValue, lAssertedValue;
3148 /* safe to assume integers are NUL terminated? */
3149 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3150 if( errno == ERANGE )
3152 return LDAP_CONSTRAINT_VIOLATION;
3155 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3157 if( errno == ERANGE )
3159 return LDAP_CONSTRAINT_VIOLATION;
3162 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3163 return LDAP_SUCCESS;
3167 checkNum( struct berval *in, struct berval *out )
3169 /* parse serialNumber */
3170 ber_len_t neg = 0, extra = 0;
3173 out->bv_val = in->bv_val;
3176 if ( out->bv_val[0] == '-' ) {
3181 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3182 first = out->bv_val[2];
3185 out->bv_len += STRLENOF("0x");
3186 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3187 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3190 } else if ( out->bv_val[0] == '\'' ) {
3191 first = out->bv_val[1];
3194 out->bv_len += STRLENOF("'");
3196 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3197 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3199 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3202 out->bv_len += STRLENOF("'H");
3205 first = out->bv_val[0];
3206 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3207 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3211 if ( !( out->bv_len > neg ) ) {
3215 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3223 serialNumberAndIssuerCheck(
3231 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3233 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3234 /* Parse old format */
3235 is->bv_val = ber_bvchr( in, '$' );
3236 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3238 sn->bv_val = in->bv_val;
3239 sn->bv_len = is->bv_val - in->bv_val;
3242 is->bv_len = in->bv_len - (sn->bv_len + 1);
3244 /* eat leading zeros */
3245 for( n=0; n < (sn->bv_len-1); n++ ) {
3246 if( sn->bv_val[n] != '0' ) break;
3251 for( n=0; n < sn->bv_len; n++ ) {
3252 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3256 /* Parse GSER format */
3261 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3265 struct berval x = *in;
3271 /* eat leading spaces */
3272 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3276 /* should be at issuer or serialNumber NamedValue */
3277 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3278 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3281 x.bv_val += STRLENOF("issuer");
3282 x.bv_len -= STRLENOF("issuer");
3284 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3288 /* eat leading spaces */
3289 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3293 /* For backward compatibility, this part is optional */
3294 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3295 x.bv_val += STRLENOF("rdnSequence:");
3296 x.bv_len -= STRLENOF("rdnSequence:");
3299 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3303 is->bv_val = x.bv_val;
3306 for ( ; is->bv_len < x.bv_len; ) {
3307 if ( is->bv_val[is->bv_len] != '"' ) {
3311 if ( is->bv_val[is->bv_len+1] == '"' ) {
3318 x.bv_val += is->bv_len + 1;
3319 x.bv_len -= is->bv_len + 1;
3321 have |= HAVE_ISSUER;
3323 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3325 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3327 /* parse serialNumber */
3328 x.bv_val += STRLENOF("serialNumber");
3329 x.bv_len -= STRLENOF("serialNumber");
3331 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3335 /* eat leading spaces */
3336 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3340 if ( checkNum( &x, sn ) ) {
3341 return LDAP_INVALID_SYNTAX;
3344 x.bv_val += sn->bv_len;
3345 x.bv_len -= sn->bv_len;
3350 return LDAP_INVALID_SYNTAX;
3353 /* eat leading spaces */
3354 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3358 if ( have == HAVE_ALL ) {
3362 if ( x.bv_val[0] != ',' ) {
3363 return LDAP_INVALID_SYNTAX;
3370 /* should have no characters left... */
3371 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3373 if ( numdquotes == 0 ) {
3374 ber_dupbv_x( &ni, is, ctx );
3379 ni.bv_len = is->bv_len - numdquotes;
3380 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3381 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3382 if ( is->bv_val[src] == '"' ) {
3385 ni.bv_val[dst] = is->bv_val[src];
3387 ni.bv_val[dst] = '\0';
3397 serialNumberAndIssuerValidate(
3402 struct berval sn, i;
3404 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3407 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3412 /* validate DN -- doesn't handle double dquote */
3413 rc = dnValidate( NULL, &i );
3415 rc = LDAP_INVALID_SYNTAX;
3418 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3419 slap_sl_free( i.bv_val, NULL );
3422 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3423 in->bv_val, rc, 0 );
3430 serialNumberAndIssuerPretty(
3437 struct berval sn, i, ni = BER_BVNULL;
3440 assert( in != NULL );
3441 assert( out != NULL );
3445 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3448 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3453 rc = dnPretty( syntax, &i, &ni, ctx );
3455 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3456 slap_sl_free( i.bv_val, ctx );
3460 rc = LDAP_INVALID_SYNTAX;
3464 /* make room from sn + "$" */
3465 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3466 + sn.bv_len + ni.bv_len;
3467 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3469 if ( out->bv_val == NULL ) {
3476 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3477 p = lutil_strbvcopy( p, &sn );
3478 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3479 p = lutil_strbvcopy( p, &ni );
3480 p = lutil_strcopy( p, /*{*/ "\" }" );
3482 assert( p == &out->bv_val[out->bv_len] );
3485 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3486 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3488 slap_sl_free( ni.bv_val, ctx );
3490 return LDAP_SUCCESS;
3500 /* Use hex format. '123456789abcdef'H */
3501 unsigned char *ptr, zero = '\0';
3504 ber_len_t i, len, nlen;
3506 assert( in != NULL );
3507 assert( !BER_BVISNULL( in ) );
3508 assert( out != NULL );
3509 assert( !BER_BVISNULL( out ) );
3511 ptr = (unsigned char *)in->bv_val;
3514 /* Check for minimal encodings */
3516 if ( ptr[0] & 0x80 ) {
3517 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3521 } else if ( ptr[0] == 0 ) {
3522 if ( !( ptr[1] & 0x80 ) ) {
3529 } else if ( len == 0 ) {
3530 /* FIXME: this should not be possible,
3531 * since a value of zero would have length 1 */
3536 first = !( ptr[0] & 0xf0U );
3537 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3538 if ( nlen >= out->bv_len ) {
3539 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3545 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3549 for ( ; i < len; i++ ) {
3550 sprintf( sptr, "%02X", ptr[i] );
3557 assert( sptr == &out->bv_val[nlen] );
3564 #define SLAP_SN_BUFLEN (64)
3567 * This routine is called by certificateExactNormalize when
3568 * certificateExactNormalize receives a search string instead of
3569 * a certificate. This routine checks if the search value is valid
3570 * and then returns the normalized value
3573 serialNumberAndIssuerNormalize(
3581 struct berval sn, sn2, sn3, i, ni;
3582 char sbuf2[SLAP_SN_BUFLEN];
3583 char sbuf3[SLAP_SN_BUFLEN];
3587 assert( in != NULL );
3588 assert( out != NULL );
3590 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3593 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3598 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3600 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3601 slap_sl_free( i.bv_val, ctx );
3605 return LDAP_INVALID_SYNTAX;
3608 /* Convert sn to canonical hex */
3610 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3611 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3613 sn2.bv_len = sn.bv_len;
3615 sn3.bv_len = sizeof(sbuf3);
3616 if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
3617 rc = LDAP_INVALID_SYNTAX;
3621 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3622 + sn3.bv_len + ni.bv_len;
3623 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3624 if ( out->bv_val == NULL ) {
3632 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3633 p = lutil_strbvcopy( p, &sn3 );
3634 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3635 p = lutil_strbvcopy( p, &ni );
3636 p = lutil_strcopy( p, /*{*/ "\" }" );
3638 assert( p == &out->bv_val[out->bv_len] );
3641 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3642 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3644 if ( sn2.bv_val != sbuf2 ) {
3645 slap_sl_free( sn2.bv_val, ctx );
3648 if ( sn3.bv_val != sbuf3 ) {
3649 slap_sl_free( sn3.bv_val, ctx );
3652 slap_sl_free( ni.bv_val, ctx );
3658 certificateExactNormalize(
3663 struct berval *normalized,
3666 BerElementBuffer berbuf;
3667 BerElement *ber = (BerElement *)&berbuf;
3671 char serialbuf2[SLAP_SN_BUFLEN];
3672 struct berval sn, sn2 = BER_BVNULL;
3673 struct berval issuer_dn = BER_BVNULL, bvdn;
3675 int rc = LDAP_INVALID_SYNTAX;
3677 assert( val != NULL );
3679 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3680 val->bv_val, val->bv_len, 0 );
3682 if ( BER_BVISEMPTY( val ) ) goto done;
3684 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3685 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3688 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3690 ber_init2( ber, val, LBER_USE_DER );
3691 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3692 tag = ber_skip_tag( ber, &len ); /* Sequence */
3693 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3694 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3695 tag = ber_skip_tag( ber, &len );
3696 tag = ber_get_int( ber, &i ); /* version */
3699 /* NOTE: move the test here from certificateValidate,
3700 * so that we can validate certs with serial longer
3701 * than sizeof(ber_int_t) */
3702 tag = ber_skip_tag( ber, &len ); /* serial */
3704 sn.bv_val = (char *)ber->ber_ptr;
3705 sn2.bv_val = serialbuf2;
3706 sn2.bv_len = sizeof(serialbuf2);
3707 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3708 rc = LDAP_INVALID_SYNTAX;
3711 ber_skip_data( ber, len );
3713 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3714 ber_skip_data( ber, len );
3715 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3717 len = ber_ptrlen( ber );
3718 bvdn.bv_val = val->bv_val + len;
3719 bvdn.bv_len = val->bv_len - len;
3721 rc = dnX509normalize( &bvdn, &issuer_dn );
3722 if ( rc != LDAP_SUCCESS ) goto done;
3725 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3726 + sn2.bv_len + issuer_dn.bv_len;
3727 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3729 p = normalized->bv_val;
3731 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3732 p = lutil_strbvcopy( p, &sn2 );
3733 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3734 p = lutil_strbvcopy( p, &issuer_dn );
3735 p = lutil_strcopy( p, /*{*/ "\" }" );
3740 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3741 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3743 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3744 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3749 /* X.509 PKI certificateList stuff */
3751 checkTime( struct berval *in, struct berval *out )
3755 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3758 assert( in != NULL );
3759 assert( !BER_BVISNULL( in ) );
3760 assert( !BER_BVISEMPTY( in ) );
3762 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3766 if ( out != NULL ) {
3767 assert( !BER_BVISNULL( out ) );
3768 assert( out->bv_len >= sizeof( buf ) );
3769 bv.bv_val = out->bv_val;
3775 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3776 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3779 if ( in->bv_val[i] != 'Z' ) {
3784 if ( i != in->bv_len ) {
3788 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3789 lutil_strncopy( bv.bv_val, in->bv_val, i );
3792 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3793 char *p = bv.bv_val;
3794 if ( in->bv_val[0] < '7' ) {
3795 p = lutil_strcopy( p, "20" );
3798 p = lutil_strcopy( p, "19" );
3800 lutil_strncopy( p, in->bv_val, i );
3807 rc = generalizedTimeValidate( NULL, &bv );
3808 if ( rc == LDAP_SUCCESS && out != NULL ) {
3809 if ( out->bv_len > bv.bv_len ) {
3810 out->bv_val[ bv.bv_len ] = '\0';
3812 out->bv_len = bv.bv_len;
3815 return rc != LDAP_SUCCESS;
3819 issuerAndThisUpdateCheck(
3826 struct berval x = *in;
3827 struct berval ni = BER_BVNULL;
3828 /* Parse GSER format */
3832 HAVE_THISUPDATE = 0x2,
3833 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3837 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3839 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3840 return LDAP_INVALID_SYNTAX;
3844 x.bv_len -= STRLENOF("{}");
3847 /* eat leading spaces */
3848 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3852 /* should be at issuer or thisUpdate */
3853 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3854 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3857 x.bv_val += STRLENOF("issuer");
3858 x.bv_len -= STRLENOF("issuer");
3860 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3864 /* eat leading spaces */
3865 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3869 /* For backward compatibility, this part is optional */
3870 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3871 return LDAP_INVALID_SYNTAX;
3873 x.bv_val += STRLENOF("rdnSequence:");
3874 x.bv_len -= STRLENOF("rdnSequence:");
3876 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3880 is->bv_val = x.bv_val;
3883 for ( ; is->bv_len < x.bv_len; ) {
3884 if ( is->bv_val[is->bv_len] != '"' ) {
3888 if ( is->bv_val[is->bv_len+1] == '"' ) {
3895 x.bv_val += is->bv_len + 1;
3896 x.bv_len -= is->bv_len + 1;
3898 have |= HAVE_ISSUER;
3900 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3902 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3904 /* parse thisUpdate */
3905 x.bv_val += STRLENOF("thisUpdate");
3906 x.bv_len -= STRLENOF("thisUpdate");
3908 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3912 /* eat leading spaces */
3913 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3917 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3921 tu->bv_val = x.bv_val;
3924 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3925 if ( tu->bv_val[tu->bv_len] == '"' ) {
3929 x.bv_val += tu->bv_len + 1;
3930 x.bv_len -= tu->bv_len + 1;
3932 have |= HAVE_THISUPDATE;
3935 return LDAP_INVALID_SYNTAX;
3938 /* eat leading spaces */
3939 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3943 if ( have == HAVE_ALL ) {
3947 if ( x.bv_val[0] != ',' ) {
3948 return LDAP_INVALID_SYNTAX;
3955 /* should have no characters left... */
3956 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3958 if ( numdquotes == 0 ) {
3959 ber_dupbv_x( &ni, is, ctx );
3964 ni.bv_len = is->bv_len - numdquotes;
3965 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3966 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3967 if ( is->bv_val[src] == '"' ) {
3970 ni.bv_val[dst] = is->bv_val[src];
3972 ni.bv_val[dst] = '\0';
3981 issuerAndThisUpdateValidate(
3986 struct berval i, tu;
3988 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3991 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3996 /* validate DN -- doesn't handle double dquote */
3997 rc = dnValidate( NULL, &i );
3999 rc = LDAP_INVALID_SYNTAX;
4001 } else if ( checkTime( &tu, NULL ) ) {
4002 rc = LDAP_INVALID_SYNTAX;
4005 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4006 slap_sl_free( i.bv_val, NULL );
4009 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
4010 in->bv_val, rc, 0 );
4017 issuerAndThisUpdatePretty(
4024 struct berval i, tu, ni = BER_BVNULL;
4027 assert( in != NULL );
4028 assert( out != NULL );
4032 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
4035 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4040 rc = dnPretty( syntax, &i, &ni, ctx );
4042 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4043 slap_sl_free( i.bv_val, ctx );
4046 if ( rc || checkTime( &tu, NULL ) ) {
4047 rc = LDAP_INVALID_SYNTAX;
4052 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
4053 + ni.bv_len + tu.bv_len;
4054 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4056 if ( out->bv_val == NULL ) {
4063 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4064 p = lutil_strbvcopy( p, &ni );
4065 p = lutil_strcopy( p, "\", thisUpdate \"" );
4066 p = lutil_strbvcopy( p, &tu );
4067 p = lutil_strcopy( p, /*{*/ "\" }" );
4069 assert( p == &out->bv_val[out->bv_len] );
4072 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
4073 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4075 slap_sl_free( ni.bv_val, ctx );
4081 issuerAndThisUpdateNormalize(
4089 struct berval i, ni, tu, tu2;
4090 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4094 assert( in != NULL );
4095 assert( out != NULL );
4097 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
4100 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4105 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4107 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4108 slap_sl_free( i.bv_val, ctx );
4112 tu2.bv_len = sizeof( sbuf );
4113 if ( rc || checkTime( &tu, &tu2 ) ) {
4114 return LDAP_INVALID_SYNTAX;
4117 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4118 + ni.bv_len + tu2.bv_len;
4119 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4121 if ( out->bv_val == NULL ) {
4129 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4130 p = lutil_strbvcopy( p, &ni );
4131 p = lutil_strcopy( p, "\", thisUpdate \"" );
4132 p = lutil_strbvcopy( p, &tu2 );
4133 p = lutil_strcopy( p, /*{*/ "\" }" );
4135 assert( p == &out->bv_val[out->bv_len] );
4138 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4139 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4141 slap_sl_free( ni.bv_val, ctx );
4147 certificateListExactNormalize(
4152 struct berval *normalized,
4155 BerElementBuffer berbuf;
4156 BerElement *ber = (BerElement *)&berbuf;
4160 struct berval issuer_dn = BER_BVNULL, bvdn,
4162 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4163 int rc = LDAP_INVALID_SYNTAX;
4165 assert( val != NULL );
4167 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4168 val->bv_val, val->bv_len, 0 );
4170 if ( BER_BVISEMPTY( val ) ) goto done;
4172 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4173 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4176 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4178 ber_init2( ber, val, LBER_USE_DER );
4179 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4180 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4181 tag = ber_skip_tag( ber, &len ); /* Sequence */
4182 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4183 tag = ber_peek_tag( ber, &len );
4184 /* Optional version */
4185 if ( tag == LBER_INTEGER ) {
4186 tag = ber_get_int( ber, &version );
4187 assert( tag == LBER_INTEGER );
4188 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4190 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4191 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4192 ber_skip_data( ber, len );
4194 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4195 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4196 len = ber_ptrlen( ber );
4197 bvdn.bv_val = val->bv_val + len;
4198 bvdn.bv_len = val->bv_len - len;
4199 tag = ber_skip_tag( ber, &len );
4200 ber_skip_data( ber, len );
4202 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4203 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4204 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4205 bvtu.bv_val = (char *)ber->ber_ptr;
4208 rc = dnX509normalize( &bvdn, &issuer_dn );
4209 if ( rc != LDAP_SUCCESS ) goto done;
4211 thisUpdate.bv_val = tubuf;
4212 thisUpdate.bv_len = sizeof(tubuf);
4213 if ( checkTime( &bvtu, &thisUpdate ) ) {
4214 rc = LDAP_INVALID_SYNTAX;
4218 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4219 + issuer_dn.bv_len + thisUpdate.bv_len;
4220 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4222 p = normalized->bv_val;
4224 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4225 p = lutil_strbvcopy( p, &issuer_dn );
4226 p = lutil_strcopy( p, "\", thisUpdate \"" );
4227 p = lutil_strbvcopy( p, &thisUpdate );
4228 p = lutil_strcopy( p, /*{*/ "\" }" );
4233 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4234 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4236 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4241 /* X.509 PMI serialNumberAndIssuerSerialCheck
4243 AttributeCertificateExactAssertion ::= SEQUENCE {
4244 serialNumber CertificateSerialNumber,
4245 issuer AttCertIssuer }
4247 CertificateSerialNumber ::= INTEGER
4249 AttCertIssuer ::= [0] SEQUENCE {
4250 issuerName GeneralNames OPTIONAL,
4251 baseCertificateID [0] IssuerSerial OPTIONAL,
4252 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4253 -- At least one component shall be present
4255 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4257 GeneralName ::= CHOICE {
4258 otherName [0] INSTANCE OF OTHER-NAME,
4259 rfc822Name [1] IA5String,
4260 dNSName [2] IA5String,
4261 x400Address [3] ORAddress,
4262 directoryName [4] Name,
4263 ediPartyName [5] EDIPartyName,
4264 uniformResourceIdentifier [6] IA5String,
4265 iPAddress [7] OCTET STRING,
4266 registeredID [8] OBJECT IDENTIFIER }
4268 IssuerSerial ::= SEQUENCE {
4269 issuer GeneralNames,
4270 serial CertificateSerialNumber,
4271 issuerUID UniqueIdentifier OPTIONAL }
4273 ObjectDigestInfo ::= SEQUENCE {
4274 digestedObjectType ENUMERATED {
4277 otherObjectTypes (2) },
4278 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4279 digestAlgorithm AlgorithmIdentifier,
4280 objectDigest BIT STRING }
4282 * The way I interpret it, an assertion should look like
4284 { serialNumber 'dd'H,
4285 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4286 baseCertificateID { serial '1d'H,
4287 issuer { directoryName:rdnSequence:"cn=zzz" },
4288 issuerUID <value> -- optional
4290 objectDigestInfo { ... } -- optional
4294 * with issuerName, baseCertificateID and objectDigestInfo optional,
4295 * at least one present; the way it's currently implemented, it is
4297 { serialNumber 'dd'H,
4298 issuer { baseCertificateID { serial '1d'H,
4299 issuer { directoryName:rdnSequence:"cn=zzz" }
4304 * with all the above parts mandatory.
4307 serialNumberAndIssuerSerialCheck(
4311 struct berval *i_sn, /* contain serial of baseCertificateID */
4314 /* Parse GSER format */
4319 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4320 } have = HAVE_NONE, have2 = HAVE_NONE;
4322 struct berval x = *in;
4325 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4328 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4335 /* eat leading spaces */
4336 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4340 /* should be at issuer or serialNumber NamedValue */
4341 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4342 if ( have & HAVE_ISSUER ) {
4343 return LDAP_INVALID_SYNTAX;
4346 /* parse IssuerSerial */
4347 x.bv_val += STRLENOF("issuer");
4348 x.bv_len -= STRLENOF("issuer");
4350 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4354 /* eat leading spaces */
4355 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4359 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4363 /* eat leading spaces */
4364 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4368 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4369 return LDAP_INVALID_SYNTAX;
4371 x.bv_val += STRLENOF("baseCertificateID ");
4372 x.bv_len -= STRLENOF("baseCertificateID ");
4374 /* eat leading spaces */
4375 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4379 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4384 /* eat leading spaces */
4385 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4389 /* parse issuer of baseCertificateID */
4390 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4391 if ( have2 & HAVE_ISSUER ) {
4392 return LDAP_INVALID_SYNTAX;
4395 x.bv_val += STRLENOF("issuer ");
4396 x.bv_len -= STRLENOF("issuer ");
4398 /* eat leading spaces */
4399 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4403 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4407 /* eat leading spaces */
4408 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4412 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4413 return LDAP_INVALID_SYNTAX;
4415 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4416 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4418 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4422 is->bv_val = x.bv_val;
4425 for ( ; is->bv_len < x.bv_len; ) {
4426 if ( is->bv_val[is->bv_len] != '"' ) {
4430 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4437 x.bv_val += is->bv_len + 1;
4438 x.bv_len -= is->bv_len + 1;
4440 /* eat leading spaces */
4441 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4445 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4449 have2 |= HAVE_ISSUER;
4451 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4452 if ( have2 & HAVE_SN ) {
4453 return LDAP_INVALID_SYNTAX;
4456 x.bv_val += STRLENOF("serial ");
4457 x.bv_len -= STRLENOF("serial ");
4459 /* eat leading spaces */
4460 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4464 if ( checkNum( &x, i_sn ) ) {
4465 return LDAP_INVALID_SYNTAX;
4468 x.bv_val += i_sn->bv_len;
4469 x.bv_len -= i_sn->bv_len;
4474 return LDAP_INVALID_SYNTAX;
4477 /* eat leading spaces */
4478 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4482 if ( have2 == HAVE_ALL ) {
4486 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4491 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4495 /* eat leading spaces */
4496 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4500 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4504 have |= HAVE_ISSUER;
4506 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4507 if ( have & HAVE_SN ) {
4508 return LDAP_INVALID_SYNTAX;
4511 /* parse serialNumber */
4512 x.bv_val += STRLENOF("serialNumber");
4513 x.bv_len -= STRLENOF("serialNumber");
4515 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4519 /* eat leading spaces */
4520 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4524 if ( checkNum( &x, sn ) ) {
4525 return LDAP_INVALID_SYNTAX;
4528 x.bv_val += sn->bv_len;
4529 x.bv_len -= sn->bv_len;
4534 return LDAP_INVALID_SYNTAX;
4538 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4542 if ( have == HAVE_ALL ) {
4546 if ( x.bv_val[0] != ',' ) {
4547 return LDAP_INVALID_SYNTAX;
4553 /* should have no characters left... */
4554 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4556 if ( numdquotes == 0 ) {
4557 ber_dupbv_x( &ni, is, ctx );
4562 ni.bv_len = is->bv_len - numdquotes;
4563 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4564 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4565 if ( is->bv_val[src] == '"' ) {
4568 ni.bv_val[dst] = is->bv_val[src];
4570 ni.bv_val[dst] = '\0';
4575 /* need to handle double dquotes here */
4579 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4581 serialNumberAndIssuerSerialValidate(
4586 struct berval sn, i, i_sn;
4588 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4591 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4596 /* validate DN -- doesn't handle double dquote */
4597 rc = dnValidate( NULL, &i );
4599 rc = LDAP_INVALID_SYNTAX;
4602 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4603 slap_sl_free( i.bv_val, NULL );
4607 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4608 in->bv_val, rc, 0 );
4613 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4615 serialNumberAndIssuerSerialPretty(
4621 struct berval sn, i, i_sn, ni = BER_BVNULL;
4625 assert( in != NULL );
4626 assert( out != NULL );
4628 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4631 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4636 rc = dnPretty( syntax, &i, &ni, ctx );
4638 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4639 slap_sl_free( i.bv_val, ctx );
4643 rc = LDAP_INVALID_SYNTAX;
4647 /* make room from sn + "$" */
4648 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4649 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4650 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4652 if ( out->bv_val == NULL ) {
4659 p = lutil_strcopy( p, "{ serialNumber " );
4660 p = lutil_strbvcopy( p, &sn );
4661 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4662 p = lutil_strbvcopy( p, &ni );
4663 p = lutil_strcopy( p, "\" }, serial " );
4664 p = lutil_strbvcopy( p, &i_sn );
4665 p = lutil_strcopy( p, " } } }" );
4667 assert( p == &out->bv_val[out->bv_len] );
4670 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4671 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4673 slap_sl_free( ni.bv_val, ctx );
4678 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4680 * This routine is called by attributeCertificateExactNormalize
4681 * when attributeCertificateExactNormalize receives a search
4682 * string instead of a attribute certificate. This routine
4683 * checks if the search value is valid and then returns the
4687 serialNumberAndIssuerSerialNormalize(
4695 struct berval i, ni = BER_BVNULL,
4696 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4697 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4698 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4699 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4703 assert( in != NULL );
4704 assert( out != NULL );
4706 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4709 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4714 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4716 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4717 slap_sl_free( i.bv_val, ctx );
4721 rc = LDAP_INVALID_SYNTAX;
4725 /* Convert sn to canonical hex */
4727 sn2.bv_len = sn.bv_len;
4728 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4729 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4731 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4732 rc = LDAP_INVALID_SYNTAX;
4736 /* Convert i_sn to canonical hex */
4737 i_sn2.bv_val = i_sbuf2;
4738 i_sn2.bv_len = i_sn.bv_len;
4739 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4740 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4742 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4743 rc = LDAP_INVALID_SYNTAX;
4748 sn3.bv_len = sizeof(sbuf3);
4749 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4750 rc = LDAP_INVALID_SYNTAX;
4754 i_sn3.bv_val = i_sbuf3;
4755 i_sn3.bv_len = sizeof(i_sbuf3);
4756 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4757 rc = LDAP_INVALID_SYNTAX;
4761 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4762 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4763 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4765 if ( out->bv_val == NULL ) {
4773 p = lutil_strcopy( p, "{ serialNumber " );
4774 p = lutil_strbvcopy( p, &sn3 );
4775 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4776 p = lutil_strbvcopy( p, &ni );
4777 p = lutil_strcopy( p, "\" }, serial " );
4778 p = lutil_strbvcopy( p, &i_sn3 );
4779 p = lutil_strcopy( p, " } } }" );
4781 assert( p == &out->bv_val[out->bv_len] );
4784 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4785 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4787 if ( sn2.bv_val != sbuf2 ) {
4788 slap_sl_free( sn2.bv_val, ctx );
4791 if ( i_sn2.bv_val != i_sbuf2 ) {
4792 slap_sl_free( i_sn2.bv_val, ctx );
4795 if ( sn3.bv_val != sbuf3 ) {
4796 slap_sl_free( sn3.bv_val, ctx );
4799 if ( i_sn3.bv_val != i_sbuf3 ) {
4800 slap_sl_free( i_sn3.bv_val, ctx );
4803 slap_sl_free( ni.bv_val, ctx );
4808 /* X.509 PMI attributeCertificateExactNormalize */
4810 attributeCertificateExactNormalize(
4815 struct berval *normalized,
4818 BerElementBuffer berbuf;
4819 BerElement *ber = (BerElement *)&berbuf;
4822 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4823 struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
4824 struct berval issuer_dn = BER_BVNULL, bvdn;
4826 int rc = LDAP_INVALID_SYNTAX;
4828 if ( BER_BVISEMPTY( val ) ) {
4832 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4833 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4836 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4838 ber_init2( ber, val, LBER_USE_DER );
4839 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4840 tag = ber_skip_tag( ber, &len ); /* Sequence */
4841 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4842 ber_skip_data( ber, len );
4843 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4844 ber_skip_data( ber, len );
4847 tag = ber_skip_tag( ber, &len ); /* Sequence */
4848 /* issuerName (GeneralNames sequence; optional)? */
4849 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4850 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4851 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4852 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4853 return LDAP_INVALID_SYNTAX;
4855 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4856 len = ber_ptrlen( ber );
4857 bvdn.bv_val = val->bv_val + len;
4858 bvdn.bv_len = val->bv_len - len;
4859 rc = dnX509normalize( &bvdn, &issuer_dn );
4860 if ( rc != LDAP_SUCCESS ) goto done;
4862 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4863 ber_skip_data( ber, len );
4864 tag = ber_skip_tag( ber, &len ); /* serial number */
4865 if ( tag != LBER_INTEGER ) {
4866 rc = LDAP_INVALID_SYNTAX;
4869 i_sn.bv_val = (char *)ber->ber_ptr;
4871 i_sn2.bv_val = issuer_serialbuf;
4872 i_sn2.bv_len = sizeof(issuer_serialbuf);
4873 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4874 rc = LDAP_INVALID_SYNTAX;
4877 ber_skip_data( ber, len );
4879 /* issuerUID (bitstring; optional)? */
4880 /* objectDigestInfo (sequence; optional)? */
4882 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4883 ber_skip_data( ber, len );
4884 tag = ber_skip_tag( ber, &len ); /* serial number */
4885 if ( tag != LBER_INTEGER ) {
4886 rc = LDAP_INVALID_SYNTAX;
4889 sn.bv_val = (char *)ber->ber_ptr;
4891 sn2.bv_val = serialbuf;
4892 sn2.bv_len = sizeof(serialbuf);
4893 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4894 rc = LDAP_INVALID_SYNTAX;
4897 ber_skip_data( ber, len );
4899 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4900 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4901 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4903 p = normalized->bv_val;
4905 p = lutil_strcopy( p, "{ serialNumber " );
4906 p = lutil_strbvcopy( p, &sn2 );
4907 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4908 p = lutil_strbvcopy( p, &issuer_dn );
4909 p = lutil_strcopy( p, "\" }, serial " );
4910 p = lutil_strbvcopy( p, &i_sn2 );
4911 p = lutil_strcopy( p, " } } }" );
4913 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4914 normalized->bv_val, NULL, NULL );
4919 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4920 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4921 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4934 assert( in != NULL );
4935 assert( !BER_BVISNULL( in ) );
4937 for ( i = 0; i < in->bv_len; i++ ) {
4938 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4939 return LDAP_INVALID_SYNTAX;
4943 return LDAP_SUCCESS;
4946 /* Normalize a SID as used inside a CSN:
4947 * three-digit numeric string */
4954 struct berval *normalized,
4959 assert( val != NULL );
4960 assert( normalized != NULL );
4962 ber_dupbv_x( normalized, val, ctx );
4964 for ( i = 0; i < normalized->bv_len; i++ ) {
4965 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4966 ber_memfree_x( normalized->bv_val, ctx );
4967 BER_BVZERO( normalized );
4968 return LDAP_INVALID_SYNTAX;
4971 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4974 return LDAP_SUCCESS;
4982 assert( in != NULL );
4983 assert( !BER_BVISNULL( in ) );
4985 if ( in->bv_len != 3 ) {
4986 return LDAP_INVALID_SYNTAX;
4989 return hexValidate( NULL, in );
4992 /* Normalize a SID as used inside a CSN:
4993 * three-digit numeric string */
5000 struct berval *normalized,
5003 if ( val->bv_len != 3 ) {
5004 return LDAP_INVALID_SYNTAX;
5007 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
5017 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5020 /* Normalize a SID as used inside a CSN, either as-is
5021 * (assertion value) or extracted from the CSN
5022 * (attribute value) */
5029 struct berval *normalized,
5037 if ( BER_BVISEMPTY( val ) ) {
5038 return LDAP_INVALID_SYNTAX;
5041 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
5042 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
5045 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
5047 ptr = ber_bvchr( val, '#' );
5048 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5049 return LDAP_INVALID_SYNTAX;
5052 bv.bv_val = ptr + 1;
5053 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5055 ptr = ber_bvchr( &bv, '#' );
5056 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5057 return LDAP_INVALID_SYNTAX;
5060 bv.bv_val = ptr + 1;
5061 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5063 ptr = ber_bvchr( &bv, '#' );
5064 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5065 return LDAP_INVALID_SYNTAX;
5068 bv.bv_len = ptr - bv.bv_val;
5070 if ( bv.bv_len == 2 ) {
5071 /* OpenLDAP 2.3 SID */
5073 buf[ 1 ] = bv.bv_val[ 0 ];
5074 buf[ 2 ] = bv.bv_val[ 1 ];
5081 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
5093 assert( in != NULL );
5094 assert( !BER_BVISNULL( in ) );
5096 if ( BER_BVISEMPTY( in ) ) {
5097 return LDAP_INVALID_SYNTAX;
5102 ptr = ber_bvchr( &bv, '#' );
5103 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
5104 return LDAP_INVALID_SYNTAX;
5107 bv.bv_len = ptr - bv.bv_val;
5108 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
5109 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
5111 return LDAP_INVALID_SYNTAX;
5114 rc = generalizedTimeValidate( NULL, &bv );
5115 if ( rc != LDAP_SUCCESS ) {
5119 bv.bv_val = ptr + 1;
5120 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5122 ptr = ber_bvchr( &bv, '#' );
5123 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5124 return LDAP_INVALID_SYNTAX;
5127 bv.bv_len = ptr - bv.bv_val;
5128 if ( bv.bv_len != 6 ) {
5129 return LDAP_INVALID_SYNTAX;
5132 rc = hexValidate( NULL, &bv );
5133 if ( rc != LDAP_SUCCESS ) {
5137 bv.bv_val = ptr + 1;
5138 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5140 ptr = ber_bvchr( &bv, '#' );
5141 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5142 return LDAP_INVALID_SYNTAX;
5145 bv.bv_len = ptr - bv.bv_val;
5146 if ( bv.bv_len == 2 ) {
5147 /* tolerate old 2-digit replica-id */
5148 rc = hexValidate( NULL, &bv );
5151 rc = sidValidate( NULL, &bv );
5153 if ( rc != LDAP_SUCCESS ) {
5157 bv.bv_val = ptr + 1;
5158 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5160 if ( bv.bv_len != 6 ) {
5161 return LDAP_INVALID_SYNTAX;
5164 return hexValidate( NULL, &bv );
5167 /* Normalize a CSN in OpenLDAP 2.1 format */
5174 struct berval *normalized,
5177 struct berval gt, cnt, sid, mod;
5179 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5183 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5184 assert( !BER_BVISEMPTY( val ) );
5188 ptr = ber_bvchr( >, '#' );
5189 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5190 return LDAP_INVALID_SYNTAX;
5193 gt.bv_len = ptr - gt.bv_val;
5194 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5195 return LDAP_INVALID_SYNTAX;
5198 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5199 return LDAP_INVALID_SYNTAX;
5202 cnt.bv_val = ptr + 1;
5203 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5205 ptr = ber_bvchr( &cnt, '#' );
5206 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5207 return LDAP_INVALID_SYNTAX;
5210 cnt.bv_len = ptr - cnt.bv_val;
5211 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5212 return LDAP_INVALID_SYNTAX;
5215 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5216 return LDAP_INVALID_SYNTAX;
5219 cnt.bv_val += STRLENOF( "0x" );
5220 cnt.bv_len -= STRLENOF( "0x" );
5222 sid.bv_val = ptr + 1;
5223 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5225 ptr = ber_bvchr( &sid, '#' );
5226 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5227 return LDAP_INVALID_SYNTAX;
5230 sid.bv_len = ptr - sid.bv_val;
5231 if ( sid.bv_len != STRLENOF( "0" ) ) {
5232 return LDAP_INVALID_SYNTAX;
5235 mod.bv_val = ptr + 1;
5236 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5237 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5238 return LDAP_INVALID_SYNTAX;
5241 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5245 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5246 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5248 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5250 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5251 ptr = lutil_strbvcopy( ptr, &cnt );
5255 *ptr++ = sid.bv_val[ 0 ];
5259 for ( i = 0; i < mod.bv_len; i++ ) {
5260 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5264 assert( ptr == &bv.bv_val[bv.bv_len] );
5266 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5267 return LDAP_INVALID_SYNTAX;
5270 ber_dupbv_x( normalized, &bv, ctx );
5272 return LDAP_SUCCESS;
5275 /* Normalize a CSN in OpenLDAP 2.3 format */
5282 struct berval *normalized,
5285 struct berval gt, cnt, sid, mod;
5287 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5291 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5292 assert( !BER_BVISEMPTY( val ) );
5296 ptr = ber_bvchr( >, '#' );
5297 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5298 return LDAP_INVALID_SYNTAX;
5301 gt.bv_len = ptr - gt.bv_val;
5302 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5303 return LDAP_INVALID_SYNTAX;
5306 cnt.bv_val = ptr + 1;
5307 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5309 ptr = ber_bvchr( &cnt, '#' );
5310 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5311 return LDAP_INVALID_SYNTAX;
5314 cnt.bv_len = ptr - cnt.bv_val;
5315 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5316 return LDAP_INVALID_SYNTAX;
5319 sid.bv_val = ptr + 1;
5320 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5322 ptr = ber_bvchr( &sid, '#' );
5323 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5324 return LDAP_INVALID_SYNTAX;
5327 sid.bv_len = ptr - sid.bv_val;
5328 if ( sid.bv_len != STRLENOF( "00" ) ) {
5329 return LDAP_INVALID_SYNTAX;
5332 mod.bv_val = ptr + 1;
5333 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5334 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5335 return LDAP_INVALID_SYNTAX;
5338 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5342 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5343 ptr = lutil_strcopy( ptr, ".000000Z#" );
5344 ptr = lutil_strbvcopy( ptr, &cnt );
5347 for ( i = 0; i < sid.bv_len; i++ ) {
5348 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5351 for ( i = 0; i < mod.bv_len; i++ ) {
5352 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5356 assert( ptr == &bv.bv_val[bv.bv_len] );
5357 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5358 return LDAP_INVALID_SYNTAX;
5361 ber_dupbv_x( normalized, &bv, ctx );
5363 return LDAP_SUCCESS;
5366 /* Normalize a CSN */
5373 struct berval *normalized,
5376 struct berval cnt, sid, mod;
5380 assert( val != NULL );
5381 assert( normalized != NULL );
5383 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5385 if ( BER_BVISEMPTY( val ) ) {
5386 return LDAP_INVALID_SYNTAX;
5389 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5390 /* Openldap <= 2.3 */
5392 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5395 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5398 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5401 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5402 return LDAP_INVALID_SYNTAX;
5405 ptr = ber_bvchr( val, '#' );
5406 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5407 return LDAP_INVALID_SYNTAX;
5410 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5411 return LDAP_INVALID_SYNTAX;
5414 cnt.bv_val = ptr + 1;
5415 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5417 ptr = ber_bvchr( &cnt, '#' );
5418 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5419 return LDAP_INVALID_SYNTAX;
5422 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5423 return LDAP_INVALID_SYNTAX;
5426 sid.bv_val = ptr + 1;
5427 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5429 ptr = ber_bvchr( &sid, '#' );
5430 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5431 return LDAP_INVALID_SYNTAX;
5434 sid.bv_len = ptr - sid.bv_val;
5435 if ( sid.bv_len != STRLENOF( "000" ) ) {
5436 return LDAP_INVALID_SYNTAX;
5439 mod.bv_val = ptr + 1;
5440 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5442 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5443 return LDAP_INVALID_SYNTAX;
5446 ber_dupbv_x( normalized, val, ctx );
5448 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5449 i < normalized->bv_len; i++ )
5451 /* assume it's already validated that's all hex digits */
5452 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5455 return LDAP_SUCCESS;
5465 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5468 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5469 /* slight optimization - does not need the start parameter */
5470 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5475 check_time_syntax (struct berval *val,
5478 struct berval *fraction)
5481 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5482 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5483 * GeneralizedTime supports leap seconds, UTCTime does not.
5485 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5486 static const int mdays[2][12] = {
5487 /* non-leap years */
5488 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5490 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5493 int part, c, c1, c2, tzoffset, leapyear = 0;
5496 e = p + val->bv_len;
5498 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5499 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5501 for (part = start; part < 7 && p < e; part++) {
5503 if (!ASCII_DIGIT(c1)) {
5508 return LDAP_INVALID_SYNTAX;
5511 if (!ASCII_DIGIT(c)) {
5512 return LDAP_INVALID_SYNTAX;
5514 c += c1 * 10 - '0' * 11;
5515 if ((part | 1) == 3) {
5518 return LDAP_INVALID_SYNTAX;
5521 if (c >= ceiling[part]) {
5522 if (! (c == 60 && part == 6 && start == 0))
5523 return LDAP_INVALID_SYNTAX;
5527 if (part < 5 + start) {
5528 return LDAP_INVALID_SYNTAX;
5530 for (; part < 9; part++) {
5534 /* leapyear check for the Gregorian calendar (year>1581) */
5535 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5539 if (parts[3] >= mdays[leapyear][parts[2]]) {
5540 return LDAP_INVALID_SYNTAX;
5544 fraction->bv_val = p;
5545 fraction->bv_len = 0;
5546 if (p < e && (*p == '.' || *p == ',')) {
5548 while (++p < e && ASCII_DIGIT(*p)) {
5551 if (p - fraction->bv_val == 1) {
5552 return LDAP_INVALID_SYNTAX;
5554 for (end_num = p; end_num[-1] == '0'; --end_num) {
5557 c = end_num - fraction->bv_val;
5558 if (c != 1) fraction->bv_len = c;
5564 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5570 return LDAP_INVALID_SYNTAX;
5576 for (part = 7; part < 9 && p < e; part++) {
5578 if (!ASCII_DIGIT(c1)) {
5583 return LDAP_INVALID_SYNTAX;
5586 if (!ASCII_DIGIT(c2)) {
5587 return LDAP_INVALID_SYNTAX;
5589 parts[part] = c1 * 10 + c2 - '0' * 11;
5590 if (parts[part] >= ceiling[part]) {
5591 return LDAP_INVALID_SYNTAX;
5594 if (part < 8 + start) {
5595 return LDAP_INVALID_SYNTAX;
5598 if (tzoffset == '-') {
5599 /* negative offset to UTC, ie west of Greenwich */
5600 parts[4] += parts[7];
5601 parts[5] += parts[8];
5602 /* offset is just hhmm, no seconds */
5603 for (part = 6; --part >= 0; ) {
5607 c = mdays[leapyear][parts[2]];
5609 if (parts[part] >= c) {
5611 return LDAP_INVALID_SYNTAX;
5616 } else if (part != 5) {
5621 /* positive offset to UTC, ie east of Greenwich */
5622 parts[4] -= parts[7];
5623 parts[5] -= parts[8];
5624 for (part = 6; --part >= 0; ) {
5625 if (parts[part] < 0) {
5627 return LDAP_INVALID_SYNTAX;
5632 /* make first arg to % non-negative */
5633 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5638 } else if (part != 5) {
5645 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5648 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5655 struct berval *normalized )
5659 rc = check_time_syntax(val, 1, parts, NULL);
5660 if (rc != LDAP_SUCCESS) {
5664 normalized->bv_val = ch_malloc( 14 );
5665 if ( normalized->bv_val == NULL ) {
5666 return LBER_ERROR_MEMORY;
5669 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5670 parts[1], parts[2] + 1, parts[3] + 1,
5671 parts[4], parts[5], parts[6] );
5672 normalized->bv_len = 13;
5674 return LDAP_SUCCESS;
5684 return check_time_syntax(in, 1, parts, NULL);
5687 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5690 generalizedTimeValidate(
5695 struct berval fraction;
5696 return check_time_syntax(in, 0, parts, &fraction);
5700 generalizedTimeNormalize(
5705 struct berval *normalized,
5710 struct berval fraction;
5712 rc = check_time_syntax(val, 0, parts, &fraction);
5713 if (rc != LDAP_SUCCESS) {
5717 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5718 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5719 if ( BER_BVISNULL( normalized ) ) {
5720 return LBER_ERROR_MEMORY;
5723 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5724 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5725 parts[4], parts[5], parts[6] );
5726 if ( !BER_BVISEMPTY( &fraction ) ) {
5727 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5728 fraction.bv_val, fraction.bv_len );
5729 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5731 strcpy( normalized->bv_val + len-1, "Z" );
5732 normalized->bv_len = len;
5734 return LDAP_SUCCESS;
5738 generalizedTimeOrderingMatch(
5743 struct berval *value,
5744 void *assertedValue )
5746 struct berval *asserted = (struct berval *) assertedValue;
5747 ber_len_t v_len = value->bv_len;
5748 ber_len_t av_len = asserted->bv_len;
5750 /* ignore trailing 'Z' when comparing */
5751 int match = memcmp( value->bv_val, asserted->bv_val,
5752 (v_len < av_len ? v_len : av_len) - 1 );
5753 if ( match == 0 ) match = v_len - av_len;
5755 /* If used in extensible match filter, match if value < asserted */
5756 if ( flags & SLAP_MR_EXT )
5757 match = (match >= 0);
5760 return LDAP_SUCCESS;
5763 /* Index generation function: Ordered index */
5764 int generalizedTimeIndexer(
5769 struct berval *prefix,
5777 BerValue bvtmp; /* 40 bit index */
5779 struct lutil_timet tt;
5781 bvtmp.bv_len = sizeof(tmp);
5783 for( i=0; values[i].bv_val != NULL; i++ ) {
5784 /* just count them */
5787 /* we should have at least one value at this point */
5790 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5792 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5793 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5794 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5795 /* Use 40 bits of time for key */
5796 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5797 lutil_tm2time( &tm, &tt );
5798 tmp[0] = tt.tt_gsec & 0xff;
5799 tmp[4] = tt.tt_sec & 0xff;
5801 tmp[3] = tt.tt_sec & 0xff;
5803 tmp[2] = tt.tt_sec & 0xff;
5805 tmp[1] = tt.tt_sec & 0xff;
5807 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5811 keys[j].bv_val = NULL;
5816 return LDAP_SUCCESS;
5819 /* Index generation function: Ordered index */
5820 int generalizedTimeFilter(
5825 struct berval *prefix,
5826 void * assertedValue,
5832 BerValue bvtmp; /* 40 bit index */
5833 BerValue *value = (BerValue *) assertedValue;
5835 struct lutil_timet tt;
5837 bvtmp.bv_len = sizeof(tmp);
5839 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5840 /* Use 40 bits of time for key */
5841 if ( value->bv_val && value->bv_len >= 10 &&
5842 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5844 lutil_tm2time( &tm, &tt );
5845 tmp[0] = tt.tt_gsec & 0xff;
5846 tmp[4] = tt.tt_sec & 0xff;
5848 tmp[3] = tt.tt_sec & 0xff;
5850 tmp[2] = tt.tt_sec & 0xff;
5852 tmp[1] = tt.tt_sec & 0xff;
5854 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5855 ber_dupbv_x(keys, &bvtmp, ctx );
5856 keys[1].bv_val = NULL;
5864 return LDAP_SUCCESS;
5868 deliveryMethodValidate(
5870 struct berval *val )
5873 #define LENOF(s) (sizeof(s)-1)
5874 struct berval tmp = *val;
5876 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5877 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5878 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5881 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5883 switch( tmp.bv_val[0] ) {
5886 if(( tmp.bv_len >= LENOF("any") ) &&
5887 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5889 tmp.bv_len -= LENOF("any");
5890 tmp.bv_val += LENOF("any");
5893 return LDAP_INVALID_SYNTAX;
5897 if(( tmp.bv_len >= LENOF("mhs") ) &&
5898 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5900 tmp.bv_len -= LENOF("mhs");
5901 tmp.bv_val += LENOF("mhs");
5904 return LDAP_INVALID_SYNTAX;
5908 if(( tmp.bv_len >= LENOF("physical") ) &&
5909 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5911 tmp.bv_len -= LENOF("physical");
5912 tmp.bv_val += LENOF("physical");
5915 return LDAP_INVALID_SYNTAX;
5918 case 'T': /* telex or teletex or telephone */
5919 if(( tmp.bv_len >= LENOF("telex") ) &&
5920 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5922 tmp.bv_len -= LENOF("telex");
5923 tmp.bv_val += LENOF("telex");
5926 if(( tmp.bv_len >= LENOF("teletex") ) &&
5927 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5929 tmp.bv_len -= LENOF("teletex");
5930 tmp.bv_val += LENOF("teletex");
5933 if(( tmp.bv_len >= LENOF("telephone") ) &&
5934 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5936 tmp.bv_len -= LENOF("telephone");
5937 tmp.bv_val += LENOF("telephone");
5940 return LDAP_INVALID_SYNTAX;
5943 case 'G': /* g3fax or g4fax */
5944 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5945 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5946 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5948 tmp.bv_len -= LENOF("g3fax");
5949 tmp.bv_val += LENOF("g3fax");
5952 return LDAP_INVALID_SYNTAX;
5956 if(( tmp.bv_len >= LENOF("ia5") ) &&
5957 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5959 tmp.bv_len -= LENOF("ia5");
5960 tmp.bv_val += LENOF("ia5");
5963 return LDAP_INVALID_SYNTAX;
5967 if(( tmp.bv_len >= LENOF("videotex") ) &&
5968 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5970 tmp.bv_len -= LENOF("videotex");
5971 tmp.bv_val += LENOF("videotex");
5974 return LDAP_INVALID_SYNTAX;
5977 return LDAP_INVALID_SYNTAX;
5980 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5982 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5986 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5990 return LDAP_INVALID_SYNTAX;
5992 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
6001 nisNetgroupTripleValidate(
6003 struct berval *val )
6008 if ( BER_BVISEMPTY( val ) ) {
6009 return LDAP_INVALID_SYNTAX;
6012 p = (char *)val->bv_val;
6013 e = p + val->bv_len;
6015 if ( *p != '(' /*')'*/ ) {
6016 return LDAP_INVALID_SYNTAX;
6019 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
6023 return LDAP_INVALID_SYNTAX;
6026 } else if ( !AD_CHAR( *p ) ) {
6027 return LDAP_INVALID_SYNTAX;
6031 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
6032 return LDAP_INVALID_SYNTAX;
6038 return LDAP_INVALID_SYNTAX;
6041 return LDAP_SUCCESS;
6045 bootParameterValidate(
6047 struct berval *val )
6051 if ( BER_BVISEMPTY( val ) ) {
6052 return LDAP_INVALID_SYNTAX;
6055 p = (char *)val->bv_val;
6056 e = p + val->bv_len;
6059 for (; ( p < e ) && ( *p != '=' ); p++ ) {
6060 if ( !AD_CHAR( *p ) ) {
6061 return LDAP_INVALID_SYNTAX;
6066 return LDAP_INVALID_SYNTAX;
6070 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
6071 if ( !AD_CHAR( *p ) ) {
6072 return LDAP_INVALID_SYNTAX;
6077 return LDAP_INVALID_SYNTAX;
6081 for ( p++; p < e; p++ ) {
6082 if ( !SLAP_PRINTABLE( *p ) ) {
6083 return LDAP_INVALID_SYNTAX;
6087 return LDAP_SUCCESS;
6091 firstComponentNormalize(
6096 struct berval *normalized,
6103 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
6104 ber_dupbv_x( normalized, val, ctx );
6105 return LDAP_SUCCESS;
6108 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
6110 if( ! ( val->bv_val[0] == '(' /*')'*/
6111 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
6112 && ! ( val->bv_val[0] == '{' /*'}'*/
6113 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
6115 return LDAP_INVALID_SYNTAX;
6118 /* trim leading white space */
6120 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
6126 /* grab next word */
6127 comp.bv_val = &val->bv_val[len];
6128 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
6129 for( comp.bv_len = 0;
6130 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
6136 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
6137 rc = numericoidValidate( NULL, &comp );
6138 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
6139 rc = integerValidate( NULL, &comp );
6141 rc = LDAP_INVALID_SYNTAX;
6145 if( rc == LDAP_SUCCESS ) {
6146 ber_dupbv_x( normalized, &comp, ctx );
6152 static char *country_gen_syn[] = {
6153 "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */
6154 "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */
6155 "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */
6159 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6160 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6162 static slap_syntax_defs_rec syntax_defs[] = {
6163 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6164 X_BINARY X_NOT_H_R ")",
6165 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6166 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6167 0, NULL, NULL, NULL},
6168 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6169 0, NULL, NULL, NULL},
6170 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6172 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6173 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6175 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6176 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6177 0, NULL, bitStringValidate, NULL },
6178 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6179 0, NULL, booleanValidate, NULL},
6180 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6181 X_BINARY X_NOT_H_R ")",
6182 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6183 NULL, certificateValidate, NULL},
6184 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6185 X_BINARY X_NOT_H_R ")",
6186 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6187 NULL, certificateListValidate, NULL},
6188 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6189 X_BINARY X_NOT_H_R ")",
6190 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6191 NULL, sequenceValidate, NULL},
6192 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6193 X_BINARY X_NOT_H_R ")",
6194 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6195 NULL, attributeCertificateValidate, NULL},
6196 #if 0 /* need to go __after__ printableString */
6197 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6198 0, "1.3.6.1.4.1.1466.115.121.1.44",
6199 countryStringValidate, NULL},
6201 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6202 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6203 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6204 0, NULL, rdnValidate, rdnPretty},
6205 #ifdef LDAP_COMP_MATCH
6206 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6207 0, NULL, allComponentsValidate, NULL},
6208 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6209 0, NULL, componentFilterValidate, NULL},
6211 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6212 0, NULL, NULL, NULL},
6213 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6214 0, NULL, deliveryMethodValidate, NULL},
6215 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6216 0, NULL, UTF8StringValidate, NULL},
6217 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6218 0, NULL, NULL, NULL},
6219 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6220 0, NULL, NULL, NULL},
6221 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6222 0, NULL, NULL, NULL},
6223 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6224 0, NULL, NULL, NULL},
6225 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6226 0, NULL, NULL, NULL},
6227 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6228 0, NULL, printablesStringValidate, NULL},
6229 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6230 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6231 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6232 0, NULL, generalizedTimeValidate, NULL},
6233 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6234 0, NULL, NULL, NULL},
6235 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6236 0, NULL, IA5StringValidate, NULL},
6237 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6238 0, NULL, integerValidate, NULL},
6239 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6240 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6241 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6242 0, NULL, NULL, NULL},
6243 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6244 0, NULL, NULL, NULL},
6245 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6246 0, NULL, NULL, NULL},
6247 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6248 0, NULL, NULL, NULL},
6249 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6250 0, NULL, NULL, NULL},
6251 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6252 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6253 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6254 0, NULL, NULL, NULL},
6255 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6256 0, NULL, numericStringValidate, NULL},
6257 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6258 0, NULL, NULL, NULL},
6259 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6260 0, NULL, numericoidValidate, NULL},
6261 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6262 0, NULL, IA5StringValidate, NULL},
6263 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6264 0, NULL, blobValidate, NULL},
6265 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6266 0, NULL, postalAddressValidate, NULL},
6267 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6268 0, NULL, NULL, NULL},
6269 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6270 0, NULL, NULL, NULL},
6271 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6272 0, NULL, printableStringValidate, NULL},
6273 /* moved here because now depends on Directory String, IA5 String
6274 * and Printable String */
6275 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6276 0, country_gen_syn, countryStringValidate, NULL},
6277 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6278 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6279 0, NULL, subtreeSpecificationValidate, NULL},
6280 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6281 X_BINARY X_NOT_H_R ")",
6282 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6283 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6284 0, NULL, printableStringValidate, NULL},
6285 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6286 0, NULL, NULL, NULL},
6287 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6288 0, NULL, printablesStringValidate, NULL},
6289 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6290 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6291 0, NULL, utcTimeValidate, NULL},
6293 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6294 0, NULL, NULL, NULL},
6295 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6296 0, NULL, NULL, NULL},
6297 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6298 0, NULL, NULL, NULL},
6299 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6300 0, NULL, NULL, NULL},
6301 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6302 0, NULL, NULL, NULL},
6304 /* RFC 2307 NIS Syntaxes */
6305 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6306 0, NULL, nisNetgroupTripleValidate, NULL},
6307 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6308 0, NULL, bootParameterValidate, NULL},
6310 /* draft-zeilenga-ldap-x509 */
6311 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6312 SLAP_SYNTAX_HIDE, NULL,
6313 serialNumberAndIssuerValidate,
6314 serialNumberAndIssuerPretty},
6315 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6316 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6317 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6318 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6319 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6320 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6321 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6322 SLAP_SYNTAX_HIDE, NULL,
6323 issuerAndThisUpdateValidate,
6324 issuerAndThisUpdatePretty},
6325 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6326 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6327 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6328 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6329 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6330 SLAP_SYNTAX_HIDE, NULL,
6331 serialNumberAndIssuerSerialValidate,
6332 serialNumberAndIssuerSerialPretty},
6333 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6334 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6336 #ifdef SLAPD_AUTHPASSWD
6337 /* needs updating */
6338 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6339 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6342 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6343 0, NULL, UUIDValidate, UUIDPretty},
6345 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6346 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6348 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6349 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6351 /* OpenLDAP Void Syntax */
6352 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6353 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6355 /* FIXME: OID is unused, but not registered yet */
6356 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6357 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6359 {NULL, 0, NULL, NULL, NULL}
6362 char *csnSIDMatchSyntaxes[] = {
6363 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6366 char *certificateExactMatchSyntaxes[] = {
6367 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6370 char *certificateListExactMatchSyntaxes[] = {
6371 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6374 char *attributeCertificateExactMatchSyntaxes[] = {
6375 attributeCertificateSyntaxOID /* attributeCertificate */,
6379 #ifdef LDAP_COMP_MATCH
6380 char *componentFilterMatchSyntaxes[] = {
6381 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6382 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6383 attributeCertificateSyntaxOID /* attributeCertificate */,
6388 char *directoryStringSyntaxes[] = {
6389 "1.3.6.1.4.1.1466.115.121.1.11" /* countryString */,
6390 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6391 "1.3.6.1.4.1.1466.115.121.1.50" /* telephoneNumber */,
6394 char *integerFirstComponentMatchSyntaxes[] = {
6395 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6396 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6399 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6400 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6401 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6402 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6403 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6404 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6405 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6406 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6407 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6412 * Other matching rules in X.520 that we do not use (yet):
6414 * 2.5.13.25 uTCTimeMatch
6415 * 2.5.13.26 uTCTimeOrderingMatch
6416 * 2.5.13.31* directoryStringFirstComponentMatch
6417 * 2.5.13.32* wordMatch
6418 * 2.5.13.33* keywordMatch
6419 * 2.5.13.36+ certificatePairExactMatch
6420 * 2.5.13.37+ certificatePairMatch
6421 * 2.5.13.40+ algorithmIdentifierMatch
6422 * 2.5.13.41* storedPrefixMatch
6423 * 2.5.13.42 attributeCertificateMatch
6424 * 2.5.13.43 readerAndKeyIDMatch
6425 * 2.5.13.44 attributeIntegrityMatch
6427 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6428 * (+) described in draft-zeilenga-ldap-x509
6430 static slap_mrule_defs_rec mrule_defs[] = {
6432 * EQUALITY matching rules must be listed after associated APPROX
6433 * matching rules. So, we list all APPROX matching rules first.
6435 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6436 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6437 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6438 NULL, NULL, directoryStringApproxMatch,
6439 directoryStringApproxIndexer, directoryStringApproxFilter,
6442 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6443 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6444 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6445 NULL, NULL, IA5StringApproxMatch,
6446 IA5StringApproxIndexer, IA5StringApproxFilter,
6450 * Other matching rules
6453 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6454 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6455 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6456 NULL, NULL, octetStringMatch,
6457 octetStringIndexer, octetStringFilter,
6460 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6461 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6462 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6463 NULL, dnNormalize, dnMatch,
6464 octetStringIndexer, octetStringFilter,
6467 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6468 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6469 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6470 NULL, dnNormalize, dnRelativeMatch,
6474 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6475 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6476 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6477 NULL, dnNormalize, dnRelativeMatch,
6481 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6482 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6483 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6484 NULL, dnNormalize, dnRelativeMatch,
6488 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6489 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6490 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6491 NULL, dnNormalize, dnRelativeMatch,
6495 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6496 "SYNTAX 1.2.36.79672281.1.5.0 )",
6497 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6498 NULL, rdnNormalize, rdnMatch,
6499 octetStringIndexer, octetStringFilter,
6502 #ifdef LDAP_COMP_MATCH
6503 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6504 "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */
6505 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6506 NULL, NULL , componentFilterMatch,
6507 octetStringIndexer, octetStringFilter,
6510 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6511 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6512 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6513 NULL, NULL , allComponentsMatch,
6514 octetStringIndexer, octetStringFilter,
6517 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6518 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6519 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6520 NULL, NULL , directoryComponentsMatch,
6521 octetStringIndexer, octetStringFilter,
6525 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6527 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6528 NULL, UTF8StringNormalize, octetStringMatch,
6529 octetStringIndexer, octetStringFilter,
6530 directoryStringApproxMatchOID },
6532 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6534 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6535 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6537 "caseIgnoreMatch" },
6539 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6540 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6541 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6542 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6543 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6544 "caseIgnoreMatch" },
6546 {"( 2.5.13.5 NAME 'caseExactMatch' "
6547 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6548 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6549 NULL, UTF8StringNormalize, octetStringMatch,
6550 octetStringIndexer, octetStringFilter,
6551 directoryStringApproxMatchOID },
6553 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6555 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6556 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6560 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6561 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6562 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6563 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6564 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6567 {"( 2.5.13.8 NAME 'numericStringMatch' "
6568 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6569 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6570 NULL, numericStringNormalize, octetStringMatch,
6571 octetStringIndexer, octetStringFilter,
6574 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6575 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6576 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6577 NULL, numericStringNormalize, octetStringOrderingMatch,
6579 "numericStringMatch" },
6581 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6582 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6583 SLAP_MR_SUBSTR, NULL,
6584 NULL, numericStringNormalize, octetStringSubstringsMatch,
6585 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6586 "numericStringMatch" },
6588 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6589 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */
6590 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6591 NULL, postalAddressNormalize, octetStringMatch,
6592 octetStringIndexer, octetStringFilter,
6595 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6596 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6597 SLAP_MR_SUBSTR, NULL,
6598 NULL, NULL, NULL, NULL, NULL,
6599 "caseIgnoreListMatch" },
6601 {"( 2.5.13.13 NAME 'booleanMatch' "
6602 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6603 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6604 NULL, NULL, booleanMatch,
6605 octetStringIndexer, octetStringFilter,
6608 {"( 2.5.13.14 NAME 'integerMatch' "
6609 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6610 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6611 NULL, NULL, integerMatch,
6612 integerIndexer, integerFilter,
6615 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6616 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6617 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6618 NULL, NULL, integerMatch,
6622 {"( 2.5.13.16 NAME 'bitStringMatch' "
6623 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6624 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6625 NULL, NULL, octetStringMatch,
6626 octetStringIndexer, octetStringFilter,
6629 {"( 2.5.13.17 NAME 'octetStringMatch' "
6630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6631 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6632 NULL, NULL, octetStringMatch,
6633 octetStringIndexer, octetStringFilter,
6636 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6637 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6638 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6639 NULL, NULL, octetStringOrderingMatch,
6641 "octetStringMatch" },
6643 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6644 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6645 SLAP_MR_SUBSTR, NULL,
6646 NULL, NULL, octetStringSubstringsMatch,
6647 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6648 "octetStringMatch" },
6650 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6651 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6652 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6654 telephoneNumberNormalize, octetStringMatch,
6655 octetStringIndexer, octetStringFilter,
6658 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6659 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6660 SLAP_MR_SUBSTR, NULL,
6661 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6662 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6663 "telephoneNumberMatch" },
6665 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6666 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6667 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6668 NULL, NULL, NULL, NULL, NULL, NULL },
6670 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6671 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */
6672 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6673 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6674 uniqueMemberIndexer, uniqueMemberFilter,
6677 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6678 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6679 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6680 NULL, NULL, NULL, NULL, NULL, NULL },
6682 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6683 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6684 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6685 NULL, generalizedTimeNormalize, octetStringMatch,
6686 generalizedTimeIndexer, generalizedTimeFilter,
6689 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6690 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6691 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6692 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6694 "generalizedTimeMatch" },
6696 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6697 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6698 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6699 integerFirstComponentMatchSyntaxes,
6700 NULL, firstComponentNormalize, integerMatch,
6701 octetStringIndexer, octetStringFilter,
6704 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6705 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */
6706 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6707 objectIdentifierFirstComponentMatchSyntaxes,
6708 NULL, firstComponentNormalize, octetStringMatch,
6709 octetStringIndexer, octetStringFilter,
6712 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6713 "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */
6714 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6715 NULL, certificateExactNormalize, octetStringMatch,
6716 octetStringIndexer, octetStringFilter,
6719 {"( 2.5.13.35 NAME 'certificateMatch' "
6720 "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */
6721 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6722 NULL, NULL, NULL, NULL, NULL,
6725 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6726 "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */
6727 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6728 NULL, certificateListExactNormalize, octetStringMatch,
6729 octetStringIndexer, octetStringFilter,
6732 {"( 2.5.13.39 NAME 'certificateListMatch' "
6733 "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */
6734 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6735 NULL, NULL, NULL, NULL, NULL,
6738 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6739 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6740 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6741 NULL, attributeCertificateExactNormalize, octetStringMatch,
6742 octetStringIndexer, octetStringFilter,
6745 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6746 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6747 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6748 NULL, NULL, NULL, NULL, NULL,
6751 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6752 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6753 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6754 NULL, IA5StringNormalize, octetStringMatch,
6755 octetStringIndexer, octetStringFilter,
6756 IA5StringApproxMatchOID },
6758 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6759 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6760 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6761 NULL, IA5StringNormalize, octetStringMatch,
6762 octetStringIndexer, octetStringFilter,
6763 IA5StringApproxMatchOID },
6765 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6766 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6767 SLAP_MR_SUBSTR, NULL,
6768 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6769 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6770 "caseIgnoreIA5Match" },
6772 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6773 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6774 SLAP_MR_SUBSTR, NULL,
6775 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6776 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6777 "caseExactIA5Match" },
6779 #ifdef SLAPD_AUTHPASSWD
6780 /* needs updating */
6781 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6782 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */
6783 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6784 NULL, NULL, authPasswordMatch,
6789 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6790 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6792 NULL, NULL, integerBitAndMatch,
6796 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6797 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6799 NULL, NULL, integerBitOrMatch,
6803 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6804 "SYNTAX 1.3.6.1.1.16.1 )",
6805 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6806 NULL, UUIDNormalize, octetStringMatch,
6807 octetStringIndexer, octetStringFilter,
6810 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6811 "SYNTAX 1.3.6.1.1.16.1 )",
6812 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6813 NULL, UUIDNormalize, octetStringOrderingMatch,
6814 octetStringIndexer, octetStringFilter,
6817 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6818 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6819 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6820 NULL, csnNormalize, csnMatch,
6821 csnIndexer, csnFilter,
6824 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6825 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6826 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6827 NULL, csnNormalize, csnOrderingMatch,
6831 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6832 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6833 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6834 NULL, csnSidNormalize, octetStringMatch,
6835 octetStringIndexer, octetStringFilter,
6838 /* FIXME: OID is unused, but not registered yet */
6839 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6840 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */
6841 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6842 NULL, authzNormalize, authzMatch,
6846 {NULL, SLAP_MR_NONE, NULL,
6847 NULL, NULL, NULL, NULL, NULL,
6852 slap_schema_init( void )
6857 /* we should only be called once (from main) */
6858 assert( schema_init_done == 0 );
6860 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6861 res = register_syntax( &syntax_defs[i] );
6864 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6865 syntax_defs[i].sd_desc );
6870 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6871 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6872 mrule_defs[i].mrd_compat_syntaxes == NULL )
6875 "slap_schema_init: Ignoring unusable matching rule %s\n",
6876 mrule_defs[i].mrd_desc );
6880 res = register_matching_rule( &mrule_defs[i] );
6884 "slap_schema_init: Error registering matching rule %s\n",
6885 mrule_defs[i].mrd_desc );
6890 res = slap_schema_load();
6891 schema_init_done = 1;
6896 schema_destroy( void )
6905 if( schema_init_done ) {
6906 ldap_pvt_thread_mutex_destroy( &ad_index_mutex );
6907 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6908 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );