1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2014 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
18 * Syntaxes - implementation notes:
20 * Validate function(syntax, value):
21 * Called before the other functions here to check if the value
22 * is valid according to the syntax.
24 * Pretty function(syntax, input value, output prettified...):
25 * If it exists, maps different notations of the same value to a
26 * unique representation which can be stored in the directory and
27 * possibly be passed to the Match/Indexer/Filter() functions.
29 * E.g. DN "2.5.4.3 = foo\,bar, o = BAZ" -> "cn=foo\2Cbar,o=BAZ",
30 * but unlike DN normalization, "BAZ" is not mapped to "baz".
34 * Matching rules - implementation notes:
36 * Matching rules match an attribute value (often from the directory)
37 * against an asserted value (e.g. from a filter).
39 * Invoked with validated and commonly pretty/normalized arguments, thus
40 * a number of matching rules can simply use the octetString functions.
42 * Normalize function(...input value, output normalized...):
43 * If it exists, maps matching values to a unique representation
44 * which is passed to the Match/Indexer/Filter() functions.
46 * Different matching rules can normalize values of the same syntax
47 * differently. E.g. caseIgnore rules normalize to lowercase,
48 * caseExact rules do not.
50 * Match function(*output matchp, ...value, asserted value):
51 * On success, set *matchp. 0 means match. For ORDERING/most EQUALITY,
52 * less/greater than 0 means value less/greater than asserted. However:
54 * In extensible match filters, ORDERING rules match if value<asserted.
56 * EQUALITY rules may order values differently than ORDERING rules for
57 * speed, since EQUALITY ordering is only used for SLAP_AT_SORTED_VAL.
58 * Some EQUALITY rules do not order values (ITS#6722).
60 * Indexer function(...attribute values, *output keysp,...):
61 * Generates index keys for the attribute values. Backends can store
62 * them in an index, a {key->entry ID set} mapping, for the attribute.
64 * A search can look up the DN/scope and asserted values in the
65 * indexes, if any, to narrow down the number of entires to check
66 * against the search criteria.
68 * Filter function(...asserted value, *output keysp,...):
69 * Generates index key(s) for the asserted value, to be looked up in
70 * the index from the Indexer function. *keysp is an array because
71 * substring matching rules can generate multiple lookup keys.
74 * A key is usually a hash of match type, attribute value and schema
75 * info, because one index can contain keys for many filtering types.
77 * Some indexes instead have EQUALITY keys ordered so that if
78 * key(val1) < key(val2), then val1 < val2 by the ORDERING rule.
79 * That way the ORDERING rule can use the EQUALITY index.
82 * This chops the attribute values up in small chunks and indexes all
83 * possible chunks of certain sizes. Substring filtering looks up
84 * SOME of the asserted value's chunks, and the caller uses the
85 * intersection of the resulting entry ID sets.
86 * See the index_substr_* keywords in slapd.conf(5).
98 #include <ac/string.h>
99 #include <ac/socket.h>
102 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
104 #include "ldap_utf8.h"
107 #include "lutil_hash.h"
109 #ifdef LUTIL_HASH64_BYTES
110 #define HASH_BYTES LUTIL_HASH64_BYTES
111 #define HASH_LEN hashlen
112 static void (*hashinit)(lutil_HASH_CTX *ctx) = lutil_HASHInit;
113 static void (*hashupdate)(lutil_HASH_CTX *ctx,unsigned char const *buf, ber_len_t len) = lutil_HASHUpdate;
114 static void (*hashfinal)(unsigned char digest[HASH_BYTES], lutil_HASH_CTX *ctx) = lutil_HASHFinal;
115 static int hashlen = LUTIL_HASH_BYTES;
116 #define HASH_Init(c) hashinit(c)
117 #define HASH_Update(c,buf,len) hashupdate(c,buf,len)
118 #define HASH_Final(d,c) hashfinal(d,c)
120 /* Toggle between 32 and 64 bit hashing, default to 32 for compatibility
121 -1 to query, returns 1 if 64 bit, 0 if 32.
122 0/1 to set 32/64, returns 0 on success, -1 on failure */
123 int slap_hash64( int onoff )
126 return hashlen == LUTIL_HASH64_BYTES;
127 } else if ( onoff ) {
128 hashinit = lutil_HASH64Init;
129 hashupdate = lutil_HASH64Update;
130 hashfinal = lutil_HASH64Final;
131 hashlen = LUTIL_HASH64_BYTES;
133 hashinit = lutil_HASHInit;
134 hashupdate = lutil_HASHUpdate;
135 hashfinal = lutil_HASHFinal;
136 hashlen = LUTIL_HASH_BYTES;
142 #define HASH_BYTES LUTIL_HASH_BYTES
143 #define HASH_LEN HASH_BYTES
144 #define HASH_Init(c) lutil_HASHInit(c)
145 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
146 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
148 int slap_has64( int onoff )
153 return onoff ? -1 : 0;
157 #define HASH_CONTEXT lutil_HASH_CTX
159 /* approx matching rules */
160 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
161 #define directoryStringApproxMatch approxMatch
162 #define directoryStringApproxIndexer approxIndexer
163 #define directoryStringApproxFilter approxFilter
164 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
165 #define IA5StringApproxMatch approxMatch
166 #define IA5StringApproxIndexer approxIndexer
167 #define IA5StringApproxFilter approxFilter
169 /* Change Sequence Number (CSN) - much of this will change */
170 #define csnMatch octetStringMatch
171 #define csnOrderingMatch octetStringOrderingMatch
172 #define csnIndexer generalizedTimeIndexer
173 #define csnFilter generalizedTimeFilter
175 #define authzMatch octetStringMatch
177 /* X.509 PMI ldapSyntaxes */
178 /* FIXME: need to create temporary OIDs under OpenLDAP's arc;
179 * these are currently hijacked
181 * 1.3.6.1.4.1.4203.666 OpenLDAP
182 * 1.3.6.1.4.1.4203.666.11 self-contained works
183 * 1.3.6.1.4.1.4203.666.11.10 X.509 PMI
184 * 1.3.6.1.4.1.4203.666.11.10.2 X.509 PMI ldapSyntaxes
185 * 1.3.6.1.4.1.4203.666.11.10.2.1 AttributeCertificate (supported)
186 * 1.3.6.1.4.1.4203.666.11.10.2.2 AttributeCertificateExactAssertion (supported)
187 * 1.3.6.1.4.1.4203.666.11.10.2.3 AttributeCertificateAssertion (not supported)
188 * 1.3.6.1.4.1.4203.666.11.10.2.4 AttCertPath (X-SUBST'ed right now in pmi.schema)
189 * 1.3.6.1.4.1.4203.666.11.10.2.5 PolicySyntax (X-SUBST'ed right now in pmi.schema)
190 * 1.3.6.1.4.1.4203.666.11.10.2.6 RoleSyntax (X-SUBST'ed right now in pmi.schema)
192 #if 0 /* from <draft-ietf-pkix-ldap-schema-02.txt> (expired) */
193 #define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5"
194 #define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6"
195 #define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7"
196 #else /* from OpenLDAP's experimental oid arc */
197 #define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2"
198 #define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1"
199 #define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2"
200 #define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3"
203 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
204 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
205 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
206 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
208 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
209 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
210 SLAP_INDEX_INTLEN_DEFAULT );
212 ldap_pvt_thread_mutex_t ad_index_mutex;
213 ldap_pvt_thread_mutex_t ad_undef_mutex;
214 ldap_pvt_thread_mutex_t oc_undef_mutex;
217 generalizedTimeValidate(
221 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
226 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
233 /* no value allowed */
234 return LDAP_INVALID_SYNTAX;
242 /* any value allowed */
246 #define berValidate blobValidate
253 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
254 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
259 /* X.509 related stuff */
268 SLAP_TAG_UTCTIME = 0x17U,
269 SLAP_TAG_GENERALIZEDTIME = 0x18U
273 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
276 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
277 SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1,
278 SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2,
279 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
283 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
287 GeneralName ::= CHOICE {
288 otherName [0] INSTANCE OF OTHER-NAME,
289 rfc822Name [1] IA5String,
290 dNSName [2] IA5String,
291 x400Address [3] ORAddress,
292 directoryName [4] Name,
293 ediPartyName [5] EDIPartyName,
294 uniformResourceIdentifier [6] IA5String,
295 iPAddress [7] OCTET STRING,
296 registeredID [8] OBJECT IDENTIFIER }
299 SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0,
300 SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1,
301 SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2,
302 SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3,
303 SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4,
304 SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5,
305 SLAP_X509_GN_URI = SLAP_X509_OPTION + 6,
306 SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7,
307 SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8
310 /* X.509 PMI related stuff */
317 SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0
320 /* X.509 certificate validation */
322 certificateValidate( Syntax *syntax, struct berval *in )
324 BerElementBuffer berbuf;
325 BerElement *ber = (BerElement *)&berbuf;
328 ber_int_t version = SLAP_X509_V1;
330 ber_init2( ber, in, LBER_USE_DER );
331 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
332 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
333 tag = ber_skip_tag( ber, &len ); /* Sequence */
334 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
335 tag = ber_peek_tag( ber, &len );
336 /* Optional version */
337 if ( tag == SLAP_X509_OPT_C_VERSION ) {
338 tag = ber_skip_tag( ber, &len );
339 tag = ber_get_int( ber, &version );
340 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
342 /* NOTE: don't try to parse Serial, because it might be longer
343 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
344 tag = ber_skip_tag( ber, &len ); /* Serial */
345 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
346 ber_skip_data( ber, len );
347 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
348 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
349 ber_skip_data( ber, len );
350 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
351 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
352 ber_skip_data( ber, len );
353 tag = ber_skip_tag( ber, &len ); /* Validity */
354 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
355 ber_skip_data( ber, len );
356 tag = ber_skip_tag( ber, &len ); /* Subject DN */
357 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
358 ber_skip_data( ber, len );
359 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
360 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
361 ber_skip_data( ber, len );
362 tag = ber_skip_tag( ber, &len );
363 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
364 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
365 ber_skip_data( ber, len );
366 tag = ber_skip_tag( ber, &len );
368 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
369 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
370 ber_skip_data( ber, len );
371 tag = ber_skip_tag( ber, &len );
373 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
374 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
375 tag = ber_skip_tag( ber, &len );
376 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
377 ber_skip_data( ber, len );
378 tag = ber_skip_tag( ber, &len );
380 /* signatureAlgorithm */
381 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
382 ber_skip_data( ber, len );
383 tag = ber_skip_tag( ber, &len );
385 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
386 ber_skip_data( ber, len );
387 tag = ber_skip_tag( ber, &len );
388 /* Must be at end now */
389 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
393 /* X.509 certificate list validation */
395 checkTime( struct berval *in, struct berval *out );
398 certificateListValidate( Syntax *syntax, struct berval *in )
400 BerElementBuffer berbuf;
401 BerElement *ber = (BerElement *)&berbuf;
403 ber_len_t len, wrapper_len;
406 ber_int_t version = SLAP_X509_V1;
407 struct berval bvdn, bvtu;
409 ber_init2( ber, in, LBER_USE_DER );
410 tag = ber_skip_tag( ber, &wrapper_len ); /* Signed wrapper */
411 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
412 wrapper_start = ber->ber_ptr;
413 tag = ber_skip_tag( ber, &len ); /* Sequence */
414 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
415 tag = ber_peek_tag( ber, &len );
416 /* Optional version */
417 if ( tag == LBER_INTEGER ) {
418 tag = ber_get_int( ber, &version );
419 assert( tag == LBER_INTEGER );
420 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
422 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
423 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
424 ber_skip_data( ber, len );
425 tag = ber_peek_tag( ber, &len ); /* Issuer DN */
426 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
427 len = ber_ptrlen( ber );
428 bvdn.bv_val = in->bv_val + len;
429 bvdn.bv_len = in->bv_len - len;
430 tag = ber_skip_tag( ber, &len );
431 ber_skip_data( ber, len );
432 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
433 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
434 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
435 bvtu.bv_val = (char *)ber->ber_ptr;
437 ber_skip_data( ber, len );
438 /* Optional nextUpdate */
439 tag = ber_skip_tag( ber, &len );
440 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
441 ber_skip_data( ber, len );
442 tag = ber_skip_tag( ber, &len );
444 /* revokedCertificates - Sequence of Sequence, Optional */
445 if ( tag == LBER_SEQUENCE ) {
448 stag = ber_peek_tag( ber, &seqlen );
449 if ( stag == LBER_SEQUENCE || !len ) {
450 /* RFC5280 requires non-empty, but X.509(2005) allows empty. */
452 ber_skip_data( ber, len );
453 tag = ber_skip_tag( ber, &len );
456 /* Optional Extensions - Sequence of Sequence */
457 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
459 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
460 tag = ber_peek_tag( ber, &seqlen );
461 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
462 ber_skip_data( ber, len );
463 tag = ber_skip_tag( ber, &len );
465 /* signatureAlgorithm */
466 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
467 ber_skip_data( ber, len );
468 tag = ber_skip_tag( ber, &len );
470 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
471 ber_skip_data( ber, len );
472 if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
473 tag = ber_skip_tag( ber, &len );
474 /* Must be at end now */
475 /* NOTE: OpenSSL tolerates CL with garbage past the end */
476 if ( len || tag != LBER_DEFAULT ) {
477 struct berval issuer_dn = BER_BVNULL, thisUpdate;
478 char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
481 if ( ! wrapper_ok ) {
482 return LDAP_INVALID_SYNTAX;
485 rc = dnX509normalize( &bvdn, &issuer_dn );
486 if ( rc != LDAP_SUCCESS ) {
487 rc = LDAP_INVALID_SYNTAX;
491 thisUpdate.bv_val = tubuf;
492 thisUpdate.bv_len = sizeof(tubuf);
493 if ( checkTime( &bvtu, &thisUpdate ) ) {
494 rc = LDAP_INVALID_SYNTAX;
498 Debug( LDAP_DEBUG_ANY,
499 "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
500 issuer_dn.bv_val, thisUpdate.bv_val, 0 );
503 if ( ! BER_BVISNULL( &issuer_dn ) ) {
504 ber_memfree( issuer_dn.bv_val );
513 /* X.509 PMI Attribute Certificate Validate */
515 attributeCertificateValidate( Syntax *syntax, struct berval *in )
517 BerElementBuffer berbuf;
518 BerElement *ber = (BerElement *)&berbuf;
524 ber_init2( ber, in, LBER_USE_DER );
526 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
527 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
529 tag = ber_skip_tag( ber, &len ); /* Sequence */
530 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
532 tag = ber_peek_tag( ber, &len ); /* Version */
533 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
534 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
535 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
537 tag = ber_skip_tag( ber, &len ); /* Holder */
538 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
539 ber_skip_data( ber, len );
541 tag = ber_skip_tag( ber, &len ); /* Issuer */
542 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
543 ber_skip_data( ber, len );
545 tag = ber_skip_tag( ber, &len ); /* Signature */
546 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
547 ber_skip_data( ber, len );
549 tag = ber_skip_tag( ber, &len ); /* Serial number */
550 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
551 ber_skip_data( ber, len );
553 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
554 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
555 ber_skip_data( ber, len );
557 tag = ber_skip_tag( ber, &len ); /* Attributes */
558 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
559 ber_skip_data( ber, len );
561 tag = ber_peek_tag( ber, &len );
563 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
564 tag = ber_skip_tag( ber, &len );
565 ber_skip_data( ber, len );
566 tag = ber_peek_tag( ber, &len );
569 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
570 tag = ber_skip_tag( ber, &len );
571 ber_skip_data( ber, len );
573 tag = ber_peek_tag( ber, &len );
576 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
577 tag = ber_skip_tag( ber, &len );
578 ber_skip_data( ber, len );
580 tag = ber_peek_tag( ber, &len );
583 if ( tag == LBER_BITSTRING ) { /* Signature */
584 tag = ber_skip_tag( ber, &len );
585 ber_skip_data( ber, len );
587 tag = ber_peek_tag( ber, &len );
590 /* Must be at end now */
591 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
602 struct berval *value,
603 void *assertedValue )
605 struct berval *asserted = (struct berval *) assertedValue;
606 ber_slen_t d = (ber_slen_t) value->bv_len - (ber_slen_t) asserted->bv_len;
608 /* For speed, order first by length, then by contents */
609 *matchp = d ? (sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1)
610 : memcmp( value->bv_val, asserted->bv_val, value->bv_len );
616 octetStringOrderingMatch(
621 struct berval *value,
622 void *assertedValue )
624 struct berval *asserted = (struct berval *) assertedValue;
625 ber_len_t v_len = value->bv_len;
626 ber_len_t av_len = asserted->bv_len;
628 int match = memcmp( value->bv_val, asserted->bv_val,
629 (v_len < av_len ? v_len : av_len) );
632 match = sizeof(v_len) == sizeof(int)
633 ? (int) v_len - (int) av_len
634 : v_len < av_len ? -1 : v_len > av_len;
636 /* If used in extensible match filter, match if value < asserted */
637 if ( flags & SLAP_MR_EXT )
638 match = (match >= 0);
644 /* Initialize HASHcontext from match type and schema info */
647 HASH_CONTEXT *HASHcontext,
648 struct berval *prefix,
653 HASH_Init(HASHcontext);
654 if(prefix && prefix->bv_len > 0) {
655 HASH_Update(HASHcontext,
656 (unsigned char *)prefix->bv_val, prefix->bv_len);
658 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
659 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
660 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
664 /* Set HASHdigest from HASHcontext and value:len */
667 HASH_CONTEXT *HASHcontext,
668 unsigned char *HASHdigest,
669 unsigned char *value,
672 HASH_CONTEXT ctx = *HASHcontext;
673 HASH_Update( &ctx, value, len );
674 HASH_Final( HASHdigest, &ctx );
677 /* Index generation function: Attribute values -> index hash keys */
678 int octetStringIndexer(
683 struct berval *prefix,
691 HASH_CONTEXT HASHcontext;
692 unsigned char HASHdigest[HASH_BYTES];
693 struct berval digest;
694 digest.bv_val = (char *)HASHdigest;
695 digest.bv_len = HASH_LEN;
697 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
698 /* just count them */
701 /* we should have at least one value at this point */
704 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
706 slen = syntax->ssyn_oidlen;
707 mlen = mr->smr_oidlen;
709 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
710 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
711 hashIter( &HASHcontext, HASHdigest,
712 (unsigned char *)values[i].bv_val, values[i].bv_len );
713 ber_dupbv_x( &keys[i], &digest, ctx );
716 BER_BVZERO( &keys[i] );
723 /* Index generation function: Asserted value -> index hash key */
724 int octetStringFilter(
729 struct berval *prefix,
730 void * assertedValue,
736 HASH_CONTEXT HASHcontext;
737 unsigned char HASHdigest[HASH_BYTES];
738 struct berval *value = (struct berval *) assertedValue;
739 struct berval digest;
740 digest.bv_val = (char *)HASHdigest;
741 digest.bv_len = HASH_LEN;
743 slen = syntax->ssyn_oidlen;
744 mlen = mr->smr_oidlen;
746 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
748 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
749 hashIter( &HASHcontext, HASHdigest,
750 (unsigned char *)value->bv_val, value->bv_len );
752 ber_dupbv_x( keys, &digest, ctx );
753 BER_BVZERO( &keys[1] );
761 octetStringSubstringsMatch(
766 struct berval *value,
767 void *assertedValue )
770 SubstringsAssertion *sub = assertedValue;
771 struct berval left = *value;
775 /* Add up asserted input length */
776 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
777 inlen += sub->sa_initial.bv_len;
780 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
781 inlen += sub->sa_any[i].bv_len;
784 if ( !BER_BVISNULL( &sub->sa_final ) ) {
785 inlen += sub->sa_final.bv_len;
788 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
789 if ( inlen > left.bv_len ) {
794 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
795 sub->sa_initial.bv_len );
801 left.bv_val += sub->sa_initial.bv_len;
802 left.bv_len -= sub->sa_initial.bv_len;
803 inlen -= sub->sa_initial.bv_len;
806 if ( !BER_BVISNULL( &sub->sa_final ) ) {
807 if ( inlen > left.bv_len ) {
812 match = memcmp( sub->sa_final.bv_val,
813 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
814 sub->sa_final.bv_len );
820 left.bv_len -= sub->sa_final.bv_len;
821 inlen -= sub->sa_final.bv_len;
825 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
830 if ( inlen > left.bv_len ) {
831 /* not enough length */
836 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
840 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
847 idx = p - left.bv_val;
849 if ( idx >= left.bv_len ) {
850 /* this shouldn't happen */
857 if ( sub->sa_any[i].bv_len > left.bv_len ) {
858 /* not enough left */
863 match = memcmp( left.bv_val,
864 sub->sa_any[i].bv_val,
865 sub->sa_any[i].bv_len );
873 left.bv_val += sub->sa_any[i].bv_len;
874 left.bv_len -= sub->sa_any[i].bv_len;
875 inlen -= sub->sa_any[i].bv_len;
884 /* Substring index generation function: Attribute values -> index hash keys */
886 octetStringSubstringsIndexer(
891 struct berval *prefix,
900 HASH_CONTEXT HCany, HCini, HCfin;
901 unsigned char HASHdigest[HASH_BYTES];
902 struct berval digest;
903 digest.bv_val = (char *)HASHdigest;
904 digest.bv_len = HASH_LEN;
908 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
909 /* count number of indices to generate */
910 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
911 if( values[i].bv_len >= index_substr_if_maxlen ) {
912 nkeys += index_substr_if_maxlen -
913 (index_substr_if_minlen - 1);
914 } else if( values[i].bv_len >= index_substr_if_minlen ) {
915 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
919 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
920 if( values[i].bv_len >= index_substr_any_len ) {
921 nkeys += values[i].bv_len - (index_substr_any_len - 1);
925 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
926 if( values[i].bv_len >= index_substr_if_maxlen ) {
927 nkeys += index_substr_if_maxlen -
928 (index_substr_if_minlen - 1);
929 } else if( values[i].bv_len >= index_substr_if_minlen ) {
930 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
936 /* no keys to generate */
941 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
943 slen = syntax->ssyn_oidlen;
944 mlen = mr->smr_oidlen;
946 if ( flags & SLAP_INDEX_SUBSTR_ANY )
947 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
948 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
949 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
950 if( flags & SLAP_INDEX_SUBSTR_FINAL )
951 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
954 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
957 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
958 ( values[i].bv_len >= index_substr_any_len ) )
960 max = values[i].bv_len - (index_substr_any_len - 1);
962 for( j=0; j<max; j++ ) {
963 hashIter( &HCany, HASHdigest,
964 (unsigned char *)&values[i].bv_val[j],
965 index_substr_any_len );
966 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
970 /* skip if too short */
971 if( values[i].bv_len < index_substr_if_minlen ) continue;
973 max = index_substr_if_maxlen < values[i].bv_len
974 ? index_substr_if_maxlen : values[i].bv_len;
976 for( j=index_substr_if_minlen; j<=max; j++ ) {
978 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
979 hashIter( &HCini, HASHdigest,
980 (unsigned char *)values[i].bv_val, j );
981 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
984 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
985 hashIter( &HCfin, HASHdigest,
986 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
987 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
994 BER_BVZERO( &keys[nkeys] );
1001 return LDAP_SUCCESS;
1004 /* Substring index generation function: Assertion value -> index hash keys */
1006 octetStringSubstringsFilter (
1011 struct berval *prefix,
1012 void * assertedValue,
1016 SubstringsAssertion *sa;
1018 ber_len_t nkeys = 0;
1019 size_t slen, mlen, klen;
1021 HASH_CONTEXT HASHcontext;
1022 unsigned char HASHdigest[HASH_BYTES];
1023 struct berval *value;
1024 struct berval digest;
1026 sa = (SubstringsAssertion *) assertedValue;
1028 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
1029 !BER_BVISNULL( &sa->sa_initial ) &&
1030 sa->sa_initial.bv_len >= index_substr_if_minlen )
1033 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
1034 ( flags & SLAP_INDEX_SUBSTR_ANY ))
1036 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
1040 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1042 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
1043 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
1044 /* don't bother accounting with stepping */
1045 nkeys += sa->sa_any[i].bv_len -
1046 ( index_substr_any_len - 1 );
1051 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1052 !BER_BVISNULL( &sa->sa_final ) &&
1053 sa->sa_final.bv_len >= index_substr_if_minlen )
1056 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
1057 ( flags & SLAP_INDEX_SUBSTR_ANY ))
1059 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
1065 return LDAP_SUCCESS;
1068 digest.bv_val = (char *)HASHdigest;
1069 digest.bv_len = HASH_LEN;
1071 slen = syntax->ssyn_oidlen;
1072 mlen = mr->smr_oidlen;
1074 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
1077 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
1078 !BER_BVISNULL( &sa->sa_initial ) &&
1079 sa->sa_initial.bv_len >= index_substr_if_minlen )
1081 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1082 value = &sa->sa_initial;
1084 klen = index_substr_if_maxlen < value->bv_len
1085 ? index_substr_if_maxlen : value->bv_len;
1087 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1088 hashIter( &HASHcontext, HASHdigest,
1089 (unsigned char *)value->bv_val, klen );
1090 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1092 /* If initial is too long and we have subany indexed, use it
1093 * to match the excess...
1095 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1098 pre = SLAP_INDEX_SUBSTR_PREFIX;
1099 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1100 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
1102 hashIter( &HASHcontext, HASHdigest,
1103 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1104 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1109 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1111 pre = SLAP_INDEX_SUBSTR_PREFIX;
1112 klen = index_substr_any_len;
1114 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
1115 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
1119 value = &sa->sa_any[i];
1121 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1123 j <= value->bv_len - index_substr_any_len;
1124 j += index_substr_any_step )
1126 hashIter( &HASHcontext, HASHdigest,
1127 (unsigned char *)&value->bv_val[j], klen );
1128 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1133 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1134 !BER_BVISNULL( &sa->sa_final ) &&
1135 sa->sa_final.bv_len >= index_substr_if_minlen )
1137 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1138 value = &sa->sa_final;
1140 klen = index_substr_if_maxlen < value->bv_len
1141 ? index_substr_if_maxlen : value->bv_len;
1143 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1144 hashIter( &HASHcontext, HASHdigest,
1145 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
1146 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1148 /* If final is too long and we have subany indexed, use it
1149 * to match the excess...
1151 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1154 pre = SLAP_INDEX_SUBSTR_PREFIX;
1155 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1156 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
1158 hashIter( &HASHcontext, HASHdigest,
1159 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1160 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1166 BER_BVZERO( &keys[nkeys] );
1173 return LDAP_SUCCESS;
1183 /* very unforgiving validation, requires no normalization
1184 * before simplistic matching
1186 if( in->bv_len < 3 ) {
1187 return LDAP_INVALID_SYNTAX;
1190 /* RFC 4517 Section 3.3.2 Bit String:
1191 * BitString = SQUOTE *binary-digit SQUOTE "B"
1192 * binary-digit = "0" / "1"
1194 * where SQUOTE [RFC4512] is
1195 * SQUOTE = %x27 ; single quote ("'")
1197 * Example: '0101111101'B
1200 if( in->bv_val[0] != '\'' ||
1201 in->bv_val[in->bv_len - 2] != '\'' ||
1202 in->bv_val[in->bv_len - 1] != 'B' )
1204 return LDAP_INVALID_SYNTAX;
1207 for( i = in->bv_len - 3; i > 0; i-- ) {
1208 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1209 return LDAP_INVALID_SYNTAX;
1213 return LDAP_SUCCESS;
1217 * Syntaxes from RFC 4517
1222 A value of the Bit String syntax is a sequence of binary digits. The
1223 LDAP-specific encoding of a value of this syntax is defined by the
1226 BitString = SQUOTE *binary-digit SQUOTE "B"
1228 binary-digit = "0" / "1"
1230 The <SQUOTE> rule is defined in [MODELS].
1235 The LDAP definition for the Bit String syntax is:
1237 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1239 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1243 3.3.21. Name and Optional UID
1245 A value of the Name and Optional UID syntax is the distinguished name
1246 [MODELS] of an entity optionally accompanied by a unique identifier
1247 that serves to differentiate the entity from others with an identical
1250 The LDAP-specific encoding of a value of this syntax is defined by
1253 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1255 The <BitString> rule is defined in Section 3.3.2. The
1256 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1257 defined in [MODELS].
1259 Note that although the '#' character may occur in the string
1260 representation of a distinguished name, no additional escaping of
1261 this character is performed when a <distinguishedName> is encoded in
1262 a <NameAndOptionalUID>.
1265 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1267 The LDAP definition for the Name and Optional UID syntax is:
1269 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1271 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1278 1.4. Common ABNF Productions
1281 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1283 SQUOTE = %x27 ; single quote ("'")
1288 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1289 * be escaped except when at the beginning of a value, the
1290 * definition of Name and Optional UID appears to be flawed,
1291 * because there is no clear means to determine whether the
1292 * UID part is present or not.
1296 * cn=Someone,dc=example,dc=com#'1'B
1298 * could be either a NameAndOptionalUID with trailing UID, i.e.
1300 * DN = "cn=Someone,dc=example,dc=com"
1303 * or a NameAndOptionalUID with no trailing UID, and the AVA
1304 * in the last RDN made of
1306 * attributeType = dc
1307 * attributeValue = com#'1'B
1309 * in fact "com#'1'B" is a valid IA5 string.
1311 * As a consequence, current slapd code takes the presence of
1312 * #<valid BitString> at the end of the string representation
1313 * of a NameAndOptionalUID to mean this is indeed a BitString.
1314 * This is quite arbitrary - it has changed the past and might
1315 * change in the future.
1325 struct berval dn, uid;
1327 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1329 ber_dupbv( &dn, in );
1330 if( !dn.bv_val ) return LDAP_OTHER;
1332 /* if there's a "#", try bitStringValidate()... */
1333 uid.bv_val = strrchr( dn.bv_val, '#' );
1334 if ( !BER_BVISNULL( &uid ) ) {
1336 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1338 rc = bitStringValidate( NULL, &uid );
1339 if ( rc == LDAP_SUCCESS ) {
1340 /* in case of success, trim the UID,
1341 * otherwise treat it as part of the DN */
1342 dn.bv_len -= uid.bv_len + 1;
1343 uid.bv_val[-1] = '\0';
1347 rc = dnValidate( NULL, &dn );
1349 ber_memfree( dn.bv_val );
1360 assert( val != NULL );
1361 assert( out != NULL );
1364 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1366 if( BER_BVISEMPTY( val ) ) {
1367 ber_dupbv_x( out, val, ctx );
1369 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1370 return LDAP_INVALID_SYNTAX;
1374 struct berval dnval = *val;
1375 struct berval uidval = BER_BVNULL;
1377 uidval.bv_val = strrchr( val->bv_val, '#' );
1378 if ( !BER_BVISNULL( &uidval ) ) {
1380 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1382 rc = bitStringValidate( NULL, &uidval );
1384 if ( rc == LDAP_SUCCESS ) {
1385 ber_dupbv_x( &dnval, val, ctx );
1387 dnval.bv_len -= ++uidval.bv_len;
1388 dnval.bv_val[dnval.bv_len] = '\0';
1391 BER_BVZERO( &uidval );
1395 rc = dnPretty( syntax, &dnval, out, ctx );
1396 if ( dnval.bv_val != val->bv_val ) {
1397 slap_sl_free( dnval.bv_val, ctx );
1399 if( rc != LDAP_SUCCESS ) {
1403 if( !BER_BVISNULL( &uidval ) ) {
1406 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1407 + uidval.bv_len + 1,
1410 ber_memfree_x( out->bv_val, ctx );
1414 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1415 out->bv_len += uidval.bv_len;
1416 out->bv_val[out->bv_len] = '\0';
1420 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1422 return LDAP_SUCCESS;
1426 uniqueMemberNormalize(
1431 struct berval *normalized,
1437 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1439 ber_dupbv_x( &out, val, ctx );
1440 if ( BER_BVISEMPTY( &out ) ) {
1444 struct berval uid = BER_BVNULL;
1446 uid.bv_val = strrchr( out.bv_val, '#' );
1447 if ( !BER_BVISNULL( &uid ) ) {
1449 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1451 rc = bitStringValidate( NULL, &uid );
1452 if ( rc == LDAP_SUCCESS ) {
1453 uid.bv_val[-1] = '\0';
1454 out.bv_len -= uid.bv_len + 1;
1460 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1462 if( rc != LDAP_SUCCESS ) {
1463 slap_sl_free( out.bv_val, ctx );
1464 return LDAP_INVALID_SYNTAX;
1467 if( !BER_BVISNULL( &uid ) ) {
1470 tmp = ch_realloc( normalized->bv_val,
1471 normalized->bv_len + uid.bv_len
1472 + STRLENOF("#") + 1 );
1473 if ( tmp == NULL ) {
1474 ber_memfree_x( normalized->bv_val, ctx );
1478 normalized->bv_val = tmp;
1480 /* insert the separator */
1481 normalized->bv_val[normalized->bv_len++] = '#';
1483 /* append the UID */
1484 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1485 uid.bv_val, uid.bv_len );
1486 normalized->bv_len += uid.bv_len;
1489 normalized->bv_val[normalized->bv_len] = '\0';
1492 slap_sl_free( out.bv_val, ctx );
1495 return LDAP_SUCCESS;
1504 struct berval *value,
1505 void *assertedValue )
1508 struct berval *asserted = (struct berval *) assertedValue;
1509 struct berval assertedDN = *asserted;
1510 struct berval assertedUID = BER_BVNULL;
1511 struct berval valueDN = *value;
1512 struct berval valueUID = BER_BVNULL;
1513 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1515 if ( !BER_BVISEMPTY( asserted ) ) {
1516 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1517 if ( !BER_BVISNULL( &assertedUID ) ) {
1518 assertedUID.bv_val++;
1519 assertedUID.bv_len = assertedDN.bv_len
1520 - ( assertedUID.bv_val - assertedDN.bv_val );
1522 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1523 assertedDN.bv_len -= assertedUID.bv_len + 1;
1526 BER_BVZERO( &assertedUID );
1531 if ( !BER_BVISEMPTY( value ) ) {
1533 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1534 if ( !BER_BVISNULL( &valueUID ) ) {
1536 valueUID.bv_len = valueDN.bv_len
1537 - ( valueUID.bv_val - valueDN.bv_val );
1539 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1540 valueDN.bv_len -= valueUID.bv_len + 1;
1543 BER_BVZERO( &valueUID );
1548 if( valueUID.bv_len && assertedUID.bv_len ) {
1550 d = (ber_slen_t) valueUID.bv_len - (ber_slen_t) assertedUID.bv_len;
1552 *matchp = sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1;
1553 return LDAP_SUCCESS;
1556 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1559 return LDAP_SUCCESS;
1562 } else if ( !approx && valueUID.bv_len ) {
1565 return LDAP_SUCCESS;
1567 } else if ( !approx && assertedUID.bv_len ) {
1570 return LDAP_SUCCESS;
1573 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1577 uniqueMemberIndexer(
1582 struct berval *prefix,
1590 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1591 /* just count them */
1595 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1597 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1598 struct berval assertedDN = values[i];
1599 struct berval assertedUID = BER_BVNULL;
1601 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1602 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1603 if ( !BER_BVISNULL( &assertedUID ) ) {
1604 assertedUID.bv_val++;
1605 assertedUID.bv_len = assertedDN.bv_len
1606 - ( assertedUID.bv_val - assertedDN.bv_val );
1608 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1609 assertedDN.bv_len -= assertedUID.bv_len + 1;
1612 BER_BVZERO( &assertedUID );
1617 dnvalues[i] = assertedDN;
1619 BER_BVZERO( &dnvalues[i] );
1621 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1622 dnvalues, keysp, ctx );
1624 slap_sl_free( dnvalues, ctx );
1634 struct berval *prefix,
1635 void * assertedValue,
1639 struct berval *asserted = (struct berval *) assertedValue;
1640 struct berval assertedDN = *asserted;
1641 struct berval assertedUID = BER_BVNULL;
1643 if ( !BER_BVISEMPTY( asserted ) ) {
1644 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1645 if ( !BER_BVISNULL( &assertedUID ) ) {
1646 assertedUID.bv_val++;
1647 assertedUID.bv_len = assertedDN.bv_len
1648 - ( assertedUID.bv_val - assertedDN.bv_val );
1650 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1651 assertedDN.bv_len -= assertedUID.bv_len + 1;
1654 BER_BVZERO( &assertedUID );
1659 return octetStringFilter( use, flags, syntax, mr, prefix,
1660 &assertedDN, keysp, ctx );
1665 * Handling boolean syntax and matching is quite rigid.
1666 * A more flexible approach would be to allow a variety
1667 * of strings to be normalized and prettied into TRUE
1675 /* very unforgiving validation, requires no normalization
1676 * before simplistic matching
1679 if( in->bv_len == 4 ) {
1680 if( bvmatch( in, &slap_true_bv ) ) {
1681 return LDAP_SUCCESS;
1683 } else if( in->bv_len == 5 ) {
1684 if( bvmatch( in, &slap_false_bv ) ) {
1685 return LDAP_SUCCESS;
1689 return LDAP_INVALID_SYNTAX;
1698 struct berval *value,
1699 void *assertedValue )
1701 /* simplistic matching allowed by rigid validation */
1702 struct berval *asserted = (struct berval *) assertedValue;
1703 *matchp = (int) asserted->bv_len - (int) value->bv_len;
1704 return LDAP_SUCCESS;
1707 /*-------------------------------------------------------------------
1708 LDAP/X.500 string syntax / matching rules have a few oddities. This
1709 comment attempts to detail how slapd(8) treats them.
1712 StringSyntax X.500 LDAP Matching/Comments
1713 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1714 PrintableString subset subset i/e + ignore insignificant spaces
1715 PrintableString subset subset i/e + ignore insignificant spaces
1716 NumericString subset subset ignore all spaces
1717 IA5String ASCII ASCII i/e + ignore insignificant spaces
1718 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1720 TelephoneNumber subset subset i + ignore all spaces and "-"
1722 See RFC 4518 for details.
1726 In X.500(93), a directory string can be either a PrintableString,
1727 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1728 In later versions, more CHOICEs were added. In all cases the string
1731 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1732 A directory string cannot be zero length.
1734 For matching, there are both case ignore and exact rules. Both
1735 also require that "insignificant" spaces be ignored.
1736 spaces before the first non-space are ignored;
1737 spaces after the last non-space are ignored;
1738 spaces after a space are ignored.
1739 Note: by these rules (and as clarified in X.520), a string of only
1740 spaces is to be treated as if held one space, not empty (which
1741 would be a syntax error).
1744 In ASN.1, numeric string is just a string of digits and spaces
1745 and could be empty. However, in X.500, all attribute values of
1746 numeric string carry a non-empty constraint. For example:
1748 internationalISDNNumber ATTRIBUTE ::= {
1749 WITH SYNTAX InternationalISDNNumber
1750 EQUALITY MATCHING RULE numericStringMatch
1751 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1752 ID id-at-internationalISDNNumber }
1753 InternationalISDNNumber ::=
1754 NumericString (SIZE(1..ub-international-isdn-number))
1756 Unforunately, some assertion values are don't carry the same
1757 constraint (but its unclear how such an assertion could ever
1758 be true). In LDAP, there is one syntax (numericString) not two
1759 (numericString with constraint, numericString without constraint).
1760 This should be treated as numericString with non-empty constraint.
1761 Note that while someone may have no ISDN number, there are no ISDN
1762 numbers which are zero length.
1764 In matching, spaces are ignored.
1767 In ASN.1, Printable string is just a string of printable characters
1768 and can be empty. In X.500, semantics much like NumericString (see
1769 serialNumber for a like example) excepting uses insignificant space
1770 handling instead of ignore all spaces. They must be non-empty.
1773 Basically same as PrintableString. There are no examples in X.500,
1774 but same logic applies. Empty strings are allowed.
1776 -------------------------------------------------------------------*/
1784 unsigned char *u = (unsigned char *)in->bv_val, *end = in->bv_val + in->bv_len;
1786 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1787 /* directory strings cannot be empty */
1788 return LDAP_INVALID_SYNTAX;
1791 for( ; u < end; u += len ) {
1792 /* get the length indicated by the first byte */
1793 len = LDAP_UTF8_CHARLEN2( u, len );
1795 /* very basic checks */
1798 if( (u[5] & 0xC0) != 0x80 ) {
1799 return LDAP_INVALID_SYNTAX;
1802 if( (u[4] & 0xC0) != 0x80 ) {
1803 return LDAP_INVALID_SYNTAX;
1806 if( (u[3] & 0xC0) != 0x80 ) {
1807 return LDAP_INVALID_SYNTAX;
1810 if( (u[2] & 0xC0 )!= 0x80 ) {
1811 return LDAP_INVALID_SYNTAX;
1814 if( (u[1] & 0xC0) != 0x80 ) {
1815 return LDAP_INVALID_SYNTAX;
1818 /* CHARLEN already validated it */
1821 return LDAP_INVALID_SYNTAX;
1824 /* make sure len corresponds with the offset
1825 to the next character */
1826 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1830 return LDAP_INVALID_SYNTAX;
1833 return LDAP_SUCCESS;
1837 UTF8StringNormalize(
1842 struct berval *normalized,
1845 struct berval tmp, nvalue;
1846 int flags, wasspace;
1849 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1851 if( BER_BVISNULL( val ) ) {
1852 /* assume we're dealing with a syntax (e.g., UTF8String)
1853 * which allows empty strings
1855 BER_BVZERO( normalized );
1856 return LDAP_SUCCESS;
1859 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1860 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1861 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1862 ? LDAP_UTF8_APPROX : 0;
1864 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1865 /* out of memory or syntax error, the former is unlikely */
1867 return LDAP_INVALID_SYNTAX;
1870 /* collapse spaces (in place) */
1872 nvalue.bv_val = tmp.bv_val;
1874 /* trim leading spaces? */
1875 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1876 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1878 for( i = 0; i < tmp.bv_len; i++) {
1879 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1880 if( wasspace++ == 0 ) {
1881 /* trim repeated spaces */
1882 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1886 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1890 if( !BER_BVISEMPTY( &nvalue ) ) {
1891 /* trim trailing space? */
1893 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1894 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1898 nvalue.bv_val[nvalue.bv_len] = '\0';
1900 } else if ( tmp.bv_len ) {
1901 /* string of all spaces is treated as one space */
1902 nvalue.bv_val[0] = ' ';
1903 nvalue.bv_val[1] = '\0';
1905 } /* should never be entered with 0-length val */
1907 *normalized = nvalue;
1908 return LDAP_SUCCESS;
1912 directoryStringSubstringsMatch(
1917 struct berval *value,
1918 void *assertedValue )
1921 SubstringsAssertion *sub = assertedValue;
1922 struct berval left = *value;
1926 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1927 if ( sub->sa_initial.bv_len > left.bv_len ) {
1928 /* not enough left */
1933 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1934 sub->sa_initial.bv_len );
1940 left.bv_val += sub->sa_initial.bv_len;
1941 left.bv_len -= sub->sa_initial.bv_len;
1943 priorspace = ASCII_SPACE(
1944 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1947 if ( sub->sa_any ) {
1948 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1952 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1953 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1955 /* allow next space to match */
1962 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1966 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1967 /* not enough left */
1972 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1979 idx = p - left.bv_val;
1981 if ( idx >= left.bv_len ) {
1982 /* this shouldn't happen */
1989 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1990 /* not enough left */
1995 match = memcmp( left.bv_val,
1996 sub->sa_any[i].bv_val,
1997 sub->sa_any[i].bv_len );
2005 left.bv_val += sub->sa_any[i].bv_len;
2006 left.bv_len -= sub->sa_any[i].bv_len;
2008 priorspace = ASCII_SPACE(
2009 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
2013 if ( !BER_BVISNULL( &sub->sa_final ) ) {
2014 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
2015 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
2017 /* allow next space to match */
2022 if ( sub->sa_final.bv_len > left.bv_len ) {
2023 /* not enough left */
2028 match = memcmp( sub->sa_final.bv_val,
2029 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2030 sub->sa_final.bv_len );
2039 return LDAP_SUCCESS;
2042 #if defined(SLAPD_APPROX_INITIALS)
2043 # define SLAPD_APPROX_DELIMITER "._ "
2044 # define SLAPD_APPROX_WORDLEN 2
2046 # define SLAPD_APPROX_DELIMITER " "
2047 # define SLAPD_APPROX_WORDLEN 1
2056 struct berval *value,
2057 void *assertedValue )
2059 struct berval *nval, *assertv;
2060 char *val, **values, **words, *c;
2061 int i, count, len, nextchunk=0, nextavail=0;
2063 /* Yes, this is necessary */
2064 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
2065 if( nval == NULL ) {
2067 return LDAP_SUCCESS;
2070 /* Yes, this is necessary */
2071 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
2072 NULL, LDAP_UTF8_APPROX, NULL );
2073 if( assertv == NULL ) {
2076 return LDAP_SUCCESS;
2079 /* Isolate how many words there are */
2080 for ( c = nval->bv_val, count = 1; *c; c++ ) {
2081 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
2082 if ( c == NULL ) break;
2087 /* Get a phonetic copy of each word */
2088 words = (char **)ch_malloc( count * sizeof(char *) );
2089 values = (char **)ch_malloc( count * sizeof(char *) );
2090 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
2092 values[i] = phonetic(c);
2095 /* Work through the asserted value's words, to see if at least some
2096 * of the words are there, in the same order. */
2098 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
2099 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
2104 #if defined(SLAPD_APPROX_INITIALS)
2105 else if( len == 1 ) {
2106 /* Single letter words need to at least match one word's initial */
2107 for( i=nextavail; i<count; i++ )
2108 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
2115 /* Isolate the next word in the asserted value and phonetic it */
2116 assertv->bv_val[nextchunk+len] = '\0';
2117 val = phonetic( assertv->bv_val + nextchunk );
2119 /* See if this phonetic chunk is in the remaining words of *value */
2120 for( i=nextavail; i<count; i++ ){
2121 if( !strcmp( val, values[i] ) ){
2129 /* This chunk in the asserted value was NOT within the *value. */
2135 /* Go on to the next word in the asserted value */
2139 /* If some of the words were seen, call it a match */
2140 if( nextavail > 0 ) {
2147 /* Cleanup allocs */
2148 ber_bvfree( assertv );
2149 for( i=0; i<count; i++ ) {
2150 ch_free( values[i] );
2156 return LDAP_SUCCESS;
2165 struct berval *prefix,
2171 int i,j, len, wordcount, keycount=0;
2172 struct berval *newkeys;
2173 BerVarray keys=NULL;
2175 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2176 struct berval val = BER_BVNULL;
2177 /* Yes, this is necessary */
2178 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2179 assert( !BER_BVISNULL( &val ) );
2181 /* Isolate how many words there are. There will be a key for each */
2182 for( wordcount = 0, c = val.bv_val; *c; c++) {
2183 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2184 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2186 if (*c == '\0') break;
2190 /* Allocate/increase storage to account for new keys */
2191 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2192 * sizeof(struct berval) );
2193 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2194 if( keys ) ch_free( keys );
2197 /* Get a phonetic copy of each word */
2198 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2200 if( len < SLAPD_APPROX_WORDLEN ) continue;
2201 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2202 if( keys[keycount].bv_len ) {
2205 ch_free( keys[keycount].bv_val );
2210 ber_memfree( val.bv_val );
2212 BER_BVZERO( &keys[keycount] );
2215 return LDAP_SUCCESS;
2224 struct berval *prefix,
2225 void * assertedValue,
2234 /* Yes, this is necessary */
2235 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2236 NULL, LDAP_UTF8_APPROX, NULL );
2237 if( val == NULL || BER_BVISNULL( val ) ) {
2238 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2239 BER_BVZERO( &keys[0] );
2242 return LDAP_SUCCESS;
2245 /* Isolate how many words there are. There will be a key for each */
2246 for( count = 0,c = val->bv_val; *c; c++) {
2247 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2248 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2250 if (*c == '\0') break;
2254 /* Allocate storage for new keys */
2255 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2257 /* Get a phonetic copy of each word */
2258 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2260 if( len < SLAPD_APPROX_WORDLEN ) continue;
2261 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2267 BER_BVZERO( &keys[count] );
2270 return LDAP_SUCCESS;
2273 /* Remove all spaces and '-' characters */
2275 telephoneNumberNormalize(
2280 struct berval *normalized,
2285 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2287 /* validator should have refused an empty string */
2288 assert( !BER_BVISEMPTY( val ) );
2290 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2292 for( p = val->bv_val; *p; p++ ) {
2293 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2299 normalized->bv_len = q - normalized->bv_val;
2301 if( BER_BVISEMPTY( normalized ) ) {
2302 slap_sl_free( normalized->bv_val, ctx );
2303 BER_BVZERO( normalized );
2304 return LDAP_INVALID_SYNTAX;
2307 return LDAP_SUCCESS;
2311 postalAddressValidate(
2315 struct berval bv = *in;
2318 for ( c = 0; c < in->bv_len; c++ ) {
2319 if ( in->bv_val[c] == '\\' ) {
2321 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2322 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2324 return LDAP_INVALID_SYNTAX;
2329 if ( in->bv_val[c] == '$' ) {
2330 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2331 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2332 return LDAP_INVALID_SYNTAX;
2334 bv.bv_val = &in->bv_val[c] + 1;
2338 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2339 return UTF8StringValidate( NULL, &bv );
2343 postalAddressNormalize(
2348 struct berval *normalized,
2351 BerVarray lines = NULL, nlines = NULL;
2353 int rc = LDAP_SUCCESS;
2354 MatchingRule *xmr = NULL;
2357 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2358 xmr = slap_schema.si_mr_caseIgnoreMatch;
2361 xmr = slap_schema.si_mr_caseExactMatch;
2364 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2365 if ( val->bv_val[c] == '$' ) {
2370 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2371 nlines = &lines[l + 2];
2373 lines[0].bv_val = val->bv_val;
2374 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2375 if ( val->bv_val[c] == '$' ) {
2376 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2378 lines[l].bv_val = &val->bv_val[c + 1];
2381 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2383 normalized->bv_len = c = l;
2385 for ( l = 0; l <= c; l++ ) {
2386 /* NOTE: we directly normalize each line,
2387 * without unescaping the values, since the special
2388 * values '\24' ('$') and '\5C' ('\') are not affected
2389 * by normalization */
2390 if ( !lines[l].bv_len ) {
2391 nlines[l].bv_len = 0;
2392 nlines[l].bv_val = NULL;
2395 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2396 if ( rc != LDAP_SUCCESS ) {
2397 rc = LDAP_INVALID_SYNTAX;
2401 normalized->bv_len += nlines[l].bv_len;
2404 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2406 p = normalized->bv_val;
2407 for ( l = 0; l <= c ; l++ ) {
2408 p = lutil_strbvcopy( p, &nlines[l] );
2413 assert( p == &normalized->bv_val[normalized->bv_len] );
2416 if ( nlines != NULL ) {
2417 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2418 slap_sl_free( nlines[l].bv_val, ctx );
2421 slap_sl_free( lines, ctx );
2432 struct berval val = *in;
2434 if( BER_BVISEMPTY( &val ) ) {
2435 /* disallow empty strings */
2436 return LDAP_INVALID_SYNTAX;
2439 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2440 if ( val.bv_len == 1 ) {
2441 return LDAP_SUCCESS;
2444 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2451 while ( OID_LEADCHAR( val.bv_val[0] )) {
2455 if ( val.bv_len == 0 ) {
2456 return LDAP_SUCCESS;
2460 if( !OID_SEPARATOR( val.bv_val[0] )) {
2468 return LDAP_INVALID_SYNTAX;
2477 struct berval val = *in;
2479 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2481 if ( val.bv_val[0] == '-' ) {
2485 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2486 return LDAP_INVALID_SYNTAX;
2489 if( val.bv_val[0] == '0' ) { /* "-0" */
2490 return LDAP_INVALID_SYNTAX;
2493 } else if ( val.bv_val[0] == '0' ) {
2494 if( val.bv_len > 1 ) { /* "0<more>" */
2495 return LDAP_INVALID_SYNTAX;
2498 return LDAP_SUCCESS;
2501 for( i=0; i < val.bv_len; i++ ) {
2502 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2503 return LDAP_INVALID_SYNTAX;
2507 return LDAP_SUCCESS;
2516 struct berval *value,
2517 void *assertedValue )
2519 struct berval *asserted = (struct berval *) assertedValue;
2520 int vsign = 1, asign = 1; /* default sign = '+' */
2525 if( v.bv_val[0] == '-' ) {
2531 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2534 if( a.bv_val[0] == '-' ) {
2540 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2542 match = vsign - asign;
2544 match = ( v.bv_len != a.bv_len
2545 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2546 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2547 if( vsign < 0 ) match = -match;
2550 /* Ordering rule used in extensible match filter? */
2551 if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
2552 match = (match >= 0);
2555 return LDAP_SUCCESS;
2558 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2559 #define INDEX_INTLEN_CHOP 7
2560 #define INDEX_INTLEN_CHOPBYTES 3
2569 /* Integer index key format, designed for memcmp to collate correctly:
2570 * if too large: one's complement sign*<approx exponent=chopped bytes>,
2571 * two's complement value (sign-extended or chopped as needed),
2572 * however in first byte above, the top <number of exponent-bytes + 1>
2573 * bits are the inverse sign and next bit is the sign as delimiter.
2575 ber_slen_t k = index_intlen_strlen;
2577 unsigned signmask = ~0x7fU;
2578 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2579 struct berval val = *in, itmp = *tmp;
2581 if ( val.bv_val[0] != '-' ) {
2586 /* Chop least significant digits, increase length instead */
2587 if ( val.bv_len > (ber_len_t) k ) {
2588 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2589 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2590 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2593 if ( lutil_str2bin( &val, &itmp, ctx )) {
2594 return LDAP_INVALID_SYNTAX;
2597 /* Omit leading sign byte */
2598 if ( itmp.bv_val[0] == neg ) {
2603 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2605 assert( chop == 0 );
2606 memset( key->bv_val, neg, k ); /* sign-extend */
2607 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2608 /* Got exponent -k, or no room for 2 sign bits */
2609 lenp = lenbuf + sizeof(lenbuf);
2610 chop = - (ber_len_t) k;
2612 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2614 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2615 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2616 * are 1, and the top n+2 bits of lenp[0] are the sign bit. */
2617 k = (lenbuf + sizeof(lenbuf)) - lenp;
2618 if ( k > (ber_slen_t) index_intlen )
2620 memcpy( key->bv_val, lenp, k );
2621 itmp.bv_len = index_intlen - k;
2623 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2624 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2628 /* Index generation function: Ordered index */
2635 struct berval *prefix,
2645 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2647 /* count the values and find max needed length */
2649 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2650 if ( vlen < values[i].bv_len )
2651 vlen = values[i].bv_len;
2653 if ( vlen > maxstrlen )
2656 /* we should have at least one value at this point */
2659 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2660 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2661 keys[i].bv_len = index_intlen;
2662 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2665 keys[i].bv_val = NULL;
2667 if ( vlen > sizeof(ibuf) ) {
2668 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2672 itmp.bv_len = sizeof(ibuf);
2674 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2675 if ( itmp.bv_val != ibuf ) {
2676 itmp.bv_len = values[i].bv_len;
2677 if ( itmp.bv_len <= sizeof(ibuf) )
2678 itmp.bv_len = sizeof(ibuf);
2679 else if ( itmp.bv_len > maxstrlen )
2680 itmp.bv_len = maxstrlen;
2682 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2688 if ( itmp.bv_val != ibuf ) {
2689 slap_sl_free( itmp.bv_val, ctx );
2694 /* Index generation function: Ordered index */
2701 struct berval *prefix,
2702 void * assertedValue,
2709 struct berval *value;
2712 value = (struct berval *) assertedValue;
2714 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2716 keys[0].bv_len = index_intlen;
2717 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2719 keys[1].bv_val = NULL;
2721 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2722 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2723 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2724 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2727 iv.bv_len = sizeof(ibuf);
2730 rc = integerVal2Key( value, keys, &iv, ctx );
2734 if ( iv.bv_val != ibuf ) {
2735 slap_sl_free( iv.bv_val, ctx );
2741 countryStringValidate(
2743 struct berval *val )
2745 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2747 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2748 return LDAP_INVALID_SYNTAX;
2750 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2751 return LDAP_INVALID_SYNTAX;
2754 return LDAP_SUCCESS;
2758 printableStringValidate(
2760 struct berval *val )
2764 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2766 for(i=0; i < val->bv_len; i++) {
2767 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2768 return LDAP_INVALID_SYNTAX;
2772 return LDAP_SUCCESS;
2776 printablesStringValidate(
2778 struct berval *val )
2782 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2784 for(i=0,len=0; i < val->bv_len; i++) {
2785 int c = val->bv_val[i];
2789 return LDAP_INVALID_SYNTAX;
2793 } else if ( SLAP_PRINTABLE(c) ) {
2796 return LDAP_INVALID_SYNTAX;
2801 return LDAP_INVALID_SYNTAX;
2804 return LDAP_SUCCESS;
2810 struct berval *val )
2814 for(i=0; i < val->bv_len; i++) {
2815 if( !LDAP_ASCII(val->bv_val[i]) ) {
2816 return LDAP_INVALID_SYNTAX;
2820 return LDAP_SUCCESS;
2829 struct berval *normalized,
2833 int casefold = !SLAP_MR_ASSOCIATED( mr,
2834 slap_schema.si_mr_caseExactIA5Match );
2836 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2840 /* Ignore initial whitespace */
2841 while ( ASCII_SPACE( *p ) ) p++;
2843 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2844 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2845 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2846 normalized->bv_val[normalized->bv_len] = '\0';
2848 p = q = normalized->bv_val;
2851 if ( ASCII_SPACE( *p ) ) {
2854 /* Ignore the extra whitespace */
2855 while ( ASCII_SPACE( *p ) ) {
2859 } else if ( casefold ) {
2860 /* Most IA5 rules require casefolding */
2861 *q++ = TOLOWER(*p); p++;
2868 assert( normalized->bv_val <= p );
2872 * If the string ended in space, backup the pointer one
2873 * position. One is enough because the above loop collapsed
2874 * all whitespace to a single space.
2876 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2878 /* null terminate */
2881 normalized->bv_len = q - normalized->bv_val;
2883 return LDAP_SUCCESS;
2892 if( in->bv_len != 36 ) {
2893 return LDAP_INVALID_SYNTAX;
2896 for( i=0; i<36; i++ ) {
2902 if( in->bv_val[i] != '-' ) {
2903 return LDAP_INVALID_SYNTAX;
2907 if( !ASCII_HEX( in->bv_val[i]) ) {
2908 return LDAP_INVALID_SYNTAX;
2913 return LDAP_SUCCESS;
2924 int rc=LDAP_INVALID_SYNTAX;
2926 assert( in != NULL );
2927 assert( out != NULL );
2929 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2932 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2934 for( i=0; i<36; i++ ) {
2940 if( in->bv_val[i] != '-' ) {
2943 out->bv_val[i] = '-';
2947 if( !ASCII_HEX( in->bv_val[i]) ) {
2950 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2955 out->bv_val[ out->bv_len ] = '\0';
2959 slap_sl_free( out->bv_val, ctx );
2972 struct berval *normalized,
2975 unsigned char octet = '\0';
2979 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2980 /* NOTE: must be a normalized UUID */
2981 assert( val->bv_len == 16 );
2983 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2984 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2985 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2986 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2988 return LDAP_SUCCESS;
2991 normalized->bv_len = 16;
2992 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2994 for( i=0, j=0; i<36; i++ ) {
2995 unsigned char nibble;
2996 if( val->bv_val[i] == '-' ) {
2999 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
3000 nibble = val->bv_val[i] - '0';
3002 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
3003 nibble = val->bv_val[i] - ('a'-10);
3005 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
3006 nibble = val->bv_val[i] - ('A'-10);
3009 slap_sl_free( normalized->bv_val, ctx );
3010 BER_BVZERO( normalized );
3011 return LDAP_INVALID_SYNTAX;
3016 normalized->bv_val[j>>1] = octet;
3018 octet = nibble << 4;
3023 normalized->bv_val[normalized->bv_len] = 0;
3024 return LDAP_SUCCESS;
3030 numericStringValidate(
3036 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
3038 for(i=0; i < in->bv_len; i++) {
3039 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3040 return LDAP_INVALID_SYNTAX;
3044 return LDAP_SUCCESS;
3048 numericStringNormalize(
3053 struct berval *normalized,
3056 /* removal all spaces */
3059 assert( !BER_BVISEMPTY( val ) );
3061 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
3064 q = normalized->bv_val;
3067 if ( ASCII_SPACE( *p ) ) {
3068 /* Ignore whitespace */
3075 /* we should have copied no more than is in val */
3076 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3078 /* null terminate */
3081 normalized->bv_len = q - normalized->bv_val;
3083 if( BER_BVISEMPTY( normalized ) ) {
3084 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
3085 normalized->bv_val[0] = ' ';
3086 normalized->bv_val[1] = '\0';
3087 normalized->bv_len = 1;
3090 return LDAP_SUCCESS;
3094 * Integer conversion macros that will use the largest available
3097 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
3098 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
3099 # define SLAP_LONG long long
3101 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
3102 # define SLAP_LONG long
3103 #endif /* HAVE_STRTOLL ... */
3111 struct berval *value,
3112 void *assertedValue )
3114 SLAP_LONG lValue, lAssertedValue;
3117 /* safe to assume integers are NUL terminated? */
3118 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3119 if( errno == ERANGE )
3121 return LDAP_CONSTRAINT_VIOLATION;
3124 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
3126 if( errno == ERANGE )
3128 return LDAP_CONSTRAINT_VIOLATION;
3131 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
3132 return LDAP_SUCCESS;
3141 struct berval *value,
3142 void *assertedValue )
3144 SLAP_LONG lValue, lAssertedValue;
3147 /* safe to assume integers are NUL terminated? */
3148 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3149 if( errno == ERANGE )
3151 return LDAP_CONSTRAINT_VIOLATION;
3154 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3156 if( errno == ERANGE )
3158 return LDAP_CONSTRAINT_VIOLATION;
3161 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3162 return LDAP_SUCCESS;
3166 checkNum( struct berval *in, struct berval *out )
3168 /* parse serialNumber */
3169 ber_len_t neg = 0, extra = 0;
3172 out->bv_val = in->bv_val;
3175 if ( out->bv_val[0] == '-' ) {
3180 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3181 first = out->bv_val[2];
3184 out->bv_len += STRLENOF("0x");
3185 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3186 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3189 } else if ( out->bv_val[0] == '\'' ) {
3190 first = out->bv_val[1];
3193 out->bv_len += STRLENOF("'");
3195 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3196 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3198 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3201 out->bv_len += STRLENOF("'H");
3204 first = out->bv_val[0];
3205 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3206 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3210 if ( !( out->bv_len > neg ) ) {
3214 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3222 serialNumberAndIssuerCheck(
3230 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3232 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3233 /* Parse old format */
3234 is->bv_val = ber_bvchr( in, '$' );
3235 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3237 sn->bv_val = in->bv_val;
3238 sn->bv_len = is->bv_val - in->bv_val;
3241 is->bv_len = in->bv_len - (sn->bv_len + 1);
3243 /* eat leading zeros */
3244 for( n=0; n < (sn->bv_len-1); n++ ) {
3245 if( sn->bv_val[n] != '0' ) break;
3250 for( n=0; n < sn->bv_len; n++ ) {
3251 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3255 /* Parse GSER format */
3260 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3264 struct berval x = *in;
3270 /* eat leading spaces */
3271 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3275 /* should be at issuer or serialNumber NamedValue */
3276 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3277 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3280 x.bv_val += STRLENOF("issuer");
3281 x.bv_len -= STRLENOF("issuer");
3283 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3287 /* eat leading spaces */
3288 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3292 /* For backward compatibility, this part is optional */
3293 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3294 x.bv_val += STRLENOF("rdnSequence:");
3295 x.bv_len -= STRLENOF("rdnSequence:");
3298 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3302 is->bv_val = x.bv_val;
3305 for ( ; is->bv_len < x.bv_len; ) {
3306 if ( is->bv_val[is->bv_len] != '"' ) {
3310 if ( is->bv_val[is->bv_len+1] == '"' ) {
3317 x.bv_val += is->bv_len + 1;
3318 x.bv_len -= is->bv_len + 1;
3320 have |= HAVE_ISSUER;
3322 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3324 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3326 /* parse serialNumber */
3327 x.bv_val += STRLENOF("serialNumber");
3328 x.bv_len -= STRLENOF("serialNumber");
3330 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3334 /* eat leading spaces */
3335 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3339 if ( checkNum( &x, sn ) ) {
3340 return LDAP_INVALID_SYNTAX;
3343 x.bv_val += sn->bv_len;
3344 x.bv_len -= sn->bv_len;
3349 return LDAP_INVALID_SYNTAX;
3352 /* eat leading spaces */
3353 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3357 if ( have == HAVE_ALL ) {
3361 if ( x.bv_val[0] != ',' ) {
3362 return LDAP_INVALID_SYNTAX;
3369 /* should have no characters left... */
3370 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3372 if ( numdquotes == 0 ) {
3373 ber_dupbv_x( &ni, is, ctx );
3378 ni.bv_len = is->bv_len - numdquotes;
3379 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3380 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3381 if ( is->bv_val[src] == '"' ) {
3384 ni.bv_val[dst] = is->bv_val[src];
3386 ni.bv_val[dst] = '\0';
3396 serialNumberAndIssuerValidate(
3401 struct berval sn, i;
3403 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3406 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3411 /* validate DN -- doesn't handle double dquote */
3412 rc = dnValidate( NULL, &i );
3414 rc = LDAP_INVALID_SYNTAX;
3417 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3418 slap_sl_free( i.bv_val, NULL );
3421 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3422 in->bv_val, rc, 0 );
3429 serialNumberAndIssuerPretty(
3436 struct berval sn, i, ni = BER_BVNULL;
3439 assert( in != NULL );
3440 assert( out != NULL );
3444 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3447 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3452 rc = dnPretty( syntax, &i, &ni, ctx );
3454 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3455 slap_sl_free( i.bv_val, ctx );
3459 rc = LDAP_INVALID_SYNTAX;
3463 /* make room from sn + "$" */
3464 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3465 + sn.bv_len + ni.bv_len;
3466 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3468 if ( out->bv_val == NULL ) {
3475 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3476 p = lutil_strbvcopy( p, &sn );
3477 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3478 p = lutil_strbvcopy( p, &ni );
3479 p = lutil_strcopy( p, /*{*/ "\" }" );
3481 assert( p == &out->bv_val[out->bv_len] );
3484 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3485 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3487 slap_sl_free( ni.bv_val, ctx );
3489 return LDAP_SUCCESS;
3499 /* Use hex format. '123456789abcdef'H */
3500 unsigned char *ptr, zero = '\0';
3503 ber_len_t i, len, nlen;
3505 assert( in != NULL );
3506 assert( !BER_BVISNULL( in ) );
3507 assert( out != NULL );
3508 assert( !BER_BVISNULL( out ) );
3510 ptr = (unsigned char *)in->bv_val;
3513 /* Check for minimal encodings */
3515 if ( ptr[0] & 0x80 ) {
3516 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3520 } else if ( ptr[0] == 0 ) {
3521 if ( !( ptr[1] & 0x80 ) ) {
3528 } else if ( len == 0 ) {
3529 /* FIXME: this should not be possible,
3530 * since a value of zero would have length 1 */
3535 first = !( ptr[0] & 0xf0U );
3536 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3537 if ( nlen >= out->bv_len ) {
3538 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3544 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3548 for ( ; i < len; i++ ) {
3549 sprintf( sptr, "%02X", ptr[i] );
3556 assert( sptr == &out->bv_val[nlen] );
3563 #define SLAP_SN_BUFLEN (64)
3566 * This routine is called by certificateExactNormalize when
3567 * certificateExactNormalize receives a search string instead of
3568 * a certificate. This routine checks if the search value is valid
3569 * and then returns the normalized value
3572 serialNumberAndIssuerNormalize(
3580 struct berval sn, sn2, sn3, i, ni;
3581 char sbuf2[SLAP_SN_BUFLEN];
3582 char sbuf3[SLAP_SN_BUFLEN];
3586 assert( in != NULL );
3587 assert( out != NULL );
3589 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3592 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3597 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3599 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3600 slap_sl_free( i.bv_val, ctx );
3604 return LDAP_INVALID_SYNTAX;
3607 /* Convert sn to canonical hex */
3609 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3610 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3612 sn2.bv_len = sn.bv_len;
3614 sn3.bv_len = sizeof(sbuf3);
3615 if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
3616 rc = LDAP_INVALID_SYNTAX;
3620 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3621 + sn3.bv_len + ni.bv_len;
3622 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3623 if ( out->bv_val == NULL ) {
3631 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3632 p = lutil_strbvcopy( p, &sn3 );
3633 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3634 p = lutil_strbvcopy( p, &ni );
3635 p = lutil_strcopy( p, /*{*/ "\" }" );
3637 assert( p == &out->bv_val[out->bv_len] );
3640 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3641 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3643 if ( sn2.bv_val != sbuf2 ) {
3644 slap_sl_free( sn2.bv_val, ctx );
3647 if ( sn3.bv_val != sbuf3 ) {
3648 slap_sl_free( sn3.bv_val, ctx );
3651 slap_sl_free( ni.bv_val, ctx );
3657 certificateExactNormalize(
3662 struct berval *normalized,
3665 BerElementBuffer berbuf;
3666 BerElement *ber = (BerElement *)&berbuf;
3670 char serialbuf2[SLAP_SN_BUFLEN];
3671 struct berval sn, sn2 = BER_BVNULL;
3672 struct berval issuer_dn = BER_BVNULL, bvdn;
3674 int rc = LDAP_INVALID_SYNTAX;
3676 assert( val != NULL );
3678 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3679 val->bv_val, val->bv_len, 0 );
3681 if ( BER_BVISEMPTY( val ) ) goto done;
3683 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3684 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3687 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3689 ber_init2( ber, val, LBER_USE_DER );
3690 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3691 tag = ber_skip_tag( ber, &len ); /* Sequence */
3692 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3693 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3694 tag = ber_skip_tag( ber, &len );
3695 tag = ber_get_int( ber, &i ); /* version */
3698 /* NOTE: move the test here from certificateValidate,
3699 * so that we can validate certs with serial longer
3700 * than sizeof(ber_int_t) */
3701 tag = ber_skip_tag( ber, &len ); /* serial */
3703 sn.bv_val = (char *)ber->ber_ptr;
3704 sn2.bv_val = serialbuf2;
3705 sn2.bv_len = sizeof(serialbuf2);
3706 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3707 rc = LDAP_INVALID_SYNTAX;
3710 ber_skip_data( ber, len );
3712 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3713 ber_skip_data( ber, len );
3714 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3716 len = ber_ptrlen( ber );
3717 bvdn.bv_val = val->bv_val + len;
3718 bvdn.bv_len = val->bv_len - len;
3720 rc = dnX509normalize( &bvdn, &issuer_dn );
3721 if ( rc != LDAP_SUCCESS ) goto done;
3724 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3725 + sn2.bv_len + issuer_dn.bv_len;
3726 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3728 p = normalized->bv_val;
3730 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3731 p = lutil_strbvcopy( p, &sn2 );
3732 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3733 p = lutil_strbvcopy( p, &issuer_dn );
3734 p = lutil_strcopy( p, /*{*/ "\" }" );
3739 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3740 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3742 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3743 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3748 /* X.509 PKI certificateList stuff */
3750 checkTime( struct berval *in, struct berval *out )
3754 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3757 assert( in != NULL );
3758 assert( !BER_BVISNULL( in ) );
3759 assert( !BER_BVISEMPTY( in ) );
3761 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3765 if ( out != NULL ) {
3766 assert( !BER_BVISNULL( out ) );
3767 assert( out->bv_len >= sizeof( buf ) );
3768 bv.bv_val = out->bv_val;
3774 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3775 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3778 if ( in->bv_val[i] != 'Z' ) {
3783 if ( i != in->bv_len ) {
3787 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3788 lutil_strncopy( bv.bv_val, in->bv_val, i );
3791 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3792 char *p = bv.bv_val;
3793 if ( in->bv_val[0] < '7' ) {
3794 p = lutil_strcopy( p, "20" );
3797 p = lutil_strcopy( p, "19" );
3799 lutil_strncopy( p, in->bv_val, i );
3806 rc = generalizedTimeValidate( NULL, &bv );
3807 if ( rc == LDAP_SUCCESS && out != NULL ) {
3808 if ( out->bv_len > bv.bv_len ) {
3809 out->bv_val[ bv.bv_len ] = '\0';
3811 out->bv_len = bv.bv_len;
3814 return rc != LDAP_SUCCESS;
3818 issuerAndThisUpdateCheck(
3825 struct berval x = *in;
3826 struct berval ni = BER_BVNULL;
3827 /* Parse GSER format */
3831 HAVE_THISUPDATE = 0x2,
3832 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3836 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3838 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3839 return LDAP_INVALID_SYNTAX;
3843 x.bv_len -= STRLENOF("{}");
3846 /* eat leading spaces */
3847 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3851 /* should be at issuer or thisUpdate */
3852 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3853 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3856 x.bv_val += STRLENOF("issuer");
3857 x.bv_len -= STRLENOF("issuer");
3859 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3863 /* eat leading spaces */
3864 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3868 /* For backward compatibility, this part is optional */
3869 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3870 return LDAP_INVALID_SYNTAX;
3872 x.bv_val += STRLENOF("rdnSequence:");
3873 x.bv_len -= STRLENOF("rdnSequence:");
3875 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3879 is->bv_val = x.bv_val;
3882 for ( ; is->bv_len < x.bv_len; ) {
3883 if ( is->bv_val[is->bv_len] != '"' ) {
3887 if ( is->bv_val[is->bv_len+1] == '"' ) {
3894 x.bv_val += is->bv_len + 1;
3895 x.bv_len -= is->bv_len + 1;
3897 have |= HAVE_ISSUER;
3899 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3901 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3903 /* parse thisUpdate */
3904 x.bv_val += STRLENOF("thisUpdate");
3905 x.bv_len -= STRLENOF("thisUpdate");
3907 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3911 /* eat leading spaces */
3912 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3916 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3920 tu->bv_val = x.bv_val;
3923 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3924 if ( tu->bv_val[tu->bv_len] == '"' ) {
3928 x.bv_val += tu->bv_len + 1;
3929 x.bv_len -= tu->bv_len + 1;
3931 have |= HAVE_THISUPDATE;
3934 return LDAP_INVALID_SYNTAX;
3937 /* eat leading spaces */
3938 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3942 if ( have == HAVE_ALL ) {
3946 if ( x.bv_val[0] != ',' ) {
3947 return LDAP_INVALID_SYNTAX;
3954 /* should have no characters left... */
3955 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3957 if ( numdquotes == 0 ) {
3958 ber_dupbv_x( &ni, is, ctx );
3963 ni.bv_len = is->bv_len - numdquotes;
3964 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3965 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3966 if ( is->bv_val[src] == '"' ) {
3969 ni.bv_val[dst] = is->bv_val[src];
3971 ni.bv_val[dst] = '\0';
3980 issuerAndThisUpdateValidate(
3985 struct berval i, tu;
3987 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3990 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3995 /* validate DN -- doesn't handle double dquote */
3996 rc = dnValidate( NULL, &i );
3998 rc = LDAP_INVALID_SYNTAX;
4000 } else if ( checkTime( &tu, NULL ) ) {
4001 rc = LDAP_INVALID_SYNTAX;
4004 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4005 slap_sl_free( i.bv_val, NULL );
4008 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
4009 in->bv_val, rc, 0 );
4016 issuerAndThisUpdatePretty(
4023 struct berval i, tu, ni = BER_BVNULL;
4026 assert( in != NULL );
4027 assert( out != NULL );
4031 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
4034 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4039 rc = dnPretty( syntax, &i, &ni, ctx );
4041 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4042 slap_sl_free( i.bv_val, ctx );
4045 if ( rc || checkTime( &tu, NULL ) ) {
4046 rc = LDAP_INVALID_SYNTAX;
4051 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
4052 + ni.bv_len + tu.bv_len;
4053 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4055 if ( out->bv_val == NULL ) {
4062 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4063 p = lutil_strbvcopy( p, &ni );
4064 p = lutil_strcopy( p, "\", thisUpdate \"" );
4065 p = lutil_strbvcopy( p, &tu );
4066 p = lutil_strcopy( p, /*{*/ "\" }" );
4068 assert( p == &out->bv_val[out->bv_len] );
4071 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
4072 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4074 slap_sl_free( ni.bv_val, ctx );
4080 issuerAndThisUpdateNormalize(
4088 struct berval i, ni, tu, tu2;
4089 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4093 assert( in != NULL );
4094 assert( out != NULL );
4096 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
4099 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
4104 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4106 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4107 slap_sl_free( i.bv_val, ctx );
4111 tu2.bv_len = sizeof( sbuf );
4112 if ( rc || checkTime( &tu, &tu2 ) ) {
4113 return LDAP_INVALID_SYNTAX;
4116 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4117 + ni.bv_len + tu2.bv_len;
4118 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4120 if ( out->bv_val == NULL ) {
4128 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
4129 p = lutil_strbvcopy( p, &ni );
4130 p = lutil_strcopy( p, "\", thisUpdate \"" );
4131 p = lutil_strbvcopy( p, &tu2 );
4132 p = lutil_strcopy( p, /*{*/ "\" }" );
4134 assert( p == &out->bv_val[out->bv_len] );
4137 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4138 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4140 slap_sl_free( ni.bv_val, ctx );
4146 certificateListExactNormalize(
4151 struct berval *normalized,
4154 BerElementBuffer berbuf;
4155 BerElement *ber = (BerElement *)&berbuf;
4159 struct berval issuer_dn = BER_BVNULL, bvdn,
4161 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4162 int rc = LDAP_INVALID_SYNTAX;
4164 assert( val != NULL );
4166 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4167 val->bv_val, val->bv_len, 0 );
4169 if ( BER_BVISEMPTY( val ) ) goto done;
4171 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4172 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4175 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4177 ber_init2( ber, val, LBER_USE_DER );
4178 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4179 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4180 tag = ber_skip_tag( ber, &len ); /* Sequence */
4181 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4182 tag = ber_peek_tag( ber, &len );
4183 /* Optional version */
4184 if ( tag == LBER_INTEGER ) {
4185 tag = ber_get_int( ber, &version );
4186 assert( tag == LBER_INTEGER );
4187 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4189 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4190 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4191 ber_skip_data( ber, len );
4193 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4194 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4195 len = ber_ptrlen( ber );
4196 bvdn.bv_val = val->bv_val + len;
4197 bvdn.bv_len = val->bv_len - len;
4198 tag = ber_skip_tag( ber, &len );
4199 ber_skip_data( ber, len );
4201 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4202 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4203 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4204 bvtu.bv_val = (char *)ber->ber_ptr;
4207 rc = dnX509normalize( &bvdn, &issuer_dn );
4208 if ( rc != LDAP_SUCCESS ) goto done;
4210 thisUpdate.bv_val = tubuf;
4211 thisUpdate.bv_len = sizeof(tubuf);
4212 if ( checkTime( &bvtu, &thisUpdate ) ) {
4213 rc = LDAP_INVALID_SYNTAX;
4217 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4218 + issuer_dn.bv_len + thisUpdate.bv_len;
4219 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4221 p = normalized->bv_val;
4223 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4224 p = lutil_strbvcopy( p, &issuer_dn );
4225 p = lutil_strcopy( p, "\", thisUpdate \"" );
4226 p = lutil_strbvcopy( p, &thisUpdate );
4227 p = lutil_strcopy( p, /*{*/ "\" }" );
4232 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4233 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4235 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4240 /* X.509 PMI serialNumberAndIssuerSerialCheck
4242 AttributeCertificateExactAssertion ::= SEQUENCE {
4243 serialNumber CertificateSerialNumber,
4244 issuer AttCertIssuer }
4246 CertificateSerialNumber ::= INTEGER
4248 AttCertIssuer ::= [0] SEQUENCE {
4249 issuerName GeneralNames OPTIONAL,
4250 baseCertificateID [0] IssuerSerial OPTIONAL,
4251 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4252 -- At least one component shall be present
4254 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4256 GeneralName ::= CHOICE {
4257 otherName [0] INSTANCE OF OTHER-NAME,
4258 rfc822Name [1] IA5String,
4259 dNSName [2] IA5String,
4260 x400Address [3] ORAddress,
4261 directoryName [4] Name,
4262 ediPartyName [5] EDIPartyName,
4263 uniformResourceIdentifier [6] IA5String,
4264 iPAddress [7] OCTET STRING,
4265 registeredID [8] OBJECT IDENTIFIER }
4267 IssuerSerial ::= SEQUENCE {
4268 issuer GeneralNames,
4269 serial CertificateSerialNumber,
4270 issuerUID UniqueIdentifier OPTIONAL }
4272 ObjectDigestInfo ::= SEQUENCE {
4273 digestedObjectType ENUMERATED {
4276 otherObjectTypes (2) },
4277 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4278 digestAlgorithm AlgorithmIdentifier,
4279 objectDigest BIT STRING }
4281 * The way I interpret it, an assertion should look like
4283 { serialNumber 'dd'H,
4284 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4285 baseCertificateID { serial '1d'H,
4286 issuer { directoryName:rdnSequence:"cn=zzz" },
4287 issuerUID <value> -- optional
4289 objectDigestInfo { ... } -- optional
4293 * with issuerName, baseCertificateID and objectDigestInfo optional,
4294 * at least one present; the way it's currently implemented, it is
4296 { serialNumber 'dd'H,
4297 issuer { baseCertificateID { serial '1d'H,
4298 issuer { directoryName:rdnSequence:"cn=zzz" }
4303 * with all the above parts mandatory.
4306 serialNumberAndIssuerSerialCheck(
4310 struct berval *i_sn, /* contain serial of baseCertificateID */
4313 /* Parse GSER format */
4318 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4319 } have = HAVE_NONE, have2 = HAVE_NONE;
4321 struct berval x = *in;
4324 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4327 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4334 /* eat leading spaces */
4335 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4339 /* should be at issuer or serialNumber NamedValue */
4340 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4341 if ( have & HAVE_ISSUER ) {
4342 return LDAP_INVALID_SYNTAX;
4345 /* parse IssuerSerial */
4346 x.bv_val += STRLENOF("issuer");
4347 x.bv_len -= STRLENOF("issuer");
4349 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4353 /* eat leading spaces */
4354 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4358 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4362 /* eat leading spaces */
4363 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4367 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4368 return LDAP_INVALID_SYNTAX;
4370 x.bv_val += STRLENOF("baseCertificateID ");
4371 x.bv_len -= STRLENOF("baseCertificateID ");
4373 /* eat leading spaces */
4374 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4378 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4383 /* eat leading spaces */
4384 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4388 /* parse issuer of baseCertificateID */
4389 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4390 if ( have2 & HAVE_ISSUER ) {
4391 return LDAP_INVALID_SYNTAX;
4394 x.bv_val += STRLENOF("issuer ");
4395 x.bv_len -= STRLENOF("issuer ");
4397 /* eat leading spaces */
4398 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4402 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4406 /* eat leading spaces */
4407 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4411 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4412 return LDAP_INVALID_SYNTAX;
4414 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4415 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4417 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4421 is->bv_val = x.bv_val;
4424 for ( ; is->bv_len < x.bv_len; ) {
4425 if ( is->bv_val[is->bv_len] != '"' ) {
4429 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4436 x.bv_val += is->bv_len + 1;
4437 x.bv_len -= is->bv_len + 1;
4439 /* eat leading spaces */
4440 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4444 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4448 have2 |= HAVE_ISSUER;
4450 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4451 if ( have2 & HAVE_SN ) {
4452 return LDAP_INVALID_SYNTAX;
4455 x.bv_val += STRLENOF("serial ");
4456 x.bv_len -= STRLENOF("serial ");
4458 /* eat leading spaces */
4459 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4463 if ( checkNum( &x, i_sn ) ) {
4464 return LDAP_INVALID_SYNTAX;
4467 x.bv_val += i_sn->bv_len;
4468 x.bv_len -= i_sn->bv_len;
4473 return LDAP_INVALID_SYNTAX;
4476 /* eat leading spaces */
4477 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4481 if ( have2 == HAVE_ALL ) {
4485 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4490 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4494 /* eat leading spaces */
4495 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4499 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4503 have |= HAVE_ISSUER;
4505 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4506 if ( have & HAVE_SN ) {
4507 return LDAP_INVALID_SYNTAX;
4510 /* parse serialNumber */
4511 x.bv_val += STRLENOF("serialNumber");
4512 x.bv_len -= STRLENOF("serialNumber");
4514 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4518 /* eat leading spaces */
4519 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4523 if ( checkNum( &x, sn ) ) {
4524 return LDAP_INVALID_SYNTAX;
4527 x.bv_val += sn->bv_len;
4528 x.bv_len -= sn->bv_len;
4533 return LDAP_INVALID_SYNTAX;
4537 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4541 if ( have == HAVE_ALL ) {
4545 if ( x.bv_val[0] != ',' ) {
4546 return LDAP_INVALID_SYNTAX;
4552 /* should have no characters left... */
4553 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4555 if ( numdquotes == 0 ) {
4556 ber_dupbv_x( &ni, is, ctx );
4561 ni.bv_len = is->bv_len - numdquotes;
4562 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4563 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4564 if ( is->bv_val[src] == '"' ) {
4567 ni.bv_val[dst] = is->bv_val[src];
4569 ni.bv_val[dst] = '\0';
4574 /* need to handle double dquotes here */
4578 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4580 serialNumberAndIssuerSerialValidate(
4585 struct berval sn, i, i_sn;
4587 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4590 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4595 /* validate DN -- doesn't handle double dquote */
4596 rc = dnValidate( NULL, &i );
4598 rc = LDAP_INVALID_SYNTAX;
4601 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4602 slap_sl_free( i.bv_val, NULL );
4606 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4607 in->bv_val, rc, 0 );
4612 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4614 serialNumberAndIssuerSerialPretty(
4620 struct berval sn, i, i_sn, ni = BER_BVNULL;
4624 assert( in != NULL );
4625 assert( out != NULL );
4627 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4630 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4635 rc = dnPretty( syntax, &i, &ni, ctx );
4637 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4638 slap_sl_free( i.bv_val, ctx );
4642 rc = LDAP_INVALID_SYNTAX;
4646 /* make room from sn + "$" */
4647 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4648 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4649 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4651 if ( out->bv_val == NULL ) {
4658 p = lutil_strcopy( p, "{ serialNumber " );
4659 p = lutil_strbvcopy( p, &sn );
4660 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4661 p = lutil_strbvcopy( p, &ni );
4662 p = lutil_strcopy( p, "\" }, serial " );
4663 p = lutil_strbvcopy( p, &i_sn );
4664 p = lutil_strcopy( p, " } } }" );
4666 assert( p == &out->bv_val[out->bv_len] );
4669 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4670 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4672 slap_sl_free( ni.bv_val, ctx );
4677 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4679 * This routine is called by attributeCertificateExactNormalize
4680 * when attributeCertificateExactNormalize receives a search
4681 * string instead of a attribute certificate. This routine
4682 * checks if the search value is valid and then returns the
4686 serialNumberAndIssuerSerialNormalize(
4694 struct berval i, ni = BER_BVNULL,
4695 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4696 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4697 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4698 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4702 assert( in != NULL );
4703 assert( out != NULL );
4705 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4708 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4713 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4715 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4716 slap_sl_free( i.bv_val, ctx );
4720 rc = LDAP_INVALID_SYNTAX;
4724 /* Convert sn to canonical hex */
4726 sn2.bv_len = sn.bv_len;
4727 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4728 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4730 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4731 rc = LDAP_INVALID_SYNTAX;
4735 /* Convert i_sn to canonical hex */
4736 i_sn2.bv_val = i_sbuf2;
4737 i_sn2.bv_len = i_sn.bv_len;
4738 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4739 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4741 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4742 rc = LDAP_INVALID_SYNTAX;
4747 sn3.bv_len = sizeof(sbuf3);
4748 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4749 rc = LDAP_INVALID_SYNTAX;
4753 i_sn3.bv_val = i_sbuf3;
4754 i_sn3.bv_len = sizeof(i_sbuf3);
4755 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4756 rc = LDAP_INVALID_SYNTAX;
4760 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4761 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4762 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4764 if ( out->bv_val == NULL ) {
4772 p = lutil_strcopy( p, "{ serialNumber " );
4773 p = lutil_strbvcopy( p, &sn3 );
4774 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4775 p = lutil_strbvcopy( p, &ni );
4776 p = lutil_strcopy( p, "\" }, serial " );
4777 p = lutil_strbvcopy( p, &i_sn3 );
4778 p = lutil_strcopy( p, " } } }" );
4780 assert( p == &out->bv_val[out->bv_len] );
4783 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4784 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4786 if ( sn2.bv_val != sbuf2 ) {
4787 slap_sl_free( sn2.bv_val, ctx );
4790 if ( i_sn2.bv_val != i_sbuf2 ) {
4791 slap_sl_free( i_sn2.bv_val, ctx );
4794 if ( sn3.bv_val != sbuf3 ) {
4795 slap_sl_free( sn3.bv_val, ctx );
4798 if ( i_sn3.bv_val != i_sbuf3 ) {
4799 slap_sl_free( i_sn3.bv_val, ctx );
4802 slap_sl_free( ni.bv_val, ctx );
4807 /* X.509 PMI attributeCertificateExactNormalize */
4809 attributeCertificateExactNormalize(
4814 struct berval *normalized,
4817 BerElementBuffer berbuf;
4818 BerElement *ber = (BerElement *)&berbuf;
4821 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4822 struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
4823 struct berval issuer_dn = BER_BVNULL, bvdn;
4825 int rc = LDAP_INVALID_SYNTAX;
4827 if ( BER_BVISEMPTY( val ) ) {
4831 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4832 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4835 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4837 ber_init2( ber, val, LBER_USE_DER );
4838 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4839 tag = ber_skip_tag( ber, &len ); /* Sequence */
4840 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4841 ber_skip_data( ber, len );
4842 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4843 ber_skip_data( ber, len );
4846 tag = ber_skip_tag( ber, &len ); /* Sequence */
4847 /* issuerName (GeneralNames sequence; optional)? */
4848 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4849 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4850 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4851 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4852 return LDAP_INVALID_SYNTAX;
4854 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4855 len = ber_ptrlen( ber );
4856 bvdn.bv_val = val->bv_val + len;
4857 bvdn.bv_len = val->bv_len - len;
4858 rc = dnX509normalize( &bvdn, &issuer_dn );
4859 if ( rc != LDAP_SUCCESS ) goto done;
4861 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4862 ber_skip_data( ber, len );
4863 tag = ber_skip_tag( ber, &len ); /* serial number */
4864 if ( tag != LBER_INTEGER ) {
4865 rc = LDAP_INVALID_SYNTAX;
4868 i_sn.bv_val = (char *)ber->ber_ptr;
4870 i_sn2.bv_val = issuer_serialbuf;
4871 i_sn2.bv_len = sizeof(issuer_serialbuf);
4872 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4873 rc = LDAP_INVALID_SYNTAX;
4876 ber_skip_data( ber, len );
4878 /* issuerUID (bitstring; optional)? */
4879 /* objectDigestInfo (sequence; optional)? */
4881 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4882 ber_skip_data( ber, len );
4883 tag = ber_skip_tag( ber, &len ); /* serial number */
4884 if ( tag != LBER_INTEGER ) {
4885 rc = LDAP_INVALID_SYNTAX;
4888 sn.bv_val = (char *)ber->ber_ptr;
4890 sn2.bv_val = serialbuf;
4891 sn2.bv_len = sizeof(serialbuf);
4892 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4893 rc = LDAP_INVALID_SYNTAX;
4896 ber_skip_data( ber, len );
4898 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4899 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4900 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4902 p = normalized->bv_val;
4904 p = lutil_strcopy( p, "{ serialNumber " );
4905 p = lutil_strbvcopy( p, &sn2 );
4906 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4907 p = lutil_strbvcopy( p, &issuer_dn );
4908 p = lutil_strcopy( p, "\" }, serial " );
4909 p = lutil_strbvcopy( p, &i_sn2 );
4910 p = lutil_strcopy( p, " } } }" );
4912 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4913 normalized->bv_val, NULL, NULL );
4918 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4919 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4920 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4933 assert( in != NULL );
4934 assert( !BER_BVISNULL( in ) );
4936 for ( i = 0; i < in->bv_len; i++ ) {
4937 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4938 return LDAP_INVALID_SYNTAX;
4942 return LDAP_SUCCESS;
4945 /* Normalize a SID as used inside a CSN:
4946 * three-digit numeric string */
4953 struct berval *normalized,
4958 assert( val != NULL );
4959 assert( normalized != NULL );
4961 ber_dupbv_x( normalized, val, ctx );
4963 for ( i = 0; i < normalized->bv_len; i++ ) {
4964 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4965 ber_memfree_x( normalized->bv_val, ctx );
4966 BER_BVZERO( normalized );
4967 return LDAP_INVALID_SYNTAX;
4970 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4973 return LDAP_SUCCESS;
4981 assert( in != NULL );
4982 assert( !BER_BVISNULL( in ) );
4984 if ( in->bv_len != 3 ) {
4985 return LDAP_INVALID_SYNTAX;
4988 return hexValidate( NULL, in );
4991 /* Normalize a SID as used inside a CSN:
4992 * three-digit numeric string */
4999 struct berval *normalized,
5002 if ( val->bv_len != 3 ) {
5003 return LDAP_INVALID_SYNTAX;
5006 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
5016 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5019 /* Normalize a SID as used inside a CSN, either as-is
5020 * (assertion value) or extracted from the CSN
5021 * (attribute value) */
5028 struct berval *normalized,
5036 if ( BER_BVISEMPTY( val ) ) {
5037 return LDAP_INVALID_SYNTAX;
5040 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
5041 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
5044 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
5046 ptr = ber_bvchr( val, '#' );
5047 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5048 return LDAP_INVALID_SYNTAX;
5051 bv.bv_val = ptr + 1;
5052 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5054 ptr = ber_bvchr( &bv, '#' );
5055 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5056 return LDAP_INVALID_SYNTAX;
5059 bv.bv_val = ptr + 1;
5060 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
5062 ptr = ber_bvchr( &bv, '#' );
5063 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5064 return LDAP_INVALID_SYNTAX;
5067 bv.bv_len = ptr - bv.bv_val;
5069 if ( bv.bv_len == 2 ) {
5070 /* OpenLDAP 2.3 SID */
5072 buf[ 1 ] = bv.bv_val[ 0 ];
5073 buf[ 2 ] = bv.bv_val[ 1 ];
5080 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
5092 assert( in != NULL );
5093 assert( !BER_BVISNULL( in ) );
5095 if ( BER_BVISEMPTY( in ) ) {
5096 return LDAP_INVALID_SYNTAX;
5101 ptr = ber_bvchr( &bv, '#' );
5102 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
5103 return LDAP_INVALID_SYNTAX;
5106 bv.bv_len = ptr - bv.bv_val;
5107 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
5108 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
5110 return LDAP_INVALID_SYNTAX;
5113 rc = generalizedTimeValidate( NULL, &bv );
5114 if ( rc != LDAP_SUCCESS ) {
5118 bv.bv_val = ptr + 1;
5119 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5121 ptr = ber_bvchr( &bv, '#' );
5122 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5123 return LDAP_INVALID_SYNTAX;
5126 bv.bv_len = ptr - bv.bv_val;
5127 if ( bv.bv_len != 6 ) {
5128 return LDAP_INVALID_SYNTAX;
5131 rc = hexValidate( NULL, &bv );
5132 if ( rc != LDAP_SUCCESS ) {
5136 bv.bv_val = ptr + 1;
5137 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5139 ptr = ber_bvchr( &bv, '#' );
5140 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5141 return LDAP_INVALID_SYNTAX;
5144 bv.bv_len = ptr - bv.bv_val;
5145 if ( bv.bv_len == 2 ) {
5146 /* tolerate old 2-digit replica-id */
5147 rc = hexValidate( NULL, &bv );
5150 rc = sidValidate( NULL, &bv );
5152 if ( rc != LDAP_SUCCESS ) {
5156 bv.bv_val = ptr + 1;
5157 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5159 if ( bv.bv_len != 6 ) {
5160 return LDAP_INVALID_SYNTAX;
5163 return hexValidate( NULL, &bv );
5166 /* Normalize a CSN in OpenLDAP 2.1 format */
5173 struct berval *normalized,
5176 struct berval gt, cnt, sid, mod;
5178 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5182 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5183 assert( !BER_BVISEMPTY( val ) );
5187 ptr = ber_bvchr( >, '#' );
5188 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5189 return LDAP_INVALID_SYNTAX;
5192 gt.bv_len = ptr - gt.bv_val;
5193 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5194 return LDAP_INVALID_SYNTAX;
5197 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5198 return LDAP_INVALID_SYNTAX;
5201 cnt.bv_val = ptr + 1;
5202 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5204 ptr = ber_bvchr( &cnt, '#' );
5205 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5206 return LDAP_INVALID_SYNTAX;
5209 cnt.bv_len = ptr - cnt.bv_val;
5210 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5211 return LDAP_INVALID_SYNTAX;
5214 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5215 return LDAP_INVALID_SYNTAX;
5218 cnt.bv_val += STRLENOF( "0x" );
5219 cnt.bv_len -= STRLENOF( "0x" );
5221 sid.bv_val = ptr + 1;
5222 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5224 ptr = ber_bvchr( &sid, '#' );
5225 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5226 return LDAP_INVALID_SYNTAX;
5229 sid.bv_len = ptr - sid.bv_val;
5230 if ( sid.bv_len != STRLENOF( "0" ) ) {
5231 return LDAP_INVALID_SYNTAX;
5234 mod.bv_val = ptr + 1;
5235 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5236 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5237 return LDAP_INVALID_SYNTAX;
5240 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5244 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5245 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5247 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5249 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5250 ptr = lutil_strbvcopy( ptr, &cnt );
5254 *ptr++ = sid.bv_val[ 0 ];
5258 for ( i = 0; i < mod.bv_len; i++ ) {
5259 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5263 assert( ptr == &bv.bv_val[bv.bv_len] );
5265 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5266 return LDAP_INVALID_SYNTAX;
5269 ber_dupbv_x( normalized, &bv, ctx );
5271 return LDAP_SUCCESS;
5274 /* Normalize a CSN in OpenLDAP 2.3 format */
5281 struct berval *normalized,
5284 struct berval gt, cnt, sid, mod;
5286 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5290 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5291 assert( !BER_BVISEMPTY( val ) );
5295 ptr = ber_bvchr( >, '#' );
5296 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5297 return LDAP_INVALID_SYNTAX;
5300 gt.bv_len = ptr - gt.bv_val;
5301 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5302 return LDAP_INVALID_SYNTAX;
5305 cnt.bv_val = ptr + 1;
5306 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5308 ptr = ber_bvchr( &cnt, '#' );
5309 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5310 return LDAP_INVALID_SYNTAX;
5313 cnt.bv_len = ptr - cnt.bv_val;
5314 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5315 return LDAP_INVALID_SYNTAX;
5318 sid.bv_val = ptr + 1;
5319 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5321 ptr = ber_bvchr( &sid, '#' );
5322 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5323 return LDAP_INVALID_SYNTAX;
5326 sid.bv_len = ptr - sid.bv_val;
5327 if ( sid.bv_len != STRLENOF( "00" ) ) {
5328 return LDAP_INVALID_SYNTAX;
5331 mod.bv_val = ptr + 1;
5332 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5333 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5334 return LDAP_INVALID_SYNTAX;
5337 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5341 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5342 ptr = lutil_strcopy( ptr, ".000000Z#" );
5343 ptr = lutil_strbvcopy( ptr, &cnt );
5346 for ( i = 0; i < sid.bv_len; i++ ) {
5347 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5350 for ( i = 0; i < mod.bv_len; i++ ) {
5351 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5355 assert( ptr == &bv.bv_val[bv.bv_len] );
5356 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5357 return LDAP_INVALID_SYNTAX;
5360 ber_dupbv_x( normalized, &bv, ctx );
5362 return LDAP_SUCCESS;
5365 /* Normalize a CSN */
5372 struct berval *normalized,
5375 struct berval cnt, sid, mod;
5379 assert( val != NULL );
5380 assert( normalized != NULL );
5382 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5384 if ( BER_BVISEMPTY( val ) ) {
5385 return LDAP_INVALID_SYNTAX;
5388 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5389 /* Openldap <= 2.3 */
5391 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5394 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5397 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5400 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5401 return LDAP_INVALID_SYNTAX;
5404 ptr = ber_bvchr( val, '#' );
5405 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5406 return LDAP_INVALID_SYNTAX;
5409 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5410 return LDAP_INVALID_SYNTAX;
5413 cnt.bv_val = ptr + 1;
5414 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5416 ptr = ber_bvchr( &cnt, '#' );
5417 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5418 return LDAP_INVALID_SYNTAX;
5421 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5422 return LDAP_INVALID_SYNTAX;
5425 sid.bv_val = ptr + 1;
5426 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5428 ptr = ber_bvchr( &sid, '#' );
5429 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5430 return LDAP_INVALID_SYNTAX;
5433 sid.bv_len = ptr - sid.bv_val;
5434 if ( sid.bv_len != STRLENOF( "000" ) ) {
5435 return LDAP_INVALID_SYNTAX;
5438 mod.bv_val = ptr + 1;
5439 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5441 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5442 return LDAP_INVALID_SYNTAX;
5445 ber_dupbv_x( normalized, val, ctx );
5447 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5448 i < normalized->bv_len; i++ )
5450 /* assume it's already validated that's all hex digits */
5451 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5454 return LDAP_SUCCESS;
5464 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5467 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5468 /* slight optimization - does not need the start parameter */
5469 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5474 check_time_syntax (struct berval *val,
5477 struct berval *fraction)
5480 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5481 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5482 * GeneralizedTime supports leap seconds, UTCTime does not.
5484 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5485 static const int mdays[2][12] = {
5486 /* non-leap years */
5487 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5489 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5492 int part, c, c1, c2, tzoffset, leapyear = 0;
5495 e = p + val->bv_len;
5497 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5498 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5500 for (part = start; part < 7 && p < e; part++) {
5502 if (!ASCII_DIGIT(c1)) {
5507 return LDAP_INVALID_SYNTAX;
5510 if (!ASCII_DIGIT(c)) {
5511 return LDAP_INVALID_SYNTAX;
5513 c += c1 * 10 - '0' * 11;
5514 if ((part | 1) == 3) {
5517 return LDAP_INVALID_SYNTAX;
5520 if (c >= ceiling[part]) {
5521 if (! (c == 60 && part == 6 && start == 0))
5522 return LDAP_INVALID_SYNTAX;
5526 if (part < 5 + start) {
5527 return LDAP_INVALID_SYNTAX;
5529 for (; part < 9; part++) {
5533 /* leapyear check for the Gregorian calendar (year>1581) */
5534 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5538 if (parts[3] >= mdays[leapyear][parts[2]]) {
5539 return LDAP_INVALID_SYNTAX;
5543 fraction->bv_val = p;
5544 fraction->bv_len = 0;
5545 if (p < e && (*p == '.' || *p == ',')) {
5547 while (++p < e && ASCII_DIGIT(*p)) {
5550 if (p - fraction->bv_val == 1) {
5551 return LDAP_INVALID_SYNTAX;
5553 for (end_num = p; end_num[-1] == '0'; --end_num) {
5556 c = end_num - fraction->bv_val;
5557 if (c != 1) fraction->bv_len = c;
5563 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5569 return LDAP_INVALID_SYNTAX;
5575 for (part = 7; part < 9 && p < e; part++) {
5577 if (!ASCII_DIGIT(c1)) {
5582 return LDAP_INVALID_SYNTAX;
5585 if (!ASCII_DIGIT(c2)) {
5586 return LDAP_INVALID_SYNTAX;
5588 parts[part] = c1 * 10 + c2 - '0' * 11;
5589 if (parts[part] >= ceiling[part]) {
5590 return LDAP_INVALID_SYNTAX;
5593 if (part < 8 + start) {
5594 return LDAP_INVALID_SYNTAX;
5597 if (tzoffset == '-') {
5598 /* negative offset to UTC, ie west of Greenwich */
5599 parts[4] += parts[7];
5600 parts[5] += parts[8];
5601 /* offset is just hhmm, no seconds */
5602 for (part = 6; --part >= 0; ) {
5606 c = mdays[leapyear][parts[2]];
5608 if (parts[part] >= c) {
5610 return LDAP_INVALID_SYNTAX;
5615 } else if (part != 5) {
5620 /* positive offset to UTC, ie east of Greenwich */
5621 parts[4] -= parts[7];
5622 parts[5] -= parts[8];
5623 for (part = 6; --part >= 0; ) {
5624 if (parts[part] < 0) {
5626 return LDAP_INVALID_SYNTAX;
5631 /* make first arg to % non-negative */
5632 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5637 } else if (part != 5) {
5644 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5647 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5654 struct berval *normalized )
5658 rc = check_time_syntax(val, 1, parts, NULL);
5659 if (rc != LDAP_SUCCESS) {
5663 normalized->bv_val = ch_malloc( 14 );
5664 if ( normalized->bv_val == NULL ) {
5665 return LBER_ERROR_MEMORY;
5668 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5669 parts[1], parts[2] + 1, parts[3] + 1,
5670 parts[4], parts[5], parts[6] );
5671 normalized->bv_len = 13;
5673 return LDAP_SUCCESS;
5683 return check_time_syntax(in, 1, parts, NULL);
5686 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5689 generalizedTimeValidate(
5694 struct berval fraction;
5695 return check_time_syntax(in, 0, parts, &fraction);
5699 generalizedTimeNormalize(
5704 struct berval *normalized,
5709 struct berval fraction;
5711 rc = check_time_syntax(val, 0, parts, &fraction);
5712 if (rc != LDAP_SUCCESS) {
5716 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5717 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5718 if ( BER_BVISNULL( normalized ) ) {
5719 return LBER_ERROR_MEMORY;
5722 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5723 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5724 parts[4], parts[5], parts[6] );
5725 if ( !BER_BVISEMPTY( &fraction ) ) {
5726 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5727 fraction.bv_val, fraction.bv_len );
5728 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5730 strcpy( normalized->bv_val + len-1, "Z" );
5731 normalized->bv_len = len;
5733 return LDAP_SUCCESS;
5737 generalizedTimeOrderingMatch(
5742 struct berval *value,
5743 void *assertedValue )
5745 struct berval *asserted = (struct berval *) assertedValue;
5746 ber_len_t v_len = value->bv_len;
5747 ber_len_t av_len = asserted->bv_len;
5749 /* ignore trailing 'Z' when comparing */
5750 int match = memcmp( value->bv_val, asserted->bv_val,
5751 (v_len < av_len ? v_len : av_len) - 1 );
5752 if ( match == 0 ) match = v_len - av_len;
5754 /* If used in extensible match filter, match if value < asserted */
5755 if ( flags & SLAP_MR_EXT )
5756 match = (match >= 0);
5759 return LDAP_SUCCESS;
5762 /* Index generation function: Ordered index */
5763 int generalizedTimeIndexer(
5768 struct berval *prefix,
5776 BerValue bvtmp; /* 40 bit index */
5778 struct lutil_timet tt;
5780 bvtmp.bv_len = sizeof(tmp);
5782 for( i=0; values[i].bv_val != NULL; i++ ) {
5783 /* just count them */
5786 /* we should have at least one value at this point */
5789 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5791 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5792 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5793 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5794 /* Use 40 bits of time for key */
5795 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5796 lutil_tm2time( &tm, &tt );
5797 tmp[0] = tt.tt_gsec & 0xff;
5798 tmp[4] = tt.tt_sec & 0xff;
5800 tmp[3] = tt.tt_sec & 0xff;
5802 tmp[2] = tt.tt_sec & 0xff;
5804 tmp[1] = tt.tt_sec & 0xff;
5806 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5810 keys[j].bv_val = NULL;
5815 return LDAP_SUCCESS;
5818 /* Index generation function: Ordered index */
5819 int generalizedTimeFilter(
5824 struct berval *prefix,
5825 void * assertedValue,
5831 BerValue bvtmp; /* 40 bit index */
5832 BerValue *value = (BerValue *) assertedValue;
5834 struct lutil_timet tt;
5836 bvtmp.bv_len = sizeof(tmp);
5838 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5839 /* Use 40 bits of time for key */
5840 if ( value->bv_val && value->bv_len >= 10 &&
5841 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5843 lutil_tm2time( &tm, &tt );
5844 tmp[0] = tt.tt_gsec & 0xff;
5845 tmp[4] = tt.tt_sec & 0xff;
5847 tmp[3] = tt.tt_sec & 0xff;
5849 tmp[2] = tt.tt_sec & 0xff;
5851 tmp[1] = tt.tt_sec & 0xff;
5853 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5854 ber_dupbv_x(keys, &bvtmp, ctx );
5855 keys[1].bv_val = NULL;
5863 return LDAP_SUCCESS;
5867 deliveryMethodValidate(
5869 struct berval *val )
5872 #define LENOF(s) (sizeof(s)-1)
5873 struct berval tmp = *val;
5875 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5876 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5877 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5880 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5882 switch( tmp.bv_val[0] ) {
5885 if(( tmp.bv_len >= LENOF("any") ) &&
5886 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5888 tmp.bv_len -= LENOF("any");
5889 tmp.bv_val += LENOF("any");
5892 return LDAP_INVALID_SYNTAX;
5896 if(( tmp.bv_len >= LENOF("mhs") ) &&
5897 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5899 tmp.bv_len -= LENOF("mhs");
5900 tmp.bv_val += LENOF("mhs");
5903 return LDAP_INVALID_SYNTAX;
5907 if(( tmp.bv_len >= LENOF("physical") ) &&
5908 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5910 tmp.bv_len -= LENOF("physical");
5911 tmp.bv_val += LENOF("physical");
5914 return LDAP_INVALID_SYNTAX;
5917 case 'T': /* telex or teletex or telephone */
5918 if(( tmp.bv_len >= LENOF("telex") ) &&
5919 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5921 tmp.bv_len -= LENOF("telex");
5922 tmp.bv_val += LENOF("telex");
5925 if(( tmp.bv_len >= LENOF("teletex") ) &&
5926 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5928 tmp.bv_len -= LENOF("teletex");
5929 tmp.bv_val += LENOF("teletex");
5932 if(( tmp.bv_len >= LENOF("telephone") ) &&
5933 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5935 tmp.bv_len -= LENOF("telephone");
5936 tmp.bv_val += LENOF("telephone");
5939 return LDAP_INVALID_SYNTAX;
5942 case 'G': /* g3fax or g4fax */
5943 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5944 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5945 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5947 tmp.bv_len -= LENOF("g3fax");
5948 tmp.bv_val += LENOF("g3fax");
5951 return LDAP_INVALID_SYNTAX;
5955 if(( tmp.bv_len >= LENOF("ia5") ) &&
5956 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5958 tmp.bv_len -= LENOF("ia5");
5959 tmp.bv_val += LENOF("ia5");
5962 return LDAP_INVALID_SYNTAX;
5966 if(( tmp.bv_len >= LENOF("videotex") ) &&
5967 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5969 tmp.bv_len -= LENOF("videotex");
5970 tmp.bv_val += LENOF("videotex");
5973 return LDAP_INVALID_SYNTAX;
5976 return LDAP_INVALID_SYNTAX;
5979 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5981 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5985 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5989 return LDAP_INVALID_SYNTAX;
5991 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
6000 nisNetgroupTripleValidate(
6002 struct berval *val )
6007 if ( BER_BVISEMPTY( val ) ) {
6008 return LDAP_INVALID_SYNTAX;
6011 p = (char *)val->bv_val;
6012 e = p + val->bv_len;
6014 if ( *p != '(' /*')'*/ ) {
6015 return LDAP_INVALID_SYNTAX;
6018 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
6022 return LDAP_INVALID_SYNTAX;
6025 } else if ( !AD_CHAR( *p ) ) {
6026 return LDAP_INVALID_SYNTAX;
6030 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
6031 return LDAP_INVALID_SYNTAX;
6037 return LDAP_INVALID_SYNTAX;
6040 return LDAP_SUCCESS;
6044 bootParameterValidate(
6046 struct berval *val )
6050 if ( BER_BVISEMPTY( val ) ) {
6051 return LDAP_INVALID_SYNTAX;
6054 p = (char *)val->bv_val;
6055 e = p + val->bv_len;
6058 for (; ( p < e ) && ( *p != '=' ); p++ ) {
6059 if ( !AD_CHAR( *p ) ) {
6060 return LDAP_INVALID_SYNTAX;
6065 return LDAP_INVALID_SYNTAX;
6069 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
6070 if ( !AD_CHAR( *p ) ) {
6071 return LDAP_INVALID_SYNTAX;
6076 return LDAP_INVALID_SYNTAX;
6080 for ( p++; p < e; p++ ) {
6081 if ( !SLAP_PRINTABLE( *p ) ) {
6082 return LDAP_INVALID_SYNTAX;
6086 return LDAP_SUCCESS;
6090 firstComponentNormalize(
6095 struct berval *normalized,
6102 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
6103 ber_dupbv_x( normalized, val, ctx );
6104 return LDAP_SUCCESS;
6107 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
6109 if( ! ( val->bv_val[0] == '(' /*')'*/
6110 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
6111 && ! ( val->bv_val[0] == '{' /*'}'*/
6112 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
6114 return LDAP_INVALID_SYNTAX;
6117 /* trim leading white space */
6119 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
6125 /* grab next word */
6126 comp.bv_val = &val->bv_val[len];
6127 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
6128 for( comp.bv_len = 0;
6129 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
6135 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
6136 rc = numericoidValidate( NULL, &comp );
6137 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
6138 rc = integerValidate( NULL, &comp );
6140 rc = LDAP_INVALID_SYNTAX;
6144 if( rc == LDAP_SUCCESS ) {
6145 ber_dupbv_x( normalized, &comp, ctx );
6151 static char *country_gen_syn[] = {
6152 "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */
6153 "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */
6154 "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */
6158 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6159 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6161 static slap_syntax_defs_rec syntax_defs[] = {
6162 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6163 X_BINARY X_NOT_H_R ")",
6164 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6165 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6166 0, NULL, NULL, NULL},
6167 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6168 0, NULL, NULL, NULL},
6169 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6171 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6172 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6174 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6175 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6176 0, NULL, bitStringValidate, NULL },
6177 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6178 0, NULL, booleanValidate, NULL},
6179 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6180 X_BINARY X_NOT_H_R ")",
6181 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6182 NULL, certificateValidate, NULL},
6183 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6184 X_BINARY X_NOT_H_R ")",
6185 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6186 NULL, certificateListValidate, NULL},
6187 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6188 X_BINARY X_NOT_H_R ")",
6189 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6190 NULL, sequenceValidate, NULL},
6191 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6192 X_BINARY X_NOT_H_R ")",
6193 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6194 NULL, attributeCertificateValidate, NULL},
6195 #if 0 /* need to go __after__ printableString */
6196 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6197 0, "1.3.6.1.4.1.1466.115.121.1.44",
6198 countryStringValidate, NULL},
6200 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6201 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6202 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6203 0, NULL, rdnValidate, rdnPretty},
6204 #ifdef LDAP_COMP_MATCH
6205 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6206 0, NULL, allComponentsValidate, NULL},
6207 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6208 0, NULL, componentFilterValidate, NULL},
6210 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6211 0, NULL, NULL, NULL},
6212 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6213 0, NULL, deliveryMethodValidate, NULL},
6214 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6215 0, NULL, UTF8StringValidate, NULL},
6216 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6217 0, NULL, NULL, NULL},
6218 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6219 0, NULL, NULL, NULL},
6220 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6221 0, NULL, NULL, NULL},
6222 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6223 0, NULL, NULL, NULL},
6224 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6225 0, NULL, NULL, NULL},
6226 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6227 0, NULL, printablesStringValidate, NULL},
6228 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6229 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6230 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6231 0, NULL, generalizedTimeValidate, NULL},
6232 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6233 0, NULL, NULL, NULL},
6234 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6235 0, NULL, IA5StringValidate, NULL},
6236 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6237 0, NULL, integerValidate, NULL},
6238 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6239 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6240 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6241 0, NULL, NULL, NULL},
6242 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6243 0, NULL, NULL, NULL},
6244 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6245 0, NULL, NULL, NULL},
6246 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6247 0, NULL, NULL, NULL},
6248 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6249 0, NULL, NULL, NULL},
6250 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6251 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6252 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6253 0, NULL, NULL, NULL},
6254 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6255 0, NULL, numericStringValidate, NULL},
6256 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6257 0, NULL, NULL, NULL},
6258 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6259 0, NULL, numericoidValidate, NULL},
6260 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6261 0, NULL, IA5StringValidate, NULL},
6262 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6263 0, NULL, blobValidate, NULL},
6264 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6265 0, NULL, postalAddressValidate, NULL},
6266 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6267 0, NULL, NULL, NULL},
6268 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6269 0, NULL, NULL, NULL},
6270 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6271 0, NULL, printableStringValidate, NULL},
6272 /* moved here because now depends on Directory String, IA5 String
6273 * and Printable String */
6274 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6275 0, country_gen_syn, countryStringValidate, NULL},
6276 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6277 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6278 0, NULL, subtreeSpecificationValidate, NULL},
6279 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6280 X_BINARY X_NOT_H_R ")",
6281 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6282 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6283 0, NULL, printableStringValidate, NULL},
6284 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6285 0, NULL, NULL, NULL},
6286 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6287 0, NULL, printablesStringValidate, NULL},
6288 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6289 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6290 0, NULL, utcTimeValidate, NULL},
6292 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6293 0, NULL, NULL, NULL},
6294 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6295 0, NULL, NULL, NULL},
6296 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6297 0, NULL, NULL, NULL},
6298 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6299 0, NULL, NULL, NULL},
6300 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6301 0, NULL, NULL, NULL},
6303 /* RFC 2307 NIS Syntaxes */
6304 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6305 0, NULL, nisNetgroupTripleValidate, NULL},
6306 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6307 0, NULL, bootParameterValidate, NULL},
6309 /* draft-zeilenga-ldap-x509 */
6310 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6311 SLAP_SYNTAX_HIDE, NULL,
6312 serialNumberAndIssuerValidate,
6313 serialNumberAndIssuerPretty},
6314 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6315 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6316 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6317 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6318 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6319 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6320 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6321 SLAP_SYNTAX_HIDE, NULL,
6322 issuerAndThisUpdateValidate,
6323 issuerAndThisUpdatePretty},
6324 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6325 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6326 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6327 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6328 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6329 SLAP_SYNTAX_HIDE, NULL,
6330 serialNumberAndIssuerSerialValidate,
6331 serialNumberAndIssuerSerialPretty},
6332 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6333 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6335 #ifdef SLAPD_AUTHPASSWD
6336 /* needs updating */
6337 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6338 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6341 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6342 0, NULL, UUIDValidate, UUIDPretty},
6344 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6345 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6347 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6348 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6350 /* OpenLDAP Void Syntax */
6351 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6352 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6354 /* FIXME: OID is unused, but not registered yet */
6355 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6356 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6358 {NULL, 0, NULL, NULL, NULL}
6361 char *csnSIDMatchSyntaxes[] = {
6362 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6365 char *certificateExactMatchSyntaxes[] = {
6366 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6369 char *certificateListExactMatchSyntaxes[] = {
6370 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6373 char *attributeCertificateExactMatchSyntaxes[] = {
6374 attributeCertificateSyntaxOID /* attributeCertificate */,
6378 #ifdef LDAP_COMP_MATCH
6379 char *componentFilterMatchSyntaxes[] = {
6380 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6381 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6382 attributeCertificateSyntaxOID /* attributeCertificate */,
6387 char *directoryStringSyntaxes[] = {
6388 "1.3.6.1.4.1.1466.115.121.1.11" /* countryString */,
6389 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6390 "1.3.6.1.4.1.1466.115.121.1.50" /* telephoneNumber */,
6393 char *integerFirstComponentMatchSyntaxes[] = {
6394 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6395 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6398 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6399 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6400 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6401 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6402 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6403 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6404 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6405 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6406 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6411 * Other matching rules in X.520 that we do not use (yet):
6413 * 2.5.13.25 uTCTimeMatch
6414 * 2.5.13.26 uTCTimeOrderingMatch
6415 * 2.5.13.31* directoryStringFirstComponentMatch
6416 * 2.5.13.32* wordMatch
6417 * 2.5.13.33* keywordMatch
6418 * 2.5.13.36+ certificatePairExactMatch
6419 * 2.5.13.37+ certificatePairMatch
6420 * 2.5.13.40+ algorithmIdentifierMatch
6421 * 2.5.13.41* storedPrefixMatch
6422 * 2.5.13.42 attributeCertificateMatch
6423 * 2.5.13.43 readerAndKeyIDMatch
6424 * 2.5.13.44 attributeIntegrityMatch
6426 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6427 * (+) described in draft-zeilenga-ldap-x509
6429 static slap_mrule_defs_rec mrule_defs[] = {
6431 * EQUALITY matching rules must be listed after associated APPROX
6432 * matching rules. So, we list all APPROX matching rules first.
6434 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6435 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6436 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6437 NULL, NULL, directoryStringApproxMatch,
6438 directoryStringApproxIndexer, directoryStringApproxFilter,
6441 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6442 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6443 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6444 NULL, NULL, IA5StringApproxMatch,
6445 IA5StringApproxIndexer, IA5StringApproxFilter,
6449 * Other matching rules
6452 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6453 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6454 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6455 NULL, NULL, octetStringMatch,
6456 octetStringIndexer, octetStringFilter,
6459 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6460 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6461 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6462 NULL, dnNormalize, dnMatch,
6463 octetStringIndexer, octetStringFilter,
6466 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6468 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6469 NULL, dnNormalize, dnRelativeMatch,
6473 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6475 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6476 NULL, dnNormalize, dnRelativeMatch,
6480 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6481 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6482 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6483 NULL, dnNormalize, dnRelativeMatch,
6487 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6488 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6489 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6490 NULL, dnNormalize, dnRelativeMatch,
6494 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6495 "SYNTAX 1.2.36.79672281.1.5.0 )",
6496 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6497 NULL, rdnNormalize, rdnMatch,
6498 octetStringIndexer, octetStringFilter,
6501 #ifdef LDAP_COMP_MATCH
6502 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6503 "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */
6504 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6505 NULL, NULL , componentFilterMatch,
6506 octetStringIndexer, octetStringFilter,
6509 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6510 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6511 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6512 NULL, NULL , allComponentsMatch,
6513 octetStringIndexer, octetStringFilter,
6516 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6517 "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
6518 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6519 NULL, NULL , directoryComponentsMatch,
6520 octetStringIndexer, octetStringFilter,
6524 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6525 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6526 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6527 NULL, UTF8StringNormalize, octetStringMatch,
6528 octetStringIndexer, octetStringFilter,
6529 directoryStringApproxMatchOID },
6531 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6532 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6533 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6534 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6536 "caseIgnoreMatch" },
6538 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6539 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6540 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6541 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6542 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6543 "caseIgnoreMatch" },
6545 {"( 2.5.13.5 NAME 'caseExactMatch' "
6546 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6547 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6548 NULL, UTF8StringNormalize, octetStringMatch,
6549 octetStringIndexer, octetStringFilter,
6550 directoryStringApproxMatchOID },
6552 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6553 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6554 SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
6555 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6559 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6560 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6561 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6562 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6563 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6566 {"( 2.5.13.8 NAME 'numericStringMatch' "
6567 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6568 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6569 NULL, numericStringNormalize, octetStringMatch,
6570 octetStringIndexer, octetStringFilter,
6573 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6574 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6575 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6576 NULL, numericStringNormalize, octetStringOrderingMatch,
6578 "numericStringMatch" },
6580 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6581 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6582 SLAP_MR_SUBSTR, NULL,
6583 NULL, numericStringNormalize, octetStringSubstringsMatch,
6584 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6585 "numericStringMatch" },
6587 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6588 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */
6589 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6590 NULL, postalAddressNormalize, octetStringMatch,
6591 octetStringIndexer, octetStringFilter,
6594 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6595 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6596 SLAP_MR_SUBSTR, NULL,
6597 NULL, NULL, NULL, NULL, NULL,
6598 "caseIgnoreListMatch" },
6600 {"( 2.5.13.13 NAME 'booleanMatch' "
6601 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6602 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6603 NULL, NULL, booleanMatch,
6604 octetStringIndexer, octetStringFilter,
6607 {"( 2.5.13.14 NAME 'integerMatch' "
6608 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6609 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6610 NULL, NULL, integerMatch,
6611 integerIndexer, integerFilter,
6614 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6615 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6616 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6617 NULL, NULL, integerMatch,
6621 {"( 2.5.13.16 NAME 'bitStringMatch' "
6622 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6623 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6624 NULL, NULL, octetStringMatch,
6625 octetStringIndexer, octetStringFilter,
6628 {"( 2.5.13.17 NAME 'octetStringMatch' "
6629 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6630 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6631 NULL, NULL, octetStringMatch,
6632 octetStringIndexer, octetStringFilter,
6635 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6636 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6637 SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
6638 NULL, NULL, octetStringOrderingMatch,
6640 "octetStringMatch" },
6642 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6643 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6644 SLAP_MR_SUBSTR, NULL,
6645 NULL, NULL, octetStringSubstringsMatch,
6646 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6647 "octetStringMatch" },
6649 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6651 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6653 telephoneNumberNormalize, octetStringMatch,
6654 octetStringIndexer, octetStringFilter,
6657 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6658 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
6659 SLAP_MR_SUBSTR, NULL,
6660 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6661 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6662 "telephoneNumberMatch" },
6664 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6665 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6666 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6667 NULL, NULL, NULL, NULL, NULL, NULL },
6669 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6670 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */
6671 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6672 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6673 uniqueMemberIndexer, uniqueMemberFilter,
6676 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6677 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6678 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6679 NULL, NULL, NULL, NULL, NULL, NULL },
6681 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6682 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6683 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6684 NULL, generalizedTimeNormalize, octetStringMatch,
6685 generalizedTimeIndexer, generalizedTimeFilter,
6688 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6689 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6690 SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6691 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6693 "generalizedTimeMatch" },
6695 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6696 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6697 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6698 integerFirstComponentMatchSyntaxes,
6699 NULL, firstComponentNormalize, integerMatch,
6700 octetStringIndexer, octetStringFilter,
6703 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6704 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */
6705 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6706 objectIdentifierFirstComponentMatchSyntaxes,
6707 NULL, firstComponentNormalize, octetStringMatch,
6708 octetStringIndexer, octetStringFilter,
6711 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6712 "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */
6713 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6714 NULL, certificateExactNormalize, octetStringMatch,
6715 octetStringIndexer, octetStringFilter,
6718 {"( 2.5.13.35 NAME 'certificateMatch' "
6719 "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */
6720 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6721 NULL, NULL, NULL, NULL, NULL,
6724 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6725 "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */
6726 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6727 NULL, certificateListExactNormalize, octetStringMatch,
6728 octetStringIndexer, octetStringFilter,
6731 {"( 2.5.13.39 NAME 'certificateListMatch' "
6732 "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */
6733 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6734 NULL, NULL, NULL, NULL, NULL,
6737 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6738 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6739 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6740 NULL, attributeCertificateExactNormalize, octetStringMatch,
6741 octetStringIndexer, octetStringFilter,
6744 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6745 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6746 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6747 NULL, NULL, NULL, NULL, NULL,
6750 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6751 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6752 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6753 NULL, IA5StringNormalize, octetStringMatch,
6754 octetStringIndexer, octetStringFilter,
6755 IA5StringApproxMatchOID },
6757 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6758 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6759 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6760 NULL, IA5StringNormalize, octetStringMatch,
6761 octetStringIndexer, octetStringFilter,
6762 IA5StringApproxMatchOID },
6764 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6765 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6766 SLAP_MR_SUBSTR, NULL,
6767 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6768 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6769 "caseIgnoreIA5Match" },
6771 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6772 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6773 SLAP_MR_SUBSTR, NULL,
6774 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6775 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6776 "caseExactIA5Match" },
6778 #ifdef SLAPD_AUTHPASSWD
6779 /* needs updating */
6780 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6781 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */
6782 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6783 NULL, NULL, authPasswordMatch,
6788 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6789 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6791 NULL, NULL, integerBitAndMatch,
6795 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6796 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
6798 NULL, NULL, integerBitOrMatch,
6802 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6803 "SYNTAX 1.3.6.1.1.16.1 )",
6804 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6805 NULL, UUIDNormalize, octetStringMatch,
6806 octetStringIndexer, octetStringFilter,
6809 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6810 "SYNTAX 1.3.6.1.1.16.1 )",
6811 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6812 NULL, UUIDNormalize, octetStringOrderingMatch,
6813 octetStringIndexer, octetStringFilter,
6816 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6817 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6818 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6819 NULL, csnNormalize, csnMatch,
6820 csnIndexer, csnFilter,
6823 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6824 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6825 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6826 NULL, csnNormalize, csnOrderingMatch,
6830 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6831 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6832 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6833 NULL, csnSidNormalize, octetStringMatch,
6834 octetStringIndexer, octetStringFilter,
6837 /* FIXME: OID is unused, but not registered yet */
6838 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6839 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */
6840 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6841 NULL, authzNormalize, authzMatch,
6845 {NULL, SLAP_MR_NONE, NULL,
6846 NULL, NULL, NULL, NULL, NULL,
6851 slap_schema_init( void )
6856 /* we should only be called once (from main) */
6857 assert( schema_init_done == 0 );
6859 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6860 res = register_syntax( &syntax_defs[i] );
6863 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6864 syntax_defs[i].sd_desc );
6869 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6870 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6871 mrule_defs[i].mrd_compat_syntaxes == NULL )
6874 "slap_schema_init: Ignoring unusable matching rule %s\n",
6875 mrule_defs[i].mrd_desc );
6879 res = register_matching_rule( &mrule_defs[i] );
6883 "slap_schema_init: Error registering matching rule %s\n",
6884 mrule_defs[i].mrd_desc );
6889 res = slap_schema_load();
6890 schema_init_done = 1;
6895 schema_destroy( void )
6904 if( schema_init_done ) {
6905 ldap_pvt_thread_mutex_destroy( &ad_index_mutex );
6906 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6907 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );