1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2016 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] == '"' ) {
3324 x.bv_val += is->bv_len + 1;
3325 x.bv_len -= is->bv_len + 1;
3327 have |= HAVE_ISSUER;
3329 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3331 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3333 /* parse serialNumber */
3334 x.bv_val += STRLENOF("serialNumber");
3335 x.bv_len -= STRLENOF("serialNumber");
3337 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3341 /* eat leading spaces */
3342 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3346 if ( checkNum( &x, sn ) ) {
3347 return LDAP_INVALID_SYNTAX;
3350 x.bv_val += sn->bv_len;
3351 x.bv_len -= sn->bv_len;
3356 return LDAP_INVALID_SYNTAX;
3359 /* eat leading spaces */
3360 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3364 if ( have == HAVE_ALL ) {
3368 if ( x.bv_val[0] != ',' ) {
3369 return LDAP_INVALID_SYNTAX;
3376 /* should have no characters left... */
3377 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3379 if ( numdquotes == 0 ) {
3380 ber_dupbv_x( &ni, is, ctx );
3385 ni.bv_len = is->bv_len - numdquotes;
3386 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3387 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3388 if ( is->bv_val[src] == '"' ) {
3391 ni.bv_val[dst] = is->bv_val[src];
3393 ni.bv_val[dst] = '\0';
3403 serialNumberAndIssuerValidate(
3408 struct berval sn, i;
3410 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3413 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3418 /* validate DN -- doesn't handle double dquote */
3419 rc = dnValidate( NULL, &i );
3421 rc = LDAP_INVALID_SYNTAX;
3424 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3425 slap_sl_free( i.bv_val, NULL );
3428 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3429 in->bv_val, rc, 0 );
3436 serialNumberAndIssuerPretty(
3443 struct berval sn, i, ni = BER_BVNULL;
3446 assert( in != NULL );
3447 assert( out != NULL );
3451 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3454 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3459 rc = dnPretty( syntax, &i, &ni, ctx );
3461 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3462 slap_sl_free( i.bv_val, ctx );
3466 rc = LDAP_INVALID_SYNTAX;
3470 /* make room from sn + "$" */
3471 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3472 + sn.bv_len + ni.bv_len;
3473 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3475 if ( out->bv_val == NULL ) {
3482 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3483 p = lutil_strbvcopy( p, &sn );
3484 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3485 p = lutil_strbvcopy( p, &ni );
3486 p = lutil_strcopy( p, /*{*/ "\" }" );
3488 assert( p == &out->bv_val[out->bv_len] );
3491 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3492 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3494 slap_sl_free( ni.bv_val, ctx );
3496 return LDAP_SUCCESS;
3506 /* Use hex format. '123456789abcdef'H */
3507 unsigned char *ptr, zero = '\0';
3510 ber_len_t i, len, nlen;
3512 assert( in != NULL );
3513 assert( !BER_BVISNULL( in ) );
3514 assert( out != NULL );
3515 assert( !BER_BVISNULL( out ) );
3517 ptr = (unsigned char *)in->bv_val;
3520 /* Check for minimal encodings */
3522 if ( ptr[0] & 0x80 ) {
3523 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3527 } else if ( ptr[0] == 0 ) {
3528 if ( !( ptr[1] & 0x80 ) ) {
3535 } else if ( len == 0 ) {
3536 /* FIXME: this should not be possible,
3537 * since a value of zero would have length 1 */
3542 first = !( ptr[0] & 0xf0U );
3543 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3544 if ( nlen >= out->bv_len ) {
3545 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3551 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3555 for ( ; i < len; i++ ) {
3556 sprintf( sptr, "%02X", ptr[i] );
3563 assert( sptr == &out->bv_val[nlen] );
3570 #define SLAP_SN_BUFLEN (64)
3573 * This routine is called by certificateExactNormalize when
3574 * certificateExactNormalize receives a search string instead of
3575 * a certificate. This routine checks if the search value is valid
3576 * and then returns the normalized value
3579 serialNumberAndIssuerNormalize(
3587 struct berval sn, sn2, sn3, i, ni;
3588 char sbuf2[SLAP_SN_BUFLEN];
3589 char sbuf3[SLAP_SN_BUFLEN];
3593 assert( in != NULL );
3594 assert( out != NULL );
3596 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3599 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3604 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3606 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3607 slap_sl_free( i.bv_val, ctx );
3611 return LDAP_INVALID_SYNTAX;
3614 /* Convert sn to canonical hex */
3616 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3617 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3619 sn2.bv_len = sn.bv_len;
3621 sn3.bv_len = sizeof(sbuf3);
3622 if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
3623 rc = LDAP_INVALID_SYNTAX;
3627 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3628 + sn3.bv_len + ni.bv_len;
3629 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3630 if ( out->bv_val == NULL ) {
3638 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3639 p = lutil_strbvcopy( p, &sn3 );
3640 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3641 p = lutil_strbvcopy( p, &ni );
3642 p = lutil_strcopy( p, /*{*/ "\" }" );
3644 assert( p == &out->bv_val[out->bv_len] );
3647 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3648 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3650 if ( sn2.bv_val != sbuf2 ) {
3651 slap_sl_free( sn2.bv_val, ctx );
3654 if ( sn3.bv_val != sbuf3 ) {
3655 slap_sl_free( sn3.bv_val, ctx );
3658 slap_sl_free( ni.bv_val, ctx );
3664 certificateExactNormalize(
3669 struct berval *normalized,
3672 BerElementBuffer berbuf;
3673 BerElement *ber = (BerElement *)&berbuf;
3677 char serialbuf2[SLAP_SN_BUFLEN];
3678 struct berval sn, sn2 = BER_BVNULL;
3679 struct berval issuer_dn = BER_BVNULL, bvdn;
3681 int rc = LDAP_INVALID_SYNTAX;
3683 assert( val != NULL );
3685 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3686 val->bv_val, val->bv_len, 0 );
3688 if ( BER_BVISEMPTY( val ) ) goto done;
3690 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3691 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3694 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3696 ber_init2( ber, val, LBER_USE_DER );
3697 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3698 tag = ber_skip_tag( ber, &len ); /* Sequence */
3699 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3700 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3701 tag = ber_skip_tag( ber, &len );
3702 tag = ber_get_int( ber, &i ); /* version */
3705 /* NOTE: move the test here from certificateValidate,
3706 * so that we can validate certs with serial longer
3707 * than sizeof(ber_int_t) */
3708 tag = ber_skip_tag( ber, &len ); /* serial */
3710 sn.bv_val = (char *)ber->ber_ptr;
3711 sn2.bv_val = serialbuf2;
3712 sn2.bv_len = sizeof(serialbuf2);
3713 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3714 rc = LDAP_INVALID_SYNTAX;
3717 ber_skip_data( ber, len );
3719 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3720 ber_skip_data( ber, len );
3721 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3723 len = ber_ptrlen( ber );
3724 bvdn.bv_val = val->bv_val + len;
3725 bvdn.bv_len = val->bv_len - len;
3727 rc = dnX509normalize( &bvdn, &issuer_dn );
3728 if ( rc != LDAP_SUCCESS ) goto done;
3731 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3732 + sn2.bv_len + issuer_dn.bv_len;
3733 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3735 p = normalized->bv_val;
3737 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3738 p = lutil_strbvcopy( p, &sn2 );
3739 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3740 p = lutil_strbvcopy( p, &issuer_dn );
3741 p = lutil_strcopy( p, /*{*/ "\" }" );
3746 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3747 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3749 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3750 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3755 /* X.509 PKI certificateList stuff */
3757 checkTime( struct berval *in, struct berval *out )
3761 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3764 assert( in != NULL );
3765 assert( !BER_BVISNULL( in ) );
3766 assert( !BER_BVISEMPTY( in ) );
3768 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3772 if ( out != NULL ) {
3773 assert( !BER_BVISNULL( out ) );
3774 assert( out->bv_len >= sizeof( buf ) );
3775 bv.bv_val = out->bv_val;
3781 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3782 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3785 if ( in->bv_val[i] != 'Z' ) {
3790 if ( i != in->bv_len ) {
3794 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3795 lutil_strncopy( bv.bv_val, in->bv_val, i );
3798 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3799 char *p = bv.bv_val;
3800 if ( in->bv_val[0] < '7' ) {
3801 p = lutil_strcopy( p, "20" );
3804 p = lutil_strcopy( p, "19" );
3806 lutil_strncopy( p, in->bv_val, i );
3813 rc = generalizedTimeValidate( NULL, &bv );
3814 if ( rc == LDAP_SUCCESS && out != NULL ) {
3815 if ( out->bv_len > bv.bv_len ) {
3816 out->bv_val[ bv.bv_len ] = '\0';
3818 out->bv_len = bv.bv_len;
3821 return rc != LDAP_SUCCESS;
3825 issuerAndThisUpdateCheck(
3832 struct berval x = *in;
3833 struct berval ni = BER_BVNULL;
3834 /* Parse GSER format */
3838 HAVE_THISUPDATE = 0x2,
3839 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3843 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3845 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3846 return LDAP_INVALID_SYNTAX;
3850 x.bv_len -= STRLENOF("{}");
3853 /* eat leading spaces */
3854 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3858 /* should be at issuer or thisUpdate */
3859 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3860 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3863 x.bv_val += STRLENOF("issuer");
3864 x.bv_len -= STRLENOF("issuer");
3866 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3870 /* eat leading spaces */
3871 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3875 /* For backward compatibility, this part is optional */
3876 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3877 return LDAP_INVALID_SYNTAX;
3879 x.bv_val += STRLENOF("rdnSequence:");
3880 x.bv_len -= STRLENOF("rdnSequence:");
3882 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3886 is->bv_val = x.bv_val;
3889 for ( ; is->bv_len < x.bv_len; ) {
3890 if ( is->bv_val[is->bv_len] != '"' ) {
3894 if ( is->bv_val[is->bv_len+1] == '"' ) {
3902 x.bv_val += is->bv_len + 1;
3903 x.bv_len -= is->bv_len + 1;
3905 have |= HAVE_ISSUER;
3907 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3909 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3911 /* parse thisUpdate */
3912 x.bv_val += STRLENOF("thisUpdate");
3913 x.bv_len -= STRLENOF("thisUpdate");
3915 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3919 /* eat leading spaces */
3920 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3924 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3928 tu->bv_val = x.bv_val;
3931 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3932 if ( tu->bv_val[tu->bv_len] == '"' ) {
3936 x.bv_val += tu->bv_len + 1;
3937 x.bv_len -= tu->bv_len + 1;
3939 have |= HAVE_THISUPDATE;
3942 return LDAP_INVALID_SYNTAX;
3945 /* eat leading spaces */
3946 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3950 if ( have == HAVE_ALL ) {
3954 if ( x.bv_val[0] != ',' ) {
3955 return LDAP_INVALID_SYNTAX;
3962 /* should have no characters left... */
3963 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3965 if ( numdquotes == 0 ) {
3966 ber_dupbv_x( &ni, is, ctx );
3971 ni.bv_len = is->bv_len - numdquotes;
3972 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3973 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3974 if ( is->bv_val[src] == '"' ) {
3977 ni.bv_val[dst] = is->bv_val[src];
3979 ni.bv_val[dst] = '\0';
3988 issuerAndThisUpdateValidate(
3993 struct berval i, tu;
3995 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3998 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
4003 /* validate DN -- doesn't handle double dquote */
4004 rc = dnValidate( NULL, &i );
4006 rc = LDAP_INVALID_SYNTAX;
4008 } else if ( checkTime( &tu, NULL ) ) {
4009 rc = LDAP_INVALID_SYNTAX;
4012 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4013 slap_sl_free( i.bv_val, NULL );
4016 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
4017 in->bv_val, rc, 0 );
4024 issuerAndThisUpdatePretty(
4031 struct berval i, tu, ni = BER_BVNULL;
4034 assert( in != NULL );
4035 assert( out != NULL );
4039 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
4042 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4047 rc = dnPretty( syntax, &i, &ni, ctx );
4049 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4050 slap_sl_free( i.bv_val, ctx );
4053 if ( rc || checkTime( &tu, NULL ) ) {
4054 rc = LDAP_INVALID_SYNTAX;
4059 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
4060 + ni.bv_len + tu.bv_len;
4061 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4063 if ( out->bv_val == NULL ) {
4070 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4071 p = lutil_strbvcopy( p, &ni );
4072 p = lutil_strcopy( p, "\", thisUpdate \"" );
4073 p = lutil_strbvcopy( p, &tu );
4074 p = lutil_strcopy( p, /*{*/ "\" }" );
4076 assert( p == &out->bv_val[out->bv_len] );
4079 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
4080 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4082 slap_sl_free( ni.bv_val, ctx );
4088 issuerAndThisUpdateNormalize(
4096 struct berval i, ni, tu, tu2;
4097 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4101 assert( in != NULL );
4102 assert( out != NULL );
4104 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
4107 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4112 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4114 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4115 slap_sl_free( i.bv_val, ctx );
4119 tu2.bv_len = sizeof( sbuf );
4120 if ( rc || checkTime( &tu, &tu2 ) ) {
4121 return LDAP_INVALID_SYNTAX;
4124 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4125 + ni.bv_len + tu2.bv_len;
4126 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4128 if ( out->bv_val == NULL ) {
4136 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4137 p = lutil_strbvcopy( p, &ni );
4138 p = lutil_strcopy( p, "\", thisUpdate \"" );
4139 p = lutil_strbvcopy( p, &tu2 );
4140 p = lutil_strcopy( p, /*{*/ "\" }" );
4142 assert( p == &out->bv_val[out->bv_len] );
4145 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4146 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4148 slap_sl_free( ni.bv_val, ctx );
4154 certificateListExactNormalize(
4159 struct berval *normalized,
4162 BerElementBuffer berbuf;
4163 BerElement *ber = (BerElement *)&berbuf;
4167 struct berval issuer_dn = BER_BVNULL, bvdn,
4169 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4170 int rc = LDAP_INVALID_SYNTAX;
4172 assert( val != NULL );
4174 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4175 val->bv_val, val->bv_len, 0 );
4177 if ( BER_BVISEMPTY( val ) ) goto done;
4179 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4180 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4183 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4185 ber_init2( ber, val, LBER_USE_DER );
4186 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4187 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4188 tag = ber_skip_tag( ber, &len ); /* Sequence */
4189 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4190 tag = ber_peek_tag( ber, &len );
4191 /* Optional version */
4192 if ( tag == LBER_INTEGER ) {
4193 tag = ber_get_int( ber, &version );
4194 assert( tag == LBER_INTEGER );
4195 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4197 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4198 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4199 ber_skip_data( ber, len );
4201 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4202 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4203 len = ber_ptrlen( ber );
4204 bvdn.bv_val = val->bv_val + len;
4205 bvdn.bv_len = val->bv_len - len;
4206 tag = ber_skip_tag( ber, &len );
4207 ber_skip_data( ber, len );
4209 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4210 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4211 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4212 bvtu.bv_val = (char *)ber->ber_ptr;
4215 rc = dnX509normalize( &bvdn, &issuer_dn );
4216 if ( rc != LDAP_SUCCESS ) goto done;
4218 thisUpdate.bv_val = tubuf;
4219 thisUpdate.bv_len = sizeof(tubuf);
4220 if ( checkTime( &bvtu, &thisUpdate ) ) {
4221 rc = LDAP_INVALID_SYNTAX;
4225 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4226 + issuer_dn.bv_len + thisUpdate.bv_len;
4227 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4229 p = normalized->bv_val;
4231 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4232 p = lutil_strbvcopy( p, &issuer_dn );
4233 p = lutil_strcopy( p, "\", thisUpdate \"" );
4234 p = lutil_strbvcopy( p, &thisUpdate );
4235 p = lutil_strcopy( p, /*{*/ "\" }" );
4240 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4241 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4243 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4248 /* X.509 PMI serialNumberAndIssuerSerialCheck
4250 AttributeCertificateExactAssertion ::= SEQUENCE {
4251 serialNumber CertificateSerialNumber,
4252 issuer AttCertIssuer }
4254 CertificateSerialNumber ::= INTEGER
4256 AttCertIssuer ::= [0] SEQUENCE {
4257 issuerName GeneralNames OPTIONAL,
4258 baseCertificateID [0] IssuerSerial OPTIONAL,
4259 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4260 -- At least one component shall be present
4262 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4264 GeneralName ::= CHOICE {
4265 otherName [0] INSTANCE OF OTHER-NAME,
4266 rfc822Name [1] IA5String,
4267 dNSName [2] IA5String,
4268 x400Address [3] ORAddress,
4269 directoryName [4] Name,
4270 ediPartyName [5] EDIPartyName,
4271 uniformResourceIdentifier [6] IA5String,
4272 iPAddress [7] OCTET STRING,
4273 registeredID [8] OBJECT IDENTIFIER }
4275 IssuerSerial ::= SEQUENCE {
4276 issuer GeneralNames,
4277 serial CertificateSerialNumber,
4278 issuerUID UniqueIdentifier OPTIONAL }
4280 ObjectDigestInfo ::= SEQUENCE {
4281 digestedObjectType ENUMERATED {
4284 otherObjectTypes (2) },
4285 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4286 digestAlgorithm AlgorithmIdentifier,
4287 objectDigest BIT STRING }
4289 * The way I interpret it, an assertion should look like
4291 { serialNumber 'dd'H,
4292 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4293 baseCertificateID { serial '1d'H,
4294 issuer { directoryName:rdnSequence:"cn=zzz" },
4295 issuerUID <value> -- optional
4297 objectDigestInfo { ... } -- optional
4301 * with issuerName, baseCertificateID and objectDigestInfo optional,
4302 * at least one present; the way it's currently implemented, it is
4304 { serialNumber 'dd'H,
4305 issuer { baseCertificateID { serial '1d'H,
4306 issuer { directoryName:rdnSequence:"cn=zzz" }
4311 * with all the above parts mandatory.
4314 serialNumberAndIssuerSerialCheck(
4318 struct berval *i_sn, /* contain serial of baseCertificateID */
4321 /* Parse GSER format */
4326 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4327 } have = HAVE_NONE, have2 = HAVE_NONE;
4329 struct berval x = *in;
4332 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4335 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4342 /* eat leading spaces */
4343 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4347 /* should be at issuer or serialNumber NamedValue */
4348 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4349 if ( have & HAVE_ISSUER ) {
4350 return LDAP_INVALID_SYNTAX;
4353 /* parse IssuerSerial */
4354 x.bv_val += STRLENOF("issuer");
4355 x.bv_len -= STRLENOF("issuer");
4357 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4361 /* eat leading spaces */
4362 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4366 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4370 /* eat leading spaces */
4371 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4375 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4376 return LDAP_INVALID_SYNTAX;
4378 x.bv_val += STRLENOF("baseCertificateID ");
4379 x.bv_len -= STRLENOF("baseCertificateID ");
4381 /* eat leading spaces */
4382 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4386 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4391 /* eat leading spaces */
4392 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4396 /* parse issuer of baseCertificateID */
4397 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4398 if ( have2 & HAVE_ISSUER ) {
4399 return LDAP_INVALID_SYNTAX;
4402 x.bv_val += STRLENOF("issuer ");
4403 x.bv_len -= STRLENOF("issuer ");
4405 /* eat leading spaces */
4406 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4410 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4414 /* eat leading spaces */
4415 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4419 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4420 return LDAP_INVALID_SYNTAX;
4422 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4423 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4425 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4429 is->bv_val = x.bv_val;
4432 for ( ; is->bv_len < x.bv_len; ) {
4433 if ( is->bv_val[is->bv_len] != '"' ) {
4437 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4445 x.bv_val += is->bv_len + 1;
4446 x.bv_len -= is->bv_len + 1;
4448 /* eat leading spaces */
4449 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4453 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4457 have2 |= HAVE_ISSUER;
4459 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4460 if ( have2 & HAVE_SN ) {
4461 return LDAP_INVALID_SYNTAX;
4464 x.bv_val += STRLENOF("serial ");
4465 x.bv_len -= STRLENOF("serial ");
4467 /* eat leading spaces */
4468 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4472 if ( checkNum( &x, i_sn ) ) {
4473 return LDAP_INVALID_SYNTAX;
4476 x.bv_val += i_sn->bv_len;
4477 x.bv_len -= i_sn->bv_len;
4482 return LDAP_INVALID_SYNTAX;
4485 /* eat leading spaces */
4486 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4490 if ( have2 == HAVE_ALL ) {
4494 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4499 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4503 /* eat leading spaces */
4504 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4508 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4512 have |= HAVE_ISSUER;
4514 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4515 if ( have & HAVE_SN ) {
4516 return LDAP_INVALID_SYNTAX;
4519 /* parse serialNumber */
4520 x.bv_val += STRLENOF("serialNumber");
4521 x.bv_len -= STRLENOF("serialNumber");
4523 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4527 /* eat leading spaces */
4528 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4532 if ( checkNum( &x, sn ) ) {
4533 return LDAP_INVALID_SYNTAX;
4536 x.bv_val += sn->bv_len;
4537 x.bv_len -= sn->bv_len;
4542 return LDAP_INVALID_SYNTAX;
4546 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4550 if ( have == HAVE_ALL ) {
4554 if ( x.bv_val[0] != ',' ) {
4555 return LDAP_INVALID_SYNTAX;
4561 /* should have no characters left... */
4562 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4564 if ( numdquotes == 0 ) {
4565 ber_dupbv_x( &ni, is, ctx );
4570 ni.bv_len = is->bv_len - numdquotes;
4571 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4572 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4573 if ( is->bv_val[src] == '"' ) {
4576 ni.bv_val[dst] = is->bv_val[src];
4578 ni.bv_val[dst] = '\0';
4583 /* need to handle double dquotes here */
4587 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4589 serialNumberAndIssuerSerialValidate(
4594 struct berval sn, i, i_sn;
4596 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4599 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4604 /* validate DN -- doesn't handle double dquote */
4605 rc = dnValidate( NULL, &i );
4607 rc = LDAP_INVALID_SYNTAX;
4610 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4611 slap_sl_free( i.bv_val, NULL );
4615 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4616 in->bv_val, rc, 0 );
4621 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4623 serialNumberAndIssuerSerialPretty(
4629 struct berval sn, i, i_sn, ni = BER_BVNULL;
4633 assert( in != NULL );
4634 assert( out != NULL );
4636 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4639 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4644 rc = dnPretty( syntax, &i, &ni, ctx );
4646 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4647 slap_sl_free( i.bv_val, ctx );
4651 rc = LDAP_INVALID_SYNTAX;
4655 /* make room from sn + "$" */
4656 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4657 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4658 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4660 if ( out->bv_val == NULL ) {
4667 p = lutil_strcopy( p, "{ serialNumber " );
4668 p = lutil_strbvcopy( p, &sn );
4669 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4670 p = lutil_strbvcopy( p, &ni );
4671 p = lutil_strcopy( p, "\" }, serial " );
4672 p = lutil_strbvcopy( p, &i_sn );
4673 p = lutil_strcopy( p, " } } }" );
4675 assert( p == &out->bv_val[out->bv_len] );
4678 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4679 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4681 slap_sl_free( ni.bv_val, ctx );
4686 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4688 * This routine is called by attributeCertificateExactNormalize
4689 * when attributeCertificateExactNormalize receives a search
4690 * string instead of a attribute certificate. This routine
4691 * checks if the search value is valid and then returns the
4695 serialNumberAndIssuerSerialNormalize(
4703 struct berval i, ni = BER_BVNULL,
4704 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4705 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4706 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4707 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4711 assert( in != NULL );
4712 assert( out != NULL );
4714 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4717 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4722 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4724 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4725 slap_sl_free( i.bv_val, ctx );
4729 rc = LDAP_INVALID_SYNTAX;
4733 /* Convert sn to canonical hex */
4735 sn2.bv_len = sn.bv_len;
4736 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4737 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4739 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4740 rc = LDAP_INVALID_SYNTAX;
4744 /* Convert i_sn to canonical hex */
4745 i_sn2.bv_val = i_sbuf2;
4746 i_sn2.bv_len = i_sn.bv_len;
4747 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4748 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4750 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4751 rc = LDAP_INVALID_SYNTAX;
4756 sn3.bv_len = sizeof(sbuf3);
4757 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4758 rc = LDAP_INVALID_SYNTAX;
4762 i_sn3.bv_val = i_sbuf3;
4763 i_sn3.bv_len = sizeof(i_sbuf3);
4764 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4765 rc = LDAP_INVALID_SYNTAX;
4769 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4770 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4771 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4773 if ( out->bv_val == NULL ) {
4781 p = lutil_strcopy( p, "{ serialNumber " );
4782 p = lutil_strbvcopy( p, &sn3 );
4783 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4784 p = lutil_strbvcopy( p, &ni );
4785 p = lutil_strcopy( p, "\" }, serial " );
4786 p = lutil_strbvcopy( p, &i_sn3 );
4787 p = lutil_strcopy( p, " } } }" );
4789 assert( p == &out->bv_val[out->bv_len] );
4792 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4793 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4795 if ( sn2.bv_val != sbuf2 ) {
4796 slap_sl_free( sn2.bv_val, ctx );
4799 if ( i_sn2.bv_val != i_sbuf2 ) {
4800 slap_sl_free( i_sn2.bv_val, ctx );
4803 if ( sn3.bv_val != sbuf3 ) {
4804 slap_sl_free( sn3.bv_val, ctx );
4807 if ( i_sn3.bv_val != i_sbuf3 ) {
4808 slap_sl_free( i_sn3.bv_val, ctx );
4811 slap_sl_free( ni.bv_val, ctx );
4816 /* X.509 PMI attributeCertificateExactNormalize */
4818 attributeCertificateExactNormalize(
4823 struct berval *normalized,
4826 BerElementBuffer berbuf;
4827 BerElement *ber = (BerElement *)&berbuf;
4830 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4831 struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
4832 struct berval issuer_dn = BER_BVNULL, bvdn;
4834 int rc = LDAP_INVALID_SYNTAX;
4836 if ( BER_BVISEMPTY( val ) ) {
4840 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4841 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4844 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4846 ber_init2( ber, val, LBER_USE_DER );
4847 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4848 tag = ber_skip_tag( ber, &len ); /* Sequence */
4849 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4850 ber_skip_data( ber, len );
4851 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4852 ber_skip_data( ber, len );
4855 tag = ber_skip_tag( ber, &len ); /* Sequence */
4856 /* issuerName (GeneralNames sequence; optional)? */
4857 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4858 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4859 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4860 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4861 return LDAP_INVALID_SYNTAX;
4863 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4864 len = ber_ptrlen( ber );
4865 bvdn.bv_val = val->bv_val + len;
4866 bvdn.bv_len = val->bv_len - len;
4867 rc = dnX509normalize( &bvdn, &issuer_dn );
4868 if ( rc != LDAP_SUCCESS ) goto done;
4870 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4871 ber_skip_data( ber, len );
4872 tag = ber_skip_tag( ber, &len ); /* serial number */
4873 if ( tag != LBER_INTEGER ) {
4874 rc = LDAP_INVALID_SYNTAX;
4877 i_sn.bv_val = (char *)ber->ber_ptr;
4879 i_sn2.bv_val = issuer_serialbuf;
4880 i_sn2.bv_len = sizeof(issuer_serialbuf);
4881 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4882 rc = LDAP_INVALID_SYNTAX;
4885 ber_skip_data( ber, len );
4887 /* issuerUID (bitstring; optional)? */
4888 /* objectDigestInfo (sequence; optional)? */
4890 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4891 ber_skip_data( ber, len );
4892 tag = ber_skip_tag( ber, &len ); /* serial number */
4893 if ( tag != LBER_INTEGER ) {
4894 rc = LDAP_INVALID_SYNTAX;
4897 sn.bv_val = (char *)ber->ber_ptr;
4899 sn2.bv_val = serialbuf;
4900 sn2.bv_len = sizeof(serialbuf);
4901 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4902 rc = LDAP_INVALID_SYNTAX;
4905 ber_skip_data( ber, len );
4907 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4908 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4909 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4911 p = normalized->bv_val;
4913 p = lutil_strcopy( p, "{ serialNumber " );
4914 p = lutil_strbvcopy( p, &sn2 );
4915 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4916 p = lutil_strbvcopy( p, &issuer_dn );
4917 p = lutil_strcopy( p, "\" }, serial " );
4918 p = lutil_strbvcopy( p, &i_sn2 );
4919 p = lutil_strcopy( p, " } } }" );
4921 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4922 normalized->bv_val, NULL, NULL );
4927 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4928 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4929 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4942 assert( in != NULL );
4943 assert( !BER_BVISNULL( in ) );
4945 for ( i = 0; i < in->bv_len; i++ ) {
4946 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4947 return LDAP_INVALID_SYNTAX;
4951 return LDAP_SUCCESS;
4954 /* Normalize a SID as used inside a CSN:
4955 * three-digit numeric string */
4962 struct berval *normalized,
4967 assert( val != NULL );
4968 assert( normalized != NULL );
4970 ber_dupbv_x( normalized, val, ctx );
4972 for ( i = 0; i < normalized->bv_len; i++ ) {
4973 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4974 ber_memfree_x( normalized->bv_val, ctx );
4975 BER_BVZERO( normalized );
4976 return LDAP_INVALID_SYNTAX;
4979 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4982 return LDAP_SUCCESS;
4990 assert( in != NULL );
4991 assert( !BER_BVISNULL( in ) );
4993 if ( in->bv_len != 3 ) {
4994 return LDAP_INVALID_SYNTAX;
4997 return hexValidate( NULL, in );
5000 /* Normalize a SID as used inside a CSN:
5001 * three-digit numeric string */
5008 struct berval *normalized,
5011 if ( val->bv_len != 3 ) {
5012 return LDAP_INVALID_SYNTAX;
5015 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
5025 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5028 /* Normalize a SID as used inside a CSN, either as-is
5029 * (assertion value) or extracted from the CSN
5030 * (attribute value) */
5037 struct berval *normalized,
5045 if ( BER_BVISEMPTY( val ) ) {
5046 return LDAP_INVALID_SYNTAX;
5049 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
5050 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
5053 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
5055 ptr = ber_bvchr( val, '#' );
5056 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5057 return LDAP_INVALID_SYNTAX;
5060 bv.bv_val = ptr + 1;
5061 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5063 ptr = ber_bvchr( &bv, '#' );
5064 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5065 return LDAP_INVALID_SYNTAX;
5068 bv.bv_val = ptr + 1;
5069 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5071 ptr = ber_bvchr( &bv, '#' );
5072 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5073 return LDAP_INVALID_SYNTAX;
5076 bv.bv_len = ptr - bv.bv_val;
5078 if ( bv.bv_len == 2 ) {
5079 /* OpenLDAP 2.3 SID */
5081 buf[ 1 ] = bv.bv_val[ 0 ];
5082 buf[ 2 ] = bv.bv_val[ 1 ];
5089 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
5101 assert( in != NULL );
5102 assert( !BER_BVISNULL( in ) );
5104 if ( BER_BVISEMPTY( in ) ) {
5105 return LDAP_INVALID_SYNTAX;
5110 ptr = ber_bvchr( &bv, '#' );
5111 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
5112 return LDAP_INVALID_SYNTAX;
5115 bv.bv_len = ptr - bv.bv_val;
5116 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
5117 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
5119 return LDAP_INVALID_SYNTAX;
5122 rc = generalizedTimeValidate( NULL, &bv );
5123 if ( rc != LDAP_SUCCESS ) {
5127 bv.bv_val = ptr + 1;
5128 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5130 ptr = ber_bvchr( &bv, '#' );
5131 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5132 return LDAP_INVALID_SYNTAX;
5135 bv.bv_len = ptr - bv.bv_val;
5136 if ( bv.bv_len != 6 ) {
5137 return LDAP_INVALID_SYNTAX;
5140 rc = hexValidate( NULL, &bv );
5141 if ( rc != LDAP_SUCCESS ) {
5145 bv.bv_val = ptr + 1;
5146 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5148 ptr = ber_bvchr( &bv, '#' );
5149 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5150 return LDAP_INVALID_SYNTAX;
5153 bv.bv_len = ptr - bv.bv_val;
5154 if ( bv.bv_len == 2 ) {
5155 /* tolerate old 2-digit replica-id */
5156 rc = hexValidate( NULL, &bv );
5159 rc = sidValidate( NULL, &bv );
5161 if ( rc != LDAP_SUCCESS ) {
5165 bv.bv_val = ptr + 1;
5166 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5168 if ( bv.bv_len != 6 ) {
5169 return LDAP_INVALID_SYNTAX;
5172 return hexValidate( NULL, &bv );
5175 /* Normalize a CSN in OpenLDAP 2.1 format */
5182 struct berval *normalized,
5185 struct berval gt, cnt, sid, mod;
5187 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5191 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5192 assert( !BER_BVISEMPTY( val ) );
5196 ptr = ber_bvchr( >, '#' );
5197 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5198 return LDAP_INVALID_SYNTAX;
5201 gt.bv_len = ptr - gt.bv_val;
5202 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5203 return LDAP_INVALID_SYNTAX;
5206 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5207 return LDAP_INVALID_SYNTAX;
5210 cnt.bv_val = ptr + 1;
5211 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5213 ptr = ber_bvchr( &cnt, '#' );
5214 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5215 return LDAP_INVALID_SYNTAX;
5218 cnt.bv_len = ptr - cnt.bv_val;
5219 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5220 return LDAP_INVALID_SYNTAX;
5223 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5224 return LDAP_INVALID_SYNTAX;
5227 cnt.bv_val += STRLENOF( "0x" );
5228 cnt.bv_len -= STRLENOF( "0x" );
5230 sid.bv_val = ptr + 1;
5231 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5233 ptr = ber_bvchr( &sid, '#' );
5234 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5235 return LDAP_INVALID_SYNTAX;
5238 sid.bv_len = ptr - sid.bv_val;
5239 if ( sid.bv_len != STRLENOF( "0" ) ) {
5240 return LDAP_INVALID_SYNTAX;
5243 mod.bv_val = ptr + 1;
5244 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5245 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5246 return LDAP_INVALID_SYNTAX;
5249 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5253 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5254 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5256 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5258 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5259 ptr = lutil_strbvcopy( ptr, &cnt );
5263 *ptr++ = sid.bv_val[ 0 ];
5267 for ( i = 0; i < mod.bv_len; i++ ) {
5268 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5272 assert( ptr == &bv.bv_val[bv.bv_len] );
5274 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5275 return LDAP_INVALID_SYNTAX;
5278 ber_dupbv_x( normalized, &bv, ctx );
5280 return LDAP_SUCCESS;
5283 /* Normalize a CSN in OpenLDAP 2.3 format */
5290 struct berval *normalized,
5293 struct berval gt, cnt, sid, mod;
5295 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5299 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5300 assert( !BER_BVISEMPTY( val ) );
5304 ptr = ber_bvchr( >, '#' );
5305 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5306 return LDAP_INVALID_SYNTAX;
5309 gt.bv_len = ptr - gt.bv_val;
5310 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5311 return LDAP_INVALID_SYNTAX;
5314 cnt.bv_val = ptr + 1;
5315 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5317 ptr = ber_bvchr( &cnt, '#' );
5318 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5319 return LDAP_INVALID_SYNTAX;
5322 cnt.bv_len = ptr - cnt.bv_val;
5323 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5324 return LDAP_INVALID_SYNTAX;
5327 sid.bv_val = ptr + 1;
5328 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5330 ptr = ber_bvchr( &sid, '#' );
5331 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5332 return LDAP_INVALID_SYNTAX;
5335 sid.bv_len = ptr - sid.bv_val;
5336 if ( sid.bv_len != STRLENOF( "00" ) ) {
5337 return LDAP_INVALID_SYNTAX;
5340 mod.bv_val = ptr + 1;
5341 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5342 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5343 return LDAP_INVALID_SYNTAX;
5346 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5350 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5351 ptr = lutil_strcopy( ptr, ".000000Z#" );
5352 ptr = lutil_strbvcopy( ptr, &cnt );
5355 for ( i = 0; i < sid.bv_len; i++ ) {
5356 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5359 for ( i = 0; i < mod.bv_len; i++ ) {
5360 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5364 assert( ptr == &bv.bv_val[bv.bv_len] );
5365 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5366 return LDAP_INVALID_SYNTAX;
5369 ber_dupbv_x( normalized, &bv, ctx );
5371 return LDAP_SUCCESS;
5374 /* Normalize a CSN */
5381 struct berval *normalized,
5384 struct berval cnt, sid, mod;
5388 assert( val != NULL );
5389 assert( normalized != NULL );
5391 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5393 if ( BER_BVISEMPTY( val ) ) {
5394 return LDAP_INVALID_SYNTAX;
5397 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5398 /* Openldap <= 2.3 */
5400 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5403 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5406 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5409 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5410 return LDAP_INVALID_SYNTAX;
5413 ptr = ber_bvchr( val, '#' );
5414 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5415 return LDAP_INVALID_SYNTAX;
5418 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5419 return LDAP_INVALID_SYNTAX;
5422 cnt.bv_val = ptr + 1;
5423 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5425 ptr = ber_bvchr( &cnt, '#' );
5426 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5427 return LDAP_INVALID_SYNTAX;
5430 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5431 return LDAP_INVALID_SYNTAX;
5434 sid.bv_val = ptr + 1;
5435 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5437 ptr = ber_bvchr( &sid, '#' );
5438 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5439 return LDAP_INVALID_SYNTAX;
5442 sid.bv_len = ptr - sid.bv_val;
5443 if ( sid.bv_len != STRLENOF( "000" ) ) {
5444 return LDAP_INVALID_SYNTAX;
5447 mod.bv_val = ptr + 1;
5448 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5450 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5451 return LDAP_INVALID_SYNTAX;
5454 ber_dupbv_x( normalized, val, ctx );
5456 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5457 i < normalized->bv_len; i++ )
5459 /* assume it's already validated that's all hex digits */
5460 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5463 return LDAP_SUCCESS;
5473 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5476 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5477 /* slight optimization - does not need the start parameter */
5478 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5483 check_time_syntax (struct berval *val,
5486 struct berval *fraction)
5489 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5490 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5491 * GeneralizedTime supports leap seconds, UTCTime does not.
5493 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5494 static const int mdays[2][12] = {
5495 /* non-leap years */
5496 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5498 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5501 int part, c, c1, c2, tzoffset, leapyear = 0;
5504 e = p + val->bv_len;
5506 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5507 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5509 for (part = start; part < 7 && p < e; part++) {
5511 if (!ASCII_DIGIT(c1)) {
5516 return LDAP_INVALID_SYNTAX;
5519 if (!ASCII_DIGIT(c)) {
5520 return LDAP_INVALID_SYNTAX;
5522 c += c1 * 10 - '0' * 11;
5523 if ((part | 1) == 3) {
5526 return LDAP_INVALID_SYNTAX;
5529 if (c >= ceiling[part]) {
5530 if (! (c == 60 && part == 6 && start == 0))
5531 return LDAP_INVALID_SYNTAX;
5535 if (part < 5 + start) {
5536 return LDAP_INVALID_SYNTAX;
5538 for (; part < 9; part++) {
5542 /* leapyear check for the Gregorian calendar (year>1581) */
5543 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5547 if (parts[3] >= mdays[leapyear][parts[2]]) {
5548 return LDAP_INVALID_SYNTAX;
5552 fraction->bv_val = p;
5553 fraction->bv_len = 0;
5554 if (p < e && (*p == '.' || *p == ',')) {
5556 while (++p < e && ASCII_DIGIT(*p)) {
5559 if (p - fraction->bv_val == 1) {
5560 return LDAP_INVALID_SYNTAX;
5562 for (end_num = p; end_num[-1] == '0'; --end_num) {
5565 c = end_num - fraction->bv_val;
5566 if (c != 1) fraction->bv_len = c;
5572 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5578 return LDAP_INVALID_SYNTAX;
5584 for (part = 7; part < 9 && p < e; part++) {
5586 if (!ASCII_DIGIT(c1)) {
5591 return LDAP_INVALID_SYNTAX;
5594 if (!ASCII_DIGIT(c2)) {
5595 return LDAP_INVALID_SYNTAX;
5597 parts[part] = c1 * 10 + c2 - '0' * 11;
5598 if (parts[part] >= ceiling[part]) {
5599 return LDAP_INVALID_SYNTAX;
5602 if (part < 8 + start) {
5603 return LDAP_INVALID_SYNTAX;
5606 if (tzoffset == '-') {
5607 /* negative offset to UTC, ie west of Greenwich */
5608 parts[4] += parts[7];
5609 parts[5] += parts[8];
5610 /* offset is just hhmm, no seconds */
5611 for (part = 6; --part >= 0; ) {
5615 c = mdays[leapyear][parts[2]];
5617 if (parts[part] >= c) {
5619 return LDAP_INVALID_SYNTAX;
5624 } else if (part != 5) {
5629 /* positive offset to UTC, ie east of Greenwich */
5630 parts[4] -= parts[7];
5631 parts[5] -= parts[8];
5632 for (part = 6; --part >= 0; ) {
5633 if (parts[part] < 0) {
5635 return LDAP_INVALID_SYNTAX;
5640 /* make first arg to % non-negative */
5641 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5646 } else if (part != 5) {
5653 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5656 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5663 struct berval *normalized )
5667 rc = check_time_syntax(val, 1, parts, NULL);
5668 if (rc != LDAP_SUCCESS) {
5672 normalized->bv_val = ch_malloc( 14 );
5673 if ( normalized->bv_val == NULL ) {
5674 return LBER_ERROR_MEMORY;
5677 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5678 parts[1], parts[2] + 1, parts[3] + 1,
5679 parts[4], parts[5], parts[6] );
5680 normalized->bv_len = 13;
5682 return LDAP_SUCCESS;
5692 return check_time_syntax(in, 1, parts, NULL);
5695 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5698 generalizedTimeValidate(
5703 struct berval fraction;
5704 return check_time_syntax(in, 0, parts, &fraction);
5708 generalizedTimeNormalize(
5713 struct berval *normalized,
5718 struct berval fraction;
5720 rc = check_time_syntax(val, 0, parts, &fraction);
5721 if (rc != LDAP_SUCCESS) {
5725 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5726 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5727 if ( BER_BVISNULL( normalized ) ) {
5728 return LBER_ERROR_MEMORY;
5731 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5732 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5733 parts[4], parts[5], parts[6] );
5734 if ( !BER_BVISEMPTY( &fraction ) ) {
5735 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5736 fraction.bv_val, fraction.bv_len );
5737 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5739 strcpy( normalized->bv_val + len-1, "Z" );
5740 normalized->bv_len = len;
5742 return LDAP_SUCCESS;
5746 generalizedTimeOrderingMatch(
5751 struct berval *value,
5752 void *assertedValue )
5754 struct berval *asserted = (struct berval *) assertedValue;
5755 ber_len_t v_len = value->bv_len;
5756 ber_len_t av_len = asserted->bv_len;
5758 /* ignore trailing 'Z' when comparing */
5759 int match = memcmp( value->bv_val, asserted->bv_val,
5760 (v_len < av_len ? v_len : av_len) - 1 );
5761 if ( match == 0 ) match = v_len - av_len;
5763 /* If used in extensible match filter, match if value < asserted */
5764 if ( flags & SLAP_MR_EXT )
5765 match = (match >= 0);
5768 return LDAP_SUCCESS;
5771 /* Index generation function: Ordered index */
5772 int generalizedTimeIndexer(
5777 struct berval *prefix,
5785 BerValue bvtmp; /* 40 bit index */
5787 struct lutil_timet tt;
5789 bvtmp.bv_len = sizeof(tmp);
5791 for( i=0; values[i].bv_val != NULL; i++ ) {
5792 /* just count them */
5795 /* we should have at least one value at this point */
5798 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5800 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5801 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5802 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5803 /* Use 40 bits of time for key */
5804 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5805 lutil_tm2time( &tm, &tt );
5806 tmp[0] = tt.tt_gsec & 0xff;
5807 tmp[4] = tt.tt_sec & 0xff;
5809 tmp[3] = tt.tt_sec & 0xff;
5811 tmp[2] = tt.tt_sec & 0xff;
5813 tmp[1] = tt.tt_sec & 0xff;
5815 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5819 keys[j].bv_val = NULL;
5824 return LDAP_SUCCESS;
5827 /* Index generation function: Ordered index */
5828 int generalizedTimeFilter(
5833 struct berval *prefix,
5834 void * assertedValue,
5840 BerValue bvtmp; /* 40 bit index */
5841 BerValue *value = (BerValue *) assertedValue;
5843 struct lutil_timet tt;
5845 bvtmp.bv_len = sizeof(tmp);
5847 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5848 /* Use 40 bits of time for key */
5849 if ( value->bv_val && value->bv_len >= 10 &&
5850 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5852 lutil_tm2time( &tm, &tt );
5853 tmp[0] = tt.tt_gsec & 0xff;
5854 tmp[4] = tt.tt_sec & 0xff;
5856 tmp[3] = tt.tt_sec & 0xff;
5858 tmp[2] = tt.tt_sec & 0xff;
5860 tmp[1] = tt.tt_sec & 0xff;
5862 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5863 ber_dupbv_x(keys, &bvtmp, ctx );
5864 keys[1].bv_val = NULL;
5872 return LDAP_SUCCESS;
5876 deliveryMethodValidate(
5878 struct berval *val )
5881 #define LENOF(s) (sizeof(s)-1)
5882 struct berval tmp = *val;
5884 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5885 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5886 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5889 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5891 switch( tmp.bv_val[0] ) {
5894 if(( tmp.bv_len >= LENOF("any") ) &&
5895 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5897 tmp.bv_len -= LENOF("any");
5898 tmp.bv_val += LENOF("any");
5901 return LDAP_INVALID_SYNTAX;
5905 if(( tmp.bv_len >= LENOF("mhs") ) &&
5906 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5908 tmp.bv_len -= LENOF("mhs");
5909 tmp.bv_val += LENOF("mhs");
5912 return LDAP_INVALID_SYNTAX;
5916 if(( tmp.bv_len >= LENOF("physical") ) &&
5917 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5919 tmp.bv_len -= LENOF("physical");
5920 tmp.bv_val += LENOF("physical");
5923 return LDAP_INVALID_SYNTAX;
5926 case 'T': /* telex or teletex or telephone */
5927 if(( tmp.bv_len >= LENOF("telex") ) &&
5928 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5930 tmp.bv_len -= LENOF("telex");
5931 tmp.bv_val += LENOF("telex");
5934 if(( tmp.bv_len >= LENOF("teletex") ) &&
5935 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5937 tmp.bv_len -= LENOF("teletex");
5938 tmp.bv_val += LENOF("teletex");
5941 if(( tmp.bv_len >= LENOF("telephone") ) &&
5942 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5944 tmp.bv_len -= LENOF("telephone");
5945 tmp.bv_val += LENOF("telephone");
5948 return LDAP_INVALID_SYNTAX;
5951 case 'G': /* g3fax or g4fax */
5952 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5953 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5954 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5956 tmp.bv_len -= LENOF("g3fax");
5957 tmp.bv_val += LENOF("g3fax");
5960 return LDAP_INVALID_SYNTAX;
5964 if(( tmp.bv_len >= LENOF("ia5") ) &&
5965 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5967 tmp.bv_len -= LENOF("ia5");
5968 tmp.bv_val += LENOF("ia5");
5971 return LDAP_INVALID_SYNTAX;
5975 if(( tmp.bv_len >= LENOF("videotex") ) &&
5976 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5978 tmp.bv_len -= LENOF("videotex");
5979 tmp.bv_val += LENOF("videotex");
5982 return LDAP_INVALID_SYNTAX;
5985 return LDAP_INVALID_SYNTAX;
5988 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5990 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5994 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5998 return LDAP_INVALID_SYNTAX;
6000 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
6009 nisNetgroupTripleValidate(
6011 struct berval *val )
6016 if ( BER_BVISEMPTY( val ) ) {
6017 return LDAP_INVALID_SYNTAX;
6020 p = (char *)val->bv_val;
6021 e = p + val->bv_len;
6023 if ( *p != '(' /*')'*/ ) {
6024 return LDAP_INVALID_SYNTAX;
6027 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
6031 return LDAP_INVALID_SYNTAX;
6034 } else if ( !AD_CHAR( *p ) ) {
6035 return LDAP_INVALID_SYNTAX;
6039 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
6040 return LDAP_INVALID_SYNTAX;
6046 return LDAP_INVALID_SYNTAX;
6049 return LDAP_SUCCESS;
6053 bootParameterValidate(
6055 struct berval *val )
6059 if ( BER_BVISEMPTY( val ) ) {
6060 return LDAP_INVALID_SYNTAX;
6063 p = (char *)val->bv_val;
6064 e = p + val->bv_len;
6067 for (; ( p < e ) && ( *p != '=' ); p++ ) {
6068 if ( !AD_CHAR( *p ) ) {
6069 return LDAP_INVALID_SYNTAX;
6074 return LDAP_INVALID_SYNTAX;
6078 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
6079 if ( !AD_CHAR( *p ) ) {
6080 return LDAP_INVALID_SYNTAX;
6085 return LDAP_INVALID_SYNTAX;
6089 for ( p++; p < e; p++ ) {
6090 if ( !SLAP_PRINTABLE( *p ) ) {
6091 return LDAP_INVALID_SYNTAX;
6095 return LDAP_SUCCESS;
6099 firstComponentNormalize(
6104 struct berval *normalized,
6111 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
6112 ber_dupbv_x( normalized, val, ctx );
6113 return LDAP_SUCCESS;
6116 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
6118 if( ! ( val->bv_val[0] == '(' /*')'*/
6119 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
6120 && ! ( val->bv_val[0] == '{' /*'}'*/
6121 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
6123 return LDAP_INVALID_SYNTAX;
6126 /* trim leading white space */
6128 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
6134 /* grab next word */
6135 comp.bv_val = &val->bv_val[len];
6136 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
6137 for( comp.bv_len = 0;
6138 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
6144 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
6145 rc = numericoidValidate( NULL, &comp );
6146 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
6147 rc = integerValidate( NULL, &comp );
6149 rc = LDAP_INVALID_SYNTAX;
6153 if( rc == LDAP_SUCCESS ) {
6154 ber_dupbv_x( normalized, &comp, ctx );
6160 static char *country_gen_syn[] = {
6161 "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */
6162 "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */
6163 "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */
6167 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6168 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6170 static slap_syntax_defs_rec syntax_defs[] = {
6171 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6172 X_BINARY X_NOT_H_R ")",
6173 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6174 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6175 0, NULL, NULL, NULL},
6176 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6177 0, NULL, NULL, NULL},
6178 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6180 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6181 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6183 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6184 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6185 0, NULL, bitStringValidate, NULL },
6186 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6187 0, NULL, booleanValidate, NULL},
6188 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6189 X_BINARY X_NOT_H_R ")",
6190 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6191 NULL, certificateValidate, NULL},
6192 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6193 X_BINARY X_NOT_H_R ")",
6194 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6195 NULL, certificateListValidate, NULL},
6196 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6197 X_BINARY X_NOT_H_R ")",
6198 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6199 NULL, sequenceValidate, NULL},
6200 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6201 X_BINARY X_NOT_H_R ")",
6202 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6203 NULL, attributeCertificateValidate, NULL},
6204 #if 0 /* need to go __after__ printableString */
6205 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6206 0, "1.3.6.1.4.1.1466.115.121.1.44",
6207 countryStringValidate, NULL},
6209 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6210 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6211 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6212 0, NULL, rdnValidate, rdnPretty},
6213 #ifdef LDAP_COMP_MATCH
6214 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6215 0, NULL, allComponentsValidate, NULL},
6216 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6217 0, NULL, componentFilterValidate, NULL},
6219 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6220 0, NULL, NULL, NULL},
6221 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6222 0, NULL, deliveryMethodValidate, NULL},
6223 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6224 0, NULL, UTF8StringValidate, NULL},
6225 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6226 0, NULL, NULL, NULL},
6227 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6228 0, NULL, NULL, NULL},
6229 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6230 0, NULL, NULL, NULL},
6231 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6232 0, NULL, NULL, NULL},
6233 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6234 0, NULL, NULL, NULL},
6235 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6236 0, NULL, printablesStringValidate, NULL},
6237 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6238 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6239 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6240 0, NULL, generalizedTimeValidate, NULL},
6241 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6242 0, NULL, NULL, NULL},
6243 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6244 0, NULL, IA5StringValidate, NULL},
6245 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6246 0, NULL, integerValidate, NULL},
6247 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6248 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6249 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6250 0, NULL, NULL, NULL},
6251 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6252 0, NULL, NULL, NULL},
6253 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6254 0, NULL, NULL, NULL},
6255 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6256 0, NULL, NULL, NULL},
6257 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6258 0, NULL, NULL, NULL},
6259 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6260 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6261 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6262 0, NULL, NULL, NULL},
6263 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6264 0, NULL, numericStringValidate, NULL},
6265 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6266 0, NULL, NULL, NULL},
6267 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6268 0, NULL, numericoidValidate, NULL},
6269 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6270 0, NULL, IA5StringValidate, NULL},
6271 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6272 0, NULL, blobValidate, NULL},
6273 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6274 0, NULL, postalAddressValidate, NULL},
6275 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6276 0, NULL, NULL, NULL},
6277 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6278 0, NULL, NULL, NULL},
6279 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6280 0, NULL, printableStringValidate, NULL},
6281 /* moved here because now depends on Directory String, IA5 String
6282 * and Printable String */
6283 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6284 0, country_gen_syn, countryStringValidate, NULL},
6285 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6286 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6287 0, NULL, subtreeSpecificationValidate, NULL},
6288 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6289 X_BINARY X_NOT_H_R ")",
6290 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6291 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6292 0, NULL, printableStringValidate, NULL},
6293 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6294 0, NULL, NULL, NULL},
6295 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6296 0, NULL, printablesStringValidate, NULL},
6297 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6298 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6299 0, NULL, utcTimeValidate, NULL},
6301 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6302 0, NULL, NULL, NULL},
6303 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6304 0, NULL, NULL, NULL},
6305 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6306 0, NULL, NULL, NULL},
6307 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6308 0, NULL, NULL, NULL},
6309 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6310 0, NULL, NULL, NULL},
6312 /* RFC 2307 NIS Syntaxes */
6313 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6314 0, NULL, nisNetgroupTripleValidate, NULL},
6315 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6316 0, NULL, bootParameterValidate, NULL},
6318 /* draft-zeilenga-ldap-x509 */
6319 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6320 SLAP_SYNTAX_HIDE, NULL,
6321 serialNumberAndIssuerValidate,
6322 serialNumberAndIssuerPretty},
6323 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6324 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6325 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6326 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6327 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6328 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6329 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6330 SLAP_SYNTAX_HIDE, NULL,
6331 issuerAndThisUpdateValidate,
6332 issuerAndThisUpdatePretty},
6333 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6334 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6335 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6336 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6337 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6338 SLAP_SYNTAX_HIDE, NULL,
6339 serialNumberAndIssuerSerialValidate,
6340 serialNumberAndIssuerSerialPretty},
6341 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6342 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6344 #ifdef SLAPD_AUTHPASSWD
6345 /* needs updating */
6346 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6347 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6350 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6351 0, NULL, UUIDValidate, UUIDPretty},
6353 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6354 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6356 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6357 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6359 /* OpenLDAP Void Syntax */
6360 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6361 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6363 /* FIXME: OID is unused, but not registered yet */
6364 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6365 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6367 {NULL, 0, NULL, NULL, NULL}
6370 char *csnSIDMatchSyntaxes[] = {
6371 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6374 char *certificateExactMatchSyntaxes[] = {
6375 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6378 char *certificateListExactMatchSyntaxes[] = {
6379 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6382 char *attributeCertificateExactMatchSyntaxes[] = {
6383 attributeCertificateSyntaxOID /* attributeCertificate */,
6387 #ifdef LDAP_COMP_MATCH
6388 char *componentFilterMatchSyntaxes[] = {
6389 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6390 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6391 attributeCertificateSyntaxOID /* attributeCertificate */,
6396 char *directoryStringSyntaxes[] = {
6397 "1.3.6.1.4.1.1466.115.121.1.11" /* countryString */,
6398 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6399 "1.3.6.1.4.1.1466.115.121.1.50" /* telephoneNumber */,
6402 char *integerFirstComponentMatchSyntaxes[] = {
6403 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6404 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6407 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6408 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6409 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6410 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6411 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6412 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6413 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6414 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6415 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6420 * Other matching rules in X.520 that we do not use (yet):
6422 * 2.5.13.25 uTCTimeMatch
6423 * 2.5.13.26 uTCTimeOrderingMatch
6424 * 2.5.13.31* directoryStringFirstComponentMatch
6425 * 2.5.13.32* wordMatch
6426 * 2.5.13.33* keywordMatch
6427 * 2.5.13.36+ certificatePairExactMatch
6428 * 2.5.13.37+ certificatePairMatch
6429 * 2.5.13.40+ algorithmIdentifierMatch
6430 * 2.5.13.41* storedPrefixMatch
6431 * 2.5.13.42 attributeCertificateMatch
6432 * 2.5.13.43 readerAndKeyIDMatch
6433 * 2.5.13.44 attributeIntegrityMatch
6435 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6436 * (+) described in draft-zeilenga-ldap-x509
6438 static slap_mrule_defs_rec mrule_defs[] = {
6440 * EQUALITY matching rules must be listed after associated APPROX
6441 * matching rules. So, we list all APPROX matching rules first.
6443 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6444 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6445 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6446 NULL, NULL, directoryStringApproxMatch,
6447 directoryStringApproxIndexer, directoryStringApproxFilter,
6450 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6451 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6452 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6453 NULL, NULL, IA5StringApproxMatch,
6454 IA5StringApproxIndexer, IA5StringApproxFilter,
6458 * Other matching rules
6461 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6462 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6463 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6464 NULL, NULL, octetStringMatch,
6465 octetStringIndexer, octetStringFilter,
6468 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6470 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6471 NULL, dnNormalize, dnMatch,
6472 octetStringIndexer, octetStringFilter,
6475 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6476 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6477 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6478 NULL, dnNormalize, dnRelativeMatch,
6482 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6483 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6484 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6485 NULL, dnNormalize, dnRelativeMatch,
6489 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6490 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6491 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6492 NULL, dnNormalize, dnRelativeMatch,
6496 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6497 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6498 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6499 NULL, dnNormalize, dnRelativeMatch,
6503 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6504 "SYNTAX 1.2.36.79672281.1.5.0 )",
6505 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6506 NULL, rdnNormalize, rdnMatch,
6507 octetStringIndexer, octetStringFilter,
6510 #ifdef LDAP_COMP_MATCH
6511 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6512 "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */
6513 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6514 NULL, NULL , componentFilterMatch,
6515 octetStringIndexer, octetStringFilter,
6518 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6519 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6520 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6521 NULL, NULL , allComponentsMatch,
6522 octetStringIndexer, octetStringFilter,
6525 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6526 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6527 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6528 NULL, NULL , directoryComponentsMatch,
6529 octetStringIndexer, octetStringFilter,
6533 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6534 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6535 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6536 NULL, UTF8StringNormalize, octetStringMatch,
6537 octetStringIndexer, octetStringFilter,
6538 directoryStringApproxMatchOID },
6540 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6541 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6542 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6543 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6545 "caseIgnoreMatch" },
6547 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6548 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6549 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6550 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6551 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6552 "caseIgnoreMatch" },
6554 {"( 2.5.13.5 NAME 'caseExactMatch' "
6555 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6556 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6557 NULL, UTF8StringNormalize, octetStringMatch,
6558 octetStringIndexer, octetStringFilter,
6559 directoryStringApproxMatchOID },
6561 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6562 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6563 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6564 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6568 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6570 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6571 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6572 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6575 {"( 2.5.13.8 NAME 'numericStringMatch' "
6576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6577 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6578 NULL, numericStringNormalize, octetStringMatch,
6579 octetStringIndexer, octetStringFilter,
6582 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6583 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6584 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6585 NULL, numericStringNormalize, octetStringOrderingMatch,
6587 "numericStringMatch" },
6589 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6590 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6591 SLAP_MR_SUBSTR, NULL,
6592 NULL, numericStringNormalize, octetStringSubstringsMatch,
6593 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6594 "numericStringMatch" },
6596 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6597 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */
6598 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6599 NULL, postalAddressNormalize, octetStringMatch,
6600 octetStringIndexer, octetStringFilter,
6603 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6604 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6605 SLAP_MR_SUBSTR, NULL,
6606 NULL, NULL, NULL, NULL, NULL,
6607 "caseIgnoreListMatch" },
6609 {"( 2.5.13.13 NAME 'booleanMatch' "
6610 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6611 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6612 NULL, NULL, booleanMatch,
6613 octetStringIndexer, octetStringFilter,
6616 {"( 2.5.13.14 NAME 'integerMatch' "
6617 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6618 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6619 NULL, NULL, integerMatch,
6620 integerIndexer, integerFilter,
6623 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6624 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6625 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6626 NULL, NULL, integerMatch,
6630 {"( 2.5.13.16 NAME 'bitStringMatch' "
6631 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6632 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6633 NULL, NULL, octetStringMatch,
6634 octetStringIndexer, octetStringFilter,
6637 {"( 2.5.13.17 NAME 'octetStringMatch' "
6638 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6639 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6640 NULL, NULL, octetStringMatch,
6641 octetStringIndexer, octetStringFilter,
6644 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6645 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6646 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6647 NULL, NULL, octetStringOrderingMatch,
6649 "octetStringMatch" },
6651 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6652 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6653 SLAP_MR_SUBSTR, NULL,
6654 NULL, NULL, octetStringSubstringsMatch,
6655 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6656 "octetStringMatch" },
6658 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6659 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6660 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6662 telephoneNumberNormalize, octetStringMatch,
6663 octetStringIndexer, octetStringFilter,
6666 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6667 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6668 SLAP_MR_SUBSTR, NULL,
6669 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6670 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6671 "telephoneNumberMatch" },
6673 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6674 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6675 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6676 NULL, NULL, NULL, NULL, NULL, NULL },
6678 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6679 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */
6680 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6681 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6682 uniqueMemberIndexer, uniqueMemberFilter,
6685 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6686 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6687 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6688 NULL, NULL, NULL, NULL, NULL, NULL },
6690 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6691 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6692 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6693 NULL, generalizedTimeNormalize, octetStringMatch,
6694 generalizedTimeIndexer, generalizedTimeFilter,
6697 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6698 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6699 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6700 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6702 "generalizedTimeMatch" },
6704 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6705 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6706 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6707 integerFirstComponentMatchSyntaxes,
6708 NULL, firstComponentNormalize, integerMatch,
6709 octetStringIndexer, octetStringFilter,
6712 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6713 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */
6714 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6715 objectIdentifierFirstComponentMatchSyntaxes,
6716 NULL, firstComponentNormalize, octetStringMatch,
6717 octetStringIndexer, octetStringFilter,
6720 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6721 "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */
6722 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6723 NULL, certificateExactNormalize, octetStringMatch,
6724 octetStringIndexer, octetStringFilter,
6727 {"( 2.5.13.35 NAME 'certificateMatch' "
6728 "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */
6729 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6730 NULL, NULL, NULL, NULL, NULL,
6733 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6734 "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */
6735 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6736 NULL, certificateListExactNormalize, octetStringMatch,
6737 octetStringIndexer, octetStringFilter,
6740 {"( 2.5.13.39 NAME 'certificateListMatch' "
6741 "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */
6742 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6743 NULL, NULL, NULL, NULL, NULL,
6746 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6747 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6748 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6749 NULL, attributeCertificateExactNormalize, octetStringMatch,
6750 octetStringIndexer, octetStringFilter,
6753 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6754 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6755 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6756 NULL, NULL, NULL, NULL, NULL,
6759 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6760 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6761 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6762 NULL, IA5StringNormalize, octetStringMatch,
6763 octetStringIndexer, octetStringFilter,
6764 IA5StringApproxMatchOID },
6766 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6767 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6768 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6769 NULL, IA5StringNormalize, octetStringMatch,
6770 octetStringIndexer, octetStringFilter,
6771 IA5StringApproxMatchOID },
6773 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6774 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6775 SLAP_MR_SUBSTR, NULL,
6776 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6777 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6778 "caseIgnoreIA5Match" },
6780 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6781 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6782 SLAP_MR_SUBSTR, NULL,
6783 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6784 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6785 "caseExactIA5Match" },
6787 #ifdef SLAPD_AUTHPASSWD
6788 /* needs updating */
6789 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6790 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */
6791 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6792 NULL, NULL, authPasswordMatch,
6797 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6798 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6800 NULL, NULL, integerBitAndMatch,
6804 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6805 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6807 NULL, NULL, integerBitOrMatch,
6811 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6812 "SYNTAX 1.3.6.1.1.16.1 )",
6813 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6814 NULL, UUIDNormalize, octetStringMatch,
6815 octetStringIndexer, octetStringFilter,
6818 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6819 "SYNTAX 1.3.6.1.1.16.1 )",
6820 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6821 NULL, UUIDNormalize, octetStringOrderingMatch,
6822 octetStringIndexer, octetStringFilter,
6825 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6826 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6827 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6828 NULL, csnNormalize, csnMatch,
6829 csnIndexer, csnFilter,
6832 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6833 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6834 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6835 NULL, csnNormalize, csnOrderingMatch,
6839 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6840 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6841 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6842 NULL, csnSidNormalize, octetStringMatch,
6843 octetStringIndexer, octetStringFilter,
6846 /* FIXME: OID is unused, but not registered yet */
6847 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6848 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */
6849 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6850 NULL, authzNormalize, authzMatch,
6854 {NULL, SLAP_MR_NONE, NULL,
6855 NULL, NULL, NULL, NULL, NULL,
6860 slap_schema_init( void )
6865 /* we should only be called once (from main) */
6866 assert( schema_init_done == 0 );
6868 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6869 res = register_syntax( &syntax_defs[i] );
6872 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6873 syntax_defs[i].sd_desc );
6878 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6879 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6880 mrule_defs[i].mrd_compat_syntaxes == NULL )
6883 "slap_schema_init: Ignoring unusable matching rule %s\n",
6884 mrule_defs[i].mrd_desc );
6888 res = register_matching_rule( &mrule_defs[i] );
6892 "slap_schema_init: Error registering matching rule %s\n",
6893 mrule_defs[i].mrd_desc );
6898 res = slap_schema_load();
6899 schema_init_done = 1;
6904 schema_destroy( void )
6913 if( schema_init_done ) {
6914 ldap_pvt_thread_mutex_destroy( &ad_index_mutex );
6915 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6916 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );