1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2009 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 );
1742 /* collapse spaces (in place) */
1744 nvalue.bv_val = tmp.bv_val;
1746 /* trim leading spaces? */
1747 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1748 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1750 for( i = 0; i < tmp.bv_len; i++) {
1751 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1752 if( wasspace++ == 0 ) {
1753 /* trim repeated spaces */
1754 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1758 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1762 if( !BER_BVISEMPTY( &nvalue ) ) {
1763 /* trim trailing space? */
1765 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1766 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1770 nvalue.bv_val[nvalue.bv_len] = '\0';
1773 /* string of all spaces is treated as one space */
1774 nvalue.bv_val[0] = ' ';
1775 nvalue.bv_val[1] = '\0';
1779 *normalized = nvalue;
1780 return LDAP_SUCCESS;
1784 directoryStringSubstringsMatch(
1789 struct berval *value,
1790 void *assertedValue )
1793 SubstringsAssertion *sub = assertedValue;
1794 struct berval left = *value;
1798 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1799 if ( sub->sa_initial.bv_len > left.bv_len ) {
1800 /* not enough left */
1805 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1806 sub->sa_initial.bv_len );
1812 left.bv_val += sub->sa_initial.bv_len;
1813 left.bv_len -= sub->sa_initial.bv_len;
1815 priorspace = ASCII_SPACE(
1816 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1819 if ( sub->sa_any ) {
1820 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1824 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1825 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1827 /* allow next space to match */
1834 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1838 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1839 /* not enough left */
1844 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1851 idx = p - left.bv_val;
1853 if ( idx >= left.bv_len ) {
1854 /* this shouldn't happen */
1861 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1862 /* not enough left */
1867 match = memcmp( left.bv_val,
1868 sub->sa_any[i].bv_val,
1869 sub->sa_any[i].bv_len );
1877 left.bv_val += sub->sa_any[i].bv_len;
1878 left.bv_len -= sub->sa_any[i].bv_len;
1880 priorspace = ASCII_SPACE(
1881 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1885 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1886 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1887 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1889 /* allow next space to match */
1894 if ( sub->sa_final.bv_len > left.bv_len ) {
1895 /* not enough left */
1900 match = memcmp( sub->sa_final.bv_val,
1901 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1902 sub->sa_final.bv_len );
1911 return LDAP_SUCCESS;
1914 #if defined(SLAPD_APPROX_INITIALS)
1915 # define SLAPD_APPROX_DELIMITER "._ "
1916 # define SLAPD_APPROX_WORDLEN 2
1918 # define SLAPD_APPROX_DELIMITER " "
1919 # define SLAPD_APPROX_WORDLEN 1
1928 struct berval *value,
1929 void *assertedValue )
1931 struct berval *nval, *assertv;
1932 char *val, **values, **words, *c;
1933 int i, count, len, nextchunk=0, nextavail=0;
1935 /* Yes, this is necessary */
1936 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1937 if( nval == NULL ) {
1939 return LDAP_SUCCESS;
1942 /* Yes, this is necessary */
1943 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1944 NULL, LDAP_UTF8_APPROX, NULL );
1945 if( assertv == NULL ) {
1948 return LDAP_SUCCESS;
1951 /* Isolate how many words there are */
1952 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1953 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1954 if ( c == NULL ) break;
1959 /* Get a phonetic copy of each word */
1960 words = (char **)ch_malloc( count * sizeof(char *) );
1961 values = (char **)ch_malloc( count * sizeof(char *) );
1962 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1964 values[i] = phonetic(c);
1967 /* Work through the asserted value's words, to see if at least some
1968 * of the words are there, in the same order. */
1970 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1971 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1976 #if defined(SLAPD_APPROX_INITIALS)
1977 else if( len == 1 ) {
1978 /* Single letter words need to at least match one word's initial */
1979 for( i=nextavail; i<count; i++ )
1980 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1987 /* Isolate the next word in the asserted value and phonetic it */
1988 assertv->bv_val[nextchunk+len] = '\0';
1989 val = phonetic( assertv->bv_val + nextchunk );
1991 /* See if this phonetic chunk is in the remaining words of *value */
1992 for( i=nextavail; i<count; i++ ){
1993 if( !strcmp( val, values[i] ) ){
2001 /* This chunk in the asserted value was NOT within the *value. */
2007 /* Go on to the next word in the asserted value */
2011 /* If some of the words were seen, call it a match */
2012 if( nextavail > 0 ) {
2019 /* Cleanup allocs */
2020 ber_bvfree( assertv );
2021 for( i=0; i<count; i++ ) {
2022 ch_free( values[i] );
2028 return LDAP_SUCCESS;
2037 struct berval *prefix,
2043 int i,j, len, wordcount, keycount=0;
2044 struct berval *newkeys;
2045 BerVarray keys=NULL;
2047 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2048 struct berval val = BER_BVNULL;
2049 /* Yes, this is necessary */
2050 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2051 assert( !BER_BVISNULL( &val ) );
2053 /* Isolate how many words there are. There will be a key for each */
2054 for( wordcount = 0, c = val.bv_val; *c; c++) {
2055 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2056 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2058 if (*c == '\0') break;
2062 /* Allocate/increase storage to account for new keys */
2063 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2064 * sizeof(struct berval) );
2065 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2066 if( keys ) ch_free( keys );
2069 /* Get a phonetic copy of each word */
2070 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2072 if( len < SLAPD_APPROX_WORDLEN ) continue;
2073 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2078 ber_memfree( val.bv_val );
2080 BER_BVZERO( &keys[keycount] );
2083 return LDAP_SUCCESS;
2092 struct berval *prefix,
2093 void * assertedValue,
2102 /* Yes, this is necessary */
2103 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2104 NULL, LDAP_UTF8_APPROX, NULL );
2105 if( val == NULL || BER_BVISNULL( val ) ) {
2106 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2107 BER_BVZERO( &keys[0] );
2110 return LDAP_SUCCESS;
2113 /* Isolate how many words there are. There will be a key for each */
2114 for( count = 0,c = val->bv_val; *c; c++) {
2115 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2116 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2118 if (*c == '\0') break;
2122 /* Allocate storage for new keys */
2123 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2125 /* Get a phonetic copy of each word */
2126 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2128 if( len < SLAPD_APPROX_WORDLEN ) continue;
2129 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2135 BER_BVZERO( &keys[count] );
2138 return LDAP_SUCCESS;
2141 /* Remove all spaces and '-' characters */
2143 telephoneNumberNormalize(
2148 struct berval *normalized,
2153 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2155 /* validator should have refused an empty string */
2156 assert( !BER_BVISEMPTY( val ) );
2158 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2160 for( p = val->bv_val; *p; p++ ) {
2161 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2167 normalized->bv_len = q - normalized->bv_val;
2169 if( BER_BVISEMPTY( normalized ) ) {
2170 slap_sl_free( normalized->bv_val, ctx );
2171 BER_BVZERO( normalized );
2172 return LDAP_INVALID_SYNTAX;
2175 return LDAP_SUCCESS;
2179 postalAddressValidate(
2183 struct berval bv = *in;
2186 for ( c = 0; c < in->bv_len; c++ ) {
2187 if ( in->bv_val[c] == '\\' ) {
2189 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2190 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2192 return LDAP_INVALID_SYNTAX;
2197 if ( in->bv_val[c] == '$' ) {
2198 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2199 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2200 return LDAP_INVALID_SYNTAX;
2202 bv.bv_val = &in->bv_val[c] + 1;
2206 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2207 return UTF8StringValidate( NULL, &bv );
2211 postalAddressNormalize(
2216 struct berval *normalized,
2219 BerVarray lines = NULL, nlines = NULL;
2221 int rc = LDAP_SUCCESS;
2222 MatchingRule *xmr = NULL;
2225 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2226 xmr = slap_schema.si_mr_caseIgnoreMatch;
2229 xmr = slap_schema.si_mr_caseExactMatch;
2232 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2233 if ( val->bv_val[c] == '$' ) {
2238 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2239 nlines = &lines[l + 2];
2241 lines[0].bv_val = val->bv_val;
2242 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2243 if ( val->bv_val[c] == '$' ) {
2244 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2246 lines[l].bv_val = &val->bv_val[c + 1];
2249 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2251 normalized->bv_len = l;
2253 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2254 /* NOTE: we directly normalize each line,
2255 * without unescaping the values, since the special
2256 * values '\24' ('$') and '\5C' ('\') are not affected
2257 * by normalization */
2258 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2259 if ( rc != LDAP_SUCCESS ) {
2260 rc = LDAP_INVALID_SYNTAX;
2264 normalized->bv_len += nlines[l].bv_len;
2267 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2269 p = normalized->bv_val;
2270 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2271 p = lutil_strbvcopy( p, &nlines[l] );
2276 assert( p == &normalized->bv_val[normalized->bv_len] );
2279 if ( nlines != NULL ) {
2280 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2281 slap_sl_free( nlines[l].bv_val, ctx );
2284 slap_sl_free( lines, ctx );
2295 struct berval val = *in;
2297 if( BER_BVISEMPTY( &val ) ) {
2298 /* disallow empty strings */
2299 return LDAP_INVALID_SYNTAX;
2302 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2303 if ( val.bv_len == 1 ) {
2304 return LDAP_SUCCESS;
2307 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2314 while ( OID_LEADCHAR( val.bv_val[0] )) {
2318 if ( val.bv_len == 0 ) {
2319 return LDAP_SUCCESS;
2323 if( !OID_SEPARATOR( val.bv_val[0] )) {
2331 return LDAP_INVALID_SYNTAX;
2340 struct berval val = *in;
2342 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2344 if ( val.bv_val[0] == '-' ) {
2348 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2349 return LDAP_INVALID_SYNTAX;
2352 if( val.bv_val[0] == '0' ) { /* "-0" */
2353 return LDAP_INVALID_SYNTAX;
2356 } else if ( val.bv_val[0] == '0' ) {
2357 if( val.bv_len > 1 ) { /* "0<more>" */
2358 return LDAP_INVALID_SYNTAX;
2361 return LDAP_SUCCESS;
2364 for( i=0; i < val.bv_len; i++ ) {
2365 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2366 return LDAP_INVALID_SYNTAX;
2370 return LDAP_SUCCESS;
2379 struct berval *value,
2380 void *assertedValue )
2382 struct berval *asserted = (struct berval *) assertedValue;
2383 int vsign = 1, asign = 1; /* default sign = '+' */
2388 if( v.bv_val[0] == '-' ) {
2394 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2397 if( a.bv_val[0] == '-' ) {
2403 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2405 match = vsign - asign;
2407 match = ( v.bv_len != a.bv_len
2408 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2409 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2410 if( vsign < 0 ) match = -match;
2414 return LDAP_SUCCESS;
2417 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2418 #define INDEX_INTLEN_CHOP 7
2419 #define INDEX_INTLEN_CHOPBYTES 3
2429 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2430 * two's complement value (sign-extended or chopped as needed),
2431 * however the top <number of exponent-bytes + 1> bits of first byte
2432 * above is the inverse sign. The next bit is the sign as delimiter.
2434 ber_slen_t k = index_intlen_strlen;
2436 unsigned signmask = ~0x7fU;
2437 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2438 struct berval val = *in, itmp = *tmp;
2440 if ( val.bv_val[0] != '-' ) {
2445 /* Chop least significant digits, increase length instead */
2446 if ( val.bv_len > (ber_len_t) k ) {
2447 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2448 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2449 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2452 if ( lutil_str2bin( &val, &itmp, ctx )) {
2453 return LDAP_INVALID_SYNTAX;
2456 /* Omit leading sign byte */
2457 if ( itmp.bv_val[0] == neg ) {
2462 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2464 assert( chop == 0 );
2465 memset( key->bv_val, neg, k ); /* sign-extend */
2466 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2467 lenp = lenbuf + sizeof(lenbuf);
2468 chop = - (ber_len_t) k;
2470 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2472 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2473 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2474 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2475 k = (lenbuf + sizeof(lenbuf)) - lenp;
2476 if ( k > (ber_slen_t) index_intlen )
2478 memcpy( key->bv_val, lenp, k );
2479 itmp.bv_len = index_intlen - k;
2481 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2482 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2486 /* Index generation function */
2493 struct berval *prefix,
2503 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2505 /* count the values and find max needed length */
2507 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2508 if ( vlen < values[i].bv_len )
2509 vlen = values[i].bv_len;
2511 if ( vlen > maxstrlen )
2514 /* we should have at least one value at this point */
2517 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2518 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2519 keys[i].bv_len = index_intlen;
2520 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2523 keys[i].bv_val = NULL;
2525 if ( vlen > sizeof(ibuf) ) {
2526 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2530 itmp.bv_len = sizeof(ibuf);
2532 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2533 if ( itmp.bv_val != ibuf ) {
2534 itmp.bv_len = values[i].bv_len;
2535 if ( itmp.bv_len <= sizeof(ibuf) )
2536 itmp.bv_len = sizeof(ibuf);
2537 else if ( itmp.bv_len > maxstrlen )
2538 itmp.bv_len = maxstrlen;
2540 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2546 if ( itmp.bv_val != ibuf ) {
2547 slap_sl_free( itmp.bv_val, ctx );
2552 /* Index generation function */
2559 struct berval *prefix,
2560 void * assertedValue,
2567 struct berval *value;
2570 value = (struct berval *) assertedValue;
2572 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2574 keys[0].bv_len = index_intlen;
2575 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2577 keys[1].bv_val = NULL;
2579 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2580 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2581 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2582 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2585 iv.bv_len = sizeof(ibuf);
2588 rc = integerVal2Key( value, keys, &iv, ctx );
2592 if ( iv.bv_val != ibuf ) {
2593 slap_sl_free( iv.bv_val, ctx );
2599 countryStringValidate(
2601 struct berval *val )
2603 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2605 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2606 return LDAP_INVALID_SYNTAX;
2608 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2609 return LDAP_INVALID_SYNTAX;
2612 return LDAP_SUCCESS;
2616 printableStringValidate(
2618 struct berval *val )
2622 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2624 for(i=0; i < val->bv_len; i++) {
2625 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2626 return LDAP_INVALID_SYNTAX;
2630 return LDAP_SUCCESS;
2634 printablesStringValidate(
2636 struct berval *val )
2640 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2642 for(i=0,len=0; i < val->bv_len; i++) {
2643 int c = val->bv_val[i];
2647 return LDAP_INVALID_SYNTAX;
2651 } else if ( SLAP_PRINTABLE(c) ) {
2654 return LDAP_INVALID_SYNTAX;
2659 return LDAP_INVALID_SYNTAX;
2662 return LDAP_SUCCESS;
2668 struct berval *val )
2672 for(i=0; i < val->bv_len; i++) {
2673 if( !LDAP_ASCII(val->bv_val[i]) ) {
2674 return LDAP_INVALID_SYNTAX;
2678 return LDAP_SUCCESS;
2687 struct berval *normalized,
2691 int casefold = !SLAP_MR_ASSOCIATED( mr,
2692 slap_schema.si_mr_caseExactIA5Match );
2694 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2698 /* Ignore initial whitespace */
2699 while ( ASCII_SPACE( *p ) ) p++;
2701 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2702 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2703 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2704 normalized->bv_val[normalized->bv_len] = '\0';
2706 p = q = normalized->bv_val;
2709 if ( ASCII_SPACE( *p ) ) {
2712 /* Ignore the extra whitespace */
2713 while ( ASCII_SPACE( *p ) ) {
2717 } else if ( casefold ) {
2718 /* Most IA5 rules require casefolding */
2719 *q++ = TOLOWER(*p); p++;
2726 assert( normalized->bv_val <= p );
2730 * If the string ended in space, backup the pointer one
2731 * position. One is enough because the above loop collapsed
2732 * all whitespace to a single space.
2734 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2736 /* null terminate */
2739 normalized->bv_len = q - normalized->bv_val;
2741 return LDAP_SUCCESS;
2750 if( in->bv_len != 36 ) {
2751 return LDAP_INVALID_SYNTAX;
2754 for( i=0; i<36; i++ ) {
2760 if( in->bv_val[i] != '-' ) {
2761 return LDAP_INVALID_SYNTAX;
2765 if( !ASCII_HEX( in->bv_val[i]) ) {
2766 return LDAP_INVALID_SYNTAX;
2771 return LDAP_SUCCESS;
2782 int rc=LDAP_INVALID_SYNTAX;
2784 assert( in != NULL );
2785 assert( out != NULL );
2787 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2790 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2792 for( i=0; i<36; i++ ) {
2798 if( in->bv_val[i] != '-' ) {
2801 out->bv_val[i] = '-';
2805 if( !ASCII_HEX( in->bv_val[i]) ) {
2808 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2813 out->bv_val[ out->bv_len ] = '\0';
2817 slap_sl_free( out->bv_val, ctx );
2830 struct berval *normalized,
2833 unsigned char octet = '\0';
2837 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2838 /* NOTE: must be a normalized UUID */
2839 assert( val->bv_len == 16 );
2841 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2842 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2843 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2844 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2846 return LDAP_SUCCESS;
2849 normalized->bv_len = 16;
2850 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2852 for( i=0, j=0; i<36; i++ ) {
2853 unsigned char nibble;
2854 if( val->bv_val[i] == '-' ) {
2857 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2858 nibble = val->bv_val[i] - '0';
2860 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2861 nibble = val->bv_val[i] - ('a'-10);
2863 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2864 nibble = val->bv_val[i] - ('A'-10);
2867 slap_sl_free( normalized->bv_val, ctx );
2868 BER_BVZERO( normalized );
2869 return LDAP_INVALID_SYNTAX;
2874 normalized->bv_val[j>>1] = octet;
2876 octet = nibble << 4;
2881 normalized->bv_val[normalized->bv_len] = 0;
2882 return LDAP_SUCCESS;
2888 numericStringValidate(
2894 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2896 for(i=0; i < in->bv_len; i++) {
2897 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2898 return LDAP_INVALID_SYNTAX;
2902 return LDAP_SUCCESS;
2906 numericStringNormalize(
2911 struct berval *normalized,
2914 /* removal all spaces */
2917 assert( !BER_BVISEMPTY( val ) );
2919 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2922 q = normalized->bv_val;
2925 if ( ASCII_SPACE( *p ) ) {
2926 /* Ignore whitespace */
2933 /* we should have copied no more than is in val */
2934 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2936 /* null terminate */
2939 normalized->bv_len = q - normalized->bv_val;
2941 if( BER_BVISEMPTY( normalized ) ) {
2942 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2943 normalized->bv_val[0] = ' ';
2944 normalized->bv_val[1] = '\0';
2945 normalized->bv_len = 1;
2948 return LDAP_SUCCESS;
2952 * Integer conversion macros that will use the largest available
2955 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2956 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2957 # define SLAP_LONG long long
2959 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2960 # define SLAP_LONG long
2961 #endif /* HAVE_STRTOLL ... */
2969 struct berval *value,
2970 void *assertedValue )
2972 SLAP_LONG lValue, lAssertedValue;
2975 /* safe to assume integers are NUL terminated? */
2976 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2977 if( errno == ERANGE )
2979 return LDAP_CONSTRAINT_VIOLATION;
2982 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2984 if( errno == ERANGE )
2986 return LDAP_CONSTRAINT_VIOLATION;
2989 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2990 return LDAP_SUCCESS;
2999 struct berval *value,
3000 void *assertedValue )
3002 SLAP_LONG lValue, lAssertedValue;
3005 /* safe to assume integers are NUL terminated? */
3006 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3007 if( errno == ERANGE )
3009 return LDAP_CONSTRAINT_VIOLATION;
3012 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3014 if( errno == ERANGE )
3016 return LDAP_CONSTRAINT_VIOLATION;
3019 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3020 return LDAP_SUCCESS;
3024 checkNum( struct berval *in, struct berval *out )
3026 /* parse serialNumber */
3027 ber_len_t neg = 0, extra = 0;
3030 out->bv_val = in->bv_val;
3033 if ( out->bv_val[0] == '-' ) {
3038 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3039 first = out->bv_val[2];
3042 out->bv_len += STRLENOF("0x");
3043 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3044 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3047 } else if ( out->bv_val[0] == '\'' ) {
3048 first = out->bv_val[1];
3051 out->bv_len += STRLENOF("'");
3053 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3054 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3056 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3059 out->bv_len += STRLENOF("'H");
3062 first = out->bv_val[0];
3063 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3064 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3068 if ( !( out->bv_len > neg ) ) {
3072 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3080 serialNumberAndIssuerCheck(
3088 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3090 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3091 /* Parse old format */
3092 is->bv_val = ber_bvchr( in, '$' );
3093 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3095 sn->bv_val = in->bv_val;
3096 sn->bv_len = is->bv_val - in->bv_val;
3099 is->bv_len = in->bv_len - (sn->bv_len + 1);
3101 /* eat leading zeros */
3102 for( n=0; n < (sn->bv_len-1); n++ ) {
3103 if( sn->bv_val[n] != '0' ) break;
3108 for( n=0; n < sn->bv_len; n++ ) {
3109 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3113 /* Parse GSER format */
3118 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3122 struct berval x = *in;
3128 /* eat leading spaces */
3129 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3133 /* should be at issuer or serialNumber NamedValue */
3134 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3135 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3138 x.bv_val += STRLENOF("issuer");
3139 x.bv_len -= STRLENOF("issuer");
3141 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3145 /* eat leading spaces */
3146 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3150 /* For backward compatibility, this part is optional */
3151 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3152 x.bv_val += STRLENOF("rdnSequence:");
3153 x.bv_len -= STRLENOF("rdnSequence:");
3156 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3160 is->bv_val = x.bv_val;
3163 for ( ; is->bv_len < x.bv_len; ) {
3164 if ( is->bv_val[is->bv_len] != '"' ) {
3168 if ( is->bv_val[is->bv_len+1] == '"' ) {
3175 x.bv_val += is->bv_len + 1;
3176 x.bv_len -= is->bv_len + 1;
3178 have |= HAVE_ISSUER;
3180 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3182 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3184 /* parse serialNumber */
3185 x.bv_val += STRLENOF("serialNumber");
3186 x.bv_len -= STRLENOF("serialNumber");
3188 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3192 /* eat leading spaces */
3193 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3197 if ( checkNum( &x, sn ) ) {
3198 return LDAP_INVALID_SYNTAX;
3201 x.bv_val += sn->bv_len;
3202 x.bv_len -= sn->bv_len;
3207 return LDAP_INVALID_SYNTAX;
3210 /* eat leading spaces */
3211 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3215 if ( have == HAVE_ALL ) {
3219 if ( x.bv_val[0] != ',' ) {
3220 return LDAP_INVALID_SYNTAX;
3227 /* should have no characters left... */
3228 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3230 if ( numdquotes == 0 ) {
3231 ber_dupbv_x( &ni, is, ctx );
3236 ni.bv_len = is->bv_len - numdquotes;
3237 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3238 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3239 if ( is->bv_val[src] == '"' ) {
3242 ni.bv_val[dst] = is->bv_val[src];
3244 ni.bv_val[dst] = '\0';
3254 serialNumberAndIssuerValidate(
3259 struct berval sn, i;
3261 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3264 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3269 /* validate DN -- doesn't handle double dquote */
3270 rc = dnValidate( NULL, &i );
3272 rc = LDAP_INVALID_SYNTAX;
3275 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3276 slap_sl_free( i.bv_val, NULL );
3279 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3280 in->bv_val, rc, 0 );
3287 serialNumberAndIssuerPretty(
3294 struct berval sn, i, ni = BER_BVNULL;
3297 assert( in != NULL );
3298 assert( out != NULL );
3302 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3305 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3310 rc = dnPretty( syntax, &i, &ni, ctx );
3312 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3313 slap_sl_free( i.bv_val, ctx );
3317 rc = LDAP_INVALID_SYNTAX;
3321 /* make room from sn + "$" */
3322 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3323 + sn.bv_len + ni.bv_len;
3324 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3326 if ( out->bv_val == NULL ) {
3333 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3334 p = lutil_strbvcopy( p, &sn );
3335 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3336 p = lutil_strbvcopy( p, &ni );
3337 p = lutil_strcopy( p, /*{*/ "\" }" );
3339 assert( p == &out->bv_val[out->bv_len] );
3342 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3343 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3345 slap_sl_free( ni.bv_val, ctx );
3347 return LDAP_SUCCESS;
3357 /* Use hex format. '123456789abcdef'H */
3358 unsigned char *ptr, zero = '\0';
3361 ber_len_t i, len, nlen;
3363 assert( in != NULL );
3364 assert( !BER_BVISNULL( in ) );
3365 assert( out != NULL );
3366 assert( !BER_BVISNULL( out ) );
3368 ptr = (unsigned char *)in->bv_val;
3371 /* Check for minimal encodings */
3373 if ( ptr[0] & 0x80 ) {
3374 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3378 } else if ( ptr[0] == 0 ) {
3379 if ( !( ptr[1] & 0x80 ) ) {
3386 } else if ( len == 0 ) {
3387 /* FIXME: this should not be possible,
3388 * since a value of zero would have length 1 */
3393 first = !( ptr[0] & 0xf0U );
3394 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3395 if ( nlen >= out->bv_len ) {
3396 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3402 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3406 for ( ; i < len; i++ ) {
3407 sprintf( sptr, "%02X", ptr[i] );
3414 assert( sptr == &out->bv_val[nlen] );
3421 #define SLAP_SN_BUFLEN (64)
3424 * This routine is called by certificateExactNormalize when
3425 * certificateExactNormalize receives a search string instead of
3426 * a certificate. This routine checks if the search value is valid
3427 * and then returns the normalized value
3430 serialNumberAndIssuerNormalize(
3438 struct berval sn, sn2, sn3, i, ni;
3439 char sbuf2[SLAP_SN_BUFLEN];
3440 char sbuf3[SLAP_SN_BUFLEN];
3444 assert( in != NULL );
3445 assert( out != NULL );
3447 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3450 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3455 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3457 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3458 slap_sl_free( i.bv_val, ctx );
3462 return LDAP_INVALID_SYNTAX;
3465 /* Convert sn to canonical hex */
3467 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3468 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3470 sn2.bv_len = sn.bv_len;
3471 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3472 rc = LDAP_INVALID_SYNTAX;
3477 sn3.bv_len = sizeof(sbuf3);
3478 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3479 rc = LDAP_INVALID_SYNTAX;
3483 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3484 + sn3.bv_len + ni.bv_len;
3485 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3487 if ( out->bv_val == NULL ) {
3495 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3496 p = lutil_strbvcopy( p, &sn3 );
3497 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3498 p = lutil_strbvcopy( p, &ni );
3499 p = lutil_strcopy( p, /*{*/ "\" }" );
3501 assert( p == &out->bv_val[out->bv_len] );
3504 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3505 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3507 if ( sn2.bv_val != sbuf2 ) {
3508 slap_sl_free( sn2.bv_val, ctx );
3511 if ( sn3.bv_val != sbuf3 ) {
3512 slap_sl_free( sn3.bv_val, ctx );
3515 slap_sl_free( ni.bv_val, ctx );
3521 certificateExactNormalize(
3526 struct berval *normalized,
3529 BerElementBuffer berbuf;
3530 BerElement *ber = (BerElement *)&berbuf;
3534 char serialbuf2[SLAP_SN_BUFLEN];
3535 struct berval sn, sn2 = BER_BVNULL;
3536 struct berval issuer_dn = BER_BVNULL, bvdn;
3538 int rc = LDAP_INVALID_SYNTAX;
3540 assert( val != NULL );
3542 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3543 val->bv_val, val->bv_len, 0 );
3545 if ( BER_BVISEMPTY( val ) ) goto done;
3547 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3548 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3551 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3553 ber_init2( ber, val, LBER_USE_DER );
3554 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3555 tag = ber_skip_tag( ber, &len ); /* Sequence */
3556 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3557 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3558 tag = ber_skip_tag( ber, &len );
3559 tag = ber_get_int( ber, &i ); /* version */
3562 /* NOTE: move the test here from certificateValidate,
3563 * so that we can validate certs with serial longer
3564 * than sizeof(ber_int_t) */
3565 tag = ber_skip_tag( ber, &len ); /* serial */
3567 sn.bv_val = (char *)ber->ber_ptr;
3568 sn2.bv_val = serialbuf2;
3569 sn2.bv_len = sizeof(serialbuf2);
3570 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3571 rc = LDAP_INVALID_SYNTAX;
3574 ber_skip_data( ber, len );
3576 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3577 ber_skip_data( ber, len );
3578 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3579 len = ber_ptrlen( ber );
3580 bvdn.bv_val = val->bv_val + len;
3581 bvdn.bv_len = val->bv_len - len;
3583 rc = dnX509normalize( &bvdn, &issuer_dn );
3584 if ( rc != LDAP_SUCCESS ) goto done;
3586 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3587 + sn2.bv_len + issuer_dn.bv_len;
3588 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3590 p = normalized->bv_val;
3592 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3593 p = lutil_strbvcopy( p, &sn2 );
3594 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3595 p = lutil_strbvcopy( p, &issuer_dn );
3596 p = lutil_strcopy( p, /*{*/ "\" }" );
3601 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3602 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3604 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3605 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3610 /* X.509 PKI certificateList stuff */
3612 checkTime( struct berval *in, struct berval *out )
3616 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3619 assert( in != NULL );
3620 assert( !BER_BVISNULL( in ) );
3621 assert( !BER_BVISEMPTY( in ) );
3623 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3627 if ( out != NULL ) {
3628 assert( !BER_BVISNULL( out ) );
3629 assert( out->bv_len >= sizeof( buf ) );
3630 bv.bv_val = out->bv_val;
3636 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3637 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3640 if ( in->bv_val[i] != 'Z' ) {
3645 if ( i != in->bv_len ) {
3649 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3650 lutil_strncopy( bv.bv_val, in->bv_val, i );
3653 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3654 char *p = bv.bv_val;
3655 if ( in->bv_val[0] < '7' ) {
3656 p = lutil_strcopy( p, "20" );
3659 p = lutil_strcopy( p, "19" );
3661 lutil_strncopy( p, in->bv_val, i );
3668 rc = generalizedTimeValidate( NULL, &bv );
3669 if ( rc == LDAP_SUCCESS && out != NULL ) {
3670 if ( out->bv_len > bv.bv_len ) {
3671 out->bv_val[ bv.bv_len ] = '\0';
3673 out->bv_len = bv.bv_len;
3676 return rc != LDAP_SUCCESS;
3680 issuerAndThisUpdateCheck(
3687 struct berval x = *in;
3688 struct berval ni = BER_BVNULL;
3689 /* Parse GSER format */
3693 HAVE_THISUPDATE = 0x2,
3694 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3698 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3700 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3701 return LDAP_INVALID_SYNTAX;
3705 x.bv_len -= STRLENOF("{}");
3708 /* eat leading spaces */
3709 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3713 /* should be at issuer or thisUpdate */
3714 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3715 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3718 x.bv_val += STRLENOF("issuer");
3719 x.bv_len -= STRLENOF("issuer");
3721 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3725 /* eat leading spaces */
3726 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3730 /* For backward compatibility, this part is optional */
3731 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3732 return LDAP_INVALID_SYNTAX;
3734 x.bv_val += STRLENOF("rdnSequence:");
3735 x.bv_len -= STRLENOF("rdnSequence:");
3737 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3741 is->bv_val = x.bv_val;
3744 for ( ; is->bv_len < x.bv_len; ) {
3745 if ( is->bv_val[is->bv_len] != '"' ) {
3749 if ( is->bv_val[is->bv_len+1] == '"' ) {
3756 x.bv_val += is->bv_len + 1;
3757 x.bv_len -= is->bv_len + 1;
3759 have |= HAVE_ISSUER;
3761 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3763 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3765 /* parse thisUpdate */
3766 x.bv_val += STRLENOF("thisUpdate");
3767 x.bv_len -= STRLENOF("thisUpdate");
3769 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3773 /* eat leading spaces */
3774 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3778 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3782 tu->bv_val = x.bv_val;
3785 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3786 if ( tu->bv_val[tu->bv_len] == '"' ) {
3790 x.bv_val += tu->bv_len + 1;
3791 x.bv_len -= tu->bv_len + 1;
3793 have |= HAVE_THISUPDATE;
3796 return LDAP_INVALID_SYNTAX;
3799 /* eat leading spaces */
3800 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3804 if ( have == HAVE_ALL ) {
3808 if ( x.bv_val[0] != ',' ) {
3809 return LDAP_INVALID_SYNTAX;
3816 /* should have no characters left... */
3817 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3819 if ( numdquotes == 0 ) {
3820 ber_dupbv_x( &ni, is, ctx );
3825 ni.bv_len = is->bv_len - numdquotes;
3826 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3827 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3828 if ( is->bv_val[src] == '"' ) {
3831 ni.bv_val[dst] = is->bv_val[src];
3833 ni.bv_val[dst] = '\0';
3842 issuerAndThisUpdateValidate(
3847 struct berval i, tu;
3849 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3852 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3857 /* validate DN -- doesn't handle double dquote */
3858 rc = dnValidate( NULL, &i );
3860 rc = LDAP_INVALID_SYNTAX;
3862 } else if ( checkTime( &tu, NULL ) ) {
3863 rc = LDAP_INVALID_SYNTAX;
3866 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3867 slap_sl_free( i.bv_val, NULL );
3870 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3871 in->bv_val, rc, 0 );
3878 issuerAndThisUpdatePretty(
3885 struct berval i, tu, ni = BER_BVNULL;
3888 assert( in != NULL );
3889 assert( out != NULL );
3893 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3896 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3901 rc = dnPretty( syntax, &i, &ni, ctx );
3903 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3904 slap_sl_free( i.bv_val, ctx );
3907 if ( rc || checkTime( &tu, NULL ) ) {
3908 rc = LDAP_INVALID_SYNTAX;
3913 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3914 + ni.bv_len + tu.bv_len;
3915 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3917 if ( out->bv_val == NULL ) {
3924 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3925 p = lutil_strbvcopy( p, &ni );
3926 p = lutil_strcopy( p, "\", thisUpdate \"" );
3927 p = lutil_strbvcopy( p, &tu );
3928 p = lutil_strcopy( p, /*{*/ "\" }" );
3930 assert( p == &out->bv_val[out->bv_len] );
3933 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3934 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3936 slap_sl_free( ni.bv_val, ctx );
3942 issuerAndThisUpdateNormalize(
3950 struct berval i, ni, tu, tu2;
3951 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3955 assert( in != NULL );
3956 assert( out != NULL );
3958 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3961 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3966 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3968 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3969 slap_sl_free( i.bv_val, ctx );
3973 tu2.bv_len = sizeof( sbuf );
3974 if ( rc || checkTime( &tu, &tu2 ) ) {
3975 return LDAP_INVALID_SYNTAX;
3978 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3979 + ni.bv_len + tu2.bv_len;
3980 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3982 if ( out->bv_val == NULL ) {
3990 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3991 p = lutil_strbvcopy( p, &ni );
3992 p = lutil_strcopy( p, "\", thisUpdate \"" );
3993 p = lutil_strbvcopy( p, &tu2 );
3994 p = lutil_strcopy( p, /*{*/ "\" }" );
3996 assert( p == &out->bv_val[out->bv_len] );
3999 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
4000 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4002 slap_sl_free( ni.bv_val, ctx );
4008 certificateListExactNormalize(
4013 struct berval *normalized,
4016 BerElementBuffer berbuf;
4017 BerElement *ber = (BerElement *)&berbuf;
4021 struct berval issuer_dn = BER_BVNULL, bvdn,
4023 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4024 int rc = LDAP_INVALID_SYNTAX;
4026 assert( val != NULL );
4028 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4029 val->bv_val, val->bv_len, 0 );
4031 if ( BER_BVISEMPTY( val ) ) goto done;
4033 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4034 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4037 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4039 ber_init2( ber, val, LBER_USE_DER );
4040 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4041 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4042 tag = ber_skip_tag( ber, &len ); /* Sequence */
4043 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4044 tag = ber_peek_tag( ber, &len );
4045 /* Optional version */
4046 if ( tag == LBER_INTEGER ) {
4047 tag = ber_get_int( ber, &version );
4048 assert( tag == LBER_INTEGER );
4049 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4051 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4052 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4053 ber_skip_data( ber, len );
4055 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4056 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4057 len = ber_ptrlen( ber );
4058 bvdn.bv_val = val->bv_val + len;
4059 bvdn.bv_len = val->bv_len - len;
4060 tag = ber_skip_tag( ber, &len );
4061 ber_skip_data( ber, len );
4063 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4064 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4065 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4066 bvtu.bv_val = (char *)ber->ber_ptr;
4069 rc = dnX509normalize( &bvdn, &issuer_dn );
4070 if ( rc != LDAP_SUCCESS ) goto done;
4072 thisUpdate.bv_val = tubuf;
4073 thisUpdate.bv_len = sizeof(tubuf);
4074 if ( checkTime( &bvtu, &thisUpdate ) ) {
4075 rc = LDAP_INVALID_SYNTAX;
4079 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4080 + issuer_dn.bv_len + thisUpdate.bv_len;
4081 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4083 p = normalized->bv_val;
4085 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4086 p = lutil_strbvcopy( p, &issuer_dn );
4087 p = lutil_strcopy( p, "\", thisUpdate \"" );
4088 p = lutil_strbvcopy( p, &thisUpdate );
4089 p = lutil_strcopy( p, /*{*/ "\" }" );
4094 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4095 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4097 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4102 /* X.509 PMI serialNumberAndIssuerSerialCheck
4104 AttributeCertificateExactAssertion ::= SEQUENCE {
4105 serialNumber CertificateSerialNumber,
4106 issuer AttCertIssuer }
4108 CertificateSerialNumber ::= INTEGER
4110 AttCertIssuer ::= [0] SEQUENCE {
4111 issuerName GeneralNames OPTIONAL,
4112 baseCertificateID [0] IssuerSerial OPTIONAL,
4113 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4114 -- At least one component shall be present
4116 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4118 GeneralName ::= CHOICE {
4119 otherName [0] INSTANCE OF OTHER-NAME,
4120 rfc822Name [1] IA5String,
4121 dNSName [2] IA5String,
4122 x400Address [3] ORAddress,
4123 directoryName [4] Name,
4124 ediPartyName [5] EDIPartyName,
4125 uniformResourceIdentifier [6] IA5String,
4126 iPAddress [7] OCTET STRING,
4127 registeredID [8] OBJECT IDENTIFIER }
4129 IssuerSerial ::= SEQUENCE {
4130 issuer GeneralNames,
4131 serial CertificateSerialNumber,
4132 issuerUID UniqueIdentifier OPTIONAL }
4134 ObjectDigestInfo ::= SEQUENCE {
4135 digestedObjectType ENUMERATED {
4138 otherObjectTypes (2) },
4139 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4140 digestAlgorithm AlgorithmIdentifier,
4141 objectDigest BIT STRING }
4143 * The way I interpret it, an assertion should look like
4145 { serialNumber 'dd'H,
4146 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4147 baseCertificateID { serial '1d'H,
4148 issuer { directoryName:rdnSequence:"cn=zzz" },
4149 issuerUID <value> -- optional
4151 objectDigestInfo { ... } -- optional
4155 * with issuerName, baseCertificateID and objectDigestInfo optional,
4156 * at least one present; the way it's currently implemented, it is
4158 { serialNumber 'dd'H,
4159 issuer { baseCertificateID { serial '1d'H,
4160 issuer { directoryName:rdnSequence:"cn=zzz" }
4165 * with all the above parts mandatory.
4168 serialNumberAndIssuerSerialCheck(
4172 struct berval *i_sn, /* contain serial of baseCertificateID */
4175 /* Parse GSER format */
4180 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4181 } have = HAVE_NONE, have2 = HAVE_NONE;
4183 struct berval x = *in;
4186 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4189 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4196 /* eat leading spaces */
4197 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4201 /* should be at issuer or serialNumber NamedValue */
4202 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4203 if ( have & HAVE_ISSUER ) {
4204 return LDAP_INVALID_SYNTAX;
4207 /* parse IssuerSerial */
4208 x.bv_val += STRLENOF("issuer");
4209 x.bv_len -= STRLENOF("issuer");
4211 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4215 /* eat leading spaces */
4216 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4220 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4224 /* eat leading spaces */
4225 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4229 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4230 return LDAP_INVALID_SYNTAX;
4232 x.bv_val += STRLENOF("baseCertificateID ");
4233 x.bv_len -= STRLENOF("baseCertificateID ");
4235 /* eat leading spaces */
4236 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4240 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4245 /* eat leading spaces */
4246 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4250 /* parse issuer of baseCertificateID */
4251 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4252 if ( have2 & HAVE_ISSUER ) {
4253 return LDAP_INVALID_SYNTAX;
4256 x.bv_val += STRLENOF("issuer ");
4257 x.bv_len -= STRLENOF("issuer ");
4259 /* eat leading spaces */
4260 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4264 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4268 /* eat leading spaces */
4269 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4273 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4274 return LDAP_INVALID_SYNTAX;
4276 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4277 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4279 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4283 is->bv_val = x.bv_val;
4286 for ( ; is->bv_len < x.bv_len; ) {
4287 if ( is->bv_val[is->bv_len] != '"' ) {
4291 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4298 x.bv_val += is->bv_len + 1;
4299 x.bv_len -= is->bv_len + 1;
4301 /* eat leading spaces */
4302 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4306 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4310 have2 |= HAVE_ISSUER;
4312 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4313 if ( have2 & HAVE_SN ) {
4314 return LDAP_INVALID_SYNTAX;
4317 x.bv_val += STRLENOF("serial ");
4318 x.bv_len -= STRLENOF("serial ");
4320 /* eat leading spaces */
4321 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4325 if ( checkNum( &x, i_sn ) ) {
4326 return LDAP_INVALID_SYNTAX;
4329 x.bv_val += i_sn->bv_len;
4330 x.bv_len -= i_sn->bv_len;
4335 return LDAP_INVALID_SYNTAX;
4338 /* eat leading spaces */
4339 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4343 if ( have2 == HAVE_ALL ) {
4347 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4352 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4356 /* eat leading spaces */
4357 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4361 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4365 have |= HAVE_ISSUER;
4367 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4368 if ( have & HAVE_SN ) {
4369 return LDAP_INVALID_SYNTAX;
4372 /* parse serialNumber */
4373 x.bv_val += STRLENOF("serialNumber");
4374 x.bv_len -= STRLENOF("serialNumber");
4376 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4380 /* eat leading spaces */
4381 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4385 if ( checkNum( &x, sn ) ) {
4386 return LDAP_INVALID_SYNTAX;
4389 x.bv_val += sn->bv_len;
4390 x.bv_len -= sn->bv_len;
4395 return LDAP_INVALID_SYNTAX;
4399 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4403 if ( have == HAVE_ALL ) {
4407 if ( x.bv_val[0] != ',' ) {
4408 return LDAP_INVALID_SYNTAX;
4414 /* should have no characters left... */
4415 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4417 if ( numdquotes == 0 ) {
4418 ber_dupbv_x( &ni, is, ctx );
4423 ni.bv_len = is->bv_len - numdquotes;
4424 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4425 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4426 if ( is->bv_val[src] == '"' ) {
4429 ni.bv_val[dst] = is->bv_val[src];
4431 ni.bv_val[dst] = '\0';
4436 /* need to handle double dquotes here */
4440 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4442 serialNumberAndIssuerSerialValidate(
4447 struct berval sn, i, i_sn;
4449 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4452 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4457 /* validate DN -- doesn't handle double dquote */
4458 rc = dnValidate( NULL, &i );
4460 rc = LDAP_INVALID_SYNTAX;
4463 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4464 slap_sl_free( i.bv_val, NULL );
4468 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4469 in->bv_val, rc, 0 );
4474 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4476 serialNumberAndIssuerSerialPretty(
4482 struct berval sn, i, i_sn, ni = BER_BVNULL;
4486 assert( in != NULL );
4487 assert( out != NULL );
4489 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4492 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4497 rc = dnPretty( syntax, &i, &ni, ctx );
4499 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4500 slap_sl_free( i.bv_val, ctx );
4504 rc = LDAP_INVALID_SYNTAX;
4508 /* make room from sn + "$" */
4509 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4510 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4511 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4513 if ( out->bv_val == NULL ) {
4520 p = lutil_strcopy( p, "{ serialNumber " );
4521 p = lutil_strbvcopy( p, &sn );
4522 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4523 p = lutil_strbvcopy( p, &ni );
4524 p = lutil_strcopy( p, "\" }, serial " );
4525 p = lutil_strbvcopy( p, &i_sn );
4526 p = lutil_strcopy( p, " } } }" );
4528 assert( p == &out->bv_val[out->bv_len] );
4531 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4532 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4534 slap_sl_free( ni.bv_val, ctx );
4539 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4541 * This routine is called by attributeCertificateExactNormalize
4542 * when attributeCertificateExactNormalize receives a search
4543 * string instead of a attribute certificate. This routine
4544 * checks if the search value is valid and then returns the
4548 serialNumberAndIssuerSerialNormalize(
4556 struct berval i, ni = BER_BVNULL,
4557 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4558 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4559 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4560 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4564 assert( in != NULL );
4565 assert( out != NULL );
4567 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4570 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4575 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4577 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4578 slap_sl_free( i.bv_val, ctx );
4582 rc = LDAP_INVALID_SYNTAX;
4586 /* Convert sn to canonical hex */
4588 sn2.bv_len = sn.bv_len;
4589 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4590 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4592 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4593 rc = LDAP_INVALID_SYNTAX;
4597 /* Convert i_sn to canonical hex */
4598 i_sn2.bv_val = i_sbuf2;
4599 i_sn2.bv_len = i_sn.bv_len;
4600 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4601 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4603 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4604 rc = LDAP_INVALID_SYNTAX;
4609 sn3.bv_len = sizeof(sbuf3);
4610 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4611 rc = LDAP_INVALID_SYNTAX;
4615 i_sn3.bv_val = i_sbuf3;
4616 i_sn3.bv_len = sizeof(i_sbuf3);
4617 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4618 rc = LDAP_INVALID_SYNTAX;
4622 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4623 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4624 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4626 if ( out->bv_val == NULL ) {
4634 p = lutil_strcopy( p, "{ serialNumber " );
4635 p = lutil_strbvcopy( p, &sn3 );
4636 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4637 p = lutil_strbvcopy( p, &ni );
4638 p = lutil_strcopy( p, "\" }, serial " );
4639 p = lutil_strbvcopy( p, &i_sn3 );
4640 p = lutil_strcopy( p, " } } }" );
4642 assert( p == &out->bv_val[out->bv_len] );
4645 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4646 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4648 if ( sn2.bv_val != sbuf2 ) {
4649 slap_sl_free( sn2.bv_val, ctx );
4652 if ( i_sn2.bv_val != i_sbuf2 ) {
4653 slap_sl_free( i_sn2.bv_val, ctx );
4656 if ( sn3.bv_val != sbuf3 ) {
4657 slap_sl_free( sn3.bv_val, ctx );
4660 if ( i_sn3.bv_val != i_sbuf3 ) {
4661 slap_sl_free( i_sn3.bv_val, ctx );
4664 slap_sl_free( ni.bv_val, ctx );
4669 /* X.509 PMI attributeCertificateExactNormalize */
4671 attributeCertificateExactNormalize(
4676 struct berval *normalized,
4679 BerElementBuffer berbuf;
4680 BerElement *ber = (BerElement *)&berbuf;
4683 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4684 struct berval sn, i_sn, sn2, i_sn2;
4685 struct berval issuer_dn = BER_BVNULL, bvdn;
4687 int rc = LDAP_INVALID_SYNTAX;
4689 if ( BER_BVISEMPTY( val ) ) {
4693 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4694 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4697 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4699 ber_init2( ber, val, LBER_USE_DER );
4700 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4701 tag = ber_skip_tag( ber, &len ); /* Sequence */
4702 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4703 ber_skip_data( ber, len );
4704 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4705 ber_skip_data( ber, len );
4708 tag = ber_skip_tag( ber, &len ); /* Sequence */
4709 /* issuerName (GeneralNames sequence; optional)? */
4710 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4711 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4712 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4713 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4714 rc = LDAP_INVALID_SYNTAX;
4717 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4718 len = ber_ptrlen( ber );
4719 bvdn.bv_val = val->bv_val + len;
4720 bvdn.bv_len = val->bv_len - len;
4721 rc = dnX509normalize( &bvdn, &issuer_dn );
4722 if ( rc != LDAP_SUCCESS ) goto done;
4724 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4725 ber_skip_data( ber, len );
4726 tag = ber_skip_tag( ber, &len ); /* serial number */
4727 if ( tag != LBER_INTEGER ) {
4728 rc = LDAP_INVALID_SYNTAX;
4731 i_sn.bv_val = (char *)ber->ber_ptr;
4733 i_sn2.bv_val = issuer_serialbuf;
4734 i_sn2.bv_len = sizeof(issuer_serialbuf);
4735 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4736 rc = LDAP_INVALID_SYNTAX;
4739 ber_skip_data( ber, len );
4741 /* issuerUID (bitstring; optional)? */
4742 /* objectDigestInfo (sequence; optional)? */
4744 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4745 ber_skip_data( ber, len );
4746 tag = ber_skip_tag( ber, &len ); /* serial number */
4747 if ( tag != LBER_INTEGER ) {
4748 rc = LDAP_INVALID_SYNTAX;
4751 sn.bv_val = (char *)ber->ber_ptr;
4753 sn2.bv_val = serialbuf;
4754 sn2.bv_len = sizeof(serialbuf);
4755 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4756 rc = LDAP_INVALID_SYNTAX;
4759 ber_skip_data( ber, len );
4761 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4762 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4763 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4765 p = normalized->bv_val;
4767 p = lutil_strcopy( p, "{ serialNumber " );
4768 p = lutil_strbvcopy( p, &sn2 );
4769 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4770 p = lutil_strbvcopy( p, &issuer_dn );
4771 p = lutil_strcopy( p, "\" }, serial " );
4772 p = lutil_strbvcopy( p, &i_sn2 );
4773 p = lutil_strcopy( p, " } } }" );
4775 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4776 normalized->bv_val, NULL, NULL );
4781 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4782 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4783 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4796 assert( in != NULL );
4797 assert( !BER_BVISNULL( in ) );
4799 for ( i = 0; i < in->bv_len; i++ ) {
4800 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4801 return LDAP_INVALID_SYNTAX;
4805 return LDAP_SUCCESS;
4808 /* Normalize a SID as used inside a CSN:
4809 * three-digit numeric string */
4816 struct berval *normalized,
4821 assert( val != NULL );
4822 assert( normalized != NULL );
4824 ber_dupbv_x( normalized, val, ctx );
4826 for ( i = 0; i < normalized->bv_len; i++ ) {
4827 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4828 ber_memfree_x( normalized->bv_val, ctx );
4829 BER_BVZERO( normalized );
4830 return LDAP_INVALID_SYNTAX;
4833 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4836 return LDAP_SUCCESS;
4844 assert( in != NULL );
4845 assert( !BER_BVISNULL( in ) );
4847 if ( in->bv_len != 3 ) {
4848 return LDAP_INVALID_SYNTAX;
4851 return hexValidate( NULL, in );
4854 /* Normalize a SID as used inside a CSN:
4855 * three-digit numeric string */
4862 struct berval *normalized,
4865 if ( val->bv_len != 3 ) {
4866 return LDAP_INVALID_SYNTAX;
4869 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4879 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4882 /* Normalize a SID as used inside a CSN, either as-is
4883 * (assertion value) or extracted from the CSN
4884 * (attribute value) */
4891 struct berval *normalized,
4899 if ( BER_BVISEMPTY( val ) ) {
4900 return LDAP_INVALID_SYNTAX;
4903 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4904 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4907 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4909 ptr = ber_bvchr( val, '#' );
4910 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4911 return LDAP_INVALID_SYNTAX;
4914 bv.bv_val = ptr + 1;
4915 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4917 ptr = ber_bvchr( &bv, '#' );
4918 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4919 return LDAP_INVALID_SYNTAX;
4922 bv.bv_val = ptr + 1;
4923 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4925 ptr = ber_bvchr( &bv, '#' );
4926 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4927 return LDAP_INVALID_SYNTAX;
4930 bv.bv_len = ptr - bv.bv_val;
4932 if ( bv.bv_len == 2 ) {
4933 /* OpenLDAP 2.3 SID */
4935 buf[ 1 ] = bv.bv_val[ 0 ];
4936 buf[ 2 ] = bv.bv_val[ 1 ];
4943 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4955 assert( in != NULL );
4956 assert( !BER_BVISNULL( in ) );
4958 if ( BER_BVISEMPTY( in ) ) {
4959 return LDAP_INVALID_SYNTAX;
4964 ptr = ber_bvchr( &bv, '#' );
4965 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4966 return LDAP_INVALID_SYNTAX;
4969 bv.bv_len = ptr - bv.bv_val;
4970 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4971 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4973 return LDAP_INVALID_SYNTAX;
4976 rc = generalizedTimeValidate( NULL, &bv );
4977 if ( rc != LDAP_SUCCESS ) {
4981 bv.bv_val = ptr + 1;
4982 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4984 ptr = ber_bvchr( &bv, '#' );
4985 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4986 return LDAP_INVALID_SYNTAX;
4989 bv.bv_len = ptr - bv.bv_val;
4990 if ( bv.bv_len != 6 ) {
4991 return LDAP_INVALID_SYNTAX;
4994 rc = hexValidate( NULL, &bv );
4995 if ( rc != LDAP_SUCCESS ) {
4999 bv.bv_val = ptr + 1;
5000 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5002 ptr = ber_bvchr( &bv, '#' );
5003 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5004 return LDAP_INVALID_SYNTAX;
5007 bv.bv_len = ptr - bv.bv_val;
5008 if ( bv.bv_len == 2 ) {
5009 /* tolerate old 2-digit replica-id */
5010 rc = hexValidate( NULL, &bv );
5013 rc = sidValidate( NULL, &bv );
5015 if ( rc != LDAP_SUCCESS ) {
5019 bv.bv_val = ptr + 1;
5020 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5022 if ( bv.bv_len != 6 ) {
5023 return LDAP_INVALID_SYNTAX;
5026 return hexValidate( NULL, &bv );
5029 /* Normalize a CSN in OpenLDAP 2.1 format */
5036 struct berval *normalized,
5039 struct berval gt, cnt, sid, mod;
5041 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5045 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5046 assert( !BER_BVISEMPTY( val ) );
5050 ptr = ber_bvchr( >, '#' );
5051 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5052 return LDAP_INVALID_SYNTAX;
5055 gt.bv_len = ptr - gt.bv_val;
5056 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5057 return LDAP_INVALID_SYNTAX;
5060 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5061 return LDAP_INVALID_SYNTAX;
5064 cnt.bv_val = ptr + 1;
5065 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5067 ptr = ber_bvchr( &cnt, '#' );
5068 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5069 return LDAP_INVALID_SYNTAX;
5072 cnt.bv_len = ptr - cnt.bv_val;
5073 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5074 return LDAP_INVALID_SYNTAX;
5077 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5078 return LDAP_INVALID_SYNTAX;
5081 cnt.bv_val += STRLENOF( "0x" );
5082 cnt.bv_len -= STRLENOF( "0x" );
5084 sid.bv_val = ptr + 1;
5085 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5087 ptr = ber_bvchr( &sid, '#' );
5088 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5089 return LDAP_INVALID_SYNTAX;
5092 sid.bv_len = ptr - sid.bv_val;
5093 if ( sid.bv_len != STRLENOF( "0" ) ) {
5094 return LDAP_INVALID_SYNTAX;
5097 mod.bv_val = ptr + 1;
5098 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5099 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5100 return LDAP_INVALID_SYNTAX;
5103 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5107 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5108 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5110 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5112 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5113 ptr = lutil_strbvcopy( ptr, &cnt );
5117 *ptr++ = sid.bv_val[ 0 ];
5121 for ( i = 0; i < mod.bv_len; i++ ) {
5122 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5126 assert( ptr == &bv.bv_val[bv.bv_len] );
5128 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5129 return LDAP_INVALID_SYNTAX;
5132 ber_dupbv_x( normalized, &bv, ctx );
5134 return LDAP_SUCCESS;
5137 /* Normalize a CSN in OpenLDAP 2.3 format */
5144 struct berval *normalized,
5147 struct berval gt, cnt, sid, mod;
5149 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5153 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5154 assert( !BER_BVISEMPTY( val ) );
5158 ptr = ber_bvchr( >, '#' );
5159 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5160 return LDAP_INVALID_SYNTAX;
5163 gt.bv_len = ptr - gt.bv_val;
5164 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5165 return LDAP_INVALID_SYNTAX;
5168 cnt.bv_val = ptr + 1;
5169 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5171 ptr = ber_bvchr( &cnt, '#' );
5172 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5173 return LDAP_INVALID_SYNTAX;
5176 cnt.bv_len = ptr - cnt.bv_val;
5177 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5178 return LDAP_INVALID_SYNTAX;
5181 sid.bv_val = ptr + 1;
5182 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5184 ptr = ber_bvchr( &sid, '#' );
5185 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5186 return LDAP_INVALID_SYNTAX;
5189 sid.bv_len = ptr - sid.bv_val;
5190 if ( sid.bv_len != STRLENOF( "00" ) ) {
5191 return LDAP_INVALID_SYNTAX;
5194 mod.bv_val = ptr + 1;
5195 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5196 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5197 return LDAP_INVALID_SYNTAX;
5200 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5204 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5205 ptr = lutil_strcopy( ptr, ".000000Z#" );
5206 ptr = lutil_strbvcopy( ptr, &cnt );
5209 for ( i = 0; i < sid.bv_len; i++ ) {
5210 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5213 for ( i = 0; i < mod.bv_len; i++ ) {
5214 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5218 assert( ptr == &bv.bv_val[bv.bv_len] );
5219 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5220 return LDAP_INVALID_SYNTAX;
5223 ber_dupbv_x( normalized, &bv, ctx );
5225 return LDAP_SUCCESS;
5228 /* Normalize a CSN */
5235 struct berval *normalized,
5238 struct berval cnt, sid, mod;
5242 assert( val != NULL );
5243 assert( normalized != NULL );
5245 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5247 if ( BER_BVISEMPTY( val ) ) {
5248 return LDAP_INVALID_SYNTAX;
5251 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5252 /* Openldap <= 2.3 */
5254 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5257 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5260 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5263 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5264 return LDAP_INVALID_SYNTAX;
5267 ptr = ber_bvchr( val, '#' );
5268 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5269 return LDAP_INVALID_SYNTAX;
5272 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5273 return LDAP_INVALID_SYNTAX;
5276 cnt.bv_val = ptr + 1;
5277 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5279 ptr = ber_bvchr( &cnt, '#' );
5280 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5281 return LDAP_INVALID_SYNTAX;
5284 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5285 return LDAP_INVALID_SYNTAX;
5288 sid.bv_val = ptr + 1;
5289 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5291 ptr = ber_bvchr( &sid, '#' );
5292 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5293 return LDAP_INVALID_SYNTAX;
5296 sid.bv_len = ptr - sid.bv_val;
5297 if ( sid.bv_len != STRLENOF( "000" ) ) {
5298 return LDAP_INVALID_SYNTAX;
5301 mod.bv_val = ptr + 1;
5302 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5304 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5305 return LDAP_INVALID_SYNTAX;
5308 ber_dupbv_x( normalized, val, ctx );
5310 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5311 i < normalized->bv_len; i++ )
5313 /* assume it's already validated that's all hex digits */
5314 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5317 return LDAP_SUCCESS;
5327 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5330 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5331 /* slight optimization - does not need the start parameter */
5332 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5337 check_time_syntax (struct berval *val,
5340 struct berval *fraction)
5343 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5344 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5345 * GeneralizedTime supports leap seconds, UTCTime does not.
5347 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5348 static const int mdays[2][12] = {
5349 /* non-leap years */
5350 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5352 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5355 int part, c, c1, c2, tzoffset, leapyear = 0;
5358 e = p + val->bv_len;
5360 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5361 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5363 for (part = start; part < 7 && p < e; part++) {
5365 if (!ASCII_DIGIT(c1)) {
5370 return LDAP_INVALID_SYNTAX;
5373 if (!ASCII_DIGIT(c)) {
5374 return LDAP_INVALID_SYNTAX;
5376 c += c1 * 10 - '0' * 11;
5377 if ((part | 1) == 3) {
5380 return LDAP_INVALID_SYNTAX;
5383 if (c >= ceiling[part]) {
5384 if (! (c == 60 && part == 6 && start == 0))
5385 return LDAP_INVALID_SYNTAX;
5389 if (part < 5 + start) {
5390 return LDAP_INVALID_SYNTAX;
5392 for (; part < 9; part++) {
5396 /* leapyear check for the Gregorian calendar (year>1581) */
5397 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5401 if (parts[3] >= mdays[leapyear][parts[2]]) {
5402 return LDAP_INVALID_SYNTAX;
5406 fraction->bv_val = p;
5407 fraction->bv_len = 0;
5408 if (p < e && (*p == '.' || *p == ',')) {
5410 while (++p < e && ASCII_DIGIT(*p)) {
5413 if (p - fraction->bv_val == 1) {
5414 return LDAP_INVALID_SYNTAX;
5416 for (end_num = p; end_num[-1] == '0'; --end_num) {
5419 c = end_num - fraction->bv_val;
5420 if (c != 1) fraction->bv_len = c;
5426 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5432 return LDAP_INVALID_SYNTAX;
5438 for (part = 7; part < 9 && p < e; part++) {
5440 if (!ASCII_DIGIT(c1)) {
5445 return LDAP_INVALID_SYNTAX;
5448 if (!ASCII_DIGIT(c2)) {
5449 return LDAP_INVALID_SYNTAX;
5451 parts[part] = c1 * 10 + c2 - '0' * 11;
5452 if (parts[part] >= ceiling[part]) {
5453 return LDAP_INVALID_SYNTAX;
5456 if (part < 8 + start) {
5457 return LDAP_INVALID_SYNTAX;
5460 if (tzoffset == '-') {
5461 /* negative offset to UTC, ie west of Greenwich */
5462 parts[4] += parts[7];
5463 parts[5] += parts[8];
5464 /* offset is just hhmm, no seconds */
5465 for (part = 6; --part >= 0; ) {
5469 c = mdays[leapyear][parts[2]];
5471 if (parts[part] >= c) {
5473 return LDAP_INVALID_SYNTAX;
5478 } else if (part != 5) {
5483 /* positive offset to UTC, ie east of Greenwich */
5484 parts[4] -= parts[7];
5485 parts[5] -= parts[8];
5486 for (part = 6; --part >= 0; ) {
5487 if (parts[part] < 0) {
5489 return LDAP_INVALID_SYNTAX;
5494 /* make first arg to % non-negative */
5495 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5500 } else if (part != 5) {
5507 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5510 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5517 struct berval *normalized )
5521 rc = check_time_syntax(val, 1, parts, NULL);
5522 if (rc != LDAP_SUCCESS) {
5526 normalized->bv_val = ch_malloc( 14 );
5527 if ( normalized->bv_val == NULL ) {
5528 return LBER_ERROR_MEMORY;
5531 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5532 parts[1], parts[2] + 1, parts[3] + 1,
5533 parts[4], parts[5], parts[6] );
5534 normalized->bv_len = 13;
5536 return LDAP_SUCCESS;
5546 return check_time_syntax(in, 1, parts, NULL);
5549 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5552 generalizedTimeValidate(
5557 struct berval fraction;
5558 return check_time_syntax(in, 0, parts, &fraction);
5562 generalizedTimeNormalize(
5567 struct berval *normalized,
5572 struct berval fraction;
5574 rc = check_time_syntax(val, 0, parts, &fraction);
5575 if (rc != LDAP_SUCCESS) {
5579 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5580 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5581 if ( BER_BVISNULL( normalized ) ) {
5582 return LBER_ERROR_MEMORY;
5585 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5586 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5587 parts[4], parts[5], parts[6] );
5588 if ( !BER_BVISEMPTY( &fraction ) ) {
5589 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5590 fraction.bv_val, fraction.bv_len );
5591 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5593 strcpy( normalized->bv_val + len-1, "Z" );
5594 normalized->bv_len = len;
5596 return LDAP_SUCCESS;
5600 generalizedTimeOrderingMatch(
5605 struct berval *value,
5606 void *assertedValue )
5608 struct berval *asserted = (struct berval *) assertedValue;
5609 ber_len_t v_len = value->bv_len;
5610 ber_len_t av_len = asserted->bv_len;
5612 /* ignore trailing 'Z' when comparing */
5613 int match = memcmp( value->bv_val, asserted->bv_val,
5614 (v_len < av_len ? v_len : av_len) - 1 );
5615 if ( match == 0 ) match = v_len - av_len;
5618 return LDAP_SUCCESS;
5621 /* Index generation function */
5622 int generalizedTimeIndexer(
5627 struct berval *prefix,
5635 BerValue bvtmp; /* 40 bit index */
5637 struct lutil_timet tt;
5639 bvtmp.bv_len = sizeof(tmp);
5641 for( i=0; values[i].bv_val != NULL; i++ ) {
5642 /* just count them */
5645 /* we should have at least one value at this point */
5648 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5650 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5651 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5652 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5653 /* Use 40 bits of time for key */
5654 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5655 lutil_tm2time( &tm, &tt );
5656 tmp[0] = tt.tt_gsec & 0xff;
5657 tmp[4] = tt.tt_sec & 0xff;
5659 tmp[3] = tt.tt_sec & 0xff;
5661 tmp[2] = tt.tt_sec & 0xff;
5663 tmp[1] = tt.tt_sec & 0xff;
5665 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5669 keys[j].bv_val = NULL;
5674 return LDAP_SUCCESS;
5677 /* Index generation function */
5678 int generalizedTimeFilter(
5683 struct berval *prefix,
5684 void * assertedValue,
5690 BerValue bvtmp; /* 40 bit index */
5691 BerValue *value = (BerValue *) assertedValue;
5693 struct lutil_timet tt;
5695 bvtmp.bv_len = sizeof(tmp);
5697 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5698 /* Use 40 bits of time for key */
5699 if ( value->bv_val && value->bv_len >= 10 &&
5700 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5702 lutil_tm2time( &tm, &tt );
5703 tmp[0] = tt.tt_gsec & 0xff;
5704 tmp[4] = tt.tt_sec & 0xff;
5706 tmp[3] = tt.tt_sec & 0xff;
5708 tmp[2] = tt.tt_sec & 0xff;
5710 tmp[1] = tt.tt_sec & 0xff;
5712 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5713 ber_dupbv_x(keys, &bvtmp, ctx );
5714 keys[1].bv_val = NULL;
5722 return LDAP_SUCCESS;
5726 deliveryMethodValidate(
5728 struct berval *val )
5731 #define LENOF(s) (sizeof(s)-1)
5732 struct berval tmp = *val;
5734 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5735 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5736 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5739 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5741 switch( tmp.bv_val[0] ) {
5744 if(( tmp.bv_len >= LENOF("any") ) &&
5745 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5747 tmp.bv_len -= LENOF("any");
5748 tmp.bv_val += LENOF("any");
5751 return LDAP_INVALID_SYNTAX;
5755 if(( tmp.bv_len >= LENOF("mhs") ) &&
5756 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5758 tmp.bv_len -= LENOF("mhs");
5759 tmp.bv_val += LENOF("mhs");
5762 return LDAP_INVALID_SYNTAX;
5766 if(( tmp.bv_len >= LENOF("physical") ) &&
5767 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5769 tmp.bv_len -= LENOF("physical");
5770 tmp.bv_val += LENOF("physical");
5773 return LDAP_INVALID_SYNTAX;
5776 case 'T': /* telex or teletex or telephone */
5777 if(( tmp.bv_len >= LENOF("telex") ) &&
5778 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5780 tmp.bv_len -= LENOF("telex");
5781 tmp.bv_val += LENOF("telex");
5784 if(( tmp.bv_len >= LENOF("teletex") ) &&
5785 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5787 tmp.bv_len -= LENOF("teletex");
5788 tmp.bv_val += LENOF("teletex");
5791 if(( tmp.bv_len >= LENOF("telephone") ) &&
5792 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5794 tmp.bv_len -= LENOF("telephone");
5795 tmp.bv_val += LENOF("telephone");
5798 return LDAP_INVALID_SYNTAX;
5801 case 'G': /* g3fax or g4fax */
5802 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5803 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5804 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5806 tmp.bv_len -= LENOF("g3fax");
5807 tmp.bv_val += LENOF("g3fax");
5810 return LDAP_INVALID_SYNTAX;
5814 if(( tmp.bv_len >= LENOF("ia5") ) &&
5815 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5817 tmp.bv_len -= LENOF("ia5");
5818 tmp.bv_val += LENOF("ia5");
5821 return LDAP_INVALID_SYNTAX;
5825 if(( tmp.bv_len >= LENOF("videotex") ) &&
5826 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5828 tmp.bv_len -= LENOF("videotex");
5829 tmp.bv_val += LENOF("videotex");
5832 return LDAP_INVALID_SYNTAX;
5835 return LDAP_INVALID_SYNTAX;
5838 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5840 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5844 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5848 return LDAP_INVALID_SYNTAX;
5850 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5859 nisNetgroupTripleValidate(
5861 struct berval *val )
5866 if ( BER_BVISEMPTY( val ) ) {
5867 return LDAP_INVALID_SYNTAX;
5870 p = (char *)val->bv_val;
5871 e = p + val->bv_len;
5873 if ( *p != '(' /*')'*/ ) {
5874 return LDAP_INVALID_SYNTAX;
5877 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5881 return LDAP_INVALID_SYNTAX;
5884 } else if ( !AD_CHAR( *p ) ) {
5885 return LDAP_INVALID_SYNTAX;
5889 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5890 return LDAP_INVALID_SYNTAX;
5896 return LDAP_INVALID_SYNTAX;
5899 return LDAP_SUCCESS;
5903 bootParameterValidate(
5905 struct berval *val )
5909 if ( BER_BVISEMPTY( val ) ) {
5910 return LDAP_INVALID_SYNTAX;
5913 p = (char *)val->bv_val;
5914 e = p + val->bv_len;
5917 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5918 if ( !AD_CHAR( *p ) ) {
5919 return LDAP_INVALID_SYNTAX;
5924 return LDAP_INVALID_SYNTAX;
5928 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5929 if ( !AD_CHAR( *p ) ) {
5930 return LDAP_INVALID_SYNTAX;
5935 return LDAP_INVALID_SYNTAX;
5939 for ( p++; p < e; p++ ) {
5940 if ( !SLAP_PRINTABLE( *p ) ) {
5941 return LDAP_INVALID_SYNTAX;
5945 return LDAP_SUCCESS;
5949 firstComponentNormalize(
5954 struct berval *normalized,
5961 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5962 ber_dupbv_x( normalized, val, ctx );
5963 return LDAP_SUCCESS;
5966 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5968 if( ! ( val->bv_val[0] == '(' /*')'*/
5969 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5970 && ! ( val->bv_val[0] == '{' /*'}'*/
5971 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5973 return LDAP_INVALID_SYNTAX;
5976 /* trim leading white space */
5978 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5984 /* grab next word */
5985 comp.bv_val = &val->bv_val[len];
5986 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5987 for( comp.bv_len = 0;
5988 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5994 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5995 rc = numericoidValidate( NULL, &comp );
5996 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5997 rc = integerValidate( NULL, &comp );
5999 rc = LDAP_INVALID_SYNTAX;
6003 if( rc == LDAP_SUCCESS ) {
6004 ber_dupbv_x( normalized, &comp, ctx );
6010 static char *country_gen_syn[] = {
6011 "1.3.6.1.4.1.1466.115.121.1.15",
6012 "1.3.6.1.4.1.1466.115.121.1.26",
6013 "1.3.6.1.4.1.1466.115.121.1.44",
6017 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6018 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6020 static slap_syntax_defs_rec syntax_defs[] = {
6021 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6022 X_BINARY X_NOT_H_R ")",
6023 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6024 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6025 0, NULL, NULL, NULL},
6026 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6027 0, NULL, NULL, NULL},
6028 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6030 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6031 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6033 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6034 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6035 0, NULL, bitStringValidate, NULL },
6036 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6037 0, NULL, booleanValidate, NULL},
6038 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6039 X_BINARY X_NOT_H_R ")",
6040 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6041 NULL, certificateValidate, NULL},
6042 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6043 X_BINARY X_NOT_H_R ")",
6044 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6045 NULL, certificateListValidate, NULL},
6046 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6047 X_BINARY X_NOT_H_R ")",
6048 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6049 NULL, sequenceValidate, NULL},
6050 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6051 X_BINARY X_NOT_H_R ")",
6052 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6053 NULL, attributeCertificateValidate, NULL},
6054 #if 0 /* need to go __after__ printableString */
6055 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6056 0, "1.3.6.1.4.1.1466.115.121.1.44",
6057 countryStringValidate, NULL},
6059 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6060 0, NULL, dnValidate, dnPretty},
6061 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6062 0, NULL, rdnValidate, rdnPretty},
6063 #ifdef LDAP_COMP_MATCH
6064 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6065 0, NULL, allComponentsValidate, NULL},
6066 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6067 0, NULL, componentFilterValidate, NULL},
6069 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6070 0, NULL, NULL, NULL},
6071 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6072 0, NULL, deliveryMethodValidate, NULL},
6073 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6074 0, NULL, UTF8StringValidate, NULL},
6075 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6076 0, NULL, NULL, NULL},
6077 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6078 0, NULL, NULL, NULL},
6079 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6080 0, NULL, NULL, NULL},
6081 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6082 0, NULL, NULL, NULL},
6083 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6084 0, NULL, NULL, NULL},
6085 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6086 0, NULL, printablesStringValidate, NULL},
6087 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6088 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6089 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6090 0, NULL, generalizedTimeValidate, NULL},
6091 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6092 0, NULL, NULL, NULL},
6093 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6094 0, NULL, IA5StringValidate, NULL},
6095 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6096 0, NULL, integerValidate, NULL},
6097 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6098 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6099 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6100 0, NULL, NULL, NULL},
6101 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6102 0, NULL, NULL, NULL},
6103 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6104 0, NULL, NULL, NULL},
6105 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6106 0, NULL, NULL, NULL},
6107 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6108 0, NULL, NULL, NULL},
6109 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6110 0, NULL, nameUIDValidate, nameUIDPretty },
6111 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6112 0, NULL, NULL, NULL},
6113 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6114 0, NULL, numericStringValidate, NULL},
6115 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6116 0, NULL, NULL, NULL},
6117 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6118 0, NULL, numericoidValidate, NULL},
6119 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6120 0, NULL, IA5StringValidate, NULL},
6121 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6122 0, NULL, blobValidate, NULL},
6123 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6124 0, NULL, postalAddressValidate, NULL},
6125 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6126 0, NULL, NULL, NULL},
6127 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6128 0, NULL, NULL, NULL},
6129 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6130 0, NULL, printableStringValidate, NULL},
6131 /* moved here because now depends on Directory String, IA5 String
6132 * and Printable String */
6133 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6134 0, country_gen_syn, countryStringValidate, NULL},
6135 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6136 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6137 0, NULL, subtreeSpecificationValidate, NULL},
6138 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6139 X_BINARY X_NOT_H_R ")",
6140 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6141 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6142 0, NULL, printableStringValidate, NULL},
6143 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6144 0, NULL, NULL, NULL},
6145 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6146 0, NULL, printablesStringValidate, NULL},
6147 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6148 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6149 0, NULL, utcTimeValidate, NULL},
6151 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6152 0, NULL, NULL, NULL},
6153 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6154 0, NULL, NULL, NULL},
6155 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6156 0, NULL, NULL, NULL},
6157 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6158 0, NULL, NULL, NULL},
6159 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6160 0, NULL, NULL, NULL},
6162 /* RFC 2307 NIS Syntaxes */
6163 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6164 0, NULL, nisNetgroupTripleValidate, NULL},
6165 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6166 0, NULL, bootParameterValidate, NULL},
6168 /* draft-zeilenga-ldap-x509 */
6169 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6170 SLAP_SYNTAX_HIDE, NULL,
6171 serialNumberAndIssuerValidate,
6172 serialNumberAndIssuerPretty},
6173 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6174 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6175 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6176 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6177 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6178 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6179 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6180 SLAP_SYNTAX_HIDE, NULL,
6181 issuerAndThisUpdateValidate,
6182 issuerAndThisUpdatePretty},
6183 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6184 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6185 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6186 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6187 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6188 SLAP_SYNTAX_HIDE, NULL,
6189 serialNumberAndIssuerSerialValidate,
6190 serialNumberAndIssuerSerialPretty},
6191 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6192 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6194 #ifdef SLAPD_AUTHPASSWD
6195 /* needs updating */
6196 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6197 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6200 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6201 0, NULL, UUIDValidate, UUIDPretty},
6203 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6204 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6206 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6207 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6209 /* OpenLDAP Void Syntax */
6210 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6211 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6213 /* FIXME: OID is unused, but not registered yet */
6214 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6215 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6217 {NULL, 0, NULL, NULL, NULL}
6220 char *csnSIDMatchSyntaxes[] = {
6221 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6224 char *certificateExactMatchSyntaxes[] = {
6225 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6228 char *certificateListExactMatchSyntaxes[] = {
6229 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6232 char *attributeCertificateExactMatchSyntaxes[] = {
6233 attributeCertificateSyntaxOID /* attributeCertificate */,
6237 #ifdef LDAP_COMP_MATCH
6238 char *componentFilterMatchSyntaxes[] = {
6239 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6240 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6241 attributeCertificateSyntaxOID /* attributeCertificate */,
6246 char *directoryStringSyntaxes[] = {
6247 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6250 char *integerFirstComponentMatchSyntaxes[] = {
6251 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6252 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6255 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6256 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6257 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6258 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6259 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6260 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6261 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6262 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6263 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6268 * Other matching rules in X.520 that we do not use (yet):
6270 * 2.5.13.25 uTCTimeMatch
6271 * 2.5.13.26 uTCTimeOrderingMatch
6272 * 2.5.13.31* directoryStringFirstComponentMatch
6273 * 2.5.13.32* wordMatch
6274 * 2.5.13.33* keywordMatch
6275 * 2.5.13.36+ certificatePairExactMatch
6276 * 2.5.13.37+ certificatePairMatch
6277 * 2.5.13.40+ algorithmIdentifierMatch
6278 * 2.5.13.41* storedPrefixMatch
6279 * 2.5.13.42 attributeCertificateMatch
6280 * 2.5.13.43 readerAndKeyIDMatch
6281 * 2.5.13.44 attributeIntegrityMatch
6283 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6284 * (+) described in draft-zeilenga-ldap-x509
6286 static slap_mrule_defs_rec mrule_defs[] = {
6288 * EQUALITY matching rules must be listed after associated APPROX
6289 * matching rules. So, we list all APPROX matching rules first.
6291 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6292 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6293 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6294 NULL, NULL, directoryStringApproxMatch,
6295 directoryStringApproxIndexer, directoryStringApproxFilter,
6298 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6299 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6300 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6301 NULL, NULL, IA5StringApproxMatch,
6302 IA5StringApproxIndexer, IA5StringApproxFilter,
6306 * Other matching rules
6309 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6310 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6311 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6312 NULL, NULL, octetStringMatch,
6313 octetStringIndexer, octetStringFilter,
6316 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6317 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6318 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6319 NULL, dnNormalize, dnMatch,
6320 octetStringIndexer, octetStringFilter,
6323 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6324 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6325 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6326 NULL, dnNormalize, dnRelativeMatch,
6330 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6331 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6332 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6333 NULL, dnNormalize, dnRelativeMatch,
6337 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6338 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6339 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6340 NULL, dnNormalize, dnRelativeMatch,
6344 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6345 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6346 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6347 NULL, dnNormalize, dnRelativeMatch,
6351 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6352 "SYNTAX 1.2.36.79672281.1.5.0 )",
6353 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6354 NULL, rdnNormalize, rdnMatch,
6355 octetStringIndexer, octetStringFilter,
6358 #ifdef LDAP_COMP_MATCH
6359 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6360 "SYNTAX 1.2.36.79672281.1.5.2 )",
6361 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6362 NULL, NULL , componentFilterMatch,
6363 octetStringIndexer, octetStringFilter,
6366 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6367 "SYNTAX 1.2.36.79672281.1.5.3 )",
6368 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6369 NULL, NULL , allComponentsMatch,
6370 octetStringIndexer, octetStringFilter,
6373 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6374 "SYNTAX 1.2.36.79672281.1.5.3 )",
6375 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6376 NULL, NULL , directoryComponentsMatch,
6377 octetStringIndexer, octetStringFilter,
6381 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6382 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6383 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6384 NULL, UTF8StringNormalize, octetStringMatch,
6385 octetStringIndexer, octetStringFilter,
6386 directoryStringApproxMatchOID },
6388 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6389 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6390 SLAP_MR_ORDERING, directoryStringSyntaxes,
6391 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6393 "caseIgnoreMatch" },
6395 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6396 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6397 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6398 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6399 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6400 "caseIgnoreMatch" },
6402 {"( 2.5.13.5 NAME 'caseExactMatch' "
6403 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6404 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6405 NULL, UTF8StringNormalize, octetStringMatch,
6406 octetStringIndexer, octetStringFilter,
6407 directoryStringApproxMatchOID },
6409 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6410 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6411 SLAP_MR_ORDERING, directoryStringSyntaxes,
6412 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6416 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6417 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6418 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6419 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6420 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6423 {"( 2.5.13.8 NAME 'numericStringMatch' "
6424 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6425 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6426 NULL, numericStringNormalize, octetStringMatch,
6427 octetStringIndexer, octetStringFilter,
6430 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6432 SLAP_MR_ORDERING, NULL,
6433 NULL, numericStringNormalize, octetStringOrderingMatch,
6435 "numericStringMatch" },
6437 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6438 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6439 SLAP_MR_SUBSTR, NULL,
6440 NULL, numericStringNormalize, octetStringSubstringsMatch,
6441 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6442 "numericStringMatch" },
6444 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6445 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6446 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6447 NULL, postalAddressNormalize, octetStringMatch,
6448 octetStringIndexer, octetStringFilter,
6451 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6453 SLAP_MR_SUBSTR, NULL,
6454 NULL, NULL, NULL, NULL, NULL,
6455 "caseIgnoreListMatch" },
6457 {"( 2.5.13.13 NAME 'booleanMatch' "
6458 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6459 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6460 NULL, NULL, booleanMatch,
6461 octetStringIndexer, octetStringFilter,
6464 {"( 2.5.13.14 NAME 'integerMatch' "
6465 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6466 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6467 NULL, NULL, integerMatch,
6468 integerIndexer, integerFilter,
6471 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6472 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6473 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6474 NULL, NULL, integerMatch,
6478 {"( 2.5.13.16 NAME 'bitStringMatch' "
6479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6480 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6481 NULL, NULL, octetStringMatch,
6482 octetStringIndexer, octetStringFilter,
6485 {"( 2.5.13.17 NAME 'octetStringMatch' "
6486 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6487 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6488 NULL, NULL, octetStringMatch,
6489 octetStringIndexer, octetStringFilter,
6492 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6493 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6494 SLAP_MR_ORDERING, NULL,
6495 NULL, NULL, octetStringOrderingMatch,
6497 "octetStringMatch" },
6499 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6500 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6501 SLAP_MR_SUBSTR, NULL,
6502 NULL, NULL, octetStringSubstringsMatch,
6503 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6504 "octetStringMatch" },
6506 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6507 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6508 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6510 telephoneNumberNormalize, octetStringMatch,
6511 octetStringIndexer, octetStringFilter,
6514 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6515 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6516 SLAP_MR_SUBSTR, NULL,
6517 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6518 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6519 "telephoneNumberMatch" },
6521 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6522 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6523 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6524 NULL, NULL, NULL, NULL, NULL, NULL },
6526 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6527 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6528 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6529 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6530 uniqueMemberIndexer, uniqueMemberFilter,
6533 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6534 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6535 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6536 NULL, NULL, NULL, NULL, NULL, NULL },
6538 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6539 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6540 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6541 NULL, generalizedTimeNormalize, octetStringMatch,
6542 generalizedTimeIndexer, generalizedTimeFilter,
6545 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6546 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6547 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6548 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6550 "generalizedTimeMatch" },
6552 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6553 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6554 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6555 integerFirstComponentMatchSyntaxes,
6556 NULL, firstComponentNormalize, integerMatch,
6557 octetStringIndexer, octetStringFilter,
6560 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6561 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6562 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6563 objectIdentifierFirstComponentMatchSyntaxes,
6564 NULL, firstComponentNormalize, octetStringMatch,
6565 octetStringIndexer, octetStringFilter,
6568 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6569 "SYNTAX 1.3.6.1.1.15.1 )",
6570 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6571 NULL, certificateExactNormalize, octetStringMatch,
6572 octetStringIndexer, octetStringFilter,
6575 {"( 2.5.13.35 NAME 'certificateMatch' "
6576 "SYNTAX 1.3.6.1.1.15.2 )",
6577 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6578 NULL, NULL, NULL, NULL, NULL,
6581 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6582 "SYNTAX 1.3.6.1.1.15.5 )",
6583 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6584 NULL, certificateListExactNormalize, octetStringMatch,
6585 octetStringIndexer, octetStringFilter,
6588 {"( 2.5.13.39 NAME 'certificateListMatch' "
6589 "SYNTAX 1.3.6.1.1.15.6 )",
6590 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6591 NULL, NULL, NULL, NULL, NULL,
6594 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6595 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6596 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6597 NULL, attributeCertificateExactNormalize, octetStringMatch,
6598 octetStringIndexer, octetStringFilter,
6601 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6602 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6603 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6604 NULL, NULL, NULL, NULL, NULL,
6607 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6608 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6609 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6610 NULL, IA5StringNormalize, octetStringMatch,
6611 octetStringIndexer, octetStringFilter,
6612 IA5StringApproxMatchOID },
6614 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6615 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6616 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6617 NULL, IA5StringNormalize, octetStringMatch,
6618 octetStringIndexer, octetStringFilter,
6619 IA5StringApproxMatchOID },
6621 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6622 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6623 SLAP_MR_SUBSTR, NULL,
6624 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6625 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6626 "caseIgnoreIA5Match" },
6628 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6629 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6630 SLAP_MR_SUBSTR, NULL,
6631 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6632 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6633 "caseExactIA5Match" },
6635 #ifdef SLAPD_AUTHPASSWD
6636 /* needs updating */
6637 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6638 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6639 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6640 NULL, NULL, authPasswordMatch,
6645 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6646 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6648 NULL, NULL, integerBitAndMatch,
6652 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6653 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6655 NULL, NULL, integerBitOrMatch,
6659 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6660 "SYNTAX 1.3.6.1.1.16.1 )",
6661 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6662 NULL, UUIDNormalize, octetStringMatch,
6663 octetStringIndexer, octetStringFilter,
6666 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6667 "SYNTAX 1.3.6.1.1.16.1 )",
6668 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6669 NULL, UUIDNormalize, octetStringOrderingMatch,
6670 octetStringIndexer, octetStringFilter,
6673 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6674 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6675 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6676 NULL, csnNormalize, csnMatch,
6677 csnIndexer, csnFilter,
6680 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6681 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6682 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6683 NULL, csnNormalize, csnOrderingMatch,
6687 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6688 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6689 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6690 NULL, csnSidNormalize, octetStringMatch,
6691 octetStringIndexer, octetStringFilter,
6694 /* FIXME: OID is unused, but not registered yet */
6695 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6696 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6697 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6698 NULL, authzNormalize, authzMatch,
6702 {NULL, SLAP_MR_NONE, NULL,
6703 NULL, NULL, NULL, NULL, NULL,
6708 slap_schema_init( void )
6713 /* we should only be called once (from main) */
6714 assert( schema_init_done == 0 );
6716 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6717 res = register_syntax( &syntax_defs[i] );
6720 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6721 syntax_defs[i].sd_desc );
6726 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6727 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6728 mrule_defs[i].mrd_compat_syntaxes == NULL )
6731 "slap_schema_init: Ignoring unusable matching rule %s\n",
6732 mrule_defs[i].mrd_desc );
6736 res = register_matching_rule( &mrule_defs[i] );
6740 "slap_schema_init: Error registering matching rule %s\n",
6741 mrule_defs[i].mrd_desc );
6746 res = slap_schema_load();
6747 schema_init_done = 1;
6752 schema_destroy( void )
6761 if( schema_init_done ) {
6762 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6763 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );