1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2010 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>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 /* X.509 PMI ldapSyntaxes */
61 /* FIXME: need to create temporary OIDs under OpenLDAP's arc;
62 * these are currently hijacked
64 * 1.3.6.1.4.1.4203.666 OpenLDAP
65 * 1.3.6.1.4.1.4203.666.11 self-contained works
66 * 1.3.6.1.4.1.4203.666.11.10 X.509 PMI
67 * 1.3.6.1.4.1.4203.666.11.10.2 X.509 PMI ldapSyntaxes
68 * 1.3.6.1.4.1.4203.666.11.10.2.1 AttributeCertificate (supported)
69 * 1.3.6.1.4.1.4203.666.11.10.2.2 AttributeCertificateExactAssertion (supported)
70 * 1.3.6.1.4.1.4203.666.11.10.2.3 AttributeCertificateAssertion (not supported)
71 * 1.3.6.1.4.1.4203.666.11.10.2.4 AttCertPath (X-SUBST'ed right now in pmi.schema)
72 * 1.3.6.1.4.1.4203.666.11.10.2.5 PolicySyntax (X-SUBST'ed right now in pmi.schema)
73 * 1.3.6.1.4.1.4203.666.11.10.2.6 RoleSyntax (X-SUBST'ed right now in pmi.schema)
75 #if 0 /* from <draft-ietf-pkix-ldap-schema-02.txt> (expired) */
76 #define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5"
77 #define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6"
78 #define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7"
79 #else /* from OpenLDAP's experimental oid arc */
80 #define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2"
81 #define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1"
82 #define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2"
83 #define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3"
86 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
87 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
88 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
89 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
91 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
92 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
93 SLAP_INDEX_INTLEN_DEFAULT );
95 ldap_pvt_thread_mutex_t ad_undef_mutex;
96 ldap_pvt_thread_mutex_t oc_undef_mutex;
99 generalizedTimeValidate(
103 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
108 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
115 /* no value allowed */
116 return LDAP_INVALID_SYNTAX;
124 /* any value allowed */
128 #define berValidate blobValidate
135 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
136 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 /* X.509 related stuff */
150 SLAP_TAG_UTCTIME = 0x17U,
151 SLAP_TAG_GENERALIZEDTIME = 0x18U
155 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
158 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
159 SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1,
160 SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2,
161 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
165 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
169 GeneralName ::= CHOICE {
170 otherName [0] INSTANCE OF OTHER-NAME,
171 rfc822Name [1] IA5String,
172 dNSName [2] IA5String,
173 x400Address [3] ORAddress,
174 directoryName [4] Name,
175 ediPartyName [5] EDIPartyName,
176 uniformResourceIdentifier [6] IA5String,
177 iPAddress [7] OCTET STRING,
178 registeredID [8] OBJECT IDENTIFIER }
181 SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0,
182 SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1,
183 SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2,
184 SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3,
185 SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4,
186 SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5,
187 SLAP_X509_GN_URI = SLAP_X509_OPTION + 6,
188 SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7,
189 SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8
192 /* X.509 PMI related stuff */
199 SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0
202 /* X.509 certificate validation */
204 certificateValidate( Syntax *syntax, struct berval *in )
206 BerElementBuffer berbuf;
207 BerElement *ber = (BerElement *)&berbuf;
210 ber_int_t version = SLAP_X509_V1;
212 ber_init2( ber, in, LBER_USE_DER );
213 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
214 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
215 tag = ber_skip_tag( ber, &len ); /* Sequence */
216 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
217 tag = ber_peek_tag( ber, &len );
218 /* Optional version */
219 if ( tag == SLAP_X509_OPT_C_VERSION ) {
220 tag = ber_skip_tag( ber, &len );
221 tag = ber_get_int( ber, &version );
222 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
224 /* NOTE: don't try to parse Serial, because it might be longer
225 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
226 tag = ber_skip_tag( ber, &len ); /* Serial */
227 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
228 ber_skip_data( ber, len );
229 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
230 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
231 ber_skip_data( ber, len );
232 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
233 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
234 ber_skip_data( ber, len );
235 tag = ber_skip_tag( ber, &len ); /* Validity */
236 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
237 ber_skip_data( ber, len );
238 tag = ber_skip_tag( ber, &len ); /* Subject DN */
239 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
240 ber_skip_data( ber, len );
241 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
242 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
243 ber_skip_data( ber, len );
244 tag = ber_skip_tag( ber, &len );
245 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
246 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
247 ber_skip_data( ber, len );
248 tag = ber_skip_tag( ber, &len );
250 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
251 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
252 ber_skip_data( ber, len );
253 tag = ber_skip_tag( ber, &len );
255 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
256 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
257 tag = ber_skip_tag( ber, &len );
258 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
259 ber_skip_data( ber, len );
260 tag = ber_skip_tag( ber, &len );
262 /* signatureAlgorithm */
263 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
264 ber_skip_data( ber, len );
265 tag = ber_skip_tag( ber, &len );
267 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
268 ber_skip_data( ber, len );
269 tag = ber_skip_tag( ber, &len );
270 /* Must be at end now */
271 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
275 /* X.509 certificate list validation */
277 checkTime( struct berval *in, struct berval *out );
280 certificateListValidate( Syntax *syntax, struct berval *in )
282 BerElementBuffer berbuf;
283 BerElement *ber = (BerElement *)&berbuf;
285 ber_len_t len, wrapper_len;
288 ber_int_t version = SLAP_X509_V1;
289 struct berval bvdn, bvtu;
291 ber_init2( ber, in, LBER_USE_DER );
292 tag = ber_skip_tag( ber, &wrapper_len ); /* Signed wrapper */
293 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
294 wrapper_start = ber->ber_ptr;
295 tag = ber_skip_tag( ber, &len ); /* Sequence */
296 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
297 tag = ber_peek_tag( ber, &len );
298 /* Optional version */
299 if ( tag == LBER_INTEGER ) {
300 tag = ber_get_int( ber, &version );
301 assert( tag == LBER_INTEGER );
302 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
304 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
305 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
306 ber_skip_data( ber, len );
307 tag = ber_peek_tag( ber, &len ); /* Issuer DN */
308 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
309 len = ber_ptrlen( ber );
310 bvdn.bv_val = in->bv_val + len;
311 bvdn.bv_len = in->bv_len - len;
312 tag = ber_skip_tag( ber, &len );
313 ber_skip_data( ber, len );
314 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
315 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
316 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
317 bvtu.bv_val = (char *)ber->ber_ptr;
319 ber_skip_data( ber, len );
320 /* Optional nextUpdate */
321 tag = ber_skip_tag( ber, &len );
322 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
323 ber_skip_data( ber, len );
324 tag = ber_skip_tag( ber, &len );
326 /* revokedCertificates - Sequence of Sequence, Optional */
327 if ( tag == LBER_SEQUENCE ) {
330 stag = ber_peek_tag( ber, &seqlen );
331 if ( stag == LBER_SEQUENCE || !len ) {
332 /* RFC5280 requires non-empty, but X.509(2005) allows empty. */
334 ber_skip_data( ber, len );
335 tag = ber_skip_tag( ber, &len );
338 /* Optional Extensions - Sequence of Sequence */
339 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
341 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
342 tag = ber_peek_tag( ber, &seqlen );
343 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
344 ber_skip_data( ber, len );
345 tag = ber_skip_tag( ber, &len );
347 /* signatureAlgorithm */
348 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
349 ber_skip_data( ber, len );
350 tag = ber_skip_tag( ber, &len );
352 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
353 ber_skip_data( ber, len );
354 if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
355 tag = ber_skip_tag( ber, &len );
356 /* Must be at end now */
357 /* NOTE: OpenSSL tolerates CL with garbage past the end */
358 if ( len || tag != LBER_DEFAULT ) {
359 struct berval issuer_dn = BER_BVNULL, thisUpdate;
360 char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
363 if ( ! wrapper_ok ) {
364 return LDAP_INVALID_SYNTAX;
367 rc = dnX509normalize( &bvdn, &issuer_dn );
368 if ( rc != LDAP_SUCCESS ) {
369 rc = LDAP_INVALID_SYNTAX;
373 thisUpdate.bv_val = tubuf;
374 thisUpdate.bv_len = sizeof(tubuf);
375 if ( checkTime( &bvtu, &thisUpdate ) ) {
376 rc = LDAP_INVALID_SYNTAX;
380 Debug( LDAP_DEBUG_ANY,
381 "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
382 issuer_dn.bv_val, thisUpdate.bv_val, 0 );
385 if ( ! BER_BVISNULL( &issuer_dn ) ) {
386 ber_memfree( issuer_dn.bv_val );
395 /* X.509 PMI Attribute Certificate Validate */
397 attributeCertificateValidate( Syntax *syntax, struct berval *in )
399 BerElementBuffer berbuf;
400 BerElement *ber = (BerElement *)&berbuf;
406 ber_init2( ber, in, LBER_USE_DER );
408 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
409 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
411 tag = ber_skip_tag( ber, &len ); /* Sequence */
412 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
414 tag = ber_peek_tag( ber, &len ); /* Version */
415 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
416 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
417 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
419 tag = ber_skip_tag( ber, &len ); /* Holder */
420 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
421 ber_skip_data( ber, len );
423 tag = ber_skip_tag( ber, &len ); /* Issuer */
424 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
425 ber_skip_data( ber, len );
427 tag = ber_skip_tag( ber, &len ); /* Signature */
428 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
429 ber_skip_data( ber, len );
431 tag = ber_skip_tag( ber, &len ); /* Serial number */
432 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
433 ber_skip_data( ber, len );
435 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
436 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
437 ber_skip_data( ber, len );
439 tag = ber_skip_tag( ber, &len ); /* Attributes */
440 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
441 ber_skip_data( ber, len );
443 tag = ber_peek_tag( ber, &len );
445 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
446 tag = ber_skip_tag( ber, &len );
447 ber_skip_data( ber, len );
448 tag = ber_peek_tag( ber, &len );
451 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
452 tag = ber_skip_tag( ber, &len );
453 ber_skip_data( ber, len );
455 tag = ber_peek_tag( ber, &len );
458 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
459 tag = ber_skip_tag( ber, &len );
460 ber_skip_data( ber, len );
462 tag = ber_peek_tag( ber, &len );
465 if ( tag == LBER_BITSTRING ) { /* Signature */
466 tag = ber_skip_tag( ber, &len );
467 ber_skip_data( ber, len );
469 tag = ber_peek_tag( ber, &len );
472 /* Must be at end now */
473 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
484 struct berval *value,
485 void *assertedValue )
487 struct berval *asserted = (struct berval *) assertedValue;
488 int match = value->bv_len - asserted->bv_len;
491 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
499 octetStringOrderingMatch(
504 struct berval *value,
505 void *assertedValue )
507 struct berval *asserted = (struct berval *) assertedValue;
508 ber_len_t v_len = value->bv_len;
509 ber_len_t av_len = asserted->bv_len;
511 int match = memcmp( value->bv_val, asserted->bv_val,
512 (v_len < av_len ? v_len : av_len) );
514 if( match == 0 ) match = v_len - av_len;
522 HASH_CONTEXT *HASHcontext,
523 struct berval *prefix,
528 HASH_Init(HASHcontext);
529 if(prefix && prefix->bv_len > 0) {
530 HASH_Update(HASHcontext,
531 (unsigned char *)prefix->bv_val, prefix->bv_len);
533 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
534 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
535 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
541 HASH_CONTEXT *HASHcontext,
542 unsigned char *HASHdigest,
543 unsigned char *value,
546 HASH_CONTEXT ctx = *HASHcontext;
547 HASH_Update( &ctx, value, len );
548 HASH_Final( HASHdigest, &ctx );
551 /* Index generation function */
552 int octetStringIndexer(
557 struct berval *prefix,
565 HASH_CONTEXT HASHcontext;
566 unsigned char HASHdigest[HASH_BYTES];
567 struct berval digest;
568 digest.bv_val = (char *)HASHdigest;
569 digest.bv_len = sizeof(HASHdigest);
571 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
572 /* just count them */
575 /* we should have at least one value at this point */
578 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
580 slen = syntax->ssyn_oidlen;
581 mlen = mr->smr_oidlen;
583 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
584 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
585 hashIter( &HASHcontext, HASHdigest,
586 (unsigned char *)values[i].bv_val, values[i].bv_len );
587 ber_dupbv_x( &keys[i], &digest, ctx );
590 BER_BVZERO( &keys[i] );
597 /* Index generation function */
598 int octetStringFilter(
603 struct berval *prefix,
604 void * assertedValue,
610 HASH_CONTEXT HASHcontext;
611 unsigned char HASHdigest[HASH_BYTES];
612 struct berval *value = (struct berval *) assertedValue;
613 struct berval digest;
614 digest.bv_val = (char *)HASHdigest;
615 digest.bv_len = sizeof(HASHdigest);
617 slen = syntax->ssyn_oidlen;
618 mlen = mr->smr_oidlen;
620 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
622 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
623 hashIter( &HASHcontext, HASHdigest,
624 (unsigned char *)value->bv_val, value->bv_len );
626 ber_dupbv_x( keys, &digest, ctx );
627 BER_BVZERO( &keys[1] );
635 octetStringSubstringsMatch(
640 struct berval *value,
641 void *assertedValue )
644 SubstringsAssertion *sub = assertedValue;
645 struct berval left = *value;
649 /* Add up asserted input length */
650 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
651 inlen += sub->sa_initial.bv_len;
654 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
655 inlen += sub->sa_any[i].bv_len;
658 if ( !BER_BVISNULL( &sub->sa_final ) ) {
659 inlen += sub->sa_final.bv_len;
662 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
663 if ( inlen > left.bv_len ) {
668 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
669 sub->sa_initial.bv_len );
675 left.bv_val += sub->sa_initial.bv_len;
676 left.bv_len -= sub->sa_initial.bv_len;
677 inlen -= sub->sa_initial.bv_len;
680 if ( !BER_BVISNULL( &sub->sa_final ) ) {
681 if ( inlen > left.bv_len ) {
686 match = memcmp( sub->sa_final.bv_val,
687 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
688 sub->sa_final.bv_len );
694 left.bv_len -= sub->sa_final.bv_len;
695 inlen -= sub->sa_final.bv_len;
699 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
704 if ( inlen > left.bv_len ) {
705 /* not enough length */
710 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
714 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
721 idx = p - left.bv_val;
723 if ( idx >= left.bv_len ) {
724 /* this shouldn't happen */
731 if ( sub->sa_any[i].bv_len > left.bv_len ) {
732 /* not enough left */
737 match = memcmp( left.bv_val,
738 sub->sa_any[i].bv_val,
739 sub->sa_any[i].bv_len );
747 left.bv_val += sub->sa_any[i].bv_len;
748 left.bv_len -= sub->sa_any[i].bv_len;
749 inlen -= sub->sa_any[i].bv_len;
758 /* Substrings Index generation function */
760 octetStringSubstringsIndexer(
765 struct berval *prefix,
774 HASH_CONTEXT HCany, HCini, HCfin;
775 unsigned char HASHdigest[HASH_BYTES];
776 struct berval digest;
777 digest.bv_val = (char *)HASHdigest;
778 digest.bv_len = sizeof(HASHdigest);
782 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
783 /* count number of indices to generate */
784 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
785 if( values[i].bv_len >= index_substr_if_maxlen ) {
786 nkeys += index_substr_if_maxlen -
787 (index_substr_if_minlen - 1);
788 } else if( values[i].bv_len >= index_substr_if_minlen ) {
789 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
793 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
794 if( values[i].bv_len >= index_substr_any_len ) {
795 nkeys += values[i].bv_len - (index_substr_any_len - 1);
799 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
800 if( values[i].bv_len >= index_substr_if_maxlen ) {
801 nkeys += index_substr_if_maxlen -
802 (index_substr_if_minlen - 1);
803 } else if( values[i].bv_len >= index_substr_if_minlen ) {
804 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
810 /* no keys to generate */
815 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
817 slen = syntax->ssyn_oidlen;
818 mlen = mr->smr_oidlen;
820 if ( flags & SLAP_INDEX_SUBSTR_ANY )
821 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
822 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
823 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
824 if( flags & SLAP_INDEX_SUBSTR_FINAL )
825 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
828 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
831 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
832 ( values[i].bv_len >= index_substr_any_len ) )
834 max = values[i].bv_len - (index_substr_any_len - 1);
836 for( j=0; j<max; j++ ) {
837 hashIter( &HCany, HASHdigest,
838 (unsigned char *)&values[i].bv_val[j],
839 index_substr_any_len );
840 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
844 /* skip if too short */
845 if( values[i].bv_len < index_substr_if_minlen ) continue;
847 max = index_substr_if_maxlen < values[i].bv_len
848 ? index_substr_if_maxlen : values[i].bv_len;
850 for( j=index_substr_if_minlen; j<=max; j++ ) {
852 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
853 hashIter( &HCini, HASHdigest,
854 (unsigned char *)values[i].bv_val, j );
855 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
858 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
859 hashIter( &HCfin, HASHdigest,
860 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
861 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
868 BER_BVZERO( &keys[nkeys] );
879 octetStringSubstringsFilter (
884 struct berval *prefix,
885 void * assertedValue,
889 SubstringsAssertion *sa;
892 size_t slen, mlen, klen;
894 HASH_CONTEXT HASHcontext;
895 unsigned char HASHdigest[HASH_BYTES];
896 struct berval *value;
897 struct berval digest;
899 sa = (SubstringsAssertion *) assertedValue;
901 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
902 !BER_BVISNULL( &sa->sa_initial ) &&
903 sa->sa_initial.bv_len >= index_substr_if_minlen )
906 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
907 ( flags & SLAP_INDEX_SUBSTR_ANY ))
909 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
913 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
915 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
916 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
917 /* don't bother accounting with stepping */
918 nkeys += sa->sa_any[i].bv_len -
919 ( index_substr_any_len - 1 );
924 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
925 !BER_BVISNULL( &sa->sa_final ) &&
926 sa->sa_final.bv_len >= index_substr_if_minlen )
929 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
930 ( flags & SLAP_INDEX_SUBSTR_ANY ))
932 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
941 digest.bv_val = (char *)HASHdigest;
942 digest.bv_len = sizeof(HASHdigest);
944 slen = syntax->ssyn_oidlen;
945 mlen = mr->smr_oidlen;
947 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
950 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
951 !BER_BVISNULL( &sa->sa_initial ) &&
952 sa->sa_initial.bv_len >= index_substr_if_minlen )
954 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
955 value = &sa->sa_initial;
957 klen = index_substr_if_maxlen < value->bv_len
958 ? index_substr_if_maxlen : value->bv_len;
960 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
961 hashIter( &HASHcontext, HASHdigest,
962 (unsigned char *)value->bv_val, klen );
963 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
965 /* If initial is too long and we have subany indexed, use it
966 * to match the excess...
968 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
971 pre = SLAP_INDEX_SUBSTR_PREFIX;
972 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
973 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
975 hashIter( &HASHcontext, HASHdigest,
976 (unsigned char *)&value->bv_val[j], index_substr_any_len );
977 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
982 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
984 pre = SLAP_INDEX_SUBSTR_PREFIX;
985 klen = index_substr_any_len;
987 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
988 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
992 value = &sa->sa_any[i];
994 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
996 j <= value->bv_len - index_substr_any_len;
997 j += index_substr_any_step )
999 hashIter( &HASHcontext, HASHdigest,
1000 (unsigned char *)&value->bv_val[j], klen );
1001 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1006 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1007 !BER_BVISNULL( &sa->sa_final ) &&
1008 sa->sa_final.bv_len >= index_substr_if_minlen )
1010 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1011 value = &sa->sa_final;
1013 klen = index_substr_if_maxlen < value->bv_len
1014 ? index_substr_if_maxlen : value->bv_len;
1016 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1017 hashIter( &HASHcontext, HASHdigest,
1018 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
1019 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1021 /* If final is too long and we have subany indexed, use it
1022 * to match the excess...
1024 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1027 pre = SLAP_INDEX_SUBSTR_PREFIX;
1028 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1029 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
1031 hashIter( &HASHcontext, HASHdigest,
1032 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1033 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1039 BER_BVZERO( &keys[nkeys] );
1046 return LDAP_SUCCESS;
1056 /* very unforgiving validation, requires no normalization
1057 * before simplistic matching
1059 if( in->bv_len < 3 ) {
1060 return LDAP_INVALID_SYNTAX;
1063 /* RFC 4517 Section 3.3.2 Bit String:
1064 * BitString = SQUOTE *binary-digit SQUOTE "B"
1065 * binary-digit = "0" / "1"
1067 * where SQUOTE [RFC4512] is
1068 * SQUOTE = %x27 ; single quote ("'")
1070 * Example: '0101111101'B
1073 if( in->bv_val[0] != '\'' ||
1074 in->bv_val[in->bv_len - 2] != '\'' ||
1075 in->bv_val[in->bv_len - 1] != 'B' )
1077 return LDAP_INVALID_SYNTAX;
1080 for( i = in->bv_len - 3; i > 0; i-- ) {
1081 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1082 return LDAP_INVALID_SYNTAX;
1086 return LDAP_SUCCESS;
1090 * Syntaxes from RFC 4517
1095 A value of the Bit String syntax is a sequence of binary digits. The
1096 LDAP-specific encoding of a value of this syntax is defined by the
1099 BitString = SQUOTE *binary-digit SQUOTE "B"
1101 binary-digit = "0" / "1"
1103 The <SQUOTE> rule is defined in [MODELS].
1108 The LDAP definition for the Bit String syntax is:
1110 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1112 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1116 3.3.21. Name and Optional UID
1118 A value of the Name and Optional UID syntax is the distinguished name
1119 [MODELS] of an entity optionally accompanied by a unique identifier
1120 that serves to differentiate the entity from others with an identical
1123 The LDAP-specific encoding of a value of this syntax is defined by
1126 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1128 The <BitString> rule is defined in Section 3.3.2. The
1129 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1130 defined in [MODELS].
1132 Note that although the '#' character may occur in the string
1133 representation of a distinguished name, no additional escaping of
1134 this character is performed when a <distinguishedName> is encoded in
1135 a <NameAndOptionalUID>.
1138 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1140 The LDAP definition for the Name and Optional UID syntax is:
1142 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1144 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1151 1.4. Common ABNF Productions
1154 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1156 SQUOTE = %x27 ; single quote ("'")
1161 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1162 * be escaped except when at the beginning of a value, the
1163 * definition of Name and Optional UID appears to be flawed,
1164 * because there is no clear means to determine whether the
1165 * UID part is present or not.
1169 * cn=Someone,dc=example,dc=com#'1'B
1171 * could be either a NameAndOptionalUID with trailing UID, i.e.
1173 * DN = "cn=Someone,dc=example,dc=com"
1176 * or a NameAndOptionalUID with no trailing UID, and the AVA
1177 * in the last RDN made of
1179 * attributeType = dc
1180 * attributeValue = com#'1'B
1182 * in fact "com#'1'B" is a valid IA5 string.
1184 * As a consequence, current slapd code takes the presence of
1185 * #<valid BitString> at the end of the string representation
1186 * of a NameAndOptionalUID to mean this is indeed a BitString.
1187 * This is quite arbitrary - it has changed the past and might
1188 * change in the future.
1198 struct berval dn, uid;
1200 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1202 ber_dupbv( &dn, in );
1203 if( !dn.bv_val ) return LDAP_OTHER;
1205 /* if there's a "#", try bitStringValidate()... */
1206 uid.bv_val = strrchr( dn.bv_val, '#' );
1207 if ( !BER_BVISNULL( &uid ) ) {
1209 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1211 rc = bitStringValidate( NULL, &uid );
1212 if ( rc == LDAP_SUCCESS ) {
1213 /* in case of success, trim the UID,
1214 * otherwise treat it as part of the DN */
1215 dn.bv_len -= uid.bv_len + 1;
1216 uid.bv_val[-1] = '\0';
1220 rc = dnValidate( NULL, &dn );
1222 ber_memfree( dn.bv_val );
1233 assert( val != NULL );
1234 assert( out != NULL );
1237 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1239 if( BER_BVISEMPTY( val ) ) {
1240 ber_dupbv_x( out, val, ctx );
1242 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1243 return LDAP_INVALID_SYNTAX;
1247 struct berval dnval = *val;
1248 struct berval uidval = BER_BVNULL;
1250 uidval.bv_val = strrchr( val->bv_val, '#' );
1251 if ( !BER_BVISNULL( &uidval ) ) {
1253 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1255 rc = bitStringValidate( NULL, &uidval );
1257 if ( rc == LDAP_SUCCESS ) {
1258 ber_dupbv_x( &dnval, val, ctx );
1260 dnval.bv_len -= ++uidval.bv_len;
1261 dnval.bv_val[dnval.bv_len] = '\0';
1264 BER_BVZERO( &uidval );
1268 rc = dnPretty( syntax, &dnval, out, ctx );
1269 if ( dnval.bv_val != val->bv_val ) {
1270 slap_sl_free( dnval.bv_val, ctx );
1272 if( rc != LDAP_SUCCESS ) {
1276 if( !BER_BVISNULL( &uidval ) ) {
1279 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1280 + uidval.bv_len + 1,
1283 ber_memfree_x( out->bv_val, ctx );
1287 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1288 out->bv_len += uidval.bv_len;
1289 out->bv_val[out->bv_len] = '\0';
1293 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1295 return LDAP_SUCCESS;
1299 uniqueMemberNormalize(
1304 struct berval *normalized,
1310 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1312 ber_dupbv_x( &out, val, ctx );
1313 if ( BER_BVISEMPTY( &out ) ) {
1317 struct berval uid = BER_BVNULL;
1319 uid.bv_val = strrchr( out.bv_val, '#' );
1320 if ( !BER_BVISNULL( &uid ) ) {
1322 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1324 rc = bitStringValidate( NULL, &uid );
1325 if ( rc == LDAP_SUCCESS ) {
1326 uid.bv_val[-1] = '\0';
1327 out.bv_len -= uid.bv_len + 1;
1333 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1335 if( rc != LDAP_SUCCESS ) {
1336 slap_sl_free( out.bv_val, ctx );
1337 return LDAP_INVALID_SYNTAX;
1340 if( !BER_BVISNULL( &uid ) ) {
1343 tmp = ch_realloc( normalized->bv_val,
1344 normalized->bv_len + uid.bv_len
1345 + STRLENOF("#") + 1 );
1346 if ( tmp == NULL ) {
1347 ber_memfree_x( normalized->bv_val, ctx );
1351 normalized->bv_val = tmp;
1353 /* insert the separator */
1354 normalized->bv_val[normalized->bv_len++] = '#';
1356 /* append the UID */
1357 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1358 uid.bv_val, uid.bv_len );
1359 normalized->bv_len += uid.bv_len;
1362 normalized->bv_val[normalized->bv_len] = '\0';
1365 slap_sl_free( out.bv_val, ctx );
1368 return LDAP_SUCCESS;
1377 struct berval *value,
1378 void *assertedValue )
1381 struct berval *asserted = (struct berval *) assertedValue;
1382 struct berval assertedDN = *asserted;
1383 struct berval assertedUID = BER_BVNULL;
1384 struct berval valueDN = *value;
1385 struct berval valueUID = BER_BVNULL;
1386 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1388 if ( !BER_BVISEMPTY( asserted ) ) {
1389 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1390 if ( !BER_BVISNULL( &assertedUID ) ) {
1391 assertedUID.bv_val++;
1392 assertedUID.bv_len = assertedDN.bv_len
1393 - ( assertedUID.bv_val - assertedDN.bv_val );
1395 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1396 assertedDN.bv_len -= assertedUID.bv_len + 1;
1399 BER_BVZERO( &assertedUID );
1404 if ( !BER_BVISEMPTY( value ) ) {
1406 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1407 if ( !BER_BVISNULL( &valueUID ) ) {
1409 valueUID.bv_len = valueDN.bv_len
1410 - ( valueUID.bv_val - valueDN.bv_val );
1412 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1413 valueDN.bv_len -= valueUID.bv_len + 1;
1416 BER_BVZERO( &valueUID );
1421 if( valueUID.bv_len && assertedUID.bv_len ) {
1422 match = valueUID.bv_len - assertedUID.bv_len;
1425 return LDAP_SUCCESS;
1428 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1431 return LDAP_SUCCESS;
1434 } else if ( !approx && valueUID.bv_len ) {
1437 return LDAP_SUCCESS;
1439 } else if ( !approx && assertedUID.bv_len ) {
1442 return LDAP_SUCCESS;
1445 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1449 uniqueMemberIndexer(
1454 struct berval *prefix,
1462 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1463 /* just count them */
1467 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1469 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1470 struct berval assertedDN = values[i];
1471 struct berval assertedUID = BER_BVNULL;
1473 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1474 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1475 if ( !BER_BVISNULL( &assertedUID ) ) {
1476 assertedUID.bv_val++;
1477 assertedUID.bv_len = assertedDN.bv_len
1478 - ( assertedUID.bv_val - assertedDN.bv_val );
1480 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1481 assertedDN.bv_len -= assertedUID.bv_len + 1;
1484 BER_BVZERO( &assertedUID );
1489 dnvalues[i] = assertedDN;
1491 BER_BVZERO( &dnvalues[i] );
1493 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1494 dnvalues, keysp, ctx );
1496 slap_sl_free( dnvalues, ctx );
1506 struct berval *prefix,
1507 void * assertedValue,
1511 struct berval *asserted = (struct berval *) assertedValue;
1512 struct berval assertedDN = *asserted;
1513 struct berval assertedUID = BER_BVNULL;
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 return octetStringFilter( use, flags, syntax, mr, prefix,
1532 &assertedDN, keysp, ctx );
1537 * Handling boolean syntax and matching is quite rigid.
1538 * A more flexible approach would be to allow a variety
1539 * of strings to be normalized and prettied into TRUE
1547 /* very unforgiving validation, requires no normalization
1548 * before simplistic matching
1551 if( in->bv_len == 4 ) {
1552 if( bvmatch( in, &slap_true_bv ) ) {
1553 return LDAP_SUCCESS;
1555 } else if( in->bv_len == 5 ) {
1556 if( bvmatch( in, &slap_false_bv ) ) {
1557 return LDAP_SUCCESS;
1561 return LDAP_INVALID_SYNTAX;
1570 struct berval *value,
1571 void *assertedValue )
1573 /* simplistic matching allowed by rigid validation */
1574 struct berval *asserted = (struct berval *) assertedValue;
1575 *matchp = value->bv_len != asserted->bv_len;
1576 return LDAP_SUCCESS;
1579 /*-------------------------------------------------------------------
1580 LDAP/X.500 string syntax / matching rules have a few oddities. This
1581 comment attempts to detail how slapd(8) treats them.
1584 StringSyntax X.500 LDAP Matching/Comments
1585 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1586 PrintableString subset subset i/e + ignore insignificant spaces
1587 PrintableString subset subset i/e + ignore insignificant spaces
1588 NumericString subset subset ignore all spaces
1589 IA5String ASCII ASCII i/e + ignore insignificant spaces
1590 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1592 TelephoneNumber subset subset i + ignore all spaces and "-"
1594 See RFC 4518 for details.
1598 In X.500(93), a directory string can be either a PrintableString,
1599 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1600 In later versions, more CHOICEs were added. In all cases the string
1603 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1604 A directory string cannot be zero length.
1606 For matching, there are both case ignore and exact rules. Both
1607 also require that "insignificant" spaces be ignored.
1608 spaces before the first non-space are ignored;
1609 spaces after the last non-space are ignored;
1610 spaces after a space are ignored.
1611 Note: by these rules (and as clarified in X.520), a string of only
1612 spaces is to be treated as if held one space, not empty (which
1613 would be a syntax error).
1616 In ASN.1, numeric string is just a string of digits and spaces
1617 and could be empty. However, in X.500, all attribute values of
1618 numeric string carry a non-empty constraint. For example:
1620 internationalISDNNumber ATTRIBUTE ::= {
1621 WITH SYNTAX InternationalISDNNumber
1622 EQUALITY MATCHING RULE numericStringMatch
1623 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1624 ID id-at-internationalISDNNumber }
1625 InternationalISDNNumber ::=
1626 NumericString (SIZE(1..ub-international-isdn-number))
1628 Unforunately, some assertion values are don't carry the same
1629 constraint (but its unclear how such an assertion could ever
1630 be true). In LDAP, there is one syntax (numericString) not two
1631 (numericString with constraint, numericString without constraint).
1632 This should be treated as numericString with non-empty constraint.
1633 Note that while someone may have no ISDN number, there are no ISDN
1634 numbers which are zero length.
1636 In matching, spaces are ignored.
1639 In ASN.1, Printable string is just a string of printable characters
1640 and can be empty. In X.500, semantics much like NumericString (see
1641 serialNumber for a like example) excepting uses insignificant space
1642 handling instead of ignore all spaces. They must be non-empty.
1645 Basically same as PrintableString. There are no examples in X.500,
1646 but same logic applies. Empty strings are allowed.
1648 -------------------------------------------------------------------*/
1657 unsigned char *u = (unsigned char *)in->bv_val;
1659 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1660 /* directory strings cannot be empty */
1661 return LDAP_INVALID_SYNTAX;
1664 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1665 /* get the length indicated by the first byte */
1666 len = LDAP_UTF8_CHARLEN2( u, len );
1668 /* very basic checks */
1671 if( (u[5] & 0xC0) != 0x80 ) {
1672 return LDAP_INVALID_SYNTAX;
1675 if( (u[4] & 0xC0) != 0x80 ) {
1676 return LDAP_INVALID_SYNTAX;
1679 if( (u[3] & 0xC0) != 0x80 ) {
1680 return LDAP_INVALID_SYNTAX;
1683 if( (u[2] & 0xC0 )!= 0x80 ) {
1684 return LDAP_INVALID_SYNTAX;
1687 if( (u[1] & 0xC0) != 0x80 ) {
1688 return LDAP_INVALID_SYNTAX;
1691 /* CHARLEN already validated it */
1694 return LDAP_INVALID_SYNTAX;
1697 /* make sure len corresponds with the offset
1698 to the next character */
1699 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1703 return LDAP_INVALID_SYNTAX;
1706 return LDAP_SUCCESS;
1710 UTF8StringNormalize(
1715 struct berval *normalized,
1718 struct berval tmp, nvalue;
1719 int flags, wasspace;
1722 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1724 if( BER_BVISNULL( val ) ) {
1725 /* assume we're dealing with a syntax (e.g., UTF8String)
1726 * which allows empty strings
1728 BER_BVZERO( normalized );
1729 return LDAP_SUCCESS;
1732 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1733 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1734 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1735 ? LDAP_UTF8_APPROX : 0;
1737 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1738 /* out of memory or syntax error, the former is unlikely */
1740 return LDAP_INVALID_SYNTAX;
1743 /* collapse spaces (in place) */
1745 nvalue.bv_val = tmp.bv_val;
1747 /* trim leading spaces? */
1748 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1749 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1751 for( i = 0; i < tmp.bv_len; i++) {
1752 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1753 if( wasspace++ == 0 ) {
1754 /* trim repeated spaces */
1755 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1759 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1763 if( !BER_BVISEMPTY( &nvalue ) ) {
1764 /* trim trailing space? */
1766 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1767 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1771 nvalue.bv_val[nvalue.bv_len] = '\0';
1774 /* string of all spaces is treated as one space */
1775 nvalue.bv_val[0] = ' ';
1776 nvalue.bv_val[1] = '\0';
1780 *normalized = nvalue;
1781 return LDAP_SUCCESS;
1785 directoryStringSubstringsMatch(
1790 struct berval *value,
1791 void *assertedValue )
1794 SubstringsAssertion *sub = assertedValue;
1795 struct berval left = *value;
1799 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1800 if ( sub->sa_initial.bv_len > left.bv_len ) {
1801 /* not enough left */
1806 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1807 sub->sa_initial.bv_len );
1813 left.bv_val += sub->sa_initial.bv_len;
1814 left.bv_len -= sub->sa_initial.bv_len;
1816 priorspace = ASCII_SPACE(
1817 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1820 if ( sub->sa_any ) {
1821 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1825 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1826 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1828 /* allow next space to match */
1835 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1839 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1840 /* not enough left */
1845 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1852 idx = p - left.bv_val;
1854 if ( idx >= left.bv_len ) {
1855 /* this shouldn't happen */
1862 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1863 /* not enough left */
1868 match = memcmp( left.bv_val,
1869 sub->sa_any[i].bv_val,
1870 sub->sa_any[i].bv_len );
1878 left.bv_val += sub->sa_any[i].bv_len;
1879 left.bv_len -= sub->sa_any[i].bv_len;
1881 priorspace = ASCII_SPACE(
1882 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1886 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1887 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1888 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1890 /* allow next space to match */
1895 if ( sub->sa_final.bv_len > left.bv_len ) {
1896 /* not enough left */
1901 match = memcmp( sub->sa_final.bv_val,
1902 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1903 sub->sa_final.bv_len );
1912 return LDAP_SUCCESS;
1915 #if defined(SLAPD_APPROX_INITIALS)
1916 # define SLAPD_APPROX_DELIMITER "._ "
1917 # define SLAPD_APPROX_WORDLEN 2
1919 # define SLAPD_APPROX_DELIMITER " "
1920 # define SLAPD_APPROX_WORDLEN 1
1929 struct berval *value,
1930 void *assertedValue )
1932 struct berval *nval, *assertv;
1933 char *val, **values, **words, *c;
1934 int i, count, len, nextchunk=0, nextavail=0;
1936 /* Yes, this is necessary */
1937 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1938 if( nval == NULL ) {
1940 return LDAP_SUCCESS;
1943 /* Yes, this is necessary */
1944 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1945 NULL, LDAP_UTF8_APPROX, NULL );
1946 if( assertv == NULL ) {
1949 return LDAP_SUCCESS;
1952 /* Isolate how many words there are */
1953 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1954 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1955 if ( c == NULL ) break;
1960 /* Get a phonetic copy of each word */
1961 words = (char **)ch_malloc( count * sizeof(char *) );
1962 values = (char **)ch_malloc( count * sizeof(char *) );
1963 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1965 values[i] = phonetic(c);
1968 /* Work through the asserted value's words, to see if at least some
1969 * of the words are there, in the same order. */
1971 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1972 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1977 #if defined(SLAPD_APPROX_INITIALS)
1978 else if( len == 1 ) {
1979 /* Single letter words need to at least match one word's initial */
1980 for( i=nextavail; i<count; i++ )
1981 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1988 /* Isolate the next word in the asserted value and phonetic it */
1989 assertv->bv_val[nextchunk+len] = '\0';
1990 val = phonetic( assertv->bv_val + nextchunk );
1992 /* See if this phonetic chunk is in the remaining words of *value */
1993 for( i=nextavail; i<count; i++ ){
1994 if( !strcmp( val, values[i] ) ){
2002 /* This chunk in the asserted value was NOT within the *value. */
2008 /* Go on to the next word in the asserted value */
2012 /* If some of the words were seen, call it a match */
2013 if( nextavail > 0 ) {
2020 /* Cleanup allocs */
2021 ber_bvfree( assertv );
2022 for( i=0; i<count; i++ ) {
2023 ch_free( values[i] );
2029 return LDAP_SUCCESS;
2038 struct berval *prefix,
2044 int i,j, len, wordcount, keycount=0;
2045 struct berval *newkeys;
2046 BerVarray keys=NULL;
2048 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2049 struct berval val = BER_BVNULL;
2050 /* Yes, this is necessary */
2051 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2052 assert( !BER_BVISNULL( &val ) );
2054 /* Isolate how many words there are. There will be a key for each */
2055 for( wordcount = 0, c = val.bv_val; *c; c++) {
2056 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2057 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2059 if (*c == '\0') break;
2063 /* Allocate/increase storage to account for new keys */
2064 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2065 * sizeof(struct berval) );
2066 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2067 if( keys ) ch_free( keys );
2070 /* Get a phonetic copy of each word */
2071 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2073 if( len < SLAPD_APPROX_WORDLEN ) continue;
2074 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2079 ber_memfree( val.bv_val );
2081 BER_BVZERO( &keys[keycount] );
2084 return LDAP_SUCCESS;
2093 struct berval *prefix,
2094 void * assertedValue,
2103 /* Yes, this is necessary */
2104 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2105 NULL, LDAP_UTF8_APPROX, NULL );
2106 if( val == NULL || BER_BVISNULL( val ) ) {
2107 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2108 BER_BVZERO( &keys[0] );
2111 return LDAP_SUCCESS;
2114 /* Isolate how many words there are. There will be a key for each */
2115 for( count = 0,c = val->bv_val; *c; c++) {
2116 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2117 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2119 if (*c == '\0') break;
2123 /* Allocate storage for new keys */
2124 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2126 /* Get a phonetic copy of each word */
2127 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2129 if( len < SLAPD_APPROX_WORDLEN ) continue;
2130 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2136 BER_BVZERO( &keys[count] );
2139 return LDAP_SUCCESS;
2142 /* Remove all spaces and '-' characters */
2144 telephoneNumberNormalize(
2149 struct berval *normalized,
2154 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2156 /* validator should have refused an empty string */
2157 assert( !BER_BVISEMPTY( val ) );
2159 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2161 for( p = val->bv_val; *p; p++ ) {
2162 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2168 normalized->bv_len = q - normalized->bv_val;
2170 if( BER_BVISEMPTY( normalized ) ) {
2171 slap_sl_free( normalized->bv_val, ctx );
2172 BER_BVZERO( normalized );
2173 return LDAP_INVALID_SYNTAX;
2176 return LDAP_SUCCESS;
2180 postalAddressValidate(
2184 struct berval bv = *in;
2187 for ( c = 0; c < in->bv_len; c++ ) {
2188 if ( in->bv_val[c] == '\\' ) {
2190 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2191 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2193 return LDAP_INVALID_SYNTAX;
2198 if ( in->bv_val[c] == '$' ) {
2199 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2200 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2201 return LDAP_INVALID_SYNTAX;
2203 bv.bv_val = &in->bv_val[c] + 1;
2207 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2208 return UTF8StringValidate( NULL, &bv );
2212 postalAddressNormalize(
2217 struct berval *normalized,
2220 BerVarray lines = NULL, nlines = NULL;
2222 int rc = LDAP_SUCCESS;
2223 MatchingRule *xmr = NULL;
2226 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2227 xmr = slap_schema.si_mr_caseIgnoreMatch;
2230 xmr = slap_schema.si_mr_caseExactMatch;
2233 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2234 if ( val->bv_val[c] == '$' ) {
2239 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2240 nlines = &lines[l + 2];
2242 lines[0].bv_val = val->bv_val;
2243 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2244 if ( val->bv_val[c] == '$' ) {
2245 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2247 lines[l].bv_val = &val->bv_val[c + 1];
2250 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2252 normalized->bv_len = l;
2254 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2255 /* NOTE: we directly normalize each line,
2256 * without unescaping the values, since the special
2257 * values '\24' ('$') and '\5C' ('\') are not affected
2258 * by normalization */
2259 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2260 if ( rc != LDAP_SUCCESS ) {
2261 rc = LDAP_INVALID_SYNTAX;
2265 normalized->bv_len += nlines[l].bv_len;
2268 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2270 p = normalized->bv_val;
2271 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2272 p = lutil_strbvcopy( p, &nlines[l] );
2277 assert( p == &normalized->bv_val[normalized->bv_len] );
2280 if ( nlines != NULL ) {
2281 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2282 slap_sl_free( nlines[l].bv_val, ctx );
2285 slap_sl_free( lines, ctx );
2296 struct berval val = *in;
2298 if( BER_BVISEMPTY( &val ) ) {
2299 /* disallow empty strings */
2300 return LDAP_INVALID_SYNTAX;
2303 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2304 if ( val.bv_len == 1 ) {
2305 return LDAP_SUCCESS;
2308 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2315 while ( OID_LEADCHAR( val.bv_val[0] )) {
2319 if ( val.bv_len == 0 ) {
2320 return LDAP_SUCCESS;
2324 if( !OID_SEPARATOR( val.bv_val[0] )) {
2332 return LDAP_INVALID_SYNTAX;
2341 struct berval val = *in;
2343 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2345 if ( val.bv_val[0] == '-' ) {
2349 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2350 return LDAP_INVALID_SYNTAX;
2353 if( val.bv_val[0] == '0' ) { /* "-0" */
2354 return LDAP_INVALID_SYNTAX;
2357 } else if ( val.bv_val[0] == '0' ) {
2358 if( val.bv_len > 1 ) { /* "0<more>" */
2359 return LDAP_INVALID_SYNTAX;
2362 return LDAP_SUCCESS;
2365 for( i=0; i < val.bv_len; i++ ) {
2366 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2367 return LDAP_INVALID_SYNTAX;
2371 return LDAP_SUCCESS;
2380 struct berval *value,
2381 void *assertedValue )
2383 struct berval *asserted = (struct berval *) assertedValue;
2384 int vsign = 1, asign = 1; /* default sign = '+' */
2389 if( v.bv_val[0] == '-' ) {
2395 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2398 if( a.bv_val[0] == '-' ) {
2404 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2406 match = vsign - asign;
2408 match = ( v.bv_len != a.bv_len
2409 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2410 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2411 if( vsign < 0 ) match = -match;
2415 return LDAP_SUCCESS;
2418 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2419 #define INDEX_INTLEN_CHOP 7
2420 #define INDEX_INTLEN_CHOPBYTES 3
2430 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2431 * two's complement value (sign-extended or chopped as needed),
2432 * however the top <number of exponent-bytes + 1> bits of first byte
2433 * above is the inverse sign. The next bit is the sign as delimiter.
2435 ber_slen_t k = index_intlen_strlen;
2437 unsigned signmask = ~0x7fU;
2438 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2439 struct berval val = *in, itmp = *tmp;
2441 if ( val.bv_val[0] != '-' ) {
2446 /* Chop least significant digits, increase length instead */
2447 if ( val.bv_len > (ber_len_t) k ) {
2448 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2449 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2450 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2453 if ( lutil_str2bin( &val, &itmp, ctx )) {
2454 return LDAP_INVALID_SYNTAX;
2457 /* Omit leading sign byte */
2458 if ( itmp.bv_val[0] == neg ) {
2463 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2465 assert( chop == 0 );
2466 memset( key->bv_val, neg, k ); /* sign-extend */
2467 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2468 lenp = lenbuf + sizeof(lenbuf);
2469 chop = - (ber_len_t) k;
2471 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2473 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2474 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2475 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2476 k = (lenbuf + sizeof(lenbuf)) - lenp;
2477 if ( k > (ber_slen_t) index_intlen )
2479 memcpy( key->bv_val, lenp, k );
2480 itmp.bv_len = index_intlen - k;
2482 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2483 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2487 /* Index generation function */
2494 struct berval *prefix,
2504 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2506 /* count the values and find max needed length */
2508 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2509 if ( vlen < values[i].bv_len )
2510 vlen = values[i].bv_len;
2512 if ( vlen > maxstrlen )
2515 /* we should have at least one value at this point */
2518 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2519 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2520 keys[i].bv_len = index_intlen;
2521 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2524 keys[i].bv_val = NULL;
2526 if ( vlen > sizeof(ibuf) ) {
2527 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2531 itmp.bv_len = sizeof(ibuf);
2533 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2534 if ( itmp.bv_val != ibuf ) {
2535 itmp.bv_len = values[i].bv_len;
2536 if ( itmp.bv_len <= sizeof(ibuf) )
2537 itmp.bv_len = sizeof(ibuf);
2538 else if ( itmp.bv_len > maxstrlen )
2539 itmp.bv_len = maxstrlen;
2541 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2547 if ( itmp.bv_val != ibuf ) {
2548 slap_sl_free( itmp.bv_val, ctx );
2553 /* Index generation function */
2560 struct berval *prefix,
2561 void * assertedValue,
2568 struct berval *value;
2571 value = (struct berval *) assertedValue;
2573 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2575 keys[0].bv_len = index_intlen;
2576 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2578 keys[1].bv_val = NULL;
2580 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2581 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2582 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2583 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2586 iv.bv_len = sizeof(ibuf);
2589 rc = integerVal2Key( value, keys, &iv, ctx );
2593 if ( iv.bv_val != ibuf ) {
2594 slap_sl_free( iv.bv_val, ctx );
2600 countryStringValidate(
2602 struct berval *val )
2604 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2606 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2607 return LDAP_INVALID_SYNTAX;
2609 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2610 return LDAP_INVALID_SYNTAX;
2613 return LDAP_SUCCESS;
2617 printableStringValidate(
2619 struct berval *val )
2623 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2625 for(i=0; i < val->bv_len; i++) {
2626 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2627 return LDAP_INVALID_SYNTAX;
2631 return LDAP_SUCCESS;
2635 printablesStringValidate(
2637 struct berval *val )
2641 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2643 for(i=0,len=0; i < val->bv_len; i++) {
2644 int c = val->bv_val[i];
2648 return LDAP_INVALID_SYNTAX;
2652 } else if ( SLAP_PRINTABLE(c) ) {
2655 return LDAP_INVALID_SYNTAX;
2660 return LDAP_INVALID_SYNTAX;
2663 return LDAP_SUCCESS;
2669 struct berval *val )
2673 for(i=0; i < val->bv_len; i++) {
2674 if( !LDAP_ASCII(val->bv_val[i]) ) {
2675 return LDAP_INVALID_SYNTAX;
2679 return LDAP_SUCCESS;
2688 struct berval *normalized,
2692 int casefold = !SLAP_MR_ASSOCIATED( mr,
2693 slap_schema.si_mr_caseExactIA5Match );
2695 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2699 /* Ignore initial whitespace */
2700 while ( ASCII_SPACE( *p ) ) p++;
2702 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2703 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2704 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2705 normalized->bv_val[normalized->bv_len] = '\0';
2707 p = q = normalized->bv_val;
2710 if ( ASCII_SPACE( *p ) ) {
2713 /* Ignore the extra whitespace */
2714 while ( ASCII_SPACE( *p ) ) {
2718 } else if ( casefold ) {
2719 /* Most IA5 rules require casefolding */
2720 *q++ = TOLOWER(*p); p++;
2727 assert( normalized->bv_val <= p );
2731 * If the string ended in space, backup the pointer one
2732 * position. One is enough because the above loop collapsed
2733 * all whitespace to a single space.
2735 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2737 /* null terminate */
2740 normalized->bv_len = q - normalized->bv_val;
2742 return LDAP_SUCCESS;
2751 if( in->bv_len != 36 ) {
2752 return LDAP_INVALID_SYNTAX;
2755 for( i=0; i<36; i++ ) {
2761 if( in->bv_val[i] != '-' ) {
2762 return LDAP_INVALID_SYNTAX;
2766 if( !ASCII_HEX( in->bv_val[i]) ) {
2767 return LDAP_INVALID_SYNTAX;
2772 return LDAP_SUCCESS;
2783 int rc=LDAP_INVALID_SYNTAX;
2785 assert( in != NULL );
2786 assert( out != NULL );
2788 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2791 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2793 for( i=0; i<36; i++ ) {
2799 if( in->bv_val[i] != '-' ) {
2802 out->bv_val[i] = '-';
2806 if( !ASCII_HEX( in->bv_val[i]) ) {
2809 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2814 out->bv_val[ out->bv_len ] = '\0';
2818 slap_sl_free( out->bv_val, ctx );
2831 struct berval *normalized,
2834 unsigned char octet = '\0';
2838 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2839 /* NOTE: must be a normalized UUID */
2840 assert( val->bv_len == 16 );
2842 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2843 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2844 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2845 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2847 return LDAP_SUCCESS;
2850 normalized->bv_len = 16;
2851 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2853 for( i=0, j=0; i<36; i++ ) {
2854 unsigned char nibble;
2855 if( val->bv_val[i] == '-' ) {
2858 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2859 nibble = val->bv_val[i] - '0';
2861 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2862 nibble = val->bv_val[i] - ('a'-10);
2864 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2865 nibble = val->bv_val[i] - ('A'-10);
2868 slap_sl_free( normalized->bv_val, ctx );
2869 BER_BVZERO( normalized );
2870 return LDAP_INVALID_SYNTAX;
2875 normalized->bv_val[j>>1] = octet;
2877 octet = nibble << 4;
2882 normalized->bv_val[normalized->bv_len] = 0;
2883 return LDAP_SUCCESS;
2889 numericStringValidate(
2895 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2897 for(i=0; i < in->bv_len; i++) {
2898 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2899 return LDAP_INVALID_SYNTAX;
2903 return LDAP_SUCCESS;
2907 numericStringNormalize(
2912 struct berval *normalized,
2915 /* removal all spaces */
2918 assert( !BER_BVISEMPTY( val ) );
2920 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2923 q = normalized->bv_val;
2926 if ( ASCII_SPACE( *p ) ) {
2927 /* Ignore whitespace */
2934 /* we should have copied no more than is in val */
2935 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2937 /* null terminate */
2940 normalized->bv_len = q - normalized->bv_val;
2942 if( BER_BVISEMPTY( normalized ) ) {
2943 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2944 normalized->bv_val[0] = ' ';
2945 normalized->bv_val[1] = '\0';
2946 normalized->bv_len = 1;
2949 return LDAP_SUCCESS;
2953 * Integer conversion macros that will use the largest available
2956 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2957 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2958 # define SLAP_LONG long long
2960 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2961 # define SLAP_LONG long
2962 #endif /* HAVE_STRTOLL ... */
2970 struct berval *value,
2971 void *assertedValue )
2973 SLAP_LONG lValue, lAssertedValue;
2976 /* safe to assume integers are NUL terminated? */
2977 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2978 if( errno == ERANGE )
2980 return LDAP_CONSTRAINT_VIOLATION;
2983 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2985 if( errno == ERANGE )
2987 return LDAP_CONSTRAINT_VIOLATION;
2990 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2991 return LDAP_SUCCESS;
3000 struct berval *value,
3001 void *assertedValue )
3003 SLAP_LONG lValue, lAssertedValue;
3006 /* safe to assume integers are NUL terminated? */
3007 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3008 if( errno == ERANGE )
3010 return LDAP_CONSTRAINT_VIOLATION;
3013 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3015 if( errno == ERANGE )
3017 return LDAP_CONSTRAINT_VIOLATION;
3020 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3021 return LDAP_SUCCESS;
3025 checkNum( struct berval *in, struct berval *out )
3027 /* parse serialNumber */
3028 ber_len_t neg = 0, extra = 0;
3031 out->bv_val = in->bv_val;
3034 if ( out->bv_val[0] == '-' ) {
3039 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3040 first = out->bv_val[2];
3043 out->bv_len += STRLENOF("0x");
3044 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3045 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3048 } else if ( out->bv_val[0] == '\'' ) {
3049 first = out->bv_val[1];
3052 out->bv_len += STRLENOF("'");
3054 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3055 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3057 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3060 out->bv_len += STRLENOF("'H");
3063 first = out->bv_val[0];
3064 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3065 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3069 if ( !( out->bv_len > neg ) ) {
3073 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3081 serialNumberAndIssuerCheck(
3089 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3091 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3092 /* Parse old format */
3093 is->bv_val = ber_bvchr( in, '$' );
3094 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3096 sn->bv_val = in->bv_val;
3097 sn->bv_len = is->bv_val - in->bv_val;
3100 is->bv_len = in->bv_len - (sn->bv_len + 1);
3102 /* eat leading zeros */
3103 for( n=0; n < (sn->bv_len-1); n++ ) {
3104 if( sn->bv_val[n] != '0' ) break;
3109 for( n=0; n < sn->bv_len; n++ ) {
3110 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3114 /* Parse GSER format */
3119 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3123 struct berval x = *in;
3129 /* eat leading spaces */
3130 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3134 /* should be at issuer or serialNumber NamedValue */
3135 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3136 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3139 x.bv_val += STRLENOF("issuer");
3140 x.bv_len -= STRLENOF("issuer");
3142 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3146 /* eat leading spaces */
3147 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3151 /* For backward compatibility, this part is optional */
3152 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3153 x.bv_val += STRLENOF("rdnSequence:");
3154 x.bv_len -= STRLENOF("rdnSequence:");
3157 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3161 is->bv_val = x.bv_val;
3164 for ( ; is->bv_len < x.bv_len; ) {
3165 if ( is->bv_val[is->bv_len] != '"' ) {
3169 if ( is->bv_val[is->bv_len+1] == '"' ) {
3176 x.bv_val += is->bv_len + 1;
3177 x.bv_len -= is->bv_len + 1;
3179 have |= HAVE_ISSUER;
3181 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3183 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3185 /* parse serialNumber */
3186 x.bv_val += STRLENOF("serialNumber");
3187 x.bv_len -= STRLENOF("serialNumber");
3189 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3193 /* eat leading spaces */
3194 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3198 if ( checkNum( &x, sn ) ) {
3199 return LDAP_INVALID_SYNTAX;
3202 x.bv_val += sn->bv_len;
3203 x.bv_len -= sn->bv_len;
3208 return LDAP_INVALID_SYNTAX;
3211 /* eat leading spaces */
3212 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3216 if ( have == HAVE_ALL ) {
3220 if ( x.bv_val[0] != ',' ) {
3221 return LDAP_INVALID_SYNTAX;
3228 /* should have no characters left... */
3229 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3231 if ( numdquotes == 0 ) {
3232 ber_dupbv_x( &ni, is, ctx );
3237 ni.bv_len = is->bv_len - numdquotes;
3238 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3239 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3240 if ( is->bv_val[src] == '"' ) {
3243 ni.bv_val[dst] = is->bv_val[src];
3245 ni.bv_val[dst] = '\0';
3255 serialNumberAndIssuerValidate(
3260 struct berval sn, i;
3262 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3265 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3270 /* validate DN -- doesn't handle double dquote */
3271 rc = dnValidate( NULL, &i );
3273 rc = LDAP_INVALID_SYNTAX;
3276 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3277 slap_sl_free( i.bv_val, NULL );
3280 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3281 in->bv_val, rc, 0 );
3288 serialNumberAndIssuerPretty(
3295 struct berval sn, i, ni = BER_BVNULL;
3298 assert( in != NULL );
3299 assert( out != NULL );
3303 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3306 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3311 rc = dnPretty( syntax, &i, &ni, ctx );
3313 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3314 slap_sl_free( i.bv_val, ctx );
3318 rc = LDAP_INVALID_SYNTAX;
3322 /* make room from sn + "$" */
3323 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3324 + sn.bv_len + ni.bv_len;
3325 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3327 if ( out->bv_val == NULL ) {
3334 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3335 p = lutil_strbvcopy( p, &sn );
3336 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3337 p = lutil_strbvcopy( p, &ni );
3338 p = lutil_strcopy( p, /*{*/ "\" }" );
3340 assert( p == &out->bv_val[out->bv_len] );
3343 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3344 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3346 slap_sl_free( ni.bv_val, ctx );
3348 return LDAP_SUCCESS;
3358 /* Use hex format. '123456789abcdef'H */
3359 unsigned char *ptr, zero = '\0';
3362 ber_len_t i, len, nlen;
3364 assert( in != NULL );
3365 assert( !BER_BVISNULL( in ) );
3366 assert( out != NULL );
3367 assert( !BER_BVISNULL( out ) );
3369 ptr = (unsigned char *)in->bv_val;
3372 /* Check for minimal encodings */
3374 if ( ptr[0] & 0x80 ) {
3375 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3379 } else if ( ptr[0] == 0 ) {
3380 if ( !( ptr[1] & 0x80 ) ) {
3387 } else if ( len == 0 ) {
3388 /* FIXME: this should not be possible,
3389 * since a value of zero would have length 1 */
3394 first = !( ptr[0] & 0xf0U );
3395 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3396 if ( nlen >= out->bv_len ) {
3397 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3403 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3407 for ( ; i < len; i++ ) {
3408 sprintf( sptr, "%02X", ptr[i] );
3415 assert( sptr == &out->bv_val[nlen] );
3422 #define SLAP_SN_BUFLEN (64)
3425 * This routine is called by certificateExactNormalize when
3426 * certificateExactNormalize receives a search string instead of
3427 * a certificate. This routine checks if the search value is valid
3428 * and then returns the normalized value
3431 serialNumberAndIssuerNormalize(
3439 struct berval sn, sn2, sn3, i, ni;
3440 char sbuf2[SLAP_SN_BUFLEN];
3441 char sbuf3[SLAP_SN_BUFLEN];
3445 assert( in != NULL );
3446 assert( out != NULL );
3448 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3451 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3456 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3458 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3459 slap_sl_free( i.bv_val, ctx );
3463 return LDAP_INVALID_SYNTAX;
3466 /* Convert sn to canonical hex */
3468 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3469 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3471 sn2.bv_len = sn.bv_len;
3472 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3473 rc = LDAP_INVALID_SYNTAX;
3478 sn3.bv_len = sizeof(sbuf3);
3479 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3480 rc = LDAP_INVALID_SYNTAX;
3484 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3485 + sn3.bv_len + ni.bv_len;
3486 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3488 if ( out->bv_val == NULL ) {
3496 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3497 p = lutil_strbvcopy( p, &sn3 );
3498 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3499 p = lutil_strbvcopy( p, &ni );
3500 p = lutil_strcopy( p, /*{*/ "\" }" );
3502 assert( p == &out->bv_val[out->bv_len] );
3505 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3506 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3508 if ( sn2.bv_val != sbuf2 ) {
3509 slap_sl_free( sn2.bv_val, ctx );
3512 if ( sn3.bv_val != sbuf3 ) {
3513 slap_sl_free( sn3.bv_val, ctx );
3516 slap_sl_free( ni.bv_val, ctx );
3522 certificateExactNormalize(
3527 struct berval *normalized,
3530 BerElementBuffer berbuf;
3531 BerElement *ber = (BerElement *)&berbuf;
3535 char serialbuf2[SLAP_SN_BUFLEN];
3536 struct berval sn, sn2 = BER_BVNULL;
3537 struct berval issuer_dn = BER_BVNULL, bvdn;
3539 int rc = LDAP_INVALID_SYNTAX;
3541 assert( val != NULL );
3543 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3544 val->bv_val, val->bv_len, 0 );
3546 if ( BER_BVISEMPTY( val ) ) goto done;
3548 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3549 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3552 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3554 ber_init2( ber, val, LBER_USE_DER );
3555 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3556 tag = ber_skip_tag( ber, &len ); /* Sequence */
3557 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3558 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3559 tag = ber_skip_tag( ber, &len );
3560 tag = ber_get_int( ber, &i ); /* version */
3563 /* NOTE: move the test here from certificateValidate,
3564 * so that we can validate certs with serial longer
3565 * than sizeof(ber_int_t) */
3566 tag = ber_skip_tag( ber, &len ); /* serial */
3568 sn.bv_val = (char *)ber->ber_ptr;
3569 sn2.bv_val = serialbuf2;
3570 sn2.bv_len = sizeof(serialbuf2);
3571 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3572 rc = LDAP_INVALID_SYNTAX;
3575 ber_skip_data( ber, len );
3577 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3578 ber_skip_data( ber, len );
3579 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3580 len = ber_ptrlen( ber );
3581 bvdn.bv_val = val->bv_val + len;
3582 bvdn.bv_len = val->bv_len - len;
3584 rc = dnX509normalize( &bvdn, &issuer_dn );
3585 if ( rc != LDAP_SUCCESS ) goto done;
3587 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3588 + sn2.bv_len + issuer_dn.bv_len;
3589 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3591 p = normalized->bv_val;
3593 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3594 p = lutil_strbvcopy( p, &sn2 );
3595 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3596 p = lutil_strbvcopy( p, &issuer_dn );
3597 p = lutil_strcopy( p, /*{*/ "\" }" );
3602 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3603 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3605 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3606 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3611 /* X.509 PKI certificateList stuff */
3613 checkTime( struct berval *in, struct berval *out )
3617 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3620 assert( in != NULL );
3621 assert( !BER_BVISNULL( in ) );
3622 assert( !BER_BVISEMPTY( in ) );
3624 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3628 if ( out != NULL ) {
3629 assert( !BER_BVISNULL( out ) );
3630 assert( out->bv_len >= sizeof( buf ) );
3631 bv.bv_val = out->bv_val;
3637 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3638 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3641 if ( in->bv_val[i] != 'Z' ) {
3646 if ( i != in->bv_len ) {
3650 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3651 lutil_strncopy( bv.bv_val, in->bv_val, i );
3654 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3655 char *p = bv.bv_val;
3656 if ( in->bv_val[0] < '7' ) {
3657 p = lutil_strcopy( p, "20" );
3660 p = lutil_strcopy( p, "19" );
3662 lutil_strncopy( p, in->bv_val, i );
3669 rc = generalizedTimeValidate( NULL, &bv );
3670 if ( rc == LDAP_SUCCESS && out != NULL ) {
3671 if ( out->bv_len > bv.bv_len ) {
3672 out->bv_val[ bv.bv_len ] = '\0';
3674 out->bv_len = bv.bv_len;
3677 return rc != LDAP_SUCCESS;
3681 issuerAndThisUpdateCheck(
3688 struct berval x = *in;
3689 struct berval ni = BER_BVNULL;
3690 /* Parse GSER format */
3694 HAVE_THISUPDATE = 0x2,
3695 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3699 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3701 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3702 return LDAP_INVALID_SYNTAX;
3706 x.bv_len -= STRLENOF("{}");
3709 /* eat leading spaces */
3710 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3714 /* should be at issuer or thisUpdate */
3715 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3716 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3719 x.bv_val += STRLENOF("issuer");
3720 x.bv_len -= STRLENOF("issuer");
3722 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3726 /* eat leading spaces */
3727 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3731 /* For backward compatibility, this part is optional */
3732 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3733 return LDAP_INVALID_SYNTAX;
3735 x.bv_val += STRLENOF("rdnSequence:");
3736 x.bv_len -= STRLENOF("rdnSequence:");
3738 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3742 is->bv_val = x.bv_val;
3745 for ( ; is->bv_len < x.bv_len; ) {
3746 if ( is->bv_val[is->bv_len] != '"' ) {
3750 if ( is->bv_val[is->bv_len+1] == '"' ) {
3757 x.bv_val += is->bv_len + 1;
3758 x.bv_len -= is->bv_len + 1;
3760 have |= HAVE_ISSUER;
3762 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3764 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3766 /* parse thisUpdate */
3767 x.bv_val += STRLENOF("thisUpdate");
3768 x.bv_len -= STRLENOF("thisUpdate");
3770 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3774 /* eat leading spaces */
3775 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3779 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3783 tu->bv_val = x.bv_val;
3786 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3787 if ( tu->bv_val[tu->bv_len] == '"' ) {
3791 x.bv_val += tu->bv_len + 1;
3792 x.bv_len -= tu->bv_len + 1;
3794 have |= HAVE_THISUPDATE;
3797 return LDAP_INVALID_SYNTAX;
3800 /* eat leading spaces */
3801 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3805 if ( have == HAVE_ALL ) {
3809 if ( x.bv_val[0] != ',' ) {
3810 return LDAP_INVALID_SYNTAX;
3817 /* should have no characters left... */
3818 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3820 if ( numdquotes == 0 ) {
3821 ber_dupbv_x( &ni, is, ctx );
3826 ni.bv_len = is->bv_len - numdquotes;
3827 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3828 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3829 if ( is->bv_val[src] == '"' ) {
3832 ni.bv_val[dst] = is->bv_val[src];
3834 ni.bv_val[dst] = '\0';
3843 issuerAndThisUpdateValidate(
3848 struct berval i, tu;
3850 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3853 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3858 /* validate DN -- doesn't handle double dquote */
3859 rc = dnValidate( NULL, &i );
3861 rc = LDAP_INVALID_SYNTAX;
3863 } else if ( checkTime( &tu, NULL ) ) {
3864 rc = LDAP_INVALID_SYNTAX;
3867 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3868 slap_sl_free( i.bv_val, NULL );
3871 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3872 in->bv_val, rc, 0 );
3879 issuerAndThisUpdatePretty(
3886 struct berval i, tu, ni = BER_BVNULL;
3889 assert( in != NULL );
3890 assert( out != NULL );
3894 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3897 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3902 rc = dnPretty( syntax, &i, &ni, ctx );
3904 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3905 slap_sl_free( i.bv_val, ctx );
3908 if ( rc || checkTime( &tu, NULL ) ) {
3909 rc = LDAP_INVALID_SYNTAX;
3914 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3915 + ni.bv_len + tu.bv_len;
3916 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3918 if ( out->bv_val == NULL ) {
3925 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3926 p = lutil_strbvcopy( p, &ni );
3927 p = lutil_strcopy( p, "\", thisUpdate \"" );
3928 p = lutil_strbvcopy( p, &tu );
3929 p = lutil_strcopy( p, /*{*/ "\" }" );
3931 assert( p == &out->bv_val[out->bv_len] );
3934 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3935 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3937 slap_sl_free( ni.bv_val, ctx );
3943 issuerAndThisUpdateNormalize(
3951 struct berval i, ni, tu, tu2;
3952 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3956 assert( in != NULL );
3957 assert( out != NULL );
3959 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3962 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3967 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3969 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3970 slap_sl_free( i.bv_val, ctx );
3974 tu2.bv_len = sizeof( sbuf );
3975 if ( rc || checkTime( &tu, &tu2 ) ) {
3976 return LDAP_INVALID_SYNTAX;
3979 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3980 + ni.bv_len + tu2.bv_len;
3981 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3983 if ( out->bv_val == NULL ) {
3991 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3992 p = lutil_strbvcopy( p, &ni );
3993 p = lutil_strcopy( p, "\", thisUpdate \"" );
3994 p = lutil_strbvcopy( p, &tu2 );
3995 p = lutil_strcopy( p, /*{*/ "\" }" );
3997 assert( p == &out->bv_val[out->bv_len] );
4000 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4001 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4003 slap_sl_free( ni.bv_val, ctx );
4009 certificateListExactNormalize(
4014 struct berval *normalized,
4017 BerElementBuffer berbuf;
4018 BerElement *ber = (BerElement *)&berbuf;
4022 struct berval issuer_dn = BER_BVNULL, bvdn,
4024 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4025 int rc = LDAP_INVALID_SYNTAX;
4027 assert( val != NULL );
4029 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4030 val->bv_val, val->bv_len, 0 );
4032 if ( BER_BVISEMPTY( val ) ) goto done;
4034 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4035 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4038 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4040 ber_init2( ber, val, LBER_USE_DER );
4041 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4042 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4043 tag = ber_skip_tag( ber, &len ); /* Sequence */
4044 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4045 tag = ber_peek_tag( ber, &len );
4046 /* Optional version */
4047 if ( tag == LBER_INTEGER ) {
4048 tag = ber_get_int( ber, &version );
4049 assert( tag == LBER_INTEGER );
4050 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4052 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4053 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4054 ber_skip_data( ber, len );
4056 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4057 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4058 len = ber_ptrlen( ber );
4059 bvdn.bv_val = val->bv_val + len;
4060 bvdn.bv_len = val->bv_len - len;
4061 tag = ber_skip_tag( ber, &len );
4062 ber_skip_data( ber, len );
4064 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4065 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4066 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4067 bvtu.bv_val = (char *)ber->ber_ptr;
4070 rc = dnX509normalize( &bvdn, &issuer_dn );
4071 if ( rc != LDAP_SUCCESS ) goto done;
4073 thisUpdate.bv_val = tubuf;
4074 thisUpdate.bv_len = sizeof(tubuf);
4075 if ( checkTime( &bvtu, &thisUpdate ) ) {
4076 rc = LDAP_INVALID_SYNTAX;
4080 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4081 + issuer_dn.bv_len + thisUpdate.bv_len;
4082 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4084 p = normalized->bv_val;
4086 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4087 p = lutil_strbvcopy( p, &issuer_dn );
4088 p = lutil_strcopy( p, "\", thisUpdate \"" );
4089 p = lutil_strbvcopy( p, &thisUpdate );
4090 p = lutil_strcopy( p, /*{*/ "\" }" );
4095 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4096 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4098 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4103 /* X.509 PMI serialNumberAndIssuerSerialCheck
4105 AttributeCertificateExactAssertion ::= SEQUENCE {
4106 serialNumber CertificateSerialNumber,
4107 issuer AttCertIssuer }
4109 CertificateSerialNumber ::= INTEGER
4111 AttCertIssuer ::= [0] SEQUENCE {
4112 issuerName GeneralNames OPTIONAL,
4113 baseCertificateID [0] IssuerSerial OPTIONAL,
4114 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4115 -- At least one component shall be present
4117 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4119 GeneralName ::= CHOICE {
4120 otherName [0] INSTANCE OF OTHER-NAME,
4121 rfc822Name [1] IA5String,
4122 dNSName [2] IA5String,
4123 x400Address [3] ORAddress,
4124 directoryName [4] Name,
4125 ediPartyName [5] EDIPartyName,
4126 uniformResourceIdentifier [6] IA5String,
4127 iPAddress [7] OCTET STRING,
4128 registeredID [8] OBJECT IDENTIFIER }
4130 IssuerSerial ::= SEQUENCE {
4131 issuer GeneralNames,
4132 serial CertificateSerialNumber,
4133 issuerUID UniqueIdentifier OPTIONAL }
4135 ObjectDigestInfo ::= SEQUENCE {
4136 digestedObjectType ENUMERATED {
4139 otherObjectTypes (2) },
4140 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4141 digestAlgorithm AlgorithmIdentifier,
4142 objectDigest BIT STRING }
4144 * The way I interpret it, an assertion should look like
4146 { serialNumber 'dd'H,
4147 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4148 baseCertificateID { serial '1d'H,
4149 issuer { directoryName:rdnSequence:"cn=zzz" },
4150 issuerUID <value> -- optional
4152 objectDigestInfo { ... } -- optional
4156 * with issuerName, baseCertificateID and objectDigestInfo optional,
4157 * at least one present; the way it's currently implemented, it is
4159 { serialNumber 'dd'H,
4160 issuer { baseCertificateID { serial '1d'H,
4161 issuer { directoryName:rdnSequence:"cn=zzz" }
4166 * with all the above parts mandatory.
4169 serialNumberAndIssuerSerialCheck(
4173 struct berval *i_sn, /* contain serial of baseCertificateID */
4176 /* Parse GSER format */
4181 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4182 } have = HAVE_NONE, have2 = HAVE_NONE;
4184 struct berval x = *in;
4187 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4190 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4197 /* eat leading spaces */
4198 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4202 /* should be at issuer or serialNumber NamedValue */
4203 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4204 if ( have & HAVE_ISSUER ) {
4205 return LDAP_INVALID_SYNTAX;
4208 /* parse IssuerSerial */
4209 x.bv_val += STRLENOF("issuer");
4210 x.bv_len -= STRLENOF("issuer");
4212 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4216 /* eat leading spaces */
4217 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4221 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4225 /* eat leading spaces */
4226 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4230 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4231 return LDAP_INVALID_SYNTAX;
4233 x.bv_val += STRLENOF("baseCertificateID ");
4234 x.bv_len -= STRLENOF("baseCertificateID ");
4236 /* eat leading spaces */
4237 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4241 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4246 /* eat leading spaces */
4247 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4251 /* parse issuer of baseCertificateID */
4252 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4253 if ( have2 & HAVE_ISSUER ) {
4254 return LDAP_INVALID_SYNTAX;
4257 x.bv_val += STRLENOF("issuer ");
4258 x.bv_len -= STRLENOF("issuer ");
4260 /* eat leading spaces */
4261 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4265 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4269 /* eat leading spaces */
4270 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4274 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4275 return LDAP_INVALID_SYNTAX;
4277 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4278 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4280 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4284 is->bv_val = x.bv_val;
4287 for ( ; is->bv_len < x.bv_len; ) {
4288 if ( is->bv_val[is->bv_len] != '"' ) {
4292 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4299 x.bv_val += is->bv_len + 1;
4300 x.bv_len -= is->bv_len + 1;
4302 /* eat leading spaces */
4303 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4307 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4311 have2 |= HAVE_ISSUER;
4313 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4314 if ( have2 & HAVE_SN ) {
4315 return LDAP_INVALID_SYNTAX;
4318 x.bv_val += STRLENOF("serial ");
4319 x.bv_len -= STRLENOF("serial ");
4321 /* eat leading spaces */
4322 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4326 if ( checkNum( &x, i_sn ) ) {
4327 return LDAP_INVALID_SYNTAX;
4330 x.bv_val += i_sn->bv_len;
4331 x.bv_len -= i_sn->bv_len;
4336 return LDAP_INVALID_SYNTAX;
4339 /* eat leading spaces */
4340 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4344 if ( have2 == HAVE_ALL ) {
4348 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4353 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4357 /* eat leading spaces */
4358 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4362 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4366 have |= HAVE_ISSUER;
4368 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4369 if ( have & HAVE_SN ) {
4370 return LDAP_INVALID_SYNTAX;
4373 /* parse serialNumber */
4374 x.bv_val += STRLENOF("serialNumber");
4375 x.bv_len -= STRLENOF("serialNumber");
4377 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4381 /* eat leading spaces */
4382 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4386 if ( checkNum( &x, sn ) ) {
4387 return LDAP_INVALID_SYNTAX;
4390 x.bv_val += sn->bv_len;
4391 x.bv_len -= sn->bv_len;
4396 return LDAP_INVALID_SYNTAX;
4400 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4404 if ( have == HAVE_ALL ) {
4408 if ( x.bv_val[0] != ',' ) {
4409 return LDAP_INVALID_SYNTAX;
4415 /* should have no characters left... */
4416 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4418 if ( numdquotes == 0 ) {
4419 ber_dupbv_x( &ni, is, ctx );
4424 ni.bv_len = is->bv_len - numdquotes;
4425 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4426 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4427 if ( is->bv_val[src] == '"' ) {
4430 ni.bv_val[dst] = is->bv_val[src];
4432 ni.bv_val[dst] = '\0';
4437 /* need to handle double dquotes here */
4441 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4443 serialNumberAndIssuerSerialValidate(
4448 struct berval sn, i, i_sn;
4450 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4453 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4458 /* validate DN -- doesn't handle double dquote */
4459 rc = dnValidate( NULL, &i );
4461 rc = LDAP_INVALID_SYNTAX;
4464 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4465 slap_sl_free( i.bv_val, NULL );
4469 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4470 in->bv_val, rc, 0 );
4475 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4477 serialNumberAndIssuerSerialPretty(
4483 struct berval sn, i, i_sn, ni = BER_BVNULL;
4487 assert( in != NULL );
4488 assert( out != NULL );
4490 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4493 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4498 rc = dnPretty( syntax, &i, &ni, ctx );
4500 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4501 slap_sl_free( i.bv_val, ctx );
4505 rc = LDAP_INVALID_SYNTAX;
4509 /* make room from sn + "$" */
4510 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4511 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4512 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4514 if ( out->bv_val == NULL ) {
4521 p = lutil_strcopy( p, "{ serialNumber " );
4522 p = lutil_strbvcopy( p, &sn );
4523 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4524 p = lutil_strbvcopy( p, &ni );
4525 p = lutil_strcopy( p, "\" }, serial " );
4526 p = lutil_strbvcopy( p, &i_sn );
4527 p = lutil_strcopy( p, " } } }" );
4529 assert( p == &out->bv_val[out->bv_len] );
4532 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4533 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4535 slap_sl_free( ni.bv_val, ctx );
4540 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4542 * This routine is called by attributeCertificateExactNormalize
4543 * when attributeCertificateExactNormalize receives a search
4544 * string instead of a attribute certificate. This routine
4545 * checks if the search value is valid and then returns the
4549 serialNumberAndIssuerSerialNormalize(
4557 struct berval i, ni = BER_BVNULL,
4558 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4559 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4560 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4561 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4565 assert( in != NULL );
4566 assert( out != NULL );
4568 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4571 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4576 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4578 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4579 slap_sl_free( i.bv_val, ctx );
4583 rc = LDAP_INVALID_SYNTAX;
4587 /* Convert sn to canonical hex */
4589 sn2.bv_len = sn.bv_len;
4590 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4591 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4593 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4594 rc = LDAP_INVALID_SYNTAX;
4598 /* Convert i_sn to canonical hex */
4599 i_sn2.bv_val = i_sbuf2;
4600 i_sn2.bv_len = i_sn.bv_len;
4601 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4602 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4604 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4605 rc = LDAP_INVALID_SYNTAX;
4610 sn3.bv_len = sizeof(sbuf3);
4611 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4612 rc = LDAP_INVALID_SYNTAX;
4616 i_sn3.bv_val = i_sbuf3;
4617 i_sn3.bv_len = sizeof(i_sbuf3);
4618 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4619 rc = LDAP_INVALID_SYNTAX;
4623 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4624 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4625 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4627 if ( out->bv_val == NULL ) {
4635 p = lutil_strcopy( p, "{ serialNumber " );
4636 p = lutil_strbvcopy( p, &sn3 );
4637 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4638 p = lutil_strbvcopy( p, &ni );
4639 p = lutil_strcopy( p, "\" }, serial " );
4640 p = lutil_strbvcopy( p, &i_sn3 );
4641 p = lutil_strcopy( p, " } } }" );
4643 assert( p == &out->bv_val[out->bv_len] );
4646 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4647 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4649 if ( sn2.bv_val != sbuf2 ) {
4650 slap_sl_free( sn2.bv_val, ctx );
4653 if ( i_sn2.bv_val != i_sbuf2 ) {
4654 slap_sl_free( i_sn2.bv_val, ctx );
4657 if ( sn3.bv_val != sbuf3 ) {
4658 slap_sl_free( sn3.bv_val, ctx );
4661 if ( i_sn3.bv_val != i_sbuf3 ) {
4662 slap_sl_free( i_sn3.bv_val, ctx );
4665 slap_sl_free( ni.bv_val, ctx );
4670 /* X.509 PMI attributeCertificateExactNormalize */
4672 attributeCertificateExactNormalize(
4677 struct berval *normalized,
4680 BerElementBuffer berbuf;
4681 BerElement *ber = (BerElement *)&berbuf;
4684 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4685 struct berval sn, i_sn, sn2, i_sn2;
4686 struct berval issuer_dn = BER_BVNULL, bvdn;
4688 int rc = LDAP_INVALID_SYNTAX;
4690 if ( BER_BVISEMPTY( val ) ) {
4694 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4695 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4698 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4700 ber_init2( ber, val, LBER_USE_DER );
4701 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4702 tag = ber_skip_tag( ber, &len ); /* Sequence */
4703 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4704 ber_skip_data( ber, len );
4705 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4706 ber_skip_data( ber, len );
4709 tag = ber_skip_tag( ber, &len ); /* Sequence */
4710 /* issuerName (GeneralNames sequence; optional)? */
4711 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4712 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4713 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4714 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4715 rc = LDAP_INVALID_SYNTAX;
4718 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4719 len = ber_ptrlen( ber );
4720 bvdn.bv_val = val->bv_val + len;
4721 bvdn.bv_len = val->bv_len - len;
4722 rc = dnX509normalize( &bvdn, &issuer_dn );
4723 if ( rc != LDAP_SUCCESS ) goto done;
4725 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4726 ber_skip_data( ber, len );
4727 tag = ber_skip_tag( ber, &len ); /* serial number */
4728 if ( tag != LBER_INTEGER ) {
4729 rc = LDAP_INVALID_SYNTAX;
4732 i_sn.bv_val = (char *)ber->ber_ptr;
4734 i_sn2.bv_val = issuer_serialbuf;
4735 i_sn2.bv_len = sizeof(issuer_serialbuf);
4736 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4737 rc = LDAP_INVALID_SYNTAX;
4740 ber_skip_data( ber, len );
4742 /* issuerUID (bitstring; optional)? */
4743 /* objectDigestInfo (sequence; optional)? */
4745 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4746 ber_skip_data( ber, len );
4747 tag = ber_skip_tag( ber, &len ); /* serial number */
4748 if ( tag != LBER_INTEGER ) {
4749 rc = LDAP_INVALID_SYNTAX;
4752 sn.bv_val = (char *)ber->ber_ptr;
4754 sn2.bv_val = serialbuf;
4755 sn2.bv_len = sizeof(serialbuf);
4756 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4757 rc = LDAP_INVALID_SYNTAX;
4760 ber_skip_data( ber, len );
4762 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4763 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4764 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4766 p = normalized->bv_val;
4768 p = lutil_strcopy( p, "{ serialNumber " );
4769 p = lutil_strbvcopy( p, &sn2 );
4770 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4771 p = lutil_strbvcopy( p, &issuer_dn );
4772 p = lutil_strcopy( p, "\" }, serial " );
4773 p = lutil_strbvcopy( p, &i_sn2 );
4774 p = lutil_strcopy( p, " } } }" );
4776 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4777 normalized->bv_val, NULL, NULL );
4782 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4783 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4784 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4797 assert( in != NULL );
4798 assert( !BER_BVISNULL( in ) );
4800 for ( i = 0; i < in->bv_len; i++ ) {
4801 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4802 return LDAP_INVALID_SYNTAX;
4806 return LDAP_SUCCESS;
4809 /* Normalize a SID as used inside a CSN:
4810 * three-digit numeric string */
4817 struct berval *normalized,
4822 assert( val != NULL );
4823 assert( normalized != NULL );
4825 ber_dupbv_x( normalized, val, ctx );
4827 for ( i = 0; i < normalized->bv_len; i++ ) {
4828 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4829 ber_memfree_x( normalized->bv_val, ctx );
4830 BER_BVZERO( normalized );
4831 return LDAP_INVALID_SYNTAX;
4834 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4837 return LDAP_SUCCESS;
4845 assert( in != NULL );
4846 assert( !BER_BVISNULL( in ) );
4848 if ( in->bv_len != 3 ) {
4849 return LDAP_INVALID_SYNTAX;
4852 return hexValidate( NULL, in );
4855 /* Normalize a SID as used inside a CSN:
4856 * three-digit numeric string */
4863 struct berval *normalized,
4866 if ( val->bv_len != 3 ) {
4867 return LDAP_INVALID_SYNTAX;
4870 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4880 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4883 /* Normalize a SID as used inside a CSN, either as-is
4884 * (assertion value) or extracted from the CSN
4885 * (attribute value) */
4892 struct berval *normalized,
4900 if ( BER_BVISEMPTY( val ) ) {
4901 return LDAP_INVALID_SYNTAX;
4904 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4905 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4908 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4910 ptr = ber_bvchr( val, '#' );
4911 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4912 return LDAP_INVALID_SYNTAX;
4915 bv.bv_val = ptr + 1;
4916 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4918 ptr = ber_bvchr( &bv, '#' );
4919 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4920 return LDAP_INVALID_SYNTAX;
4923 bv.bv_val = ptr + 1;
4924 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4926 ptr = ber_bvchr( &bv, '#' );
4927 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4928 return LDAP_INVALID_SYNTAX;
4931 bv.bv_len = ptr - bv.bv_val;
4933 if ( bv.bv_len == 2 ) {
4934 /* OpenLDAP 2.3 SID */
4936 buf[ 1 ] = bv.bv_val[ 0 ];
4937 buf[ 2 ] = bv.bv_val[ 1 ];
4944 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4956 assert( in != NULL );
4957 assert( !BER_BVISNULL( in ) );
4959 if ( BER_BVISEMPTY( in ) ) {
4960 return LDAP_INVALID_SYNTAX;
4965 ptr = ber_bvchr( &bv, '#' );
4966 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4967 return LDAP_INVALID_SYNTAX;
4970 bv.bv_len = ptr - bv.bv_val;
4971 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4972 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4974 return LDAP_INVALID_SYNTAX;
4977 rc = generalizedTimeValidate( NULL, &bv );
4978 if ( rc != LDAP_SUCCESS ) {
4982 bv.bv_val = ptr + 1;
4983 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4985 ptr = ber_bvchr( &bv, '#' );
4986 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4987 return LDAP_INVALID_SYNTAX;
4990 bv.bv_len = ptr - bv.bv_val;
4991 if ( bv.bv_len != 6 ) {
4992 return LDAP_INVALID_SYNTAX;
4995 rc = hexValidate( NULL, &bv );
4996 if ( rc != LDAP_SUCCESS ) {
5000 bv.bv_val = ptr + 1;
5001 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5003 ptr = ber_bvchr( &bv, '#' );
5004 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5005 return LDAP_INVALID_SYNTAX;
5008 bv.bv_len = ptr - bv.bv_val;
5009 if ( bv.bv_len == 2 ) {
5010 /* tolerate old 2-digit replica-id */
5011 rc = hexValidate( NULL, &bv );
5014 rc = sidValidate( NULL, &bv );
5016 if ( rc != LDAP_SUCCESS ) {
5020 bv.bv_val = ptr + 1;
5021 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5023 if ( bv.bv_len != 6 ) {
5024 return LDAP_INVALID_SYNTAX;
5027 return hexValidate( NULL, &bv );
5030 /* Normalize a CSN in OpenLDAP 2.1 format */
5037 struct berval *normalized,
5040 struct berval gt, cnt, sid, mod;
5042 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5046 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5047 assert( !BER_BVISEMPTY( val ) );
5051 ptr = ber_bvchr( >, '#' );
5052 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5053 return LDAP_INVALID_SYNTAX;
5056 gt.bv_len = ptr - gt.bv_val;
5057 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5058 return LDAP_INVALID_SYNTAX;
5061 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5062 return LDAP_INVALID_SYNTAX;
5065 cnt.bv_val = ptr + 1;
5066 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5068 ptr = ber_bvchr( &cnt, '#' );
5069 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5070 return LDAP_INVALID_SYNTAX;
5073 cnt.bv_len = ptr - cnt.bv_val;
5074 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5075 return LDAP_INVALID_SYNTAX;
5078 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5079 return LDAP_INVALID_SYNTAX;
5082 cnt.bv_val += STRLENOF( "0x" );
5083 cnt.bv_len -= STRLENOF( "0x" );
5085 sid.bv_val = ptr + 1;
5086 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5088 ptr = ber_bvchr( &sid, '#' );
5089 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5090 return LDAP_INVALID_SYNTAX;
5093 sid.bv_len = ptr - sid.bv_val;
5094 if ( sid.bv_len != STRLENOF( "0" ) ) {
5095 return LDAP_INVALID_SYNTAX;
5098 mod.bv_val = ptr + 1;
5099 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5100 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5101 return LDAP_INVALID_SYNTAX;
5104 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5108 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5109 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5111 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5113 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5114 ptr = lutil_strbvcopy( ptr, &cnt );
5118 *ptr++ = sid.bv_val[ 0 ];
5122 for ( i = 0; i < mod.bv_len; i++ ) {
5123 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5127 assert( ptr == &bv.bv_val[bv.bv_len] );
5129 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5130 return LDAP_INVALID_SYNTAX;
5133 ber_dupbv_x( normalized, &bv, ctx );
5135 return LDAP_SUCCESS;
5138 /* Normalize a CSN in OpenLDAP 2.3 format */
5145 struct berval *normalized,
5148 struct berval gt, cnt, sid, mod;
5150 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5154 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5155 assert( !BER_BVISEMPTY( val ) );
5159 ptr = ber_bvchr( >, '#' );
5160 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5161 return LDAP_INVALID_SYNTAX;
5164 gt.bv_len = ptr - gt.bv_val;
5165 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5166 return LDAP_INVALID_SYNTAX;
5169 cnt.bv_val = ptr + 1;
5170 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5172 ptr = ber_bvchr( &cnt, '#' );
5173 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5174 return LDAP_INVALID_SYNTAX;
5177 cnt.bv_len = ptr - cnt.bv_val;
5178 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5179 return LDAP_INVALID_SYNTAX;
5182 sid.bv_val = ptr + 1;
5183 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5185 ptr = ber_bvchr( &sid, '#' );
5186 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5187 return LDAP_INVALID_SYNTAX;
5190 sid.bv_len = ptr - sid.bv_val;
5191 if ( sid.bv_len != STRLENOF( "00" ) ) {
5192 return LDAP_INVALID_SYNTAX;
5195 mod.bv_val = ptr + 1;
5196 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5197 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5198 return LDAP_INVALID_SYNTAX;
5201 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5205 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5206 ptr = lutil_strcopy( ptr, ".000000Z#" );
5207 ptr = lutil_strbvcopy( ptr, &cnt );
5210 for ( i = 0; i < sid.bv_len; i++ ) {
5211 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5214 for ( i = 0; i < mod.bv_len; i++ ) {
5215 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5219 assert( ptr == &bv.bv_val[bv.bv_len] );
5220 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5221 return LDAP_INVALID_SYNTAX;
5224 ber_dupbv_x( normalized, &bv, ctx );
5226 return LDAP_SUCCESS;
5229 /* Normalize a CSN */
5236 struct berval *normalized,
5239 struct berval cnt, sid, mod;
5243 assert( val != NULL );
5244 assert( normalized != NULL );
5246 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5248 if ( BER_BVISEMPTY( val ) ) {
5249 return LDAP_INVALID_SYNTAX;
5252 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5253 /* Openldap <= 2.3 */
5255 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5258 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5261 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5264 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5265 return LDAP_INVALID_SYNTAX;
5268 ptr = ber_bvchr( val, '#' );
5269 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5270 return LDAP_INVALID_SYNTAX;
5273 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5274 return LDAP_INVALID_SYNTAX;
5277 cnt.bv_val = ptr + 1;
5278 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5280 ptr = ber_bvchr( &cnt, '#' );
5281 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5282 return LDAP_INVALID_SYNTAX;
5285 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5286 return LDAP_INVALID_SYNTAX;
5289 sid.bv_val = ptr + 1;
5290 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5292 ptr = ber_bvchr( &sid, '#' );
5293 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5294 return LDAP_INVALID_SYNTAX;
5297 sid.bv_len = ptr - sid.bv_val;
5298 if ( sid.bv_len != STRLENOF( "000" ) ) {
5299 return LDAP_INVALID_SYNTAX;
5302 mod.bv_val = ptr + 1;
5303 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5305 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5306 return LDAP_INVALID_SYNTAX;
5309 ber_dupbv_x( normalized, val, ctx );
5311 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5312 i < normalized->bv_len; i++ )
5314 /* assume it's already validated that's all hex digits */
5315 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5318 return LDAP_SUCCESS;
5328 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5331 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5332 /* slight optimization - does not need the start parameter */
5333 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5338 check_time_syntax (struct berval *val,
5341 struct berval *fraction)
5344 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5345 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5346 * GeneralizedTime supports leap seconds, UTCTime does not.
5348 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5349 static const int mdays[2][12] = {
5350 /* non-leap years */
5351 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5353 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5356 int part, c, c1, c2, tzoffset, leapyear = 0;
5359 e = p + val->bv_len;
5361 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5362 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5364 for (part = start; part < 7 && p < e; part++) {
5366 if (!ASCII_DIGIT(c1)) {
5371 return LDAP_INVALID_SYNTAX;
5374 if (!ASCII_DIGIT(c)) {
5375 return LDAP_INVALID_SYNTAX;
5377 c += c1 * 10 - '0' * 11;
5378 if ((part | 1) == 3) {
5381 return LDAP_INVALID_SYNTAX;
5384 if (c >= ceiling[part]) {
5385 if (! (c == 60 && part == 6 && start == 0))
5386 return LDAP_INVALID_SYNTAX;
5390 if (part < 5 + start) {
5391 return LDAP_INVALID_SYNTAX;
5393 for (; part < 9; part++) {
5397 /* leapyear check for the Gregorian calendar (year>1581) */
5398 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5402 if (parts[3] >= mdays[leapyear][parts[2]]) {
5403 return LDAP_INVALID_SYNTAX;
5407 fraction->bv_val = p;
5408 fraction->bv_len = 0;
5409 if (p < e && (*p == '.' || *p == ',')) {
5411 while (++p < e && ASCII_DIGIT(*p)) {
5414 if (p - fraction->bv_val == 1) {
5415 return LDAP_INVALID_SYNTAX;
5417 for (end_num = p; end_num[-1] == '0'; --end_num) {
5420 c = end_num - fraction->bv_val;
5421 if (c != 1) fraction->bv_len = c;
5427 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5433 return LDAP_INVALID_SYNTAX;
5439 for (part = 7; part < 9 && p < e; part++) {
5441 if (!ASCII_DIGIT(c1)) {
5446 return LDAP_INVALID_SYNTAX;
5449 if (!ASCII_DIGIT(c2)) {
5450 return LDAP_INVALID_SYNTAX;
5452 parts[part] = c1 * 10 + c2 - '0' * 11;
5453 if (parts[part] >= ceiling[part]) {
5454 return LDAP_INVALID_SYNTAX;
5457 if (part < 8 + start) {
5458 return LDAP_INVALID_SYNTAX;
5461 if (tzoffset == '-') {
5462 /* negative offset to UTC, ie west of Greenwich */
5463 parts[4] += parts[7];
5464 parts[5] += parts[8];
5465 /* offset is just hhmm, no seconds */
5466 for (part = 6; --part >= 0; ) {
5470 c = mdays[leapyear][parts[2]];
5472 if (parts[part] >= c) {
5474 return LDAP_INVALID_SYNTAX;
5479 } else if (part != 5) {
5484 /* positive offset to UTC, ie east of Greenwich */
5485 parts[4] -= parts[7];
5486 parts[5] -= parts[8];
5487 for (part = 6; --part >= 0; ) {
5488 if (parts[part] < 0) {
5490 return LDAP_INVALID_SYNTAX;
5495 /* make first arg to % non-negative */
5496 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5501 } else if (part != 5) {
5508 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5511 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5518 struct berval *normalized )
5522 rc = check_time_syntax(val, 1, parts, NULL);
5523 if (rc != LDAP_SUCCESS) {
5527 normalized->bv_val = ch_malloc( 14 );
5528 if ( normalized->bv_val == NULL ) {
5529 return LBER_ERROR_MEMORY;
5532 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5533 parts[1], parts[2] + 1, parts[3] + 1,
5534 parts[4], parts[5], parts[6] );
5535 normalized->bv_len = 13;
5537 return LDAP_SUCCESS;
5547 return check_time_syntax(in, 1, parts, NULL);
5550 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5553 generalizedTimeValidate(
5558 struct berval fraction;
5559 return check_time_syntax(in, 0, parts, &fraction);
5563 generalizedTimeNormalize(
5568 struct berval *normalized,
5573 struct berval fraction;
5575 rc = check_time_syntax(val, 0, parts, &fraction);
5576 if (rc != LDAP_SUCCESS) {
5580 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5581 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5582 if ( BER_BVISNULL( normalized ) ) {
5583 return LBER_ERROR_MEMORY;
5586 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5587 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5588 parts[4], parts[5], parts[6] );
5589 if ( !BER_BVISEMPTY( &fraction ) ) {
5590 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5591 fraction.bv_val, fraction.bv_len );
5592 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5594 strcpy( normalized->bv_val + len-1, "Z" );
5595 normalized->bv_len = len;
5597 return LDAP_SUCCESS;
5601 generalizedTimeOrderingMatch(
5606 struct berval *value,
5607 void *assertedValue )
5609 struct berval *asserted = (struct berval *) assertedValue;
5610 ber_len_t v_len = value->bv_len;
5611 ber_len_t av_len = asserted->bv_len;
5613 /* ignore trailing 'Z' when comparing */
5614 int match = memcmp( value->bv_val, asserted->bv_val,
5615 (v_len < av_len ? v_len : av_len) - 1 );
5616 if ( match == 0 ) match = v_len - av_len;
5619 return LDAP_SUCCESS;
5622 /* Index generation function */
5623 int generalizedTimeIndexer(
5628 struct berval *prefix,
5636 BerValue bvtmp; /* 40 bit index */
5638 struct lutil_timet tt;
5640 bvtmp.bv_len = sizeof(tmp);
5642 for( i=0; values[i].bv_val != NULL; i++ ) {
5643 /* just count them */
5646 /* we should have at least one value at this point */
5649 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5651 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5652 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5653 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5654 /* Use 40 bits of time for key */
5655 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5656 lutil_tm2time( &tm, &tt );
5657 tmp[0] = tt.tt_gsec & 0xff;
5658 tmp[4] = tt.tt_sec & 0xff;
5660 tmp[3] = tt.tt_sec & 0xff;
5662 tmp[2] = tt.tt_sec & 0xff;
5664 tmp[1] = tt.tt_sec & 0xff;
5666 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5670 keys[j].bv_val = NULL;
5675 return LDAP_SUCCESS;
5678 /* Index generation function */
5679 int generalizedTimeFilter(
5684 struct berval *prefix,
5685 void * assertedValue,
5691 BerValue bvtmp; /* 40 bit index */
5692 BerValue *value = (BerValue *) assertedValue;
5694 struct lutil_timet tt;
5696 bvtmp.bv_len = sizeof(tmp);
5698 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5699 /* Use 40 bits of time for key */
5700 if ( value->bv_val && value->bv_len >= 10 &&
5701 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5703 lutil_tm2time( &tm, &tt );
5704 tmp[0] = tt.tt_gsec & 0xff;
5705 tmp[4] = tt.tt_sec & 0xff;
5707 tmp[3] = tt.tt_sec & 0xff;
5709 tmp[2] = tt.tt_sec & 0xff;
5711 tmp[1] = tt.tt_sec & 0xff;
5713 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5714 ber_dupbv_x(keys, &bvtmp, ctx );
5715 keys[1].bv_val = NULL;
5723 return LDAP_SUCCESS;
5727 deliveryMethodValidate(
5729 struct berval *val )
5732 #define LENOF(s) (sizeof(s)-1)
5733 struct berval tmp = *val;
5735 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5736 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5737 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5740 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5742 switch( tmp.bv_val[0] ) {
5745 if(( tmp.bv_len >= LENOF("any") ) &&
5746 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5748 tmp.bv_len -= LENOF("any");
5749 tmp.bv_val += LENOF("any");
5752 return LDAP_INVALID_SYNTAX;
5756 if(( tmp.bv_len >= LENOF("mhs") ) &&
5757 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5759 tmp.bv_len -= LENOF("mhs");
5760 tmp.bv_val += LENOF("mhs");
5763 return LDAP_INVALID_SYNTAX;
5767 if(( tmp.bv_len >= LENOF("physical") ) &&
5768 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5770 tmp.bv_len -= LENOF("physical");
5771 tmp.bv_val += LENOF("physical");
5774 return LDAP_INVALID_SYNTAX;
5777 case 'T': /* telex or teletex or telephone */
5778 if(( tmp.bv_len >= LENOF("telex") ) &&
5779 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5781 tmp.bv_len -= LENOF("telex");
5782 tmp.bv_val += LENOF("telex");
5785 if(( tmp.bv_len >= LENOF("teletex") ) &&
5786 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5788 tmp.bv_len -= LENOF("teletex");
5789 tmp.bv_val += LENOF("teletex");
5792 if(( tmp.bv_len >= LENOF("telephone") ) &&
5793 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5795 tmp.bv_len -= LENOF("telephone");
5796 tmp.bv_val += LENOF("telephone");
5799 return LDAP_INVALID_SYNTAX;
5802 case 'G': /* g3fax or g4fax */
5803 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5804 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5805 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5807 tmp.bv_len -= LENOF("g3fax");
5808 tmp.bv_val += LENOF("g3fax");
5811 return LDAP_INVALID_SYNTAX;
5815 if(( tmp.bv_len >= LENOF("ia5") ) &&
5816 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5818 tmp.bv_len -= LENOF("ia5");
5819 tmp.bv_val += LENOF("ia5");
5822 return LDAP_INVALID_SYNTAX;
5826 if(( tmp.bv_len >= LENOF("videotex") ) &&
5827 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5829 tmp.bv_len -= LENOF("videotex");
5830 tmp.bv_val += LENOF("videotex");
5833 return LDAP_INVALID_SYNTAX;
5836 return LDAP_INVALID_SYNTAX;
5839 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5841 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5845 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5849 return LDAP_INVALID_SYNTAX;
5851 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5860 nisNetgroupTripleValidate(
5862 struct berval *val )
5867 if ( BER_BVISEMPTY( val ) ) {
5868 return LDAP_INVALID_SYNTAX;
5871 p = (char *)val->bv_val;
5872 e = p + val->bv_len;
5874 if ( *p != '(' /*')'*/ ) {
5875 return LDAP_INVALID_SYNTAX;
5878 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5882 return LDAP_INVALID_SYNTAX;
5885 } else if ( !AD_CHAR( *p ) ) {
5886 return LDAP_INVALID_SYNTAX;
5890 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5891 return LDAP_INVALID_SYNTAX;
5897 return LDAP_INVALID_SYNTAX;
5900 return LDAP_SUCCESS;
5904 bootParameterValidate(
5906 struct berval *val )
5910 if ( BER_BVISEMPTY( val ) ) {
5911 return LDAP_INVALID_SYNTAX;
5914 p = (char *)val->bv_val;
5915 e = p + val->bv_len;
5918 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5919 if ( !AD_CHAR( *p ) ) {
5920 return LDAP_INVALID_SYNTAX;
5925 return LDAP_INVALID_SYNTAX;
5929 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5930 if ( !AD_CHAR( *p ) ) {
5931 return LDAP_INVALID_SYNTAX;
5936 return LDAP_INVALID_SYNTAX;
5940 for ( p++; p < e; p++ ) {
5941 if ( !SLAP_PRINTABLE( *p ) ) {
5942 return LDAP_INVALID_SYNTAX;
5946 return LDAP_SUCCESS;
5950 firstComponentNormalize(
5955 struct berval *normalized,
5962 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5963 ber_dupbv_x( normalized, val, ctx );
5964 return LDAP_SUCCESS;
5967 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5969 if( ! ( val->bv_val[0] == '(' /*')'*/
5970 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5971 && ! ( val->bv_val[0] == '{' /*'}'*/
5972 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5974 return LDAP_INVALID_SYNTAX;
5977 /* trim leading white space */
5979 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5985 /* grab next word */
5986 comp.bv_val = &val->bv_val[len];
5987 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5988 for( comp.bv_len = 0;
5989 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5995 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5996 rc = numericoidValidate( NULL, &comp );
5997 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5998 rc = integerValidate( NULL, &comp );
6000 rc = LDAP_INVALID_SYNTAX;
6004 if( rc == LDAP_SUCCESS ) {
6005 ber_dupbv_x( normalized, &comp, ctx );
6011 static char *country_gen_syn[] = {
6012 "1.3.6.1.4.1.1466.115.121.1.15",
6013 "1.3.6.1.4.1.1466.115.121.1.26",
6014 "1.3.6.1.4.1.1466.115.121.1.44",
6018 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6019 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6021 static slap_syntax_defs_rec syntax_defs[] = {
6022 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6023 X_BINARY X_NOT_H_R ")",
6024 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6025 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6026 0, NULL, NULL, NULL},
6027 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6028 0, NULL, NULL, NULL},
6029 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6031 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6032 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6034 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6035 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6036 0, NULL, bitStringValidate, NULL },
6037 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6038 0, NULL, booleanValidate, NULL},
6039 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6040 X_BINARY X_NOT_H_R ")",
6041 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6042 NULL, certificateValidate, NULL},
6043 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6044 X_BINARY X_NOT_H_R ")",
6045 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6046 NULL, certificateListValidate, NULL},
6047 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6048 X_BINARY X_NOT_H_R ")",
6049 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6050 NULL, sequenceValidate, NULL},
6051 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6052 X_BINARY X_NOT_H_R ")",
6053 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6054 NULL, attributeCertificateValidate, NULL},
6055 #if 0 /* need to go __after__ printableString */
6056 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6057 0, "1.3.6.1.4.1.1466.115.121.1.44",
6058 countryStringValidate, NULL},
6060 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6061 SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
6062 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6063 0, NULL, rdnValidate, rdnPretty},
6064 #ifdef LDAP_COMP_MATCH
6065 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6066 0, NULL, allComponentsValidate, NULL},
6067 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6068 0, NULL, componentFilterValidate, NULL},
6070 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6071 0, NULL, NULL, NULL},
6072 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6073 0, NULL, deliveryMethodValidate, NULL},
6074 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6075 0, NULL, UTF8StringValidate, NULL},
6076 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6077 0, NULL, NULL, NULL},
6078 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6079 0, NULL, NULL, NULL},
6080 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6081 0, NULL, NULL, NULL},
6082 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6083 0, NULL, NULL, NULL},
6084 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6085 0, NULL, NULL, NULL},
6086 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6087 0, NULL, printablesStringValidate, NULL},
6088 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6089 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6090 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6091 0, NULL, generalizedTimeValidate, NULL},
6092 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6093 0, NULL, NULL, NULL},
6094 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6095 0, NULL, IA5StringValidate, NULL},
6096 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6097 0, NULL, integerValidate, NULL},
6098 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6099 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6100 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6101 0, NULL, NULL, NULL},
6102 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6103 0, NULL, NULL, NULL},
6104 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6105 0, NULL, NULL, NULL},
6106 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6107 0, NULL, NULL, NULL},
6108 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6109 0, NULL, NULL, NULL},
6110 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6111 SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
6112 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6113 0, NULL, NULL, NULL},
6114 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6115 0, NULL, numericStringValidate, NULL},
6116 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6117 0, NULL, NULL, NULL},
6118 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6119 0, NULL, numericoidValidate, NULL},
6120 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6121 0, NULL, IA5StringValidate, NULL},
6122 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6123 0, NULL, blobValidate, NULL},
6124 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6125 0, NULL, postalAddressValidate, NULL},
6126 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6127 0, NULL, NULL, NULL},
6128 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6129 0, NULL, NULL, NULL},
6130 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6131 0, NULL, printableStringValidate, NULL},
6132 /* moved here because now depends on Directory String, IA5 String
6133 * and Printable String */
6134 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6135 0, country_gen_syn, countryStringValidate, NULL},
6136 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6137 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6138 0, NULL, subtreeSpecificationValidate, NULL},
6139 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6140 X_BINARY X_NOT_H_R ")",
6141 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6142 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6143 0, NULL, printableStringValidate, NULL},
6144 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6145 0, NULL, NULL, NULL},
6146 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6147 0, NULL, printablesStringValidate, NULL},
6148 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6149 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6150 0, NULL, utcTimeValidate, NULL},
6152 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6153 0, NULL, NULL, NULL},
6154 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6155 0, NULL, NULL, NULL},
6156 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6157 0, NULL, NULL, NULL},
6158 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6159 0, NULL, NULL, NULL},
6160 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6161 0, NULL, NULL, NULL},
6163 /* RFC 2307 NIS Syntaxes */
6164 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6165 0, NULL, nisNetgroupTripleValidate, NULL},
6166 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6167 0, NULL, bootParameterValidate, NULL},
6169 /* draft-zeilenga-ldap-x509 */
6170 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6171 SLAP_SYNTAX_HIDE, NULL,
6172 serialNumberAndIssuerValidate,
6173 serialNumberAndIssuerPretty},
6174 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6175 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6176 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6177 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6178 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6179 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6180 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6181 SLAP_SYNTAX_HIDE, NULL,
6182 issuerAndThisUpdateValidate,
6183 issuerAndThisUpdatePretty},
6184 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6185 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6186 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6187 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6188 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6189 SLAP_SYNTAX_HIDE, NULL,
6190 serialNumberAndIssuerSerialValidate,
6191 serialNumberAndIssuerSerialPretty},
6192 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6193 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6195 #ifdef SLAPD_AUTHPASSWD
6196 /* needs updating */
6197 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6198 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6201 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6202 0, NULL, UUIDValidate, UUIDPretty},
6204 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6205 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6207 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6208 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6210 /* OpenLDAP Void Syntax */
6211 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6212 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6214 /* FIXME: OID is unused, but not registered yet */
6215 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6216 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6218 {NULL, 0, NULL, NULL, NULL}
6221 char *csnSIDMatchSyntaxes[] = {
6222 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6225 char *certificateExactMatchSyntaxes[] = {
6226 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6229 char *certificateListExactMatchSyntaxes[] = {
6230 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6233 char *attributeCertificateExactMatchSyntaxes[] = {
6234 attributeCertificateSyntaxOID /* attributeCertificate */,
6238 #ifdef LDAP_COMP_MATCH
6239 char *componentFilterMatchSyntaxes[] = {
6240 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6241 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6242 attributeCertificateSyntaxOID /* attributeCertificate */,
6247 char *directoryStringSyntaxes[] = {
6248 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6251 char *integerFirstComponentMatchSyntaxes[] = {
6252 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6253 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6256 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6257 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6258 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6259 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6260 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6261 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6262 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6263 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6264 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6269 * Other matching rules in X.520 that we do not use (yet):
6271 * 2.5.13.25 uTCTimeMatch
6272 * 2.5.13.26 uTCTimeOrderingMatch
6273 * 2.5.13.31* directoryStringFirstComponentMatch
6274 * 2.5.13.32* wordMatch
6275 * 2.5.13.33* keywordMatch
6276 * 2.5.13.36+ certificatePairExactMatch
6277 * 2.5.13.37+ certificatePairMatch
6278 * 2.5.13.40+ algorithmIdentifierMatch
6279 * 2.5.13.41* storedPrefixMatch
6280 * 2.5.13.42 attributeCertificateMatch
6281 * 2.5.13.43 readerAndKeyIDMatch
6282 * 2.5.13.44 attributeIntegrityMatch
6284 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6285 * (+) described in draft-zeilenga-ldap-x509
6287 static slap_mrule_defs_rec mrule_defs[] = {
6289 * EQUALITY matching rules must be listed after associated APPROX
6290 * matching rules. So, we list all APPROX matching rules first.
6292 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6294 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6295 NULL, NULL, directoryStringApproxMatch,
6296 directoryStringApproxIndexer, directoryStringApproxFilter,
6299 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6300 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6301 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6302 NULL, NULL, IA5StringApproxMatch,
6303 IA5StringApproxIndexer, IA5StringApproxFilter,
6307 * Other matching rules
6310 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6311 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6312 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6313 NULL, NULL, octetStringMatch,
6314 octetStringIndexer, octetStringFilter,
6317 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6318 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6319 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6320 NULL, dnNormalize, dnMatch,
6321 octetStringIndexer, octetStringFilter,
6324 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6325 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6326 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6327 NULL, dnNormalize, dnRelativeMatch,
6331 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6332 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6333 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6334 NULL, dnNormalize, dnRelativeMatch,
6338 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6339 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6340 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6341 NULL, dnNormalize, dnRelativeMatch,
6345 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6346 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6347 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6348 NULL, dnNormalize, dnRelativeMatch,
6352 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6353 "SYNTAX 1.2.36.79672281.1.5.0 )",
6354 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6355 NULL, rdnNormalize, rdnMatch,
6356 octetStringIndexer, octetStringFilter,
6359 #ifdef LDAP_COMP_MATCH
6360 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6361 "SYNTAX 1.2.36.79672281.1.5.2 )",
6362 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6363 NULL, NULL , componentFilterMatch,
6364 octetStringIndexer, octetStringFilter,
6367 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6368 "SYNTAX 1.2.36.79672281.1.5.3 )",
6369 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6370 NULL, NULL , allComponentsMatch,
6371 octetStringIndexer, octetStringFilter,
6374 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6375 "SYNTAX 1.2.36.79672281.1.5.3 )",
6376 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6377 NULL, NULL , directoryComponentsMatch,
6378 octetStringIndexer, octetStringFilter,
6382 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6383 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6384 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6385 NULL, UTF8StringNormalize, octetStringMatch,
6386 octetStringIndexer, octetStringFilter,
6387 directoryStringApproxMatchOID },
6389 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6390 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6391 SLAP_MR_ORDERING, directoryStringSyntaxes,
6392 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6394 "caseIgnoreMatch" },
6396 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6397 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6398 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6399 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6400 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6401 "caseIgnoreMatch" },
6403 {"( 2.5.13.5 NAME 'caseExactMatch' "
6404 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6405 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6406 NULL, UTF8StringNormalize, octetStringMatch,
6407 octetStringIndexer, octetStringFilter,
6408 directoryStringApproxMatchOID },
6410 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6411 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6412 SLAP_MR_ORDERING, directoryStringSyntaxes,
6413 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6417 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6418 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6419 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6420 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6421 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6424 {"( 2.5.13.8 NAME 'numericStringMatch' "
6425 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6426 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6427 NULL, numericStringNormalize, octetStringMatch,
6428 octetStringIndexer, octetStringFilter,
6431 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6432 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6433 SLAP_MR_ORDERING, NULL,
6434 NULL, numericStringNormalize, octetStringOrderingMatch,
6436 "numericStringMatch" },
6438 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6439 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6440 SLAP_MR_SUBSTR, NULL,
6441 NULL, numericStringNormalize, octetStringSubstringsMatch,
6442 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6443 "numericStringMatch" },
6445 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6446 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6447 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6448 NULL, postalAddressNormalize, octetStringMatch,
6449 octetStringIndexer, octetStringFilter,
6452 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6453 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6454 SLAP_MR_SUBSTR, NULL,
6455 NULL, NULL, NULL, NULL, NULL,
6456 "caseIgnoreListMatch" },
6458 {"( 2.5.13.13 NAME 'booleanMatch' "
6459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6460 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6461 NULL, NULL, booleanMatch,
6462 octetStringIndexer, octetStringFilter,
6465 {"( 2.5.13.14 NAME 'integerMatch' "
6466 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6467 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6468 NULL, NULL, integerMatch,
6469 integerIndexer, integerFilter,
6472 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6473 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6474 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6475 NULL, NULL, integerMatch,
6479 {"( 2.5.13.16 NAME 'bitStringMatch' "
6480 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6481 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6482 NULL, NULL, octetStringMatch,
6483 octetStringIndexer, octetStringFilter,
6486 {"( 2.5.13.17 NAME 'octetStringMatch' "
6487 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6488 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6489 NULL, NULL, octetStringMatch,
6490 octetStringIndexer, octetStringFilter,
6493 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6495 SLAP_MR_ORDERING, NULL,
6496 NULL, NULL, octetStringOrderingMatch,
6498 "octetStringMatch" },
6500 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6501 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6502 SLAP_MR_SUBSTR, NULL,
6503 NULL, NULL, octetStringSubstringsMatch,
6504 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6505 "octetStringMatch" },
6507 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6508 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6509 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6511 telephoneNumberNormalize, octetStringMatch,
6512 octetStringIndexer, octetStringFilter,
6515 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6517 SLAP_MR_SUBSTR, NULL,
6518 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6519 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6520 "telephoneNumberMatch" },
6522 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6524 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6525 NULL, NULL, NULL, NULL, NULL, NULL },
6527 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6528 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6529 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6530 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6531 uniqueMemberIndexer, uniqueMemberFilter,
6534 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6535 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6536 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6537 NULL, NULL, NULL, NULL, NULL, NULL },
6539 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6540 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6541 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6542 NULL, generalizedTimeNormalize, octetStringMatch,
6543 generalizedTimeIndexer, generalizedTimeFilter,
6546 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6547 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6548 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6549 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6551 "generalizedTimeMatch" },
6553 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6555 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6556 integerFirstComponentMatchSyntaxes,
6557 NULL, firstComponentNormalize, integerMatch,
6558 octetStringIndexer, octetStringFilter,
6561 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6562 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6563 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6564 objectIdentifierFirstComponentMatchSyntaxes,
6565 NULL, firstComponentNormalize, octetStringMatch,
6566 octetStringIndexer, octetStringFilter,
6569 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6570 "SYNTAX 1.3.6.1.1.15.1 )",
6571 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6572 NULL, certificateExactNormalize, octetStringMatch,
6573 octetStringIndexer, octetStringFilter,
6576 {"( 2.5.13.35 NAME 'certificateMatch' "
6577 "SYNTAX 1.3.6.1.1.15.2 )",
6578 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6579 NULL, NULL, NULL, NULL, NULL,
6582 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6583 "SYNTAX 1.3.6.1.1.15.5 )",
6584 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6585 NULL, certificateListExactNormalize, octetStringMatch,
6586 octetStringIndexer, octetStringFilter,
6589 {"( 2.5.13.39 NAME 'certificateListMatch' "
6590 "SYNTAX 1.3.6.1.1.15.6 )",
6591 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6592 NULL, NULL, NULL, NULL, NULL,
6595 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6596 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6597 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6598 NULL, attributeCertificateExactNormalize, octetStringMatch,
6599 octetStringIndexer, octetStringFilter,
6602 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6603 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6604 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6605 NULL, NULL, NULL, NULL, NULL,
6608 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6609 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6610 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6611 NULL, IA5StringNormalize, octetStringMatch,
6612 octetStringIndexer, octetStringFilter,
6613 IA5StringApproxMatchOID },
6615 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6616 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6617 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6618 NULL, IA5StringNormalize, octetStringMatch,
6619 octetStringIndexer, octetStringFilter,
6620 IA5StringApproxMatchOID },
6622 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6623 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6624 SLAP_MR_SUBSTR, NULL,
6625 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6626 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6627 "caseIgnoreIA5Match" },
6629 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6630 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6631 SLAP_MR_SUBSTR, NULL,
6632 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6633 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6634 "caseExactIA5Match" },
6636 #ifdef SLAPD_AUTHPASSWD
6637 /* needs updating */
6638 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6639 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6640 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6641 NULL, NULL, authPasswordMatch,
6646 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6647 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6649 NULL, NULL, integerBitAndMatch,
6653 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6654 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6656 NULL, NULL, integerBitOrMatch,
6660 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6661 "SYNTAX 1.3.6.1.1.16.1 )",
6662 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6663 NULL, UUIDNormalize, octetStringMatch,
6664 octetStringIndexer, octetStringFilter,
6667 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6668 "SYNTAX 1.3.6.1.1.16.1 )",
6669 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6670 NULL, UUIDNormalize, octetStringOrderingMatch,
6671 octetStringIndexer, octetStringFilter,
6674 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6675 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6676 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6677 NULL, csnNormalize, csnMatch,
6678 csnIndexer, csnFilter,
6681 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6682 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6683 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6684 NULL, csnNormalize, csnOrderingMatch,
6688 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6689 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6690 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6691 NULL, csnSidNormalize, octetStringMatch,
6692 octetStringIndexer, octetStringFilter,
6695 /* FIXME: OID is unused, but not registered yet */
6696 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6697 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6698 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6699 NULL, authzNormalize, authzMatch,
6703 {NULL, SLAP_MR_NONE, NULL,
6704 NULL, NULL, NULL, NULL, NULL,
6709 slap_schema_init( void )
6714 /* we should only be called once (from main) */
6715 assert( schema_init_done == 0 );
6717 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6718 res = register_syntax( &syntax_defs[i] );
6721 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6722 syntax_defs[i].sd_desc );
6727 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6728 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6729 mrule_defs[i].mrd_compat_syntaxes == NULL )
6732 "slap_schema_init: Ignoring unusable matching rule %s\n",
6733 mrule_defs[i].mrd_desc );
6737 res = register_matching_rule( &mrule_defs[i] );
6741 "slap_schema_init: Error registering matching rule %s\n",
6742 mrule_defs[i].mrd_desc );
6747 res = slap_schema_load();
6748 schema_init_done = 1;
6753 schema_destroy( void )
6762 if( schema_init_done ) {
6763 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6764 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );