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 -------------------------------------------------------------------*/
1784 unsigned char *u = (unsigned char *)in->bv_val, *end = in->bv_val + in->bv_len;
1786 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1787 /* directory strings cannot be empty */
1788 return LDAP_INVALID_SYNTAX;
1791 for( ; u < end; u += len ) {
1792 /* get the length indicated by the first byte */
1793 len = LDAP_UTF8_CHARLEN2( u, len );
1795 /* very basic checks */
1798 if( (u[5] & 0xC0) != 0x80 ) {
1799 return LDAP_INVALID_SYNTAX;
1802 if( (u[4] & 0xC0) != 0x80 ) {
1803 return LDAP_INVALID_SYNTAX;
1806 if( (u[3] & 0xC0) != 0x80 ) {
1807 return LDAP_INVALID_SYNTAX;
1810 if( (u[2] & 0xC0 )!= 0x80 ) {
1811 return LDAP_INVALID_SYNTAX;
1814 if( (u[1] & 0xC0) != 0x80 ) {
1815 return LDAP_INVALID_SYNTAX;
1818 /* CHARLEN already validated it */
1821 return LDAP_INVALID_SYNTAX;
1824 /* make sure len corresponds with the offset
1825 to the next character */
1826 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1830 return LDAP_INVALID_SYNTAX;
1833 return LDAP_SUCCESS;
1837 UTF8StringNormalize(
1842 struct berval *normalized,
1845 struct berval tmp, nvalue;
1846 int flags, wasspace;
1849 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1851 if( BER_BVISNULL( val ) ) {
1852 /* assume we're dealing with a syntax (e.g., UTF8String)
1853 * which allows empty strings
1855 BER_BVZERO( normalized );
1856 return LDAP_SUCCESS;
1859 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1860 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1861 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1862 ? LDAP_UTF8_APPROX : 0;
1864 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1865 /* out of memory or syntax error, the former is unlikely */
1867 return LDAP_INVALID_SYNTAX;
1870 /* collapse spaces (in place) */
1872 nvalue.bv_val = tmp.bv_val;
1874 /* trim leading spaces? */
1875 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1876 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1878 for( i = 0; i < tmp.bv_len; i++) {
1879 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1880 if( wasspace++ == 0 ) {
1881 /* trim repeated spaces */
1882 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1886 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1890 if( !BER_BVISEMPTY( &nvalue ) ) {
1891 /* trim trailing space? */
1893 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1894 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1898 nvalue.bv_val[nvalue.bv_len] = '\0';
1900 } else if ( tmp.bv_len ) {
1901 /* string of all spaces is treated as one space */
1902 nvalue.bv_val[0] = ' ';
1903 nvalue.bv_val[1] = '\0';
1905 } /* should never be entered with 0-length val */
1907 *normalized = nvalue;
1908 return LDAP_SUCCESS;
1912 directoryStringSubstringsMatch(
1917 struct berval *value,
1918 void *assertedValue )
1921 SubstringsAssertion *sub = assertedValue;
1922 struct berval left = *value;
1926 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1927 if ( sub->sa_initial.bv_len > left.bv_len ) {
1928 /* not enough left */
1933 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1934 sub->sa_initial.bv_len );
1940 left.bv_val += sub->sa_initial.bv_len;
1941 left.bv_len -= sub->sa_initial.bv_len;
1943 priorspace = ASCII_SPACE(
1944 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1947 if ( sub->sa_any ) {
1948 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1952 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1953 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1955 /* allow next space to match */
1962 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1966 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1967 /* not enough left */
1972 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1979 idx = p - left.bv_val;
1981 if ( idx >= left.bv_len ) {
1982 /* this shouldn't happen */
1989 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1990 /* not enough left */
1995 match = memcmp( left.bv_val,
1996 sub->sa_any[i].bv_val,
1997 sub->sa_any[i].bv_len );
2005 left.bv_val += sub->sa_any[i].bv_len;
2006 left.bv_len -= sub->sa_any[i].bv_len;
2008 priorspace = ASCII_SPACE(
2009 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
2013 if ( !BER_BVISNULL( &sub->sa_final ) ) {
2014 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
2015 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
2017 /* allow next space to match */
2022 if ( sub->sa_final.bv_len > left.bv_len ) {
2023 /* not enough left */
2028 match = memcmp( sub->sa_final.bv_val,
2029 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2030 sub->sa_final.bv_len );
2039 return LDAP_SUCCESS;
2042 #if defined(SLAPD_APPROX_INITIALS)
2043 # define SLAPD_APPROX_DELIMITER "._ "
2044 # define SLAPD_APPROX_WORDLEN 2
2046 # define SLAPD_APPROX_DELIMITER " "
2047 # define SLAPD_APPROX_WORDLEN 1
2056 struct berval *value,
2057 void *assertedValue )
2059 struct berval *nval, *assertv;
2060 char *val, **values, **words, *c;
2061 int i, count, len, nextchunk=0, nextavail=0;
2063 /* Yes, this is necessary */
2064 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
2065 if( nval == NULL ) {
2067 return LDAP_SUCCESS;
2070 /* Yes, this is necessary */
2071 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
2072 NULL, LDAP_UTF8_APPROX, NULL );
2073 if( assertv == NULL ) {
2076 return LDAP_SUCCESS;
2079 /* Isolate how many words there are */
2080 for ( c = nval->bv_val, count = 1; *c; c++ ) {
2081 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
2082 if ( c == NULL ) break;
2087 /* Get a phonetic copy of each word */
2088 words = (char **)ch_malloc( count * sizeof(char *) );
2089 values = (char **)ch_malloc( count * sizeof(char *) );
2090 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
2092 values[i] = phonetic(c);
2095 /* Work through the asserted value's words, to see if at least some
2096 * of the words are there, in the same order. */
2098 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
2099 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
2104 #if defined(SLAPD_APPROX_INITIALS)
2105 else if( len == 1 ) {
2106 /* Single letter words need to at least match one word's initial */
2107 for( i=nextavail; i<count; i++ )
2108 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
2115 /* Isolate the next word in the asserted value and phonetic it */
2116 assertv->bv_val[nextchunk+len] = '\0';
2117 val = phonetic( assertv->bv_val + nextchunk );
2119 /* See if this phonetic chunk is in the remaining words of *value */
2120 for( i=nextavail; i<count; i++ ){
2121 if( !strcmp( val, values[i] ) ){
2129 /* This chunk in the asserted value was NOT within the *value. */
2135 /* Go on to the next word in the asserted value */
2139 /* If some of the words were seen, call it a match */
2140 if( nextavail > 0 ) {
2147 /* Cleanup allocs */
2148 ber_bvfree( assertv );
2149 for( i=0; i<count; i++ ) {
2150 ch_free( values[i] );
2156 return LDAP_SUCCESS;
2165 struct berval *prefix,
2171 int i,j, len, wordcount, keycount=0;
2172 struct berval *newkeys;
2173 BerVarray keys=NULL;
2175 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2176 struct berval val = BER_BVNULL;
2177 /* Yes, this is necessary */
2178 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2179 assert( !BER_BVISNULL( &val ) );
2181 /* Isolate how many words there are. There will be a key for each */
2182 for( wordcount = 0, c = val.bv_val; *c; c++) {
2183 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2184 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2186 if (*c == '\0') break;
2190 /* Allocate/increase storage to account for new keys */
2191 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2192 * sizeof(struct berval) );
2193 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2194 if( keys ) ch_free( keys );
2197 /* Get a phonetic copy of each word */
2198 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2200 if( len < SLAPD_APPROX_WORDLEN ) continue;
2201 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2202 if( keys[keycount].bv_len ) {
2205 ch_free( keys[keycount].bv_val );
2210 ber_memfree( val.bv_val );
2212 BER_BVZERO( &keys[keycount] );
2215 return LDAP_SUCCESS;
2224 struct berval *prefix,
2225 void * assertedValue,
2234 /* Yes, this is necessary */
2235 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2236 NULL, LDAP_UTF8_APPROX, NULL );
2237 if( val == NULL || BER_BVISNULL( val ) ) {
2238 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2239 BER_BVZERO( &keys[0] );
2242 return LDAP_SUCCESS;
2245 /* Isolate how many words there are. There will be a key for each */
2246 for( count = 0,c = val->bv_val; *c; c++) {
2247 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2248 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2250 if (*c == '\0') break;
2254 /* Allocate storage for new keys */
2255 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2257 /* Get a phonetic copy of each word */
2258 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2260 if( len < SLAPD_APPROX_WORDLEN ) continue;
2261 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2267 BER_BVZERO( &keys[count] );
2270 return LDAP_SUCCESS;
2273 /* Remove all spaces and '-' characters */
2275 telephoneNumberNormalize(
2280 struct berval *normalized,
2285 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2287 /* validator should have refused an empty string */
2288 assert( !BER_BVISEMPTY( val ) );
2290 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2292 for( p = val->bv_val; *p; p++ ) {
2293 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2299 normalized->bv_len = q - normalized->bv_val;
2301 if( BER_BVISEMPTY( normalized ) ) {
2302 slap_sl_free( normalized->bv_val, ctx );
2303 BER_BVZERO( normalized );
2304 return LDAP_INVALID_SYNTAX;
2307 return LDAP_SUCCESS;
2311 postalAddressValidate(
2315 struct berval bv = *in;
2318 for ( c = 0; c < in->bv_len; c++ ) {
2319 if ( in->bv_val[c] == '\\' ) {
2321 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2322 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2324 return LDAP_INVALID_SYNTAX;
2329 if ( in->bv_val[c] == '$' ) {
2330 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2331 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2332 return LDAP_INVALID_SYNTAX;
2334 bv.bv_val = &in->bv_val[c] + 1;
2338 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2339 return UTF8StringValidate( NULL, &bv );
2343 postalAddressNormalize(
2348 struct berval *normalized,
2351 BerVarray lines = NULL, nlines = NULL;
2353 int rc = LDAP_SUCCESS;
2354 MatchingRule *xmr = NULL;
2357 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2358 xmr = slap_schema.si_mr_caseIgnoreMatch;
2361 xmr = slap_schema.si_mr_caseExactMatch;
2364 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2365 if ( val->bv_val[c] == '$' ) {
2370 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2371 nlines = &lines[l + 2];
2373 lines[0].bv_val = val->bv_val;
2374 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2375 if ( val->bv_val[c] == '$' ) {
2376 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2378 lines[l].bv_val = &val->bv_val[c + 1];
2381 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2383 normalized->bv_len = c = l;
2385 for ( l = 0; l <= c; l++ ) {
2386 /* NOTE: we directly normalize each line,
2387 * without unescaping the values, since the special
2388 * values '\24' ('$') and '\5C' ('\') are not affected
2389 * by normalization */
2390 if ( !lines[l].bv_len ) {
2391 nlines[l].bv_len = 0;
2392 nlines[l].bv_val = NULL;
2395 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2396 if ( rc != LDAP_SUCCESS ) {
2397 rc = LDAP_INVALID_SYNTAX;
2401 normalized->bv_len += nlines[l].bv_len;
2404 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2406 p = normalized->bv_val;
2407 for ( l = 0; l <= c ; l++ ) {
2408 p = lutil_strbvcopy( p, &nlines[l] );
2413 assert( p == &normalized->bv_val[normalized->bv_len] );
2416 if ( nlines != NULL ) {
2417 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2418 slap_sl_free( nlines[l].bv_val, ctx );
2421 slap_sl_free( lines, ctx );
2432 struct berval val = *in;
2434 if( BER_BVISEMPTY( &val ) ) {
2435 /* disallow empty strings */
2436 return LDAP_INVALID_SYNTAX;
2439 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2440 if ( val.bv_len == 1 ) {
2441 return LDAP_SUCCESS;
2444 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2451 while ( OID_LEADCHAR( val.bv_val[0] )) {
2455 if ( val.bv_len == 0 ) {
2456 return LDAP_SUCCESS;
2460 if( !OID_SEPARATOR( val.bv_val[0] )) {
2468 return LDAP_INVALID_SYNTAX;
2477 struct berval val = *in;
2479 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2481 if ( val.bv_val[0] == '-' ) {
2485 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2486 return LDAP_INVALID_SYNTAX;
2489 if( val.bv_val[0] == '0' ) { /* "-0" */
2490 return LDAP_INVALID_SYNTAX;
2493 } else if ( val.bv_val[0] == '0' ) {
2494 if( val.bv_len > 1 ) { /* "0<more>" */
2495 return LDAP_INVALID_SYNTAX;
2498 return LDAP_SUCCESS;
2501 for( i=0; i < val.bv_len; i++ ) {
2502 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2503 return LDAP_INVALID_SYNTAX;
2507 return LDAP_SUCCESS;
2516 struct berval *value,
2517 void *assertedValue )
2519 struct berval *asserted = (struct berval *) assertedValue;
2520 int vsign = 1, asign = 1; /* default sign = '+' */
2525 if( v.bv_val[0] == '-' ) {
2531 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2534 if( a.bv_val[0] == '-' ) {
2540 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2542 match = vsign - asign;
2544 match = ( v.bv_len != a.bv_len
2545 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2546 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2547 if( vsign < 0 ) match = -match;
2550 /* Ordering rule used in extensible match filter? */
2551 if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
2552 match = (match >= 0);
2555 return LDAP_SUCCESS;
2558 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2559 #define INDEX_INTLEN_CHOP 7
2560 #define INDEX_INTLEN_CHOPBYTES 3
2569 /* Integer index key format, designed for memcmp to collate correctly:
2570 * if too large: one's complement sign*<approx exponent=chopped bytes>,
2571 * two's complement value (sign-extended or chopped as needed),
2572 * however in first byte above, the top <number of exponent-bytes + 1>
2573 * bits are the inverse sign and next bit is the sign as delimiter.
2575 ber_slen_t k = index_intlen_strlen;
2577 unsigned signmask = ~0x7fU;
2578 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2579 struct berval val = *in, itmp = *tmp;
2581 if ( val.bv_val[0] != '-' ) {
2586 /* Chop least significant digits, increase length instead */
2587 if ( val.bv_len > (ber_len_t) k ) {
2588 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2589 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2590 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2593 if ( lutil_str2bin( &val, &itmp, ctx )) {
2594 return LDAP_INVALID_SYNTAX;
2597 /* Omit leading sign byte */
2598 if ( itmp.bv_val[0] == neg ) {
2603 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2605 assert( chop == 0 );
2606 memset( key->bv_val, neg, k ); /* sign-extend */
2607 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2608 /* Got exponent -k, or no room for 2 sign bits */
2609 lenp = lenbuf + sizeof(lenbuf);
2610 chop = - (ber_len_t) k;
2612 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2614 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2615 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2616 * are 1, and the top n+2 bits of lenp[0] are the sign bit. */
2617 k = (lenbuf + sizeof(lenbuf)) - lenp;
2618 if ( k > (ber_slen_t) index_intlen )
2620 memcpy( key->bv_val, lenp, k );
2621 itmp.bv_len = index_intlen - k;
2623 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2624 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2628 /* Index generation function: Ordered index */
2635 struct berval *prefix,
2645 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2647 /* count the values and find max needed length */
2649 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2650 if ( vlen < values[i].bv_len )
2651 vlen = values[i].bv_len;
2653 if ( vlen > maxstrlen )
2656 /* we should have at least one value at this point */
2659 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2660 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2661 keys[i].bv_len = index_intlen;
2662 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2665 keys[i].bv_val = NULL;
2667 if ( vlen > sizeof(ibuf) ) {
2668 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2672 itmp.bv_len = sizeof(ibuf);
2674 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2675 if ( itmp.bv_val != ibuf ) {
2676 itmp.bv_len = values[i].bv_len;
2677 if ( itmp.bv_len <= sizeof(ibuf) )
2678 itmp.bv_len = sizeof(ibuf);
2679 else if ( itmp.bv_len > maxstrlen )
2680 itmp.bv_len = maxstrlen;
2682 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2684 slap_sl_free( keys, ctx );
2690 if ( itmp.bv_val != ibuf ) {
2691 slap_sl_free( itmp.bv_val, ctx );
2696 /* Index generation function: Ordered index */
2703 struct berval *prefix,
2704 void * assertedValue,
2711 struct berval *value;
2714 value = (struct berval *) assertedValue;
2716 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2718 keys[0].bv_len = index_intlen;
2719 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2721 keys[1].bv_val = NULL;
2723 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2724 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2725 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2726 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2729 iv.bv_len = sizeof(ibuf);
2732 rc = integerVal2Key( value, keys, &iv, ctx );
2734 if ( iv.bv_val != ibuf ) {
2735 slap_sl_free( iv.bv_val, ctx );
2741 slap_sl_free( keys, ctx );
2747 countryStringValidate(
2749 struct berval *val )
2751 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2753 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2754 return LDAP_INVALID_SYNTAX;
2756 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2757 return LDAP_INVALID_SYNTAX;
2760 return LDAP_SUCCESS;
2764 printableStringValidate(
2766 struct berval *val )
2770 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2772 for(i=0; i < val->bv_len; i++) {
2773 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2774 return LDAP_INVALID_SYNTAX;
2778 return LDAP_SUCCESS;
2782 printablesStringValidate(
2784 struct berval *val )
2788 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2790 for(i=0,len=0; i < val->bv_len; i++) {
2791 int c = val->bv_val[i];
2795 return LDAP_INVALID_SYNTAX;
2799 } else if ( SLAP_PRINTABLE(c) ) {
2802 return LDAP_INVALID_SYNTAX;
2807 return LDAP_INVALID_SYNTAX;
2810 return LDAP_SUCCESS;
2816 struct berval *val )
2820 for(i=0; i < val->bv_len; i++) {
2821 if( !LDAP_ASCII(val->bv_val[i]) ) {
2822 return LDAP_INVALID_SYNTAX;
2826 return LDAP_SUCCESS;
2835 struct berval *normalized,
2839 int casefold = !SLAP_MR_ASSOCIATED( mr,
2840 slap_schema.si_mr_caseExactIA5Match );
2842 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2846 /* Ignore initial whitespace */
2847 while ( ASCII_SPACE( *p ) ) p++;
2849 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2850 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2851 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2852 normalized->bv_val[normalized->bv_len] = '\0';
2854 p = q = normalized->bv_val;
2857 if ( ASCII_SPACE( *p ) ) {
2860 /* Ignore the extra whitespace */
2861 while ( ASCII_SPACE( *p ) ) {
2865 } else if ( casefold ) {
2866 /* Most IA5 rules require casefolding */
2867 *q++ = TOLOWER(*p); p++;
2874 assert( normalized->bv_val <= p );
2878 * If the string ended in space, backup the pointer one
2879 * position. One is enough because the above loop collapsed
2880 * all whitespace to a single space.
2882 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2884 /* null terminate */
2887 normalized->bv_len = q - normalized->bv_val;
2889 return LDAP_SUCCESS;
2898 if( in->bv_len != 36 ) {
2899 return LDAP_INVALID_SYNTAX;
2902 for( i=0; i<36; i++ ) {
2908 if( in->bv_val[i] != '-' ) {
2909 return LDAP_INVALID_SYNTAX;
2913 if( !ASCII_HEX( in->bv_val[i]) ) {
2914 return LDAP_INVALID_SYNTAX;
2919 return LDAP_SUCCESS;
2930 int rc=LDAP_INVALID_SYNTAX;
2932 assert( in != NULL );
2933 assert( out != NULL );
2935 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2938 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2940 for( i=0; i<36; i++ ) {
2946 if( in->bv_val[i] != '-' ) {
2949 out->bv_val[i] = '-';
2953 if( !ASCII_HEX( in->bv_val[i]) ) {
2956 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2961 out->bv_val[ out->bv_len ] = '\0';
2965 slap_sl_free( out->bv_val, ctx );
2978 struct berval *normalized,
2981 unsigned char octet = '\0';
2985 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2986 /* NOTE: must be a normalized UUID */
2987 assert( val->bv_len == 16 );
2989 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2990 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2991 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2992 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2994 return LDAP_SUCCESS;
2997 normalized->bv_len = 16;
2998 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
3000 for( i=0, j=0; i<36; i++ ) {
3001 unsigned char nibble;
3002 if( val->bv_val[i] == '-' ) {
3005 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
3006 nibble = val->bv_val[i] - '0';
3008 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
3009 nibble = val->bv_val[i] - ('a'-10);
3011 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
3012 nibble = val->bv_val[i] - ('A'-10);
3015 slap_sl_free( normalized->bv_val, ctx );
3016 BER_BVZERO( normalized );
3017 return LDAP_INVALID_SYNTAX;
3022 normalized->bv_val[j>>1] = octet;
3024 octet = nibble << 4;
3029 normalized->bv_val[normalized->bv_len] = 0;
3030 return LDAP_SUCCESS;
3036 numericStringValidate(
3042 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
3044 for(i=0; i < in->bv_len; i++) {
3045 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3046 return LDAP_INVALID_SYNTAX;
3050 return LDAP_SUCCESS;
3054 numericStringNormalize(
3059 struct berval *normalized,
3062 /* removal all spaces */
3065 assert( !BER_BVISEMPTY( val ) );
3067 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
3070 q = normalized->bv_val;
3073 if ( ASCII_SPACE( *p ) ) {
3074 /* Ignore whitespace */
3081 /* we should have copied no more than is in val */
3082 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3084 /* null terminate */
3087 normalized->bv_len = q - normalized->bv_val;
3089 if( BER_BVISEMPTY( normalized ) ) {
3090 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
3091 normalized->bv_val[0] = ' ';
3092 normalized->bv_val[1] = '\0';
3093 normalized->bv_len = 1;
3096 return LDAP_SUCCESS;
3100 * Integer conversion macros that will use the largest available
3103 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
3104 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
3105 # define SLAP_LONG long long
3107 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
3108 # define SLAP_LONG long
3109 #endif /* HAVE_STRTOLL ... */
3117 struct berval *value,
3118 void *assertedValue )
3120 SLAP_LONG lValue, lAssertedValue;
3123 /* safe to assume integers are NUL terminated? */
3124 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3125 if( errno == ERANGE )
3127 return LDAP_CONSTRAINT_VIOLATION;
3130 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
3132 if( errno == ERANGE )
3134 return LDAP_CONSTRAINT_VIOLATION;
3137 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
3138 return LDAP_SUCCESS;
3147 struct berval *value,
3148 void *assertedValue )
3150 SLAP_LONG lValue, lAssertedValue;
3153 /* safe to assume integers are NUL terminated? */
3154 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3155 if( errno == ERANGE )
3157 return LDAP_CONSTRAINT_VIOLATION;
3160 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3162 if( errno == ERANGE )
3164 return LDAP_CONSTRAINT_VIOLATION;
3167 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3168 return LDAP_SUCCESS;
3172 checkNum( struct berval *in, struct berval *out )
3174 /* parse serialNumber */
3175 ber_len_t neg = 0, extra = 0;
3178 out->bv_val = in->bv_val;
3181 if ( out->bv_val[0] == '-' ) {
3186 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3187 first = out->bv_val[2];
3190 out->bv_len += STRLENOF("0x");
3191 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3192 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3195 } else if ( out->bv_val[0] == '\'' ) {
3196 first = out->bv_val[1];
3199 out->bv_len += STRLENOF("'");
3201 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3202 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3204 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3207 out->bv_len += STRLENOF("'H");
3210 first = out->bv_val[0];
3211 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3212 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3216 if ( !( out->bv_len > neg ) ) {
3220 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3228 serialNumberAndIssuerCheck(
3236 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3238 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3239 /* Parse old format */
3240 is->bv_val = ber_bvchr( in, '$' );
3241 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3243 sn->bv_val = in->bv_val;
3244 sn->bv_len = is->bv_val - in->bv_val;
3247 is->bv_len = in->bv_len - (sn->bv_len + 1);
3249 /* eat leading zeros */
3250 for( n=0; n < (sn->bv_len-1); n++ ) {
3251 if( sn->bv_val[n] != '0' ) break;
3256 for( n=0; n < sn->bv_len; n++ ) {
3257 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3261 /* Parse GSER format */
3266 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3270 struct berval x = *in;
3276 /* eat leading spaces */
3277 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3281 /* should be at issuer or serialNumber NamedValue */
3282 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3283 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3286 x.bv_val += STRLENOF("issuer");
3287 x.bv_len -= STRLENOF("issuer");
3289 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3293 /* eat leading spaces */
3294 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3298 /* For backward compatibility, this part is optional */
3299 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3300 x.bv_val += STRLENOF("rdnSequence:");
3301 x.bv_len -= STRLENOF("rdnSequence:");
3304 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3308 is->bv_val = x.bv_val;
3311 for ( ; is->bv_len < x.bv_len; ) {
3312 if ( is->bv_val[is->bv_len] != '"' ) {
3316 if ( is->bv_val[is->bv_len+1] == '"' ) {
3323 x.bv_val += is->bv_len + 1;
3324 x.bv_len -= is->bv_len + 1;
3326 have |= HAVE_ISSUER;
3328 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3330 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3332 /* parse serialNumber */
3333 x.bv_val += STRLENOF("serialNumber");
3334 x.bv_len -= STRLENOF("serialNumber");
3336 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3340 /* eat leading spaces */
3341 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3345 if ( checkNum( &x, sn ) ) {
3346 return LDAP_INVALID_SYNTAX;
3349 x.bv_val += sn->bv_len;
3350 x.bv_len -= sn->bv_len;
3355 return LDAP_INVALID_SYNTAX;
3358 /* eat leading spaces */
3359 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3363 if ( have == HAVE_ALL ) {
3367 if ( x.bv_val[0] != ',' ) {
3368 return LDAP_INVALID_SYNTAX;
3375 /* should have no characters left... */
3376 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3378 if ( numdquotes == 0 ) {
3379 ber_dupbv_x( &ni, is, ctx );
3384 ni.bv_len = is->bv_len - numdquotes;
3385 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3386 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3387 if ( is->bv_val[src] == '"' ) {
3390 ni.bv_val[dst] = is->bv_val[src];
3392 ni.bv_val[dst] = '\0';
3402 serialNumberAndIssuerValidate(
3407 struct berval sn, i;
3409 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3412 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3417 /* validate DN -- doesn't handle double dquote */
3418 rc = dnValidate( NULL, &i );
3420 rc = LDAP_INVALID_SYNTAX;
3423 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3424 slap_sl_free( i.bv_val, NULL );
3427 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3428 in->bv_val, rc, 0 );
3435 serialNumberAndIssuerPretty(
3442 struct berval sn, i, ni = BER_BVNULL;
3445 assert( in != NULL );
3446 assert( out != NULL );
3450 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3453 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3458 rc = dnPretty( syntax, &i, &ni, ctx );
3460 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3461 slap_sl_free( i.bv_val, ctx );
3465 rc = LDAP_INVALID_SYNTAX;
3469 /* make room from sn + "$" */
3470 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3471 + sn.bv_len + ni.bv_len;
3472 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3474 if ( out->bv_val == NULL ) {
3481 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3482 p = lutil_strbvcopy( p, &sn );
3483 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3484 p = lutil_strbvcopy( p, &ni );
3485 p = lutil_strcopy( p, /*{*/ "\" }" );
3487 assert( p == &out->bv_val[out->bv_len] );
3490 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3491 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3493 slap_sl_free( ni.bv_val, ctx );
3495 return LDAP_SUCCESS;
3505 /* Use hex format. '123456789abcdef'H */
3506 unsigned char *ptr, zero = '\0';
3509 ber_len_t i, len, nlen;
3511 assert( in != NULL );
3512 assert( !BER_BVISNULL( in ) );
3513 assert( out != NULL );
3514 assert( !BER_BVISNULL( out ) );
3516 ptr = (unsigned char *)in->bv_val;
3519 /* Check for minimal encodings */
3521 if ( ptr[0] & 0x80 ) {
3522 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3526 } else if ( ptr[0] == 0 ) {
3527 if ( !( ptr[1] & 0x80 ) ) {
3534 } else if ( len == 0 ) {
3535 /* FIXME: this should not be possible,
3536 * since a value of zero would have length 1 */
3541 first = !( ptr[0] & 0xf0U );
3542 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3543 if ( nlen >= out->bv_len ) {
3544 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3550 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3554 for ( ; i < len; i++ ) {
3555 sprintf( sptr, "%02X", ptr[i] );
3562 assert( sptr == &out->bv_val[nlen] );
3569 #define SLAP_SN_BUFLEN (64)
3572 * This routine is called by certificateExactNormalize when
3573 * certificateExactNormalize receives a search string instead of
3574 * a certificate. This routine checks if the search value is valid
3575 * and then returns the normalized value
3578 serialNumberAndIssuerNormalize(
3586 struct berval sn, sn2, sn3, i, ni;
3587 char sbuf2[SLAP_SN_BUFLEN];
3588 char sbuf3[SLAP_SN_BUFLEN];
3592 assert( in != NULL );
3593 assert( out != NULL );
3595 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3598 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3603 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3605 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3606 slap_sl_free( i.bv_val, ctx );
3610 return LDAP_INVALID_SYNTAX;
3613 /* Convert sn to canonical hex */
3615 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3616 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3618 sn2.bv_len = sn.bv_len;
3620 sn3.bv_len = sizeof(sbuf3);
3621 if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
3622 rc = LDAP_INVALID_SYNTAX;
3626 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3627 + sn3.bv_len + ni.bv_len;
3628 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3629 if ( out->bv_val == NULL ) {
3637 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3638 p = lutil_strbvcopy( p, &sn3 );
3639 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3640 p = lutil_strbvcopy( p, &ni );
3641 p = lutil_strcopy( p, /*{*/ "\" }" );
3643 assert( p == &out->bv_val[out->bv_len] );
3646 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3647 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3649 if ( sn2.bv_val != sbuf2 ) {
3650 slap_sl_free( sn2.bv_val, ctx );
3653 if ( sn3.bv_val != sbuf3 ) {
3654 slap_sl_free( sn3.bv_val, ctx );
3657 slap_sl_free( ni.bv_val, ctx );
3663 certificateExactNormalize(
3668 struct berval *normalized,
3671 BerElementBuffer berbuf;
3672 BerElement *ber = (BerElement *)&berbuf;
3676 char serialbuf2[SLAP_SN_BUFLEN];
3677 struct berval sn, sn2 = BER_BVNULL;
3678 struct berval issuer_dn = BER_BVNULL, bvdn;
3680 int rc = LDAP_INVALID_SYNTAX;
3682 assert( val != NULL );
3684 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3685 val->bv_val, val->bv_len, 0 );
3687 if ( BER_BVISEMPTY( val ) ) goto done;
3689 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3690 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3693 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3695 ber_init2( ber, val, LBER_USE_DER );
3696 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3697 tag = ber_skip_tag( ber, &len ); /* Sequence */
3698 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3699 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3700 tag = ber_skip_tag( ber, &len );
3701 tag = ber_get_int( ber, &i ); /* version */
3704 /* NOTE: move the test here from certificateValidate,
3705 * so that we can validate certs with serial longer
3706 * than sizeof(ber_int_t) */
3707 tag = ber_skip_tag( ber, &len ); /* serial */
3709 sn.bv_val = (char *)ber->ber_ptr;
3710 sn2.bv_val = serialbuf2;
3711 sn2.bv_len = sizeof(serialbuf2);
3712 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3713 rc = LDAP_INVALID_SYNTAX;
3716 ber_skip_data( ber, len );
3718 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3719 ber_skip_data( ber, len );
3720 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3722 len = ber_ptrlen( ber );
3723 bvdn.bv_val = val->bv_val + len;
3724 bvdn.bv_len = val->bv_len - len;
3726 rc = dnX509normalize( &bvdn, &issuer_dn );
3727 if ( rc != LDAP_SUCCESS ) goto done;
3730 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3731 + sn2.bv_len + issuer_dn.bv_len;
3732 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3734 p = normalized->bv_val;
3736 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3737 p = lutil_strbvcopy( p, &sn2 );
3738 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3739 p = lutil_strbvcopy( p, &issuer_dn );
3740 p = lutil_strcopy( p, /*{*/ "\" }" );
3745 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3746 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3748 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3749 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3754 /* X.509 PKI certificateList stuff */
3756 checkTime( struct berval *in, struct berval *out )
3760 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3763 assert( in != NULL );
3764 assert( !BER_BVISNULL( in ) );
3765 assert( !BER_BVISEMPTY( in ) );
3767 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3771 if ( out != NULL ) {
3772 assert( !BER_BVISNULL( out ) );
3773 assert( out->bv_len >= sizeof( buf ) );
3774 bv.bv_val = out->bv_val;
3780 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3781 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3784 if ( in->bv_val[i] != 'Z' ) {
3789 if ( i != in->bv_len ) {
3793 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3794 lutil_strncopy( bv.bv_val, in->bv_val, i );
3797 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3798 char *p = bv.bv_val;
3799 if ( in->bv_val[0] < '7' ) {
3800 p = lutil_strcopy( p, "20" );
3803 p = lutil_strcopy( p, "19" );
3805 lutil_strncopy( p, in->bv_val, i );
3812 rc = generalizedTimeValidate( NULL, &bv );
3813 if ( rc == LDAP_SUCCESS && out != NULL ) {
3814 if ( out->bv_len > bv.bv_len ) {
3815 out->bv_val[ bv.bv_len ] = '\0';
3817 out->bv_len = bv.bv_len;
3820 return rc != LDAP_SUCCESS;
3824 issuerAndThisUpdateCheck(
3831 struct berval x = *in;
3832 struct berval ni = BER_BVNULL;
3833 /* Parse GSER format */
3837 HAVE_THISUPDATE = 0x2,
3838 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3842 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3844 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3845 return LDAP_INVALID_SYNTAX;
3849 x.bv_len -= STRLENOF("{}");
3852 /* eat leading spaces */
3853 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3857 /* should be at issuer or thisUpdate */
3858 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3859 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3862 x.bv_val += STRLENOF("issuer");
3863 x.bv_len -= STRLENOF("issuer");
3865 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3869 /* eat leading spaces */
3870 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3874 /* For backward compatibility, this part is optional */
3875 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3876 return LDAP_INVALID_SYNTAX;
3878 x.bv_val += STRLENOF("rdnSequence:");
3879 x.bv_len -= STRLENOF("rdnSequence:");
3881 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3885 is->bv_val = x.bv_val;
3888 for ( ; is->bv_len < x.bv_len; ) {
3889 if ( is->bv_val[is->bv_len] != '"' ) {
3893 if ( is->bv_val[is->bv_len+1] == '"' ) {
3900 x.bv_val += is->bv_len + 1;
3901 x.bv_len -= is->bv_len + 1;
3903 have |= HAVE_ISSUER;
3905 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3907 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3909 /* parse thisUpdate */
3910 x.bv_val += STRLENOF("thisUpdate");
3911 x.bv_len -= STRLENOF("thisUpdate");
3913 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3917 /* eat leading spaces */
3918 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3922 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3926 tu->bv_val = x.bv_val;
3929 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3930 if ( tu->bv_val[tu->bv_len] == '"' ) {
3934 x.bv_val += tu->bv_len + 1;
3935 x.bv_len -= tu->bv_len + 1;
3937 have |= HAVE_THISUPDATE;
3940 return LDAP_INVALID_SYNTAX;
3943 /* eat leading spaces */
3944 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3948 if ( have == HAVE_ALL ) {
3952 if ( x.bv_val[0] != ',' ) {
3953 return LDAP_INVALID_SYNTAX;
3960 /* should have no characters left... */
3961 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3963 if ( numdquotes == 0 ) {
3964 ber_dupbv_x( &ni, is, ctx );
3969 ni.bv_len = is->bv_len - numdquotes;
3970 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3971 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3972 if ( is->bv_val[src] == '"' ) {
3975 ni.bv_val[dst] = is->bv_val[src];
3977 ni.bv_val[dst] = '\0';
3986 issuerAndThisUpdateValidate(
3991 struct berval i, tu;
3993 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3996 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
4001 /* validate DN -- doesn't handle double dquote */
4002 rc = dnValidate( NULL, &i );
4004 rc = LDAP_INVALID_SYNTAX;
4006 } else if ( checkTime( &tu, NULL ) ) {
4007 rc = LDAP_INVALID_SYNTAX;
4010 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4011 slap_sl_free( i.bv_val, NULL );
4014 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
4015 in->bv_val, rc, 0 );
4022 issuerAndThisUpdatePretty(
4029 struct berval i, tu, ni = BER_BVNULL;
4032 assert( in != NULL );
4033 assert( out != NULL );
4037 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
4040 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4045 rc = dnPretty( syntax, &i, &ni, ctx );
4047 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4048 slap_sl_free( i.bv_val, ctx );
4051 if ( rc || checkTime( &tu, NULL ) ) {
4052 rc = LDAP_INVALID_SYNTAX;
4057 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
4058 + ni.bv_len + tu.bv_len;
4059 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4061 if ( out->bv_val == NULL ) {
4068 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4069 p = lutil_strbvcopy( p, &ni );
4070 p = lutil_strcopy( p, "\", thisUpdate \"" );
4071 p = lutil_strbvcopy( p, &tu );
4072 p = lutil_strcopy( p, /*{*/ "\" }" );
4074 assert( p == &out->bv_val[out->bv_len] );
4077 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
4078 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4080 slap_sl_free( ni.bv_val, ctx );
4086 issuerAndThisUpdateNormalize(
4094 struct berval i, ni, tu, tu2;
4095 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4099 assert( in != NULL );
4100 assert( out != NULL );
4102 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
4105 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4110 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4112 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4113 slap_sl_free( i.bv_val, ctx );
4117 tu2.bv_len = sizeof( sbuf );
4118 if ( rc || checkTime( &tu, &tu2 ) ) {
4119 return LDAP_INVALID_SYNTAX;
4122 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4123 + ni.bv_len + tu2.bv_len;
4124 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4126 if ( out->bv_val == NULL ) {
4134 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4135 p = lutil_strbvcopy( p, &ni );
4136 p = lutil_strcopy( p, "\", thisUpdate \"" );
4137 p = lutil_strbvcopy( p, &tu2 );
4138 p = lutil_strcopy( p, /*{*/ "\" }" );
4140 assert( p == &out->bv_val[out->bv_len] );
4143 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4144 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4146 slap_sl_free( ni.bv_val, ctx );
4152 certificateListExactNormalize(
4157 struct berval *normalized,
4160 BerElementBuffer berbuf;
4161 BerElement *ber = (BerElement *)&berbuf;
4165 struct berval issuer_dn = BER_BVNULL, bvdn,
4167 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4168 int rc = LDAP_INVALID_SYNTAX;
4170 assert( val != NULL );
4172 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4173 val->bv_val, val->bv_len, 0 );
4175 if ( BER_BVISEMPTY( val ) ) goto done;
4177 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4178 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4181 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4183 ber_init2( ber, val, LBER_USE_DER );
4184 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4185 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4186 tag = ber_skip_tag( ber, &len ); /* Sequence */
4187 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4188 tag = ber_peek_tag( ber, &len );
4189 /* Optional version */
4190 if ( tag == LBER_INTEGER ) {
4191 tag = ber_get_int( ber, &version );
4192 assert( tag == LBER_INTEGER );
4193 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4195 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4196 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4197 ber_skip_data( ber, len );
4199 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4200 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4201 len = ber_ptrlen( ber );
4202 bvdn.bv_val = val->bv_val + len;
4203 bvdn.bv_len = val->bv_len - len;
4204 tag = ber_skip_tag( ber, &len );
4205 ber_skip_data( ber, len );
4207 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4208 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4209 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4210 bvtu.bv_val = (char *)ber->ber_ptr;
4213 rc = dnX509normalize( &bvdn, &issuer_dn );
4214 if ( rc != LDAP_SUCCESS ) goto done;
4216 thisUpdate.bv_val = tubuf;
4217 thisUpdate.bv_len = sizeof(tubuf);
4218 if ( checkTime( &bvtu, &thisUpdate ) ) {
4219 rc = LDAP_INVALID_SYNTAX;
4223 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4224 + issuer_dn.bv_len + thisUpdate.bv_len;
4225 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4227 p = normalized->bv_val;
4229 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4230 p = lutil_strbvcopy( p, &issuer_dn );
4231 p = lutil_strcopy( p, "\", thisUpdate \"" );
4232 p = lutil_strbvcopy( p, &thisUpdate );
4233 p = lutil_strcopy( p, /*{*/ "\" }" );
4238 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4239 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4241 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4246 /* X.509 PMI serialNumberAndIssuerSerialCheck
4248 AttributeCertificateExactAssertion ::= SEQUENCE {
4249 serialNumber CertificateSerialNumber,
4250 issuer AttCertIssuer }
4252 CertificateSerialNumber ::= INTEGER
4254 AttCertIssuer ::= [0] SEQUENCE {
4255 issuerName GeneralNames OPTIONAL,
4256 baseCertificateID [0] IssuerSerial OPTIONAL,
4257 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4258 -- At least one component shall be present
4260 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4262 GeneralName ::= CHOICE {
4263 otherName [0] INSTANCE OF OTHER-NAME,
4264 rfc822Name [1] IA5String,
4265 dNSName [2] IA5String,
4266 x400Address [3] ORAddress,
4267 directoryName [4] Name,
4268 ediPartyName [5] EDIPartyName,
4269 uniformResourceIdentifier [6] IA5String,
4270 iPAddress [7] OCTET STRING,
4271 registeredID [8] OBJECT IDENTIFIER }
4273 IssuerSerial ::= SEQUENCE {
4274 issuer GeneralNames,
4275 serial CertificateSerialNumber,
4276 issuerUID UniqueIdentifier OPTIONAL }
4278 ObjectDigestInfo ::= SEQUENCE {
4279 digestedObjectType ENUMERATED {
4282 otherObjectTypes (2) },
4283 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4284 digestAlgorithm AlgorithmIdentifier,
4285 objectDigest BIT STRING }
4287 * The way I interpret it, an assertion should look like
4289 { serialNumber 'dd'H,
4290 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4291 baseCertificateID { serial '1d'H,
4292 issuer { directoryName:rdnSequence:"cn=zzz" },
4293 issuerUID <value> -- optional
4295 objectDigestInfo { ... } -- optional
4299 * with issuerName, baseCertificateID and objectDigestInfo optional,
4300 * at least one present; the way it's currently implemented, it is
4302 { serialNumber 'dd'H,
4303 issuer { baseCertificateID { serial '1d'H,
4304 issuer { directoryName:rdnSequence:"cn=zzz" }
4309 * with all the above parts mandatory.
4312 serialNumberAndIssuerSerialCheck(
4316 struct berval *i_sn, /* contain serial of baseCertificateID */
4319 /* Parse GSER format */
4324 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4325 } have = HAVE_NONE, have2 = HAVE_NONE;
4327 struct berval x = *in;
4330 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4333 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4340 /* eat leading spaces */
4341 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4345 /* should be at issuer or serialNumber NamedValue */
4346 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4347 if ( have & HAVE_ISSUER ) {
4348 return LDAP_INVALID_SYNTAX;
4351 /* parse IssuerSerial */
4352 x.bv_val += STRLENOF("issuer");
4353 x.bv_len -= STRLENOF("issuer");
4355 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4359 /* eat leading spaces */
4360 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4364 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4368 /* eat leading spaces */
4369 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4373 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4374 return LDAP_INVALID_SYNTAX;
4376 x.bv_val += STRLENOF("baseCertificateID ");
4377 x.bv_len -= STRLENOF("baseCertificateID ");
4379 /* eat leading spaces */
4380 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4384 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4389 /* eat leading spaces */
4390 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4394 /* parse issuer of baseCertificateID */
4395 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4396 if ( have2 & HAVE_ISSUER ) {
4397 return LDAP_INVALID_SYNTAX;
4400 x.bv_val += STRLENOF("issuer ");
4401 x.bv_len -= STRLENOF("issuer ");
4403 /* eat leading spaces */
4404 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4408 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4412 /* eat leading spaces */
4413 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4417 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4418 return LDAP_INVALID_SYNTAX;
4420 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4421 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4423 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4427 is->bv_val = x.bv_val;
4430 for ( ; is->bv_len < x.bv_len; ) {
4431 if ( is->bv_val[is->bv_len] != '"' ) {
4435 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4442 x.bv_val += is->bv_len + 1;
4443 x.bv_len -= is->bv_len + 1;
4445 /* eat leading spaces */
4446 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4450 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4454 have2 |= HAVE_ISSUER;
4456 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4457 if ( have2 & HAVE_SN ) {
4458 return LDAP_INVALID_SYNTAX;
4461 x.bv_val += STRLENOF("serial ");
4462 x.bv_len -= STRLENOF("serial ");
4464 /* eat leading spaces */
4465 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4469 if ( checkNum( &x, i_sn ) ) {
4470 return LDAP_INVALID_SYNTAX;
4473 x.bv_val += i_sn->bv_len;
4474 x.bv_len -= i_sn->bv_len;
4479 return LDAP_INVALID_SYNTAX;
4482 /* eat leading spaces */
4483 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4487 if ( have2 == HAVE_ALL ) {
4491 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4496 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4500 /* eat leading spaces */
4501 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4505 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4509 have |= HAVE_ISSUER;
4511 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4512 if ( have & HAVE_SN ) {
4513 return LDAP_INVALID_SYNTAX;
4516 /* parse serialNumber */
4517 x.bv_val += STRLENOF("serialNumber");
4518 x.bv_len -= STRLENOF("serialNumber");
4520 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4524 /* eat leading spaces */
4525 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4529 if ( checkNum( &x, sn ) ) {
4530 return LDAP_INVALID_SYNTAX;
4533 x.bv_val += sn->bv_len;
4534 x.bv_len -= sn->bv_len;
4539 return LDAP_INVALID_SYNTAX;
4543 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4547 if ( have == HAVE_ALL ) {
4551 if ( x.bv_val[0] != ',' ) {
4552 return LDAP_INVALID_SYNTAX;
4558 /* should have no characters left... */
4559 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4561 if ( numdquotes == 0 ) {
4562 ber_dupbv_x( &ni, is, ctx );
4567 ni.bv_len = is->bv_len - numdquotes;
4568 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4569 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4570 if ( is->bv_val[src] == '"' ) {
4573 ni.bv_val[dst] = is->bv_val[src];
4575 ni.bv_val[dst] = '\0';
4580 /* need to handle double dquotes here */
4584 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4586 serialNumberAndIssuerSerialValidate(
4591 struct berval sn, i, i_sn;
4593 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4596 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4601 /* validate DN -- doesn't handle double dquote */
4602 rc = dnValidate( NULL, &i );
4604 rc = LDAP_INVALID_SYNTAX;
4607 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4608 slap_sl_free( i.bv_val, NULL );
4612 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4613 in->bv_val, rc, 0 );
4618 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4620 serialNumberAndIssuerSerialPretty(
4626 struct berval sn, i, i_sn, ni = BER_BVNULL;
4630 assert( in != NULL );
4631 assert( out != NULL );
4633 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4636 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4641 rc = dnPretty( syntax, &i, &ni, ctx );
4643 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4644 slap_sl_free( i.bv_val, ctx );
4648 rc = LDAP_INVALID_SYNTAX;
4652 /* make room from sn + "$" */
4653 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4654 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4655 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4657 if ( out->bv_val == NULL ) {
4664 p = lutil_strcopy( p, "{ serialNumber " );
4665 p = lutil_strbvcopy( p, &sn );
4666 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4667 p = lutil_strbvcopy( p, &ni );
4668 p = lutil_strcopy( p, "\" }, serial " );
4669 p = lutil_strbvcopy( p, &i_sn );
4670 p = lutil_strcopy( p, " } } }" );
4672 assert( p == &out->bv_val[out->bv_len] );
4675 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4676 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4678 slap_sl_free( ni.bv_val, ctx );
4683 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4685 * This routine is called by attributeCertificateExactNormalize
4686 * when attributeCertificateExactNormalize receives a search
4687 * string instead of a attribute certificate. This routine
4688 * checks if the search value is valid and then returns the
4692 serialNumberAndIssuerSerialNormalize(
4700 struct berval i, ni = BER_BVNULL,
4701 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4702 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4703 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4704 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4708 assert( in != NULL );
4709 assert( out != NULL );
4711 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4714 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4719 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4721 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4722 slap_sl_free( i.bv_val, ctx );
4726 rc = LDAP_INVALID_SYNTAX;
4730 /* Convert sn to canonical hex */
4732 sn2.bv_len = sn.bv_len;
4733 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4734 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4736 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4737 rc = LDAP_INVALID_SYNTAX;
4741 /* Convert i_sn to canonical hex */
4742 i_sn2.bv_val = i_sbuf2;
4743 i_sn2.bv_len = i_sn.bv_len;
4744 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4745 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4747 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4748 rc = LDAP_INVALID_SYNTAX;
4753 sn3.bv_len = sizeof(sbuf3);
4754 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4755 rc = LDAP_INVALID_SYNTAX;
4759 i_sn3.bv_val = i_sbuf3;
4760 i_sn3.bv_len = sizeof(i_sbuf3);
4761 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4762 rc = LDAP_INVALID_SYNTAX;
4766 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4767 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4768 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4770 if ( out->bv_val == NULL ) {
4778 p = lutil_strcopy( p, "{ serialNumber " );
4779 p = lutil_strbvcopy( p, &sn3 );
4780 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4781 p = lutil_strbvcopy( p, &ni );
4782 p = lutil_strcopy( p, "\" }, serial " );
4783 p = lutil_strbvcopy( p, &i_sn3 );
4784 p = lutil_strcopy( p, " } } }" );
4786 assert( p == &out->bv_val[out->bv_len] );
4789 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4790 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4792 if ( sn2.bv_val != sbuf2 ) {
4793 slap_sl_free( sn2.bv_val, ctx );
4796 if ( i_sn2.bv_val != i_sbuf2 ) {
4797 slap_sl_free( i_sn2.bv_val, ctx );
4800 if ( sn3.bv_val != sbuf3 ) {
4801 slap_sl_free( sn3.bv_val, ctx );
4804 if ( i_sn3.bv_val != i_sbuf3 ) {
4805 slap_sl_free( i_sn3.bv_val, ctx );
4808 slap_sl_free( ni.bv_val, ctx );
4813 /* X.509 PMI attributeCertificateExactNormalize */
4815 attributeCertificateExactNormalize(
4820 struct berval *normalized,
4823 BerElementBuffer berbuf;
4824 BerElement *ber = (BerElement *)&berbuf;
4827 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4828 struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
4829 struct berval issuer_dn = BER_BVNULL, bvdn;
4831 int rc = LDAP_INVALID_SYNTAX;
4833 if ( BER_BVISEMPTY( val ) ) {
4837 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4838 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4841 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4843 ber_init2( ber, val, LBER_USE_DER );
4844 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4845 tag = ber_skip_tag( ber, &len ); /* Sequence */
4846 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4847 ber_skip_data( ber, len );
4848 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4849 ber_skip_data( ber, len );
4852 tag = ber_skip_tag( ber, &len ); /* Sequence */
4853 /* issuerName (GeneralNames sequence; optional)? */
4854 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4855 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4856 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4857 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4858 return LDAP_INVALID_SYNTAX;
4860 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4861 len = ber_ptrlen( ber );
4862 bvdn.bv_val = val->bv_val + len;
4863 bvdn.bv_len = val->bv_len - len;
4864 rc = dnX509normalize( &bvdn, &issuer_dn );
4865 if ( rc != LDAP_SUCCESS ) goto done;
4867 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4868 ber_skip_data( ber, len );
4869 tag = ber_skip_tag( ber, &len ); /* serial number */
4870 if ( tag != LBER_INTEGER ) {
4871 rc = LDAP_INVALID_SYNTAX;
4874 i_sn.bv_val = (char *)ber->ber_ptr;
4876 i_sn2.bv_val = issuer_serialbuf;
4877 i_sn2.bv_len = sizeof(issuer_serialbuf);
4878 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4879 rc = LDAP_INVALID_SYNTAX;
4882 ber_skip_data( ber, len );
4884 /* issuerUID (bitstring; optional)? */
4885 /* objectDigestInfo (sequence; optional)? */
4887 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4888 ber_skip_data( ber, len );
4889 tag = ber_skip_tag( ber, &len ); /* serial number */
4890 if ( tag != LBER_INTEGER ) {
4891 rc = LDAP_INVALID_SYNTAX;
4894 sn.bv_val = (char *)ber->ber_ptr;
4896 sn2.bv_val = serialbuf;
4897 sn2.bv_len = sizeof(serialbuf);
4898 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4899 rc = LDAP_INVALID_SYNTAX;
4902 ber_skip_data( ber, len );
4904 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4905 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4906 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4908 p = normalized->bv_val;
4910 p = lutil_strcopy( p, "{ serialNumber " );
4911 p = lutil_strbvcopy( p, &sn2 );
4912 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4913 p = lutil_strbvcopy( p, &issuer_dn );
4914 p = lutil_strcopy( p, "\" }, serial " );
4915 p = lutil_strbvcopy( p, &i_sn2 );
4916 p = lutil_strcopy( p, " } } }" );
4918 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4919 normalized->bv_val, NULL, NULL );
4924 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4925 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4926 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4939 assert( in != NULL );
4940 assert( !BER_BVISNULL( in ) );
4942 for ( i = 0; i < in->bv_len; i++ ) {
4943 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4944 return LDAP_INVALID_SYNTAX;
4948 return LDAP_SUCCESS;
4951 /* Normalize a SID as used inside a CSN:
4952 * three-digit numeric string */
4959 struct berval *normalized,
4964 assert( val != NULL );
4965 assert( normalized != NULL );
4967 ber_dupbv_x( normalized, val, ctx );
4969 for ( i = 0; i < normalized->bv_len; i++ ) {
4970 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4971 ber_memfree_x( normalized->bv_val, ctx );
4972 BER_BVZERO( normalized );
4973 return LDAP_INVALID_SYNTAX;
4976 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4979 return LDAP_SUCCESS;
4987 assert( in != NULL );
4988 assert( !BER_BVISNULL( in ) );
4990 if ( in->bv_len != 3 ) {
4991 return LDAP_INVALID_SYNTAX;
4994 return hexValidate( NULL, in );
4997 /* Normalize a SID as used inside a CSN:
4998 * three-digit numeric string */
5005 struct berval *normalized,
5008 if ( val->bv_len != 3 ) {
5009 return LDAP_INVALID_SYNTAX;
5012 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
5022 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5025 /* Normalize a SID as used inside a CSN, either as-is
5026 * (assertion value) or extracted from the CSN
5027 * (attribute value) */
5034 struct berval *normalized,
5042 if ( BER_BVISEMPTY( val ) ) {
5043 return LDAP_INVALID_SYNTAX;
5046 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
5047 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
5050 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
5052 ptr = ber_bvchr( val, '#' );
5053 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5054 return LDAP_INVALID_SYNTAX;
5057 bv.bv_val = ptr + 1;
5058 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5060 ptr = ber_bvchr( &bv, '#' );
5061 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5062 return LDAP_INVALID_SYNTAX;
5065 bv.bv_val = ptr + 1;
5066 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5068 ptr = ber_bvchr( &bv, '#' );
5069 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5070 return LDAP_INVALID_SYNTAX;
5073 bv.bv_len = ptr - bv.bv_val;
5075 if ( bv.bv_len == 2 ) {
5076 /* OpenLDAP 2.3 SID */
5078 buf[ 1 ] = bv.bv_val[ 0 ];
5079 buf[ 2 ] = bv.bv_val[ 1 ];
5086 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
5098 assert( in != NULL );
5099 assert( !BER_BVISNULL( in ) );
5101 if ( BER_BVISEMPTY( in ) ) {
5102 return LDAP_INVALID_SYNTAX;
5107 ptr = ber_bvchr( &bv, '#' );
5108 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
5109 return LDAP_INVALID_SYNTAX;
5112 bv.bv_len = ptr - bv.bv_val;
5113 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
5114 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
5116 return LDAP_INVALID_SYNTAX;
5119 rc = generalizedTimeValidate( NULL, &bv );
5120 if ( rc != LDAP_SUCCESS ) {
5124 bv.bv_val = ptr + 1;
5125 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5127 ptr = ber_bvchr( &bv, '#' );
5128 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5129 return LDAP_INVALID_SYNTAX;
5132 bv.bv_len = ptr - bv.bv_val;
5133 if ( bv.bv_len != 6 ) {
5134 return LDAP_INVALID_SYNTAX;
5137 rc = hexValidate( NULL, &bv );
5138 if ( rc != LDAP_SUCCESS ) {
5142 bv.bv_val = ptr + 1;
5143 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5145 ptr = ber_bvchr( &bv, '#' );
5146 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5147 return LDAP_INVALID_SYNTAX;
5150 bv.bv_len = ptr - bv.bv_val;
5151 if ( bv.bv_len == 2 ) {
5152 /* tolerate old 2-digit replica-id */
5153 rc = hexValidate( NULL, &bv );
5156 rc = sidValidate( NULL, &bv );
5158 if ( rc != LDAP_SUCCESS ) {
5162 bv.bv_val = ptr + 1;
5163 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5165 if ( bv.bv_len != 6 ) {
5166 return LDAP_INVALID_SYNTAX;
5169 return hexValidate( NULL, &bv );
5172 /* Normalize a CSN in OpenLDAP 2.1 format */
5179 struct berval *normalized,
5182 struct berval gt, cnt, sid, mod;
5184 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5188 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5189 assert( !BER_BVISEMPTY( val ) );
5193 ptr = ber_bvchr( >, '#' );
5194 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5195 return LDAP_INVALID_SYNTAX;
5198 gt.bv_len = ptr - gt.bv_val;
5199 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5200 return LDAP_INVALID_SYNTAX;
5203 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5204 return LDAP_INVALID_SYNTAX;
5207 cnt.bv_val = ptr + 1;
5208 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5210 ptr = ber_bvchr( &cnt, '#' );
5211 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5212 return LDAP_INVALID_SYNTAX;
5215 cnt.bv_len = ptr - cnt.bv_val;
5216 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5217 return LDAP_INVALID_SYNTAX;
5220 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5221 return LDAP_INVALID_SYNTAX;
5224 cnt.bv_val += STRLENOF( "0x" );
5225 cnt.bv_len -= STRLENOF( "0x" );
5227 sid.bv_val = ptr + 1;
5228 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5230 ptr = ber_bvchr( &sid, '#' );
5231 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5232 return LDAP_INVALID_SYNTAX;
5235 sid.bv_len = ptr - sid.bv_val;
5236 if ( sid.bv_len != STRLENOF( "0" ) ) {
5237 return LDAP_INVALID_SYNTAX;
5240 mod.bv_val = ptr + 1;
5241 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5242 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5243 return LDAP_INVALID_SYNTAX;
5246 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5250 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5251 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5253 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5255 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5256 ptr = lutil_strbvcopy( ptr, &cnt );
5260 *ptr++ = sid.bv_val[ 0 ];
5264 for ( i = 0; i < mod.bv_len; i++ ) {
5265 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5269 assert( ptr == &bv.bv_val[bv.bv_len] );
5271 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5272 return LDAP_INVALID_SYNTAX;
5275 ber_dupbv_x( normalized, &bv, ctx );
5277 return LDAP_SUCCESS;
5280 /* Normalize a CSN in OpenLDAP 2.3 format */
5287 struct berval *normalized,
5290 struct berval gt, cnt, sid, mod;
5292 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5296 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5297 assert( !BER_BVISEMPTY( val ) );
5301 ptr = ber_bvchr( >, '#' );
5302 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5303 return LDAP_INVALID_SYNTAX;
5306 gt.bv_len = ptr - gt.bv_val;
5307 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5308 return LDAP_INVALID_SYNTAX;
5311 cnt.bv_val = ptr + 1;
5312 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5314 ptr = ber_bvchr( &cnt, '#' );
5315 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5316 return LDAP_INVALID_SYNTAX;
5319 cnt.bv_len = ptr - cnt.bv_val;
5320 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5321 return LDAP_INVALID_SYNTAX;
5324 sid.bv_val = ptr + 1;
5325 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5327 ptr = ber_bvchr( &sid, '#' );
5328 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5329 return LDAP_INVALID_SYNTAX;
5332 sid.bv_len = ptr - sid.bv_val;
5333 if ( sid.bv_len != STRLENOF( "00" ) ) {
5334 return LDAP_INVALID_SYNTAX;
5337 mod.bv_val = ptr + 1;
5338 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5339 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5340 return LDAP_INVALID_SYNTAX;
5343 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5347 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5348 ptr = lutil_strcopy( ptr, ".000000Z#" );
5349 ptr = lutil_strbvcopy( ptr, &cnt );
5352 for ( i = 0; i < sid.bv_len; i++ ) {
5353 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5356 for ( i = 0; i < mod.bv_len; i++ ) {
5357 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5361 assert( ptr == &bv.bv_val[bv.bv_len] );
5362 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5363 return LDAP_INVALID_SYNTAX;
5366 ber_dupbv_x( normalized, &bv, ctx );
5368 return LDAP_SUCCESS;
5371 /* Normalize a CSN */
5378 struct berval *normalized,
5381 struct berval cnt, sid, mod;
5385 assert( val != NULL );
5386 assert( normalized != NULL );
5388 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5390 if ( BER_BVISEMPTY( val ) ) {
5391 return LDAP_INVALID_SYNTAX;
5394 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5395 /* Openldap <= 2.3 */
5397 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5400 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5403 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5406 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5407 return LDAP_INVALID_SYNTAX;
5410 ptr = ber_bvchr( val, '#' );
5411 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5412 return LDAP_INVALID_SYNTAX;
5415 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5416 return LDAP_INVALID_SYNTAX;
5419 cnt.bv_val = ptr + 1;
5420 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5422 ptr = ber_bvchr( &cnt, '#' );
5423 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5424 return LDAP_INVALID_SYNTAX;
5427 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5428 return LDAP_INVALID_SYNTAX;
5431 sid.bv_val = ptr + 1;
5432 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5434 ptr = ber_bvchr( &sid, '#' );
5435 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5436 return LDAP_INVALID_SYNTAX;
5439 sid.bv_len = ptr - sid.bv_val;
5440 if ( sid.bv_len != STRLENOF( "000" ) ) {
5441 return LDAP_INVALID_SYNTAX;
5444 mod.bv_val = ptr + 1;
5445 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5447 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5448 return LDAP_INVALID_SYNTAX;
5451 ber_dupbv_x( normalized, val, ctx );
5453 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5454 i < normalized->bv_len; i++ )
5456 /* assume it's already validated that's all hex digits */
5457 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5460 return LDAP_SUCCESS;
5470 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5473 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5474 /* slight optimization - does not need the start parameter */
5475 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5480 check_time_syntax (struct berval *val,
5483 struct berval *fraction)
5486 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5487 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5488 * GeneralizedTime supports leap seconds, UTCTime does not.
5490 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5491 static const int mdays[2][12] = {
5492 /* non-leap years */
5493 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5495 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5498 int part, c, c1, c2, tzoffset, leapyear = 0;
5501 e = p + val->bv_len;
5503 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5504 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5506 for (part = start; part < 7 && p < e; part++) {
5508 if (!ASCII_DIGIT(c1)) {
5513 return LDAP_INVALID_SYNTAX;
5516 if (!ASCII_DIGIT(c)) {
5517 return LDAP_INVALID_SYNTAX;
5519 c += c1 * 10 - '0' * 11;
5520 if ((part | 1) == 3) {
5523 return LDAP_INVALID_SYNTAX;
5526 if (c >= ceiling[part]) {
5527 if (! (c == 60 && part == 6 && start == 0))
5528 return LDAP_INVALID_SYNTAX;
5532 if (part < 5 + start) {
5533 return LDAP_INVALID_SYNTAX;
5535 for (; part < 9; part++) {
5539 /* leapyear check for the Gregorian calendar (year>1581) */
5540 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5544 if (parts[3] >= mdays[leapyear][parts[2]]) {
5545 return LDAP_INVALID_SYNTAX;
5549 fraction->bv_val = p;
5550 fraction->bv_len = 0;
5551 if (p < e && (*p == '.' || *p == ',')) {
5553 while (++p < e && ASCII_DIGIT(*p)) {
5556 if (p - fraction->bv_val == 1) {
5557 return LDAP_INVALID_SYNTAX;
5559 for (end_num = p; end_num[-1] == '0'; --end_num) {
5562 c = end_num - fraction->bv_val;
5563 if (c != 1) fraction->bv_len = c;
5569 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5575 return LDAP_INVALID_SYNTAX;
5581 for (part = 7; part < 9 && p < e; part++) {
5583 if (!ASCII_DIGIT(c1)) {
5588 return LDAP_INVALID_SYNTAX;
5591 if (!ASCII_DIGIT(c2)) {
5592 return LDAP_INVALID_SYNTAX;
5594 parts[part] = c1 * 10 + c2 - '0' * 11;
5595 if (parts[part] >= ceiling[part]) {
5596 return LDAP_INVALID_SYNTAX;
5599 if (part < 8 + start) {
5600 return LDAP_INVALID_SYNTAX;
5603 if (tzoffset == '-') {
5604 /* negative offset to UTC, ie west of Greenwich */
5605 parts[4] += parts[7];
5606 parts[5] += parts[8];
5607 /* offset is just hhmm, no seconds */
5608 for (part = 6; --part >= 0; ) {
5612 c = mdays[leapyear][parts[2]];
5614 if (parts[part] >= c) {
5616 return LDAP_INVALID_SYNTAX;
5621 } else if (part != 5) {
5626 /* positive offset to UTC, ie east of Greenwich */
5627 parts[4] -= parts[7];
5628 parts[5] -= parts[8];
5629 for (part = 6; --part >= 0; ) {
5630 if (parts[part] < 0) {
5632 return LDAP_INVALID_SYNTAX;
5637 /* make first arg to % non-negative */
5638 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5643 } else if (part != 5) {
5650 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5653 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5660 struct berval *normalized )
5664 rc = check_time_syntax(val, 1, parts, NULL);
5665 if (rc != LDAP_SUCCESS) {
5669 normalized->bv_val = ch_malloc( 14 );
5670 if ( normalized->bv_val == NULL ) {
5671 return LBER_ERROR_MEMORY;
5674 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5675 parts[1], parts[2] + 1, parts[3] + 1,
5676 parts[4], parts[5], parts[6] );
5677 normalized->bv_len = 13;
5679 return LDAP_SUCCESS;
5689 return check_time_syntax(in, 1, parts, NULL);
5692 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5695 generalizedTimeValidate(
5700 struct berval fraction;
5701 return check_time_syntax(in, 0, parts, &fraction);
5705 generalizedTimeNormalize(
5710 struct berval *normalized,
5715 struct berval fraction;
5717 rc = check_time_syntax(val, 0, parts, &fraction);
5718 if (rc != LDAP_SUCCESS) {
5722 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5723 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5724 if ( BER_BVISNULL( normalized ) ) {
5725 return LBER_ERROR_MEMORY;
5728 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5729 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5730 parts[4], parts[5], parts[6] );
5731 if ( !BER_BVISEMPTY( &fraction ) ) {
5732 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5733 fraction.bv_val, fraction.bv_len );
5734 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5736 strcpy( normalized->bv_val + len-1, "Z" );
5737 normalized->bv_len = len;
5739 return LDAP_SUCCESS;
5743 generalizedTimeOrderingMatch(
5748 struct berval *value,
5749 void *assertedValue )
5751 struct berval *asserted = (struct berval *) assertedValue;
5752 ber_len_t v_len = value->bv_len;
5753 ber_len_t av_len = asserted->bv_len;
5755 /* ignore trailing 'Z' when comparing */
5756 int match = memcmp( value->bv_val, asserted->bv_val,
5757 (v_len < av_len ? v_len : av_len) - 1 );
5758 if ( match == 0 ) match = v_len - av_len;
5760 /* If used in extensible match filter, match if value < asserted */
5761 if ( flags & SLAP_MR_EXT )
5762 match = (match >= 0);
5765 return LDAP_SUCCESS;
5768 /* Index generation function: Ordered index */
5769 int generalizedTimeIndexer(
5774 struct berval *prefix,
5782 BerValue bvtmp; /* 40 bit index */
5784 struct lutil_timet tt;
5786 bvtmp.bv_len = sizeof(tmp);
5788 for( i=0; values[i].bv_val != NULL; i++ ) {
5789 /* just count them */
5792 /* we should have at least one value at this point */
5795 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5797 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5798 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5799 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5800 /* Use 40 bits of time for key */
5801 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5802 lutil_tm2time( &tm, &tt );
5803 tmp[0] = tt.tt_gsec & 0xff;
5804 tmp[4] = tt.tt_sec & 0xff;
5806 tmp[3] = tt.tt_sec & 0xff;
5808 tmp[2] = tt.tt_sec & 0xff;
5810 tmp[1] = tt.tt_sec & 0xff;
5812 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5816 keys[j].bv_val = NULL;
5821 return LDAP_SUCCESS;
5824 /* Index generation function: Ordered index */
5825 int generalizedTimeFilter(
5830 struct berval *prefix,
5831 void * assertedValue,
5837 BerValue bvtmp; /* 40 bit index */
5838 BerValue *value = (BerValue *) assertedValue;
5840 struct lutil_timet tt;
5842 bvtmp.bv_len = sizeof(tmp);
5844 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5845 /* Use 40 bits of time for key */
5846 if ( value->bv_val && value->bv_len >= 10 &&
5847 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5849 lutil_tm2time( &tm, &tt );
5850 tmp[0] = tt.tt_gsec & 0xff;
5851 tmp[4] = tt.tt_sec & 0xff;
5853 tmp[3] = tt.tt_sec & 0xff;
5855 tmp[2] = tt.tt_sec & 0xff;
5857 tmp[1] = tt.tt_sec & 0xff;
5859 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5860 ber_dupbv_x(keys, &bvtmp, ctx );
5861 keys[1].bv_val = NULL;
5869 return LDAP_SUCCESS;
5873 deliveryMethodValidate(
5875 struct berval *val )
5878 #define LENOF(s) (sizeof(s)-1)
5879 struct berval tmp = *val;
5881 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5882 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5883 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5886 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5888 switch( tmp.bv_val[0] ) {
5891 if(( tmp.bv_len >= LENOF("any") ) &&
5892 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5894 tmp.bv_len -= LENOF("any");
5895 tmp.bv_val += LENOF("any");
5898 return LDAP_INVALID_SYNTAX;
5902 if(( tmp.bv_len >= LENOF("mhs") ) &&
5903 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5905 tmp.bv_len -= LENOF("mhs");
5906 tmp.bv_val += LENOF("mhs");
5909 return LDAP_INVALID_SYNTAX;
5913 if(( tmp.bv_len >= LENOF("physical") ) &&
5914 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5916 tmp.bv_len -= LENOF("physical");
5917 tmp.bv_val += LENOF("physical");
5920 return LDAP_INVALID_SYNTAX;
5923 case 'T': /* telex or teletex or telephone */
5924 if(( tmp.bv_len >= LENOF("telex") ) &&
5925 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5927 tmp.bv_len -= LENOF("telex");
5928 tmp.bv_val += LENOF("telex");
5931 if(( tmp.bv_len >= LENOF("teletex") ) &&
5932 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5934 tmp.bv_len -= LENOF("teletex");
5935 tmp.bv_val += LENOF("teletex");
5938 if(( tmp.bv_len >= LENOF("telephone") ) &&
5939 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5941 tmp.bv_len -= LENOF("telephone");
5942 tmp.bv_val += LENOF("telephone");
5945 return LDAP_INVALID_SYNTAX;
5948 case 'G': /* g3fax or g4fax */
5949 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5950 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5951 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5953 tmp.bv_len -= LENOF("g3fax");
5954 tmp.bv_val += LENOF("g3fax");
5957 return LDAP_INVALID_SYNTAX;
5961 if(( tmp.bv_len >= LENOF("ia5") ) &&
5962 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5964 tmp.bv_len -= LENOF("ia5");
5965 tmp.bv_val += LENOF("ia5");
5968 return LDAP_INVALID_SYNTAX;
5972 if(( tmp.bv_len >= LENOF("videotex") ) &&
5973 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5975 tmp.bv_len -= LENOF("videotex");
5976 tmp.bv_val += LENOF("videotex");
5979 return LDAP_INVALID_SYNTAX;
5982 return LDAP_INVALID_SYNTAX;
5985 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5987 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5991 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5995 return LDAP_INVALID_SYNTAX;
5997 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
6006 nisNetgroupTripleValidate(
6008 struct berval *val )
6013 if ( BER_BVISEMPTY( val ) ) {
6014 return LDAP_INVALID_SYNTAX;
6017 p = (char *)val->bv_val;
6018 e = p + val->bv_len;
6020 if ( *p != '(' /*')'*/ ) {
6021 return LDAP_INVALID_SYNTAX;
6024 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
6028 return LDAP_INVALID_SYNTAX;
6031 } else if ( !AD_CHAR( *p ) ) {
6032 return LDAP_INVALID_SYNTAX;
6036 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
6037 return LDAP_INVALID_SYNTAX;
6043 return LDAP_INVALID_SYNTAX;
6046 return LDAP_SUCCESS;
6050 bootParameterValidate(
6052 struct berval *val )
6056 if ( BER_BVISEMPTY( val ) ) {
6057 return LDAP_INVALID_SYNTAX;
6060 p = (char *)val->bv_val;
6061 e = p + val->bv_len;
6064 for (; ( p < e ) && ( *p != '=' ); p++ ) {
6065 if ( !AD_CHAR( *p ) ) {
6066 return LDAP_INVALID_SYNTAX;
6071 return LDAP_INVALID_SYNTAX;
6075 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
6076 if ( !AD_CHAR( *p ) ) {
6077 return LDAP_INVALID_SYNTAX;
6082 return LDAP_INVALID_SYNTAX;
6086 for ( p++; p < e; p++ ) {
6087 if ( !SLAP_PRINTABLE( *p ) ) {
6088 return LDAP_INVALID_SYNTAX;
6092 return LDAP_SUCCESS;
6096 firstComponentNormalize(
6101 struct berval *normalized,
6108 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
6109 ber_dupbv_x( normalized, val, ctx );
6110 return LDAP_SUCCESS;
6113 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
6115 if( ! ( val->bv_val[0] == '(' /*')'*/
6116 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
6117 && ! ( val->bv_val[0] == '{' /*'}'*/
6118 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
6120 return LDAP_INVALID_SYNTAX;
6123 /* trim leading white space */
6125 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
6131 /* grab next word */
6132 comp.bv_val = &val->bv_val[len];
6133 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
6134 for( comp.bv_len = 0;
6135 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
6141 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
6142 rc = numericoidValidate( NULL, &comp );
6143 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
6144 rc = integerValidate( NULL, &comp );
6146 rc = LDAP_INVALID_SYNTAX;
6150 if( rc == LDAP_SUCCESS ) {
6151 ber_dupbv_x( normalized, &comp, ctx );
6157 static char *country_gen_syn[] = {
6158 "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */
6159 "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */
6160 "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */
6164 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6165 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6167 static slap_syntax_defs_rec syntax_defs[] = {
6168 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6169 X_BINARY X_NOT_H_R ")",
6170 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6171 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6172 0, NULL, NULL, NULL},
6173 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6174 0, NULL, NULL, NULL},
6175 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6177 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6178 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6180 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6181 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6182 0, NULL, bitStringValidate, NULL },
6183 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6184 0, NULL, booleanValidate, NULL},
6185 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6186 X_BINARY X_NOT_H_R ")",
6187 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6188 NULL, certificateValidate, NULL},
6189 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6190 X_BINARY X_NOT_H_R ")",
6191 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6192 NULL, certificateListValidate, NULL},
6193 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6194 X_BINARY X_NOT_H_R ")",
6195 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6196 NULL, sequenceValidate, NULL},
6197 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6198 X_BINARY X_NOT_H_R ")",
6199 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6200 NULL, attributeCertificateValidate, NULL},
6201 #if 0 /* need to go __after__ printableString */
6202 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6203 0, "1.3.6.1.4.1.1466.115.121.1.44",
6204 countryStringValidate, NULL},
6206 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6207 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6208 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6209 0, NULL, rdnValidate, rdnPretty},
6210 #ifdef LDAP_COMP_MATCH
6211 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6212 0, NULL, allComponentsValidate, NULL},
6213 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6214 0, NULL, componentFilterValidate, NULL},
6216 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6217 0, NULL, NULL, NULL},
6218 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6219 0, NULL, deliveryMethodValidate, NULL},
6220 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6221 0, NULL, UTF8StringValidate, NULL},
6222 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6223 0, NULL, NULL, NULL},
6224 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6225 0, NULL, NULL, NULL},
6226 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6227 0, NULL, NULL, NULL},
6228 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6229 0, NULL, NULL, NULL},
6230 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6231 0, NULL, NULL, NULL},
6232 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6233 0, NULL, printablesStringValidate, NULL},
6234 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6235 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6236 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6237 0, NULL, generalizedTimeValidate, NULL},
6238 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6239 0, NULL, NULL, NULL},
6240 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6241 0, NULL, IA5StringValidate, NULL},
6242 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6243 0, NULL, integerValidate, NULL},
6244 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6245 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6246 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6247 0, NULL, NULL, NULL},
6248 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6249 0, NULL, NULL, NULL},
6250 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6251 0, NULL, NULL, NULL},
6252 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6253 0, NULL, NULL, NULL},
6254 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6255 0, NULL, NULL, NULL},
6256 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6257 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6258 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6259 0, NULL, NULL, NULL},
6260 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6261 0, NULL, numericStringValidate, NULL},
6262 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6263 0, NULL, NULL, NULL},
6264 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6265 0, NULL, numericoidValidate, NULL},
6266 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6267 0, NULL, IA5StringValidate, NULL},
6268 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6269 0, NULL, blobValidate, NULL},
6270 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6271 0, NULL, postalAddressValidate, NULL},
6272 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6273 0, NULL, NULL, NULL},
6274 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6275 0, NULL, NULL, NULL},
6276 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6277 0, NULL, printableStringValidate, NULL},
6278 /* moved here because now depends on Directory String, IA5 String
6279 * and Printable String */
6280 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6281 0, country_gen_syn, countryStringValidate, NULL},
6282 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6283 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6284 0, NULL, subtreeSpecificationValidate, NULL},
6285 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6286 X_BINARY X_NOT_H_R ")",
6287 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6288 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6289 0, NULL, printableStringValidate, NULL},
6290 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6291 0, NULL, NULL, NULL},
6292 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6293 0, NULL, printablesStringValidate, NULL},
6294 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6295 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6296 0, NULL, utcTimeValidate, NULL},
6298 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6299 0, NULL, NULL, NULL},
6300 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6301 0, NULL, NULL, NULL},
6302 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6303 0, NULL, NULL, NULL},
6304 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6305 0, NULL, NULL, NULL},
6306 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6307 0, NULL, NULL, NULL},
6309 /* RFC 2307 NIS Syntaxes */
6310 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6311 0, NULL, nisNetgroupTripleValidate, NULL},
6312 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6313 0, NULL, bootParameterValidate, NULL},
6315 /* draft-zeilenga-ldap-x509 */
6316 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6317 SLAP_SYNTAX_HIDE, NULL,
6318 serialNumberAndIssuerValidate,
6319 serialNumberAndIssuerPretty},
6320 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6321 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6322 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6323 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6324 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6325 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6326 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6327 SLAP_SYNTAX_HIDE, NULL,
6328 issuerAndThisUpdateValidate,
6329 issuerAndThisUpdatePretty},
6330 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6331 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6332 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6333 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6334 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6335 SLAP_SYNTAX_HIDE, NULL,
6336 serialNumberAndIssuerSerialValidate,
6337 serialNumberAndIssuerSerialPretty},
6338 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6339 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6341 #ifdef SLAPD_AUTHPASSWD
6342 /* needs updating */
6343 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6344 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6347 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6348 0, NULL, UUIDValidate, UUIDPretty},
6350 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6351 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6353 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6354 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6356 /* OpenLDAP Void Syntax */
6357 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6358 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6360 /* FIXME: OID is unused, but not registered yet */
6361 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6362 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6364 {NULL, 0, NULL, NULL, NULL}
6367 char *csnSIDMatchSyntaxes[] = {
6368 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6371 char *certificateExactMatchSyntaxes[] = {
6372 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6375 char *certificateListExactMatchSyntaxes[] = {
6376 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6379 char *attributeCertificateExactMatchSyntaxes[] = {
6380 attributeCertificateSyntaxOID /* attributeCertificate */,
6384 #ifdef LDAP_COMP_MATCH
6385 char *componentFilterMatchSyntaxes[] = {
6386 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6387 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6388 attributeCertificateSyntaxOID /* attributeCertificate */,
6393 char *directoryStringSyntaxes[] = {
6394 "1.3.6.1.4.1.1466.115.121.1.11" /* countryString */,
6395 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6396 "1.3.6.1.4.1.1466.115.121.1.50" /* telephoneNumber */,
6399 char *integerFirstComponentMatchSyntaxes[] = {
6400 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6401 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6404 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6405 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6406 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6407 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6408 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6409 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6410 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6411 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6412 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6417 * Other matching rules in X.520 that we do not use (yet):
6419 * 2.5.13.25 uTCTimeMatch
6420 * 2.5.13.26 uTCTimeOrderingMatch
6421 * 2.5.13.31* directoryStringFirstComponentMatch
6422 * 2.5.13.32* wordMatch
6423 * 2.5.13.33* keywordMatch
6424 * 2.5.13.36+ certificatePairExactMatch
6425 * 2.5.13.37+ certificatePairMatch
6426 * 2.5.13.40+ algorithmIdentifierMatch
6427 * 2.5.13.41* storedPrefixMatch
6428 * 2.5.13.42 attributeCertificateMatch
6429 * 2.5.13.43 readerAndKeyIDMatch
6430 * 2.5.13.44 attributeIntegrityMatch
6432 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6433 * (+) described in draft-zeilenga-ldap-x509
6435 static slap_mrule_defs_rec mrule_defs[] = {
6437 * EQUALITY matching rules must be listed after associated APPROX
6438 * matching rules. So, we list all APPROX matching rules first.
6440 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6441 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6442 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6443 NULL, NULL, directoryStringApproxMatch,
6444 directoryStringApproxIndexer, directoryStringApproxFilter,
6447 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6448 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6449 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6450 NULL, NULL, IA5StringApproxMatch,
6451 IA5StringApproxIndexer, IA5StringApproxFilter,
6455 * Other matching rules
6458 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6460 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6461 NULL, NULL, octetStringMatch,
6462 octetStringIndexer, octetStringFilter,
6465 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6466 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6467 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6468 NULL, dnNormalize, dnMatch,
6469 octetStringIndexer, octetStringFilter,
6472 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6473 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6474 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6475 NULL, dnNormalize, dnRelativeMatch,
6479 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6480 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6481 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6482 NULL, dnNormalize, dnRelativeMatch,
6486 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6487 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6488 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6489 NULL, dnNormalize, dnRelativeMatch,
6493 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6495 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6496 NULL, dnNormalize, dnRelativeMatch,
6500 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6501 "SYNTAX 1.2.36.79672281.1.5.0 )",
6502 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6503 NULL, rdnNormalize, rdnMatch,
6504 octetStringIndexer, octetStringFilter,
6507 #ifdef LDAP_COMP_MATCH
6508 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6509 "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */
6510 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6511 NULL, NULL , componentFilterMatch,
6512 octetStringIndexer, octetStringFilter,
6515 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6516 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6517 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6518 NULL, NULL , allComponentsMatch,
6519 octetStringIndexer, octetStringFilter,
6522 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6523 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6524 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6525 NULL, NULL , directoryComponentsMatch,
6526 octetStringIndexer, octetStringFilter,
6530 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6531 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6532 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6533 NULL, UTF8StringNormalize, octetStringMatch,
6534 octetStringIndexer, octetStringFilter,
6535 directoryStringApproxMatchOID },
6537 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6538 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6539 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6540 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6542 "caseIgnoreMatch" },
6544 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6546 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6547 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6548 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6549 "caseIgnoreMatch" },
6551 {"( 2.5.13.5 NAME 'caseExactMatch' "
6552 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6553 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6554 NULL, UTF8StringNormalize, octetStringMatch,
6555 octetStringIndexer, octetStringFilter,
6556 directoryStringApproxMatchOID },
6558 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6559 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6560 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6561 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6565 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6566 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6567 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6568 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6569 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6572 {"( 2.5.13.8 NAME 'numericStringMatch' "
6573 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6574 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6575 NULL, numericStringNormalize, octetStringMatch,
6576 octetStringIndexer, octetStringFilter,
6579 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6580 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6581 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6582 NULL, numericStringNormalize, octetStringOrderingMatch,
6584 "numericStringMatch" },
6586 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6587 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6588 SLAP_MR_SUBSTR, NULL,
6589 NULL, numericStringNormalize, octetStringSubstringsMatch,
6590 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6591 "numericStringMatch" },
6593 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6594 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */
6595 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6596 NULL, postalAddressNormalize, octetStringMatch,
6597 octetStringIndexer, octetStringFilter,
6600 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6601 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6602 SLAP_MR_SUBSTR, NULL,
6603 NULL, NULL, NULL, NULL, NULL,
6604 "caseIgnoreListMatch" },
6606 {"( 2.5.13.13 NAME 'booleanMatch' "
6607 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6608 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6609 NULL, NULL, booleanMatch,
6610 octetStringIndexer, octetStringFilter,
6613 {"( 2.5.13.14 NAME 'integerMatch' "
6614 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6615 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6616 NULL, NULL, integerMatch,
6617 integerIndexer, integerFilter,
6620 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6621 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6622 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6623 NULL, NULL, integerMatch,
6627 {"( 2.5.13.16 NAME 'bitStringMatch' "
6628 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6629 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6630 NULL, NULL, octetStringMatch,
6631 octetStringIndexer, octetStringFilter,
6634 {"( 2.5.13.17 NAME 'octetStringMatch' "
6635 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6636 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6637 NULL, NULL, octetStringMatch,
6638 octetStringIndexer, octetStringFilter,
6641 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6642 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6643 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6644 NULL, NULL, octetStringOrderingMatch,
6646 "octetStringMatch" },
6648 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6649 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6650 SLAP_MR_SUBSTR, NULL,
6651 NULL, NULL, octetStringSubstringsMatch,
6652 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6653 "octetStringMatch" },
6655 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6656 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6657 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6659 telephoneNumberNormalize, octetStringMatch,
6660 octetStringIndexer, octetStringFilter,
6663 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6664 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6665 SLAP_MR_SUBSTR, NULL,
6666 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6667 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6668 "telephoneNumberMatch" },
6670 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6671 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6672 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6673 NULL, NULL, NULL, NULL, NULL, NULL },
6675 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6676 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */
6677 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6678 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6679 uniqueMemberIndexer, uniqueMemberFilter,
6682 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6683 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6684 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6685 NULL, NULL, NULL, NULL, NULL, NULL },
6687 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6688 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6689 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6690 NULL, generalizedTimeNormalize, octetStringMatch,
6691 generalizedTimeIndexer, generalizedTimeFilter,
6694 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6695 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6696 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6697 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6699 "generalizedTimeMatch" },
6701 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6702 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6703 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6704 integerFirstComponentMatchSyntaxes,
6705 NULL, firstComponentNormalize, integerMatch,
6706 octetStringIndexer, octetStringFilter,
6709 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6710 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */
6711 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6712 objectIdentifierFirstComponentMatchSyntaxes,
6713 NULL, firstComponentNormalize, octetStringMatch,
6714 octetStringIndexer, octetStringFilter,
6717 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6718 "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */
6719 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6720 NULL, certificateExactNormalize, octetStringMatch,
6721 octetStringIndexer, octetStringFilter,
6724 {"( 2.5.13.35 NAME 'certificateMatch' "
6725 "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */
6726 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6727 NULL, NULL, NULL, NULL, NULL,
6730 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6731 "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */
6732 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6733 NULL, certificateListExactNormalize, octetStringMatch,
6734 octetStringIndexer, octetStringFilter,
6737 {"( 2.5.13.39 NAME 'certificateListMatch' "
6738 "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */
6739 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6740 NULL, NULL, NULL, NULL, NULL,
6743 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6744 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6745 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6746 NULL, attributeCertificateExactNormalize, octetStringMatch,
6747 octetStringIndexer, octetStringFilter,
6750 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6751 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6752 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6753 NULL, NULL, NULL, NULL, NULL,
6756 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6757 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6758 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6759 NULL, IA5StringNormalize, octetStringMatch,
6760 octetStringIndexer, octetStringFilter,
6761 IA5StringApproxMatchOID },
6763 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6764 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6765 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6766 NULL, IA5StringNormalize, octetStringMatch,
6767 octetStringIndexer, octetStringFilter,
6768 IA5StringApproxMatchOID },
6770 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6771 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6772 SLAP_MR_SUBSTR, NULL,
6773 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6774 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6775 "caseIgnoreIA5Match" },
6777 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6778 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6779 SLAP_MR_SUBSTR, NULL,
6780 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6781 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6782 "caseExactIA5Match" },
6784 #ifdef SLAPD_AUTHPASSWD
6785 /* needs updating */
6786 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6787 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */
6788 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6789 NULL, NULL, authPasswordMatch,
6794 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6795 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6797 NULL, NULL, integerBitAndMatch,
6801 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6802 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6804 NULL, NULL, integerBitOrMatch,
6808 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6809 "SYNTAX 1.3.6.1.1.16.1 )",
6810 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6811 NULL, UUIDNormalize, octetStringMatch,
6812 octetStringIndexer, octetStringFilter,
6815 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6816 "SYNTAX 1.3.6.1.1.16.1 )",
6817 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6818 NULL, UUIDNormalize, octetStringOrderingMatch,
6819 octetStringIndexer, octetStringFilter,
6822 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6823 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6824 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6825 NULL, csnNormalize, csnMatch,
6826 csnIndexer, csnFilter,
6829 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6830 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6831 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6832 NULL, csnNormalize, csnOrderingMatch,
6836 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6837 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6838 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6839 NULL, csnSidNormalize, octetStringMatch,
6840 octetStringIndexer, octetStringFilter,
6843 /* FIXME: OID is unused, but not registered yet */
6844 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6845 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */
6846 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6847 NULL, authzNormalize, authzMatch,
6851 {NULL, SLAP_MR_NONE, NULL,
6852 NULL, NULL, NULL, NULL, NULL,
6857 slap_schema_init( void )
6862 /* we should only be called once (from main) */
6863 assert( schema_init_done == 0 );
6865 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6866 res = register_syntax( &syntax_defs[i] );
6869 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6870 syntax_defs[i].sd_desc );
6875 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6876 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6877 mrule_defs[i].mrd_compat_syntaxes == NULL )
6880 "slap_schema_init: Ignoring unusable matching rule %s\n",
6881 mrule_defs[i].mrd_desc );
6885 res = register_matching_rule( &mrule_defs[i] );
6889 "slap_schema_init: Error registering matching rule %s\n",
6890 mrule_defs[i].mrd_desc );
6895 res = slap_schema_load();
6896 schema_init_done = 1;
6901 schema_destroy( void )
6910 if( schema_init_done ) {
6911 ldap_pvt_thread_mutex_destroy( &ad_index_mutex );
6912 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6913 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );