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 ) {
329 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
330 /* Should NOT be empty */
331 ber_skip_data( ber, len );
332 tag = ber_skip_tag( ber, &len );
335 /* Optional Extensions - Sequence of Sequence */
336 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
338 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
339 tag = ber_peek_tag( ber, &seqlen );
340 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
341 ber_skip_data( ber, len );
342 tag = ber_skip_tag( ber, &len );
344 /* signatureAlgorithm */
345 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
346 ber_skip_data( ber, len );
347 tag = ber_skip_tag( ber, &len );
349 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
350 ber_skip_data( ber, len );
351 if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
352 tag = ber_skip_tag( ber, &len );
353 /* Must be at end now */
354 /* NOTE: OpenSSL tolerates CL with garbage past the end */
355 if ( len || tag != LBER_DEFAULT ) {
356 struct berval issuer_dn = BER_BVNULL, thisUpdate;
357 char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
360 if ( ! wrapper_ok ) {
361 return LDAP_INVALID_SYNTAX;
364 rc = dnX509normalize( &bvdn, &issuer_dn );
365 if ( rc != LDAP_SUCCESS ) {
366 rc = LDAP_INVALID_SYNTAX;
370 thisUpdate.bv_val = tubuf;
371 thisUpdate.bv_len = sizeof(tubuf);
372 if ( checkTime( &bvtu, &thisUpdate ) ) {
373 rc = LDAP_INVALID_SYNTAX;
377 Debug( LDAP_DEBUG_ANY,
378 "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
379 issuer_dn.bv_val, thisUpdate.bv_val, 0 );
382 if ( ! BER_BVISNULL( &issuer_dn ) ) {
383 ber_memfree( issuer_dn.bv_val );
392 /* X.509 PMI Attribute Certificate Validate */
394 attributeCertificateValidate( Syntax *syntax, struct berval *in )
396 BerElementBuffer berbuf;
397 BerElement *ber = (BerElement *)&berbuf;
403 ber_init2( ber, in, LBER_USE_DER );
405 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
406 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
408 tag = ber_skip_tag( ber, &len ); /* Sequence */
409 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
411 tag = ber_peek_tag( ber, &len ); /* Version */
412 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
413 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
414 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
416 tag = ber_skip_tag( ber, &len ); /* Holder */
417 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
418 ber_skip_data( ber, len );
420 tag = ber_skip_tag( ber, &len ); /* Issuer */
421 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
422 ber_skip_data( ber, len );
424 tag = ber_skip_tag( ber, &len ); /* Signature */
425 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
426 ber_skip_data( ber, len );
428 tag = ber_skip_tag( ber, &len ); /* Serial number */
429 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
430 ber_skip_data( ber, len );
432 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
433 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
434 ber_skip_data( ber, len );
436 tag = ber_skip_tag( ber, &len ); /* Attributes */
437 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
438 ber_skip_data( ber, len );
440 tag = ber_peek_tag( ber, &len );
442 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
443 tag = ber_skip_tag( ber, &len );
444 ber_skip_data( ber, len );
445 tag = ber_peek_tag( ber, &len );
448 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
449 tag = ber_skip_tag( ber, &len );
450 ber_skip_data( ber, len );
452 tag = ber_peek_tag( ber, &len );
455 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
456 tag = ber_skip_tag( ber, &len );
457 ber_skip_data( ber, len );
459 tag = ber_peek_tag( ber, &len );
462 if ( tag == LBER_BITSTRING ) { /* Signature */
463 tag = ber_skip_tag( ber, &len );
464 ber_skip_data( ber, len );
466 tag = ber_peek_tag( ber, &len );
469 /* Must be at end now */
470 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
481 struct berval *value,
482 void *assertedValue )
484 struct berval *asserted = (struct berval *) assertedValue;
485 int match = value->bv_len - asserted->bv_len;
488 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
496 octetStringOrderingMatch(
501 struct berval *value,
502 void *assertedValue )
504 struct berval *asserted = (struct berval *) assertedValue;
505 ber_len_t v_len = value->bv_len;
506 ber_len_t av_len = asserted->bv_len;
508 int match = memcmp( value->bv_val, asserted->bv_val,
509 (v_len < av_len ? v_len : av_len) );
511 if( match == 0 ) match = v_len - av_len;
519 HASH_CONTEXT *HASHcontext,
520 struct berval *prefix,
525 HASH_Init(HASHcontext);
526 if(prefix && prefix->bv_len > 0) {
527 HASH_Update(HASHcontext,
528 (unsigned char *)prefix->bv_val, prefix->bv_len);
530 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
531 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
532 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
538 HASH_CONTEXT *HASHcontext,
539 unsigned char *HASHdigest,
540 unsigned char *value,
543 HASH_CONTEXT ctx = *HASHcontext;
544 HASH_Update( &ctx, value, len );
545 HASH_Final( HASHdigest, &ctx );
548 /* Index generation function */
549 int octetStringIndexer(
554 struct berval *prefix,
562 HASH_CONTEXT HASHcontext;
563 unsigned char HASHdigest[HASH_BYTES];
564 struct berval digest;
565 digest.bv_val = (char *)HASHdigest;
566 digest.bv_len = sizeof(HASHdigest);
568 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
569 /* just count them */
572 /* we should have at least one value at this point */
575 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
577 slen = syntax->ssyn_oidlen;
578 mlen = mr->smr_oidlen;
580 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
581 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
582 hashIter( &HASHcontext, HASHdigest,
583 (unsigned char *)values[i].bv_val, values[i].bv_len );
584 ber_dupbv_x( &keys[i], &digest, ctx );
587 BER_BVZERO( &keys[i] );
594 /* Index generation function */
595 int octetStringFilter(
600 struct berval *prefix,
601 void * assertedValue,
607 HASH_CONTEXT HASHcontext;
608 unsigned char HASHdigest[HASH_BYTES];
609 struct berval *value = (struct berval *) assertedValue;
610 struct berval digest;
611 digest.bv_val = (char *)HASHdigest;
612 digest.bv_len = sizeof(HASHdigest);
614 slen = syntax->ssyn_oidlen;
615 mlen = mr->smr_oidlen;
617 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
619 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
620 hashIter( &HASHcontext, HASHdigest,
621 (unsigned char *)value->bv_val, value->bv_len );
623 ber_dupbv_x( keys, &digest, ctx );
624 BER_BVZERO( &keys[1] );
632 octetStringSubstringsMatch(
637 struct berval *value,
638 void *assertedValue )
641 SubstringsAssertion *sub = assertedValue;
642 struct berval left = *value;
646 /* Add up asserted input length */
647 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
648 inlen += sub->sa_initial.bv_len;
651 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
652 inlen += sub->sa_any[i].bv_len;
655 if ( !BER_BVISNULL( &sub->sa_final ) ) {
656 inlen += sub->sa_final.bv_len;
659 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
660 if ( inlen > left.bv_len ) {
665 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
666 sub->sa_initial.bv_len );
672 left.bv_val += sub->sa_initial.bv_len;
673 left.bv_len -= sub->sa_initial.bv_len;
674 inlen -= sub->sa_initial.bv_len;
677 if ( !BER_BVISNULL( &sub->sa_final ) ) {
678 if ( inlen > left.bv_len ) {
683 match = memcmp( sub->sa_final.bv_val,
684 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
685 sub->sa_final.bv_len );
691 left.bv_len -= sub->sa_final.bv_len;
692 inlen -= sub->sa_final.bv_len;
696 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
701 if ( inlen > left.bv_len ) {
702 /* not enough length */
707 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
711 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
718 idx = p - left.bv_val;
720 if ( idx >= left.bv_len ) {
721 /* this shouldn't happen */
728 if ( sub->sa_any[i].bv_len > left.bv_len ) {
729 /* not enough left */
734 match = memcmp( left.bv_val,
735 sub->sa_any[i].bv_val,
736 sub->sa_any[i].bv_len );
744 left.bv_val += sub->sa_any[i].bv_len;
745 left.bv_len -= sub->sa_any[i].bv_len;
746 inlen -= sub->sa_any[i].bv_len;
755 /* Substrings Index generation function */
757 octetStringSubstringsIndexer(
762 struct berval *prefix,
771 HASH_CONTEXT HCany, HCini, HCfin;
772 unsigned char HASHdigest[HASH_BYTES];
773 struct berval digest;
774 digest.bv_val = (char *)HASHdigest;
775 digest.bv_len = sizeof(HASHdigest);
779 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
780 /* count number of indices to generate */
781 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
782 if( values[i].bv_len >= index_substr_if_maxlen ) {
783 nkeys += index_substr_if_maxlen -
784 (index_substr_if_minlen - 1);
785 } else if( values[i].bv_len >= index_substr_if_minlen ) {
786 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
790 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
791 if( values[i].bv_len >= index_substr_any_len ) {
792 nkeys += values[i].bv_len - (index_substr_any_len - 1);
796 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
797 if( values[i].bv_len >= index_substr_if_maxlen ) {
798 nkeys += index_substr_if_maxlen -
799 (index_substr_if_minlen - 1);
800 } else if( values[i].bv_len >= index_substr_if_minlen ) {
801 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
807 /* no keys to generate */
812 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
814 slen = syntax->ssyn_oidlen;
815 mlen = mr->smr_oidlen;
817 if ( flags & SLAP_INDEX_SUBSTR_ANY )
818 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
819 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
820 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
821 if( flags & SLAP_INDEX_SUBSTR_FINAL )
822 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
825 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
828 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
829 ( values[i].bv_len >= index_substr_any_len ) )
831 max = values[i].bv_len - (index_substr_any_len - 1);
833 for( j=0; j<max; j++ ) {
834 hashIter( &HCany, HASHdigest,
835 (unsigned char *)&values[i].bv_val[j],
836 index_substr_any_len );
837 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
841 /* skip if too short */
842 if( values[i].bv_len < index_substr_if_minlen ) continue;
844 max = index_substr_if_maxlen < values[i].bv_len
845 ? index_substr_if_maxlen : values[i].bv_len;
847 for( j=index_substr_if_minlen; j<=max; j++ ) {
849 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
850 hashIter( &HCini, HASHdigest,
851 (unsigned char *)values[i].bv_val, j );
852 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
855 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
856 hashIter( &HCfin, HASHdigest,
857 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
858 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
865 BER_BVZERO( &keys[nkeys] );
876 octetStringSubstringsFilter (
881 struct berval *prefix,
882 void * assertedValue,
886 SubstringsAssertion *sa;
889 size_t slen, mlen, klen;
891 HASH_CONTEXT HASHcontext;
892 unsigned char HASHdigest[HASH_BYTES];
893 struct berval *value;
894 struct berval digest;
896 sa = (SubstringsAssertion *) assertedValue;
898 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
899 !BER_BVISNULL( &sa->sa_initial ) &&
900 sa->sa_initial.bv_len >= index_substr_if_minlen )
903 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
904 ( flags & SLAP_INDEX_SUBSTR_ANY ))
906 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
910 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
912 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
913 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
914 /* don't bother accounting with stepping */
915 nkeys += sa->sa_any[i].bv_len -
916 ( index_substr_any_len - 1 );
921 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
922 !BER_BVISNULL( &sa->sa_final ) &&
923 sa->sa_final.bv_len >= index_substr_if_minlen )
926 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
927 ( flags & SLAP_INDEX_SUBSTR_ANY ))
929 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
938 digest.bv_val = (char *)HASHdigest;
939 digest.bv_len = sizeof(HASHdigest);
941 slen = syntax->ssyn_oidlen;
942 mlen = mr->smr_oidlen;
944 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
947 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
948 !BER_BVISNULL( &sa->sa_initial ) &&
949 sa->sa_initial.bv_len >= index_substr_if_minlen )
951 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
952 value = &sa->sa_initial;
954 klen = index_substr_if_maxlen < value->bv_len
955 ? index_substr_if_maxlen : value->bv_len;
957 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
958 hashIter( &HASHcontext, HASHdigest,
959 (unsigned char *)value->bv_val, klen );
960 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
962 /* If initial is too long and we have subany indexed, use it
963 * to match the excess...
965 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
968 pre = SLAP_INDEX_SUBSTR_PREFIX;
969 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
970 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
972 hashIter( &HASHcontext, HASHdigest,
973 (unsigned char *)&value->bv_val[j], index_substr_any_len );
974 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
979 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
981 pre = SLAP_INDEX_SUBSTR_PREFIX;
982 klen = index_substr_any_len;
984 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
985 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
989 value = &sa->sa_any[i];
991 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
993 j <= value->bv_len - index_substr_any_len;
994 j += index_substr_any_step )
996 hashIter( &HASHcontext, HASHdigest,
997 (unsigned char *)&value->bv_val[j], klen );
998 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1003 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
1004 !BER_BVISNULL( &sa->sa_final ) &&
1005 sa->sa_final.bv_len >= index_substr_if_minlen )
1007 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1008 value = &sa->sa_final;
1010 klen = index_substr_if_maxlen < value->bv_len
1011 ? index_substr_if_maxlen : value->bv_len;
1013 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
1014 hashIter( &HASHcontext, HASHdigest,
1015 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
1016 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1018 /* If final is too long and we have subany indexed, use it
1019 * to match the excess...
1021 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
1024 pre = SLAP_INDEX_SUBSTR_PREFIX;
1025 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
1026 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
1028 hashIter( &HASHcontext, HASHdigest,
1029 (unsigned char *)&value->bv_val[j], index_substr_any_len );
1030 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
1036 BER_BVZERO( &keys[nkeys] );
1043 return LDAP_SUCCESS;
1053 /* very unforgiving validation, requires no normalization
1054 * before simplistic matching
1056 if( in->bv_len < 3 ) {
1057 return LDAP_INVALID_SYNTAX;
1060 /* RFC 4517 Section 3.3.2 Bit String:
1061 * BitString = SQUOTE *binary-digit SQUOTE "B"
1062 * binary-digit = "0" / "1"
1064 * where SQUOTE [RFC4512] is
1065 * SQUOTE = %x27 ; single quote ("'")
1067 * Example: '0101111101'B
1070 if( in->bv_val[0] != '\'' ||
1071 in->bv_val[in->bv_len - 2] != '\'' ||
1072 in->bv_val[in->bv_len - 1] != 'B' )
1074 return LDAP_INVALID_SYNTAX;
1077 for( i = in->bv_len - 3; i > 0; i-- ) {
1078 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1079 return LDAP_INVALID_SYNTAX;
1083 return LDAP_SUCCESS;
1087 * Syntaxes from RFC 4517
1092 A value of the Bit String syntax is a sequence of binary digits. The
1093 LDAP-specific encoding of a value of this syntax is defined by the
1096 BitString = SQUOTE *binary-digit SQUOTE "B"
1098 binary-digit = "0" / "1"
1100 The <SQUOTE> rule is defined in [MODELS].
1105 The LDAP definition for the Bit String syntax is:
1107 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1109 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1113 3.3.21. Name and Optional UID
1115 A value of the Name and Optional UID syntax is the distinguished name
1116 [MODELS] of an entity optionally accompanied by a unique identifier
1117 that serves to differentiate the entity from others with an identical
1120 The LDAP-specific encoding of a value of this syntax is defined by
1123 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1125 The <BitString> rule is defined in Section 3.3.2. The
1126 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1127 defined in [MODELS].
1129 Note that although the '#' character may occur in the string
1130 representation of a distinguished name, no additional escaping of
1131 this character is performed when a <distinguishedName> is encoded in
1132 a <NameAndOptionalUID>.
1135 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1137 The LDAP definition for the Name and Optional UID syntax is:
1139 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1141 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1148 1.4. Common ABNF Productions
1151 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1153 SQUOTE = %x27 ; single quote ("'")
1158 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1159 * be escaped except when at the beginning of a value, the
1160 * definition of Name and Optional UID appears to be flawed,
1161 * because there is no clear means to determine whether the
1162 * UID part is present or not.
1166 * cn=Someone,dc=example,dc=com#'1'B
1168 * could be either a NameAndOptionalUID with trailing UID, i.e.
1170 * DN = "cn=Someone,dc=example,dc=com"
1173 * or a NameAndOptionalUID with no trailing UID, and the AVA
1174 * in the last RDN made of
1176 * attributeType = dc
1177 * attributeValue = com#'1'B
1179 * in fact "com#'1'B" is a valid IA5 string.
1181 * As a consequence, current slapd code takes the presence of
1182 * #<valid BitString> at the end of the string representation
1183 * of a NameAndOptionalUID to mean this is indeed a BitString.
1184 * This is quite arbitrary - it has changed the past and might
1185 * change in the future.
1195 struct berval dn, uid;
1197 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1199 ber_dupbv( &dn, in );
1200 if( !dn.bv_val ) return LDAP_OTHER;
1202 /* if there's a "#", try bitStringValidate()... */
1203 uid.bv_val = strrchr( dn.bv_val, '#' );
1204 if ( !BER_BVISNULL( &uid ) ) {
1206 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1208 rc = bitStringValidate( NULL, &uid );
1209 if ( rc == LDAP_SUCCESS ) {
1210 /* in case of success, trim the UID,
1211 * otherwise treat it as part of the DN */
1212 dn.bv_len -= uid.bv_len + 1;
1213 uid.bv_val[-1] = '\0';
1217 rc = dnValidate( NULL, &dn );
1219 ber_memfree( dn.bv_val );
1230 assert( val != NULL );
1231 assert( out != NULL );
1234 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1236 if( BER_BVISEMPTY( val ) ) {
1237 ber_dupbv_x( out, val, ctx );
1239 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1240 return LDAP_INVALID_SYNTAX;
1244 struct berval dnval = *val;
1245 struct berval uidval = BER_BVNULL;
1247 uidval.bv_val = strrchr( val->bv_val, '#' );
1248 if ( !BER_BVISNULL( &uidval ) ) {
1250 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1252 rc = bitStringValidate( NULL, &uidval );
1254 if ( rc == LDAP_SUCCESS ) {
1255 ber_dupbv_x( &dnval, val, ctx );
1257 dnval.bv_len -= ++uidval.bv_len;
1258 dnval.bv_val[dnval.bv_len] = '\0';
1261 BER_BVZERO( &uidval );
1265 rc = dnPretty( syntax, &dnval, out, ctx );
1266 if ( dnval.bv_val != val->bv_val ) {
1267 slap_sl_free( dnval.bv_val, ctx );
1269 if( rc != LDAP_SUCCESS ) {
1273 if( !BER_BVISNULL( &uidval ) ) {
1276 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1277 + uidval.bv_len + 1,
1280 ber_memfree_x( out->bv_val, ctx );
1284 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1285 out->bv_len += uidval.bv_len;
1286 out->bv_val[out->bv_len] = '\0';
1290 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1292 return LDAP_SUCCESS;
1296 uniqueMemberNormalize(
1301 struct berval *normalized,
1307 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1309 ber_dupbv_x( &out, val, ctx );
1310 if ( BER_BVISEMPTY( &out ) ) {
1314 struct berval uid = BER_BVNULL;
1316 uid.bv_val = strrchr( out.bv_val, '#' );
1317 if ( !BER_BVISNULL( &uid ) ) {
1319 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1321 rc = bitStringValidate( NULL, &uid );
1322 if ( rc == LDAP_SUCCESS ) {
1323 uid.bv_val[-1] = '\0';
1324 out.bv_len -= uid.bv_len + 1;
1330 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1332 if( rc != LDAP_SUCCESS ) {
1333 slap_sl_free( out.bv_val, ctx );
1334 return LDAP_INVALID_SYNTAX;
1337 if( !BER_BVISNULL( &uid ) ) {
1340 tmp = ch_realloc( normalized->bv_val,
1341 normalized->bv_len + uid.bv_len
1342 + STRLENOF("#") + 1 );
1343 if ( tmp == NULL ) {
1344 ber_memfree_x( normalized->bv_val, ctx );
1348 normalized->bv_val = tmp;
1350 /* insert the separator */
1351 normalized->bv_val[normalized->bv_len++] = '#';
1353 /* append the UID */
1354 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1355 uid.bv_val, uid.bv_len );
1356 normalized->bv_len += uid.bv_len;
1359 normalized->bv_val[normalized->bv_len] = '\0';
1362 slap_sl_free( out.bv_val, ctx );
1365 return LDAP_SUCCESS;
1374 struct berval *value,
1375 void *assertedValue )
1378 struct berval *asserted = (struct berval *) assertedValue;
1379 struct berval assertedDN = *asserted;
1380 struct berval assertedUID = BER_BVNULL;
1381 struct berval valueDN = *value;
1382 struct berval valueUID = BER_BVNULL;
1383 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1385 if ( !BER_BVISEMPTY( asserted ) ) {
1386 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1387 if ( !BER_BVISNULL( &assertedUID ) ) {
1388 assertedUID.bv_val++;
1389 assertedUID.bv_len = assertedDN.bv_len
1390 - ( assertedUID.bv_val - assertedDN.bv_val );
1392 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1393 assertedDN.bv_len -= assertedUID.bv_len + 1;
1396 BER_BVZERO( &assertedUID );
1401 if ( !BER_BVISEMPTY( value ) ) {
1403 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1404 if ( !BER_BVISNULL( &valueUID ) ) {
1406 valueUID.bv_len = valueDN.bv_len
1407 - ( valueUID.bv_val - valueDN.bv_val );
1409 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1410 valueDN.bv_len -= valueUID.bv_len + 1;
1413 BER_BVZERO( &valueUID );
1418 if( valueUID.bv_len && assertedUID.bv_len ) {
1419 match = valueUID.bv_len - assertedUID.bv_len;
1422 return LDAP_SUCCESS;
1425 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1428 return LDAP_SUCCESS;
1431 } else if ( !approx && valueUID.bv_len ) {
1434 return LDAP_SUCCESS;
1436 } else if ( !approx && assertedUID.bv_len ) {
1439 return LDAP_SUCCESS;
1442 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1446 uniqueMemberIndexer(
1451 struct berval *prefix,
1459 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1460 /* just count them */
1464 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1466 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1467 struct berval assertedDN = values[i];
1468 struct berval assertedUID = BER_BVNULL;
1470 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1471 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1472 if ( !BER_BVISNULL( &assertedUID ) ) {
1473 assertedUID.bv_val++;
1474 assertedUID.bv_len = assertedDN.bv_len
1475 - ( assertedUID.bv_val - assertedDN.bv_val );
1477 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1478 assertedDN.bv_len -= assertedUID.bv_len + 1;
1481 BER_BVZERO( &assertedUID );
1486 dnvalues[i] = assertedDN;
1488 BER_BVZERO( &dnvalues[i] );
1490 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1491 dnvalues, keysp, ctx );
1493 slap_sl_free( dnvalues, ctx );
1503 struct berval *prefix,
1504 void * assertedValue,
1508 struct berval *asserted = (struct berval *) assertedValue;
1509 struct berval assertedDN = *asserted;
1510 struct berval assertedUID = BER_BVNULL;
1512 if ( !BER_BVISEMPTY( asserted ) ) {
1513 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1514 if ( !BER_BVISNULL( &assertedUID ) ) {
1515 assertedUID.bv_val++;
1516 assertedUID.bv_len = assertedDN.bv_len
1517 - ( assertedUID.bv_val - assertedDN.bv_val );
1519 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1520 assertedDN.bv_len -= assertedUID.bv_len + 1;
1523 BER_BVZERO( &assertedUID );
1528 return octetStringFilter( use, flags, syntax, mr, prefix,
1529 &assertedDN, keysp, ctx );
1534 * Handling boolean syntax and matching is quite rigid.
1535 * A more flexible approach would be to allow a variety
1536 * of strings to be normalized and prettied into TRUE
1544 /* very unforgiving validation, requires no normalization
1545 * before simplistic matching
1548 if( in->bv_len == 4 ) {
1549 if( bvmatch( in, &slap_true_bv ) ) {
1550 return LDAP_SUCCESS;
1552 } else if( in->bv_len == 5 ) {
1553 if( bvmatch( in, &slap_false_bv ) ) {
1554 return LDAP_SUCCESS;
1558 return LDAP_INVALID_SYNTAX;
1567 struct berval *value,
1568 void *assertedValue )
1570 /* simplistic matching allowed by rigid validation */
1571 struct berval *asserted = (struct berval *) assertedValue;
1572 *matchp = value->bv_len != asserted->bv_len;
1573 return LDAP_SUCCESS;
1576 /*-------------------------------------------------------------------
1577 LDAP/X.500 string syntax / matching rules have a few oddities. This
1578 comment attempts to detail how slapd(8) treats them.
1581 StringSyntax X.500 LDAP Matching/Comments
1582 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1583 PrintableString subset subset i/e + ignore insignificant spaces
1584 PrintableString subset subset i/e + ignore insignificant spaces
1585 NumericString subset subset ignore all spaces
1586 IA5String ASCII ASCII i/e + ignore insignificant spaces
1587 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1589 TelephoneNumber subset subset i + ignore all spaces and "-"
1591 See RFC 4518 for details.
1595 In X.500(93), a directory string can be either a PrintableString,
1596 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1597 In later versions, more CHOICEs were added. In all cases the string
1600 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1601 A directory string cannot be zero length.
1603 For matching, there are both case ignore and exact rules. Both
1604 also require that "insignificant" spaces be ignored.
1605 spaces before the first non-space are ignored;
1606 spaces after the last non-space are ignored;
1607 spaces after a space are ignored.
1608 Note: by these rules (and as clarified in X.520), a string of only
1609 spaces is to be treated as if held one space, not empty (which
1610 would be a syntax error).
1613 In ASN.1, numeric string is just a string of digits and spaces
1614 and could be empty. However, in X.500, all attribute values of
1615 numeric string carry a non-empty constraint. For example:
1617 internationalISDNNumber ATTRIBUTE ::= {
1618 WITH SYNTAX InternationalISDNNumber
1619 EQUALITY MATCHING RULE numericStringMatch
1620 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1621 ID id-at-internationalISDNNumber }
1622 InternationalISDNNumber ::=
1623 NumericString (SIZE(1..ub-international-isdn-number))
1625 Unforunately, some assertion values are don't carry the same
1626 constraint (but its unclear how such an assertion could ever
1627 be true). In LDAP, there is one syntax (numericString) not two
1628 (numericString with constraint, numericString without constraint).
1629 This should be treated as numericString with non-empty constraint.
1630 Note that while someone may have no ISDN number, there are no ISDN
1631 numbers which are zero length.
1633 In matching, spaces are ignored.
1636 In ASN.1, Printable string is just a string of printable characters
1637 and can be empty. In X.500, semantics much like NumericString (see
1638 serialNumber for a like example) excepting uses insignificant space
1639 handling instead of ignore all spaces. They must be non-empty.
1642 Basically same as PrintableString. There are no examples in X.500,
1643 but same logic applies. Empty strings are allowed.
1645 -------------------------------------------------------------------*/
1654 unsigned char *u = (unsigned char *)in->bv_val;
1656 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1657 /* directory strings cannot be empty */
1658 return LDAP_INVALID_SYNTAX;
1661 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1662 /* get the length indicated by the first byte */
1663 len = LDAP_UTF8_CHARLEN2( u, len );
1665 /* very basic checks */
1668 if( (u[5] & 0xC0) != 0x80 ) {
1669 return LDAP_INVALID_SYNTAX;
1672 if( (u[4] & 0xC0) != 0x80 ) {
1673 return LDAP_INVALID_SYNTAX;
1676 if( (u[3] & 0xC0) != 0x80 ) {
1677 return LDAP_INVALID_SYNTAX;
1680 if( (u[2] & 0xC0 )!= 0x80 ) {
1681 return LDAP_INVALID_SYNTAX;
1684 if( (u[1] & 0xC0) != 0x80 ) {
1685 return LDAP_INVALID_SYNTAX;
1688 /* CHARLEN already validated it */
1691 return LDAP_INVALID_SYNTAX;
1694 /* make sure len corresponds with the offset
1695 to the next character */
1696 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1700 return LDAP_INVALID_SYNTAX;
1703 return LDAP_SUCCESS;
1707 UTF8StringNormalize(
1712 struct berval *normalized,
1715 struct berval tmp, nvalue;
1716 int flags, wasspace;
1719 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1721 if( BER_BVISNULL( val ) ) {
1722 /* assume we're dealing with a syntax (e.g., UTF8String)
1723 * which allows empty strings
1725 BER_BVZERO( normalized );
1726 return LDAP_SUCCESS;
1729 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1730 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1731 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1732 ? LDAP_UTF8_APPROX : 0;
1734 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1739 /* collapse spaces (in place) */
1741 nvalue.bv_val = tmp.bv_val;
1743 /* trim leading spaces? */
1744 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1745 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1747 for( i = 0; i < tmp.bv_len; i++) {
1748 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1749 if( wasspace++ == 0 ) {
1750 /* trim repeated spaces */
1751 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1755 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1759 if( !BER_BVISEMPTY( &nvalue ) ) {
1760 /* trim trailing space? */
1762 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1763 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1767 nvalue.bv_val[nvalue.bv_len] = '\0';
1770 /* string of all spaces is treated as one space */
1771 nvalue.bv_val[0] = ' ';
1772 nvalue.bv_val[1] = '\0';
1776 *normalized = nvalue;
1777 return LDAP_SUCCESS;
1781 directoryStringSubstringsMatch(
1786 struct berval *value,
1787 void *assertedValue )
1790 SubstringsAssertion *sub = assertedValue;
1791 struct berval left = *value;
1795 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1796 if ( sub->sa_initial.bv_len > left.bv_len ) {
1797 /* not enough left */
1802 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1803 sub->sa_initial.bv_len );
1809 left.bv_val += sub->sa_initial.bv_len;
1810 left.bv_len -= sub->sa_initial.bv_len;
1812 priorspace = ASCII_SPACE(
1813 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1816 if ( sub->sa_any ) {
1817 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1821 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1822 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1824 /* allow next space to match */
1831 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1835 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1836 /* not enough left */
1841 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1848 idx = p - left.bv_val;
1850 if ( idx >= left.bv_len ) {
1851 /* this shouldn't happen */
1858 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1859 /* not enough left */
1864 match = memcmp( left.bv_val,
1865 sub->sa_any[i].bv_val,
1866 sub->sa_any[i].bv_len );
1874 left.bv_val += sub->sa_any[i].bv_len;
1875 left.bv_len -= sub->sa_any[i].bv_len;
1877 priorspace = ASCII_SPACE(
1878 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1882 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1883 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1884 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1886 /* allow next space to match */
1891 if ( sub->sa_final.bv_len > left.bv_len ) {
1892 /* not enough left */
1897 match = memcmp( sub->sa_final.bv_val,
1898 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1899 sub->sa_final.bv_len );
1908 return LDAP_SUCCESS;
1911 #if defined(SLAPD_APPROX_INITIALS)
1912 # define SLAPD_APPROX_DELIMITER "._ "
1913 # define SLAPD_APPROX_WORDLEN 2
1915 # define SLAPD_APPROX_DELIMITER " "
1916 # define SLAPD_APPROX_WORDLEN 1
1925 struct berval *value,
1926 void *assertedValue )
1928 struct berval *nval, *assertv;
1929 char *val, **values, **words, *c;
1930 int i, count, len, nextchunk=0, nextavail=0;
1932 /* Yes, this is necessary */
1933 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1934 if( nval == NULL ) {
1936 return LDAP_SUCCESS;
1939 /* Yes, this is necessary */
1940 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1941 NULL, LDAP_UTF8_APPROX, NULL );
1942 if( assertv == NULL ) {
1945 return LDAP_SUCCESS;
1948 /* Isolate how many words there are */
1949 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1950 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1951 if ( c == NULL ) break;
1956 /* Get a phonetic copy of each word */
1957 words = (char **)ch_malloc( count * sizeof(char *) );
1958 values = (char **)ch_malloc( count * sizeof(char *) );
1959 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1961 values[i] = phonetic(c);
1964 /* Work through the asserted value's words, to see if at least some
1965 * of the words are there, in the same order. */
1967 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1968 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1973 #if defined(SLAPD_APPROX_INITIALS)
1974 else if( len == 1 ) {
1975 /* Single letter words need to at least match one word's initial */
1976 for( i=nextavail; i<count; i++ )
1977 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1984 /* Isolate the next word in the asserted value and phonetic it */
1985 assertv->bv_val[nextchunk+len] = '\0';
1986 val = phonetic( assertv->bv_val + nextchunk );
1988 /* See if this phonetic chunk is in the remaining words of *value */
1989 for( i=nextavail; i<count; i++ ){
1990 if( !strcmp( val, values[i] ) ){
1998 /* This chunk in the asserted value was NOT within the *value. */
2004 /* Go on to the next word in the asserted value */
2008 /* If some of the words were seen, call it a match */
2009 if( nextavail > 0 ) {
2016 /* Cleanup allocs */
2017 ber_bvfree( assertv );
2018 for( i=0; i<count; i++ ) {
2019 ch_free( values[i] );
2025 return LDAP_SUCCESS;
2034 struct berval *prefix,
2040 int i,j, len, wordcount, keycount=0;
2041 struct berval *newkeys;
2042 BerVarray keys=NULL;
2044 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2045 struct berval val = BER_BVNULL;
2046 /* Yes, this is necessary */
2047 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2048 assert( !BER_BVISNULL( &val ) );
2050 /* Isolate how many words there are. There will be a key for each */
2051 for( wordcount = 0, c = val.bv_val; *c; c++) {
2052 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2053 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2055 if (*c == '\0') break;
2059 /* Allocate/increase storage to account for new keys */
2060 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2061 * sizeof(struct berval) );
2062 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2063 if( keys ) ch_free( keys );
2066 /* Get a phonetic copy of each word */
2067 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2069 if( len < SLAPD_APPROX_WORDLEN ) continue;
2070 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2075 ber_memfree( val.bv_val );
2077 BER_BVZERO( &keys[keycount] );
2080 return LDAP_SUCCESS;
2089 struct berval *prefix,
2090 void * assertedValue,
2099 /* Yes, this is necessary */
2100 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2101 NULL, LDAP_UTF8_APPROX, NULL );
2102 if( val == NULL || BER_BVISNULL( val ) ) {
2103 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2104 BER_BVZERO( &keys[0] );
2107 return LDAP_SUCCESS;
2110 /* Isolate how many words there are. There will be a key for each */
2111 for( count = 0,c = val->bv_val; *c; c++) {
2112 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2113 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2115 if (*c == '\0') break;
2119 /* Allocate storage for new keys */
2120 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2122 /* Get a phonetic copy of each word */
2123 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2125 if( len < SLAPD_APPROX_WORDLEN ) continue;
2126 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2132 BER_BVZERO( &keys[count] );
2135 return LDAP_SUCCESS;
2138 /* Remove all spaces and '-' characters */
2140 telephoneNumberNormalize(
2145 struct berval *normalized,
2150 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2152 /* validator should have refused an empty string */
2153 assert( !BER_BVISEMPTY( val ) );
2155 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2157 for( p = val->bv_val; *p; p++ ) {
2158 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2164 normalized->bv_len = q - normalized->bv_val;
2166 if( BER_BVISEMPTY( normalized ) ) {
2167 slap_sl_free( normalized->bv_val, ctx );
2168 BER_BVZERO( normalized );
2169 return LDAP_INVALID_SYNTAX;
2172 return LDAP_SUCCESS;
2176 postalAddressValidate(
2180 struct berval bv = *in;
2183 for ( c = 0; c < in->bv_len; c++ ) {
2184 if ( in->bv_val[c] == '\\' ) {
2186 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2187 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2189 return LDAP_INVALID_SYNTAX;
2194 if ( in->bv_val[c] == '$' ) {
2195 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2196 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2197 return LDAP_INVALID_SYNTAX;
2199 bv.bv_val = &in->bv_val[c] + 1;
2203 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2204 return UTF8StringValidate( NULL, &bv );
2208 postalAddressNormalize(
2213 struct berval *normalized,
2216 BerVarray lines = NULL, nlines = NULL;
2218 int rc = LDAP_SUCCESS;
2219 MatchingRule *xmr = NULL;
2222 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2223 xmr = slap_schema.si_mr_caseIgnoreMatch;
2226 xmr = slap_schema.si_mr_caseExactMatch;
2229 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2230 if ( val->bv_val[c] == '$' ) {
2235 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2236 nlines = &lines[l + 2];
2238 lines[0].bv_val = val->bv_val;
2239 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2240 if ( val->bv_val[c] == '$' ) {
2241 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2243 lines[l].bv_val = &val->bv_val[c + 1];
2246 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2248 normalized->bv_len = l;
2250 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2251 /* NOTE: we directly normalize each line,
2252 * without unescaping the values, since the special
2253 * values '\24' ('$') and '\5C' ('\') are not affected
2254 * by normalization */
2255 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2256 if ( rc != LDAP_SUCCESS ) {
2257 rc = LDAP_INVALID_SYNTAX;
2261 normalized->bv_len += nlines[l].bv_len;
2264 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2266 p = normalized->bv_val;
2267 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2268 p = lutil_strbvcopy( p, &nlines[l] );
2273 assert( p == &normalized->bv_val[normalized->bv_len] );
2276 if ( nlines != NULL ) {
2277 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2278 slap_sl_free( nlines[l].bv_val, ctx );
2281 slap_sl_free( lines, ctx );
2292 struct berval val = *in;
2294 if( BER_BVISEMPTY( &val ) ) {
2295 /* disallow empty strings */
2296 return LDAP_INVALID_SYNTAX;
2299 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2300 if ( val.bv_len == 1 ) {
2301 return LDAP_SUCCESS;
2304 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2311 while ( OID_LEADCHAR( val.bv_val[0] )) {
2315 if ( val.bv_len == 0 ) {
2316 return LDAP_SUCCESS;
2320 if( !OID_SEPARATOR( val.bv_val[0] )) {
2328 return LDAP_INVALID_SYNTAX;
2337 struct berval val = *in;
2339 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2341 if ( val.bv_val[0] == '-' ) {
2345 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2346 return LDAP_INVALID_SYNTAX;
2349 if( val.bv_val[0] == '0' ) { /* "-0" */
2350 return LDAP_INVALID_SYNTAX;
2353 } else if ( val.bv_val[0] == '0' ) {
2354 if( val.bv_len > 1 ) { /* "0<more>" */
2355 return LDAP_INVALID_SYNTAX;
2358 return LDAP_SUCCESS;
2361 for( i=0; i < val.bv_len; i++ ) {
2362 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2363 return LDAP_INVALID_SYNTAX;
2367 return LDAP_SUCCESS;
2376 struct berval *value,
2377 void *assertedValue )
2379 struct berval *asserted = (struct berval *) assertedValue;
2380 int vsign = 1, asign = 1; /* default sign = '+' */
2385 if( v.bv_val[0] == '-' ) {
2391 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2394 if( a.bv_val[0] == '-' ) {
2400 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2402 match = vsign - asign;
2404 match = ( v.bv_len != a.bv_len
2405 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2406 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2407 if( vsign < 0 ) match = -match;
2411 return LDAP_SUCCESS;
2414 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2415 #define INDEX_INTLEN_CHOP 7
2416 #define INDEX_INTLEN_CHOPBYTES 3
2426 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2427 * two's complement value (sign-extended or chopped as needed),
2428 * however the top <number of exponent-bytes + 1> bits of first byte
2429 * above is the inverse sign. The next bit is the sign as delimiter.
2431 ber_slen_t k = index_intlen_strlen;
2433 unsigned signmask = ~0x7fU;
2434 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2435 struct berval val = *in, itmp = *tmp;
2437 if ( val.bv_val[0] != '-' ) {
2442 /* Chop least significant digits, increase length instead */
2443 if ( val.bv_len > (ber_len_t) k ) {
2444 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2445 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2446 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2449 if ( lutil_str2bin( &val, &itmp, ctx )) {
2450 return LDAP_INVALID_SYNTAX;
2453 /* Omit leading sign byte */
2454 if ( itmp.bv_val[0] == neg ) {
2459 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2461 assert( chop == 0 );
2462 memset( key->bv_val, neg, k ); /* sign-extend */
2463 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2464 lenp = lenbuf + sizeof(lenbuf);
2465 chop = - (ber_len_t) k;
2467 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2469 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2470 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2471 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2472 k = (lenbuf + sizeof(lenbuf)) - lenp;
2473 if ( k > (ber_slen_t) index_intlen )
2475 memcpy( key->bv_val, lenp, k );
2476 itmp.bv_len = index_intlen - k;
2478 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2479 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2483 /* Index generation function */
2490 struct berval *prefix,
2500 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2502 /* count the values and find max needed length */
2504 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2505 if ( vlen < values[i].bv_len )
2506 vlen = values[i].bv_len;
2508 if ( vlen > maxstrlen )
2511 /* we should have at least one value at this point */
2514 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2515 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2516 keys[i].bv_len = index_intlen;
2517 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2520 keys[i].bv_val = NULL;
2522 if ( vlen > sizeof(ibuf) ) {
2523 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2527 itmp.bv_len = sizeof(ibuf);
2529 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2530 if ( itmp.bv_val != ibuf ) {
2531 itmp.bv_len = values[i].bv_len;
2532 if ( itmp.bv_len <= sizeof(ibuf) )
2533 itmp.bv_len = sizeof(ibuf);
2534 else if ( itmp.bv_len > maxstrlen )
2535 itmp.bv_len = maxstrlen;
2537 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2543 if ( itmp.bv_val != ibuf ) {
2544 slap_sl_free( itmp.bv_val, ctx );
2549 /* Index generation function */
2556 struct berval *prefix,
2557 void * assertedValue,
2564 struct berval *value;
2567 value = (struct berval *) assertedValue;
2569 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2571 keys[0].bv_len = index_intlen;
2572 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2574 keys[1].bv_val = NULL;
2576 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2577 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2578 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2579 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2582 iv.bv_len = sizeof(ibuf);
2585 rc = integerVal2Key( value, keys, &iv, ctx );
2589 if ( iv.bv_val != ibuf ) {
2590 slap_sl_free( iv.bv_val, ctx );
2596 countryStringValidate(
2598 struct berval *val )
2600 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2602 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2603 return LDAP_INVALID_SYNTAX;
2605 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2606 return LDAP_INVALID_SYNTAX;
2609 return LDAP_SUCCESS;
2613 printableStringValidate(
2615 struct berval *val )
2619 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2621 for(i=0; i < val->bv_len; i++) {
2622 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2623 return LDAP_INVALID_SYNTAX;
2627 return LDAP_SUCCESS;
2631 printablesStringValidate(
2633 struct berval *val )
2637 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2639 for(i=0,len=0; i < val->bv_len; i++) {
2640 int c = val->bv_val[i];
2644 return LDAP_INVALID_SYNTAX;
2648 } else if ( SLAP_PRINTABLE(c) ) {
2651 return LDAP_INVALID_SYNTAX;
2656 return LDAP_INVALID_SYNTAX;
2659 return LDAP_SUCCESS;
2665 struct berval *val )
2669 for(i=0; i < val->bv_len; i++) {
2670 if( !LDAP_ASCII(val->bv_val[i]) ) {
2671 return LDAP_INVALID_SYNTAX;
2675 return LDAP_SUCCESS;
2684 struct berval *normalized,
2688 int casefold = !SLAP_MR_ASSOCIATED( mr,
2689 slap_schema.si_mr_caseExactIA5Match );
2691 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2695 /* Ignore initial whitespace */
2696 while ( ASCII_SPACE( *p ) ) p++;
2698 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2699 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2700 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2701 normalized->bv_val[normalized->bv_len] = '\0';
2703 p = q = normalized->bv_val;
2706 if ( ASCII_SPACE( *p ) ) {
2709 /* Ignore the extra whitespace */
2710 while ( ASCII_SPACE( *p ) ) {
2714 } else if ( casefold ) {
2715 /* Most IA5 rules require casefolding */
2716 *q++ = TOLOWER(*p); p++;
2723 assert( normalized->bv_val <= p );
2727 * If the string ended in space, backup the pointer one
2728 * position. One is enough because the above loop collapsed
2729 * all whitespace to a single space.
2731 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2733 /* null terminate */
2736 normalized->bv_len = q - normalized->bv_val;
2738 return LDAP_SUCCESS;
2747 if( in->bv_len != 36 ) {
2748 return LDAP_INVALID_SYNTAX;
2751 for( i=0; i<36; i++ ) {
2757 if( in->bv_val[i] != '-' ) {
2758 return LDAP_INVALID_SYNTAX;
2762 if( !ASCII_HEX( in->bv_val[i]) ) {
2763 return LDAP_INVALID_SYNTAX;
2768 return LDAP_SUCCESS;
2779 int rc=LDAP_INVALID_SYNTAX;
2781 assert( in != NULL );
2782 assert( out != NULL );
2784 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2787 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2789 for( i=0; i<36; i++ ) {
2795 if( in->bv_val[i] != '-' ) {
2798 out->bv_val[i] = '-';
2802 if( !ASCII_HEX( in->bv_val[i]) ) {
2805 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2810 out->bv_val[ out->bv_len ] = '\0';
2814 slap_sl_free( out->bv_val, ctx );
2827 struct berval *normalized,
2830 unsigned char octet = '\0';
2834 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2835 /* NOTE: must be a normalized UUID */
2836 assert( val->bv_len == 16 );
2838 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2839 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2840 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2841 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2843 return LDAP_SUCCESS;
2846 normalized->bv_len = 16;
2847 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2849 for( i=0, j=0; i<36; i++ ) {
2850 unsigned char nibble;
2851 if( val->bv_val[i] == '-' ) {
2854 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2855 nibble = val->bv_val[i] - '0';
2857 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2858 nibble = val->bv_val[i] - ('a'-10);
2860 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2861 nibble = val->bv_val[i] - ('A'-10);
2864 slap_sl_free( normalized->bv_val, ctx );
2865 BER_BVZERO( normalized );
2866 return LDAP_INVALID_SYNTAX;
2871 normalized->bv_val[j>>1] = octet;
2873 octet = nibble << 4;
2878 normalized->bv_val[normalized->bv_len] = 0;
2879 return LDAP_SUCCESS;
2885 numericStringValidate(
2891 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2893 for(i=0; i < in->bv_len; i++) {
2894 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2895 return LDAP_INVALID_SYNTAX;
2899 return LDAP_SUCCESS;
2903 numericStringNormalize(
2908 struct berval *normalized,
2911 /* removal all spaces */
2914 assert( !BER_BVISEMPTY( val ) );
2916 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2919 q = normalized->bv_val;
2922 if ( ASCII_SPACE( *p ) ) {
2923 /* Ignore whitespace */
2930 /* we should have copied no more than is in val */
2931 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2933 /* null terminate */
2936 normalized->bv_len = q - normalized->bv_val;
2938 if( BER_BVISEMPTY( normalized ) ) {
2939 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2940 normalized->bv_val[0] = ' ';
2941 normalized->bv_val[1] = '\0';
2942 normalized->bv_len = 1;
2945 return LDAP_SUCCESS;
2949 * Integer conversion macros that will use the largest available
2952 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2953 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2954 # define SLAP_LONG long long
2956 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2957 # define SLAP_LONG long
2958 #endif /* HAVE_STRTOLL ... */
2966 struct berval *value,
2967 void *assertedValue )
2969 SLAP_LONG lValue, lAssertedValue;
2972 /* safe to assume integers are NUL terminated? */
2973 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2974 if( errno == ERANGE )
2976 return LDAP_CONSTRAINT_VIOLATION;
2979 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2981 if( errno == ERANGE )
2983 return LDAP_CONSTRAINT_VIOLATION;
2986 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2987 return LDAP_SUCCESS;
2996 struct berval *value,
2997 void *assertedValue )
2999 SLAP_LONG lValue, lAssertedValue;
3002 /* safe to assume integers are NUL terminated? */
3003 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3004 if( errno == ERANGE )
3006 return LDAP_CONSTRAINT_VIOLATION;
3009 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3011 if( errno == ERANGE )
3013 return LDAP_CONSTRAINT_VIOLATION;
3016 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3017 return LDAP_SUCCESS;
3021 checkNum( struct berval *in, struct berval *out )
3023 /* parse serialNumber */
3024 ber_len_t neg = 0, extra = 0;
3027 out->bv_val = in->bv_val;
3030 if ( out->bv_val[0] == '-' ) {
3035 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3036 first = out->bv_val[2];
3039 out->bv_len += STRLENOF("0x");
3040 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3041 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3044 } else if ( out->bv_val[0] == '\'' ) {
3045 first = out->bv_val[1];
3048 out->bv_len += STRLENOF("'");
3050 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3051 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3053 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3056 out->bv_len += STRLENOF("'H");
3059 first = out->bv_val[0];
3060 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3061 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3065 if ( !( out->bv_len > neg ) ) {
3069 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3077 serialNumberAndIssuerCheck(
3085 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3087 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3088 /* Parse old format */
3089 is->bv_val = ber_bvchr( in, '$' );
3090 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3092 sn->bv_val = in->bv_val;
3093 sn->bv_len = is->bv_val - in->bv_val;
3096 is->bv_len = in->bv_len - (sn->bv_len + 1);
3098 /* eat leading zeros */
3099 for( n=0; n < (sn->bv_len-1); n++ ) {
3100 if( sn->bv_val[n] != '0' ) break;
3105 for( n=0; n < sn->bv_len; n++ ) {
3106 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3110 /* Parse GSER format */
3115 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3119 struct berval x = *in;
3125 /* eat leading spaces */
3126 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3130 /* should be at issuer or serialNumber NamedValue */
3131 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3132 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3135 x.bv_val += STRLENOF("issuer");
3136 x.bv_len -= STRLENOF("issuer");
3138 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3142 /* eat leading spaces */
3143 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3147 /* For backward compatibility, this part is optional */
3148 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3149 x.bv_val += STRLENOF("rdnSequence:");
3150 x.bv_len -= STRLENOF("rdnSequence:");
3153 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3157 is->bv_val = x.bv_val;
3160 for ( ; is->bv_len < x.bv_len; ) {
3161 if ( is->bv_val[is->bv_len] != '"' ) {
3165 if ( is->bv_val[is->bv_len+1] == '"' ) {
3172 x.bv_val += is->bv_len + 1;
3173 x.bv_len -= is->bv_len + 1;
3175 have |= HAVE_ISSUER;
3177 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3179 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3181 /* parse serialNumber */
3182 x.bv_val += STRLENOF("serialNumber");
3183 x.bv_len -= STRLENOF("serialNumber");
3185 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3189 /* eat leading spaces */
3190 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3194 if ( checkNum( &x, sn ) ) {
3195 return LDAP_INVALID_SYNTAX;
3198 x.bv_val += sn->bv_len;
3199 x.bv_len -= sn->bv_len;
3204 return LDAP_INVALID_SYNTAX;
3207 /* eat leading spaces */
3208 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3212 if ( have == HAVE_ALL ) {
3216 if ( x.bv_val[0] != ',' ) {
3217 return LDAP_INVALID_SYNTAX;
3224 /* should have no characters left... */
3225 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3227 if ( numdquotes == 0 ) {
3228 ber_dupbv_x( &ni, is, ctx );
3233 ni.bv_len = is->bv_len - numdquotes;
3234 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3235 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3236 if ( is->bv_val[src] == '"' ) {
3239 ni.bv_val[dst] = is->bv_val[src];
3241 ni.bv_val[dst] = '\0';
3251 serialNumberAndIssuerValidate(
3256 struct berval sn, i;
3258 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3261 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3266 /* validate DN -- doesn't handle double dquote */
3267 rc = dnValidate( NULL, &i );
3269 rc = LDAP_INVALID_SYNTAX;
3272 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3273 slap_sl_free( i.bv_val, NULL );
3276 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3277 in->bv_val, rc, 0 );
3284 serialNumberAndIssuerPretty(
3291 struct berval sn, i, ni = BER_BVNULL;
3294 assert( in != NULL );
3295 assert( out != NULL );
3299 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3302 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3307 rc = dnPretty( syntax, &i, &ni, ctx );
3309 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3310 slap_sl_free( i.bv_val, ctx );
3314 rc = LDAP_INVALID_SYNTAX;
3318 /* make room from sn + "$" */
3319 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3320 + sn.bv_len + ni.bv_len;
3321 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3323 if ( out->bv_val == NULL ) {
3330 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3331 p = lutil_strbvcopy( p, &sn );
3332 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3333 p = lutil_strbvcopy( p, &ni );
3334 p = lutil_strcopy( p, /*{*/ "\" }" );
3336 assert( p == &out->bv_val[out->bv_len] );
3339 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3340 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3342 slap_sl_free( ni.bv_val, ctx );
3344 return LDAP_SUCCESS;
3354 /* Use hex format. '123456789abcdef'H */
3355 unsigned char *ptr, zero = '\0';
3358 ber_len_t i, len, nlen;
3360 assert( in != NULL );
3361 assert( !BER_BVISNULL( in ) );
3362 assert( out != NULL );
3363 assert( !BER_BVISNULL( out ) );
3365 ptr = (unsigned char *)in->bv_val;
3368 /* Check for minimal encodings */
3370 if ( ptr[0] & 0x80 ) {
3371 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3375 } else if ( ptr[0] == 0 ) {
3376 if ( !( ptr[1] & 0x80 ) ) {
3383 } else if ( len == 0 ) {
3384 /* FIXME: this should not be possible,
3385 * since a value of zero would have length 1 */
3390 first = !( ptr[0] & 0xf0U );
3391 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3392 if ( nlen >= out->bv_len ) {
3393 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3399 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3403 for ( ; i < len; i++ ) {
3404 sprintf( sptr, "%02X", ptr[i] );
3411 assert( sptr == &out->bv_val[nlen] );
3418 #define SLAP_SN_BUFLEN (64)
3421 * This routine is called by certificateExactNormalize when
3422 * certificateExactNormalize receives a search string instead of
3423 * a certificate. This routine checks if the search value is valid
3424 * and then returns the normalized value
3427 serialNumberAndIssuerNormalize(
3435 struct berval sn, sn2, sn3, i, ni;
3436 char sbuf2[SLAP_SN_BUFLEN];
3437 char sbuf3[SLAP_SN_BUFLEN];
3441 assert( in != NULL );
3442 assert( out != NULL );
3444 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3447 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3452 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3454 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3455 slap_sl_free( i.bv_val, ctx );
3459 return LDAP_INVALID_SYNTAX;
3462 /* Convert sn to canonical hex */
3464 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3465 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3467 sn2.bv_len = sn.bv_len;
3468 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3469 rc = LDAP_INVALID_SYNTAX;
3474 sn3.bv_len = sizeof(sbuf3);
3475 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3476 rc = LDAP_INVALID_SYNTAX;
3480 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3481 + sn3.bv_len + ni.bv_len;
3482 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3484 if ( out->bv_val == NULL ) {
3492 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3493 p = lutil_strbvcopy( p, &sn3 );
3494 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3495 p = lutil_strbvcopy( p, &ni );
3496 p = lutil_strcopy( p, /*{*/ "\" }" );
3498 assert( p == &out->bv_val[out->bv_len] );
3501 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3502 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3504 if ( sn2.bv_val != sbuf2 ) {
3505 slap_sl_free( sn2.bv_val, ctx );
3508 if ( sn3.bv_val != sbuf3 ) {
3509 slap_sl_free( sn3.bv_val, ctx );
3512 slap_sl_free( ni.bv_val, ctx );
3518 certificateExactNormalize(
3523 struct berval *normalized,
3526 BerElementBuffer berbuf;
3527 BerElement *ber = (BerElement *)&berbuf;
3531 char serialbuf2[SLAP_SN_BUFLEN];
3532 struct berval sn, sn2 = BER_BVNULL;
3533 struct berval issuer_dn = BER_BVNULL, bvdn;
3535 int rc = LDAP_INVALID_SYNTAX;
3537 assert( val != NULL );
3539 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3540 val->bv_val, val->bv_len, 0 );
3542 if ( BER_BVISEMPTY( val ) ) goto done;
3544 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3545 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3548 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3550 ber_init2( ber, val, LBER_USE_DER );
3551 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3552 tag = ber_skip_tag( ber, &len ); /* Sequence */
3553 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3554 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3555 tag = ber_skip_tag( ber, &len );
3556 tag = ber_get_int( ber, &i ); /* version */
3559 /* NOTE: move the test here from certificateValidate,
3560 * so that we can validate certs with serial longer
3561 * than sizeof(ber_int_t) */
3562 tag = ber_skip_tag( ber, &len ); /* serial */
3564 sn.bv_val = (char *)ber->ber_ptr;
3565 sn2.bv_val = serialbuf2;
3566 sn2.bv_len = sizeof(serialbuf2);
3567 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3568 rc = LDAP_INVALID_SYNTAX;
3571 ber_skip_data( ber, len );
3573 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3574 ber_skip_data( ber, len );
3575 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3576 len = ber_ptrlen( ber );
3577 bvdn.bv_val = val->bv_val + len;
3578 bvdn.bv_len = val->bv_len - len;
3580 rc = dnX509normalize( &bvdn, &issuer_dn );
3581 if ( rc != LDAP_SUCCESS ) goto done;
3583 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3584 + sn2.bv_len + issuer_dn.bv_len;
3585 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3587 p = normalized->bv_val;
3589 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3590 p = lutil_strbvcopy( p, &sn2 );
3591 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3592 p = lutil_strbvcopy( p, &issuer_dn );
3593 p = lutil_strcopy( p, /*{*/ "\" }" );
3598 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3599 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3601 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3602 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3607 /* X.509 PKI certificateList stuff */
3609 checkTime( struct berval *in, struct berval *out )
3613 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3616 assert( in != NULL );
3617 assert( !BER_BVISNULL( in ) );
3618 assert( !BER_BVISEMPTY( in ) );
3620 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3624 if ( out != NULL ) {
3625 assert( !BER_BVISNULL( out ) );
3626 assert( out->bv_len >= sizeof( buf ) );
3627 bv.bv_val = out->bv_val;
3633 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3634 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3637 if ( in->bv_val[i] != 'Z' ) {
3642 if ( i != in->bv_len ) {
3646 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3647 lutil_strncopy( bv.bv_val, in->bv_val, i );
3650 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3651 char *p = bv.bv_val;
3652 if ( in->bv_val[0] < '7' ) {
3653 p = lutil_strcopy( p, "20" );
3656 p = lutil_strcopy( p, "19" );
3658 lutil_strncopy( p, in->bv_val, i );
3665 rc = generalizedTimeValidate( NULL, &bv );
3666 if ( rc == LDAP_SUCCESS && out != NULL ) {
3667 if ( out->bv_len > bv.bv_len ) {
3668 out->bv_val[ bv.bv_len ] = '\0';
3670 out->bv_len = bv.bv_len;
3673 return rc != LDAP_SUCCESS;
3677 issuerAndThisUpdateCheck(
3684 struct berval x = *in;
3685 struct berval ni = BER_BVNULL;
3686 /* Parse GSER format */
3690 HAVE_THISUPDATE = 0x2,
3691 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3695 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3697 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3698 return LDAP_INVALID_SYNTAX;
3702 x.bv_len -= STRLENOF("{}");
3705 /* eat leading spaces */
3706 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3710 /* should be at issuer or thisUpdate */
3711 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3712 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3715 x.bv_val += STRLENOF("issuer");
3716 x.bv_len -= STRLENOF("issuer");
3718 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3722 /* eat leading spaces */
3723 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3727 /* For backward compatibility, this part is optional */
3728 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3729 return LDAP_INVALID_SYNTAX;
3731 x.bv_val += STRLENOF("rdnSequence:");
3732 x.bv_len -= STRLENOF("rdnSequence:");
3734 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3738 is->bv_val = x.bv_val;
3741 for ( ; is->bv_len < x.bv_len; ) {
3742 if ( is->bv_val[is->bv_len] != '"' ) {
3746 if ( is->bv_val[is->bv_len+1] == '"' ) {
3753 x.bv_val += is->bv_len + 1;
3754 x.bv_len -= is->bv_len + 1;
3756 have |= HAVE_ISSUER;
3758 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3760 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3762 /* parse thisUpdate */
3763 x.bv_val += STRLENOF("thisUpdate");
3764 x.bv_len -= STRLENOF("thisUpdate");
3766 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3770 /* eat leading spaces */
3771 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3775 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3779 tu->bv_val = x.bv_val;
3782 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3783 if ( tu->bv_val[tu->bv_len] == '"' ) {
3787 x.bv_val += tu->bv_len + 1;
3788 x.bv_len -= tu->bv_len + 1;
3790 have |= HAVE_THISUPDATE;
3793 return LDAP_INVALID_SYNTAX;
3796 /* eat leading spaces */
3797 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3801 if ( have == HAVE_ALL ) {
3805 if ( x.bv_val[0] != ',' ) {
3806 return LDAP_INVALID_SYNTAX;
3813 /* should have no characters left... */
3814 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3816 if ( numdquotes == 0 ) {
3817 ber_dupbv_x( &ni, is, ctx );
3822 ni.bv_len = is->bv_len - numdquotes;
3823 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3824 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3825 if ( is->bv_val[src] == '"' ) {
3828 ni.bv_val[dst] = is->bv_val[src];
3830 ni.bv_val[dst] = '\0';
3839 issuerAndThisUpdateValidate(
3844 struct berval i, tu;
3846 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3849 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3854 /* validate DN -- doesn't handle double dquote */
3855 rc = dnValidate( NULL, &i );
3857 rc = LDAP_INVALID_SYNTAX;
3859 } else if ( checkTime( &tu, NULL ) ) {
3860 rc = LDAP_INVALID_SYNTAX;
3863 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3864 slap_sl_free( i.bv_val, NULL );
3867 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3868 in->bv_val, rc, 0 );
3875 issuerAndThisUpdatePretty(
3882 struct berval i, tu, ni = BER_BVNULL;
3885 assert( in != NULL );
3886 assert( out != NULL );
3890 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3893 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3898 rc = dnPretty( syntax, &i, &ni, ctx );
3900 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3901 slap_sl_free( i.bv_val, ctx );
3904 if ( rc || checkTime( &tu, NULL ) ) {
3905 rc = LDAP_INVALID_SYNTAX;
3910 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3911 + ni.bv_len + tu.bv_len;
3912 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3914 if ( out->bv_val == NULL ) {
3921 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3922 p = lutil_strbvcopy( p, &ni );
3923 p = lutil_strcopy( p, "\", thisUpdate \"" );
3924 p = lutil_strbvcopy( p, &tu );
3925 p = lutil_strcopy( p, /*{*/ "\" }" );
3927 assert( p == &out->bv_val[out->bv_len] );
3930 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3931 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3933 slap_sl_free( ni.bv_val, ctx );
3939 issuerAndThisUpdateNormalize(
3947 struct berval i, ni, tu, tu2;
3948 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3952 assert( in != NULL );
3953 assert( out != NULL );
3955 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3958 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3963 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3965 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3966 slap_sl_free( i.bv_val, ctx );
3970 tu2.bv_len = sizeof( sbuf );
3971 if ( rc || checkTime( &tu, &tu2 ) ) {
3972 return LDAP_INVALID_SYNTAX;
3975 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3976 + ni.bv_len + tu2.bv_len;
3977 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3979 if ( out->bv_val == NULL ) {
3987 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3988 p = lutil_strbvcopy( p, &ni );
3989 p = lutil_strcopy( p, "\", thisUpdate \"" );
3990 p = lutil_strbvcopy( p, &tu2 );
3991 p = lutil_strcopy( p, /*{*/ "\" }" );
3993 assert( p == &out->bv_val[out->bv_len] );
3996 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3997 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3999 slap_sl_free( ni.bv_val, ctx );
4005 certificateListExactNormalize(
4010 struct berval *normalized,
4013 BerElementBuffer berbuf;
4014 BerElement *ber = (BerElement *)&berbuf;
4018 struct berval issuer_dn = BER_BVNULL, bvdn,
4020 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4021 int rc = LDAP_INVALID_SYNTAX;
4023 assert( val != NULL );
4025 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4026 val->bv_val, val->bv_len, 0 );
4028 if ( BER_BVISEMPTY( val ) ) goto done;
4030 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4031 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4034 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4036 ber_init2( ber, val, LBER_USE_DER );
4037 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4038 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4039 tag = ber_skip_tag( ber, &len ); /* Sequence */
4040 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4041 tag = ber_peek_tag( ber, &len );
4042 /* Optional version */
4043 if ( tag == LBER_INTEGER ) {
4044 tag = ber_get_int( ber, &version );
4045 assert( tag == LBER_INTEGER );
4046 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4048 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4049 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4050 ber_skip_data( ber, len );
4052 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4053 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4054 len = ber_ptrlen( ber );
4055 bvdn.bv_val = val->bv_val + len;
4056 bvdn.bv_len = val->bv_len - len;
4057 tag = ber_skip_tag( ber, &len );
4058 ber_skip_data( ber, len );
4060 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4061 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4062 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4063 bvtu.bv_val = (char *)ber->ber_ptr;
4066 rc = dnX509normalize( &bvdn, &issuer_dn );
4067 if ( rc != LDAP_SUCCESS ) goto done;
4069 thisUpdate.bv_val = tubuf;
4070 thisUpdate.bv_len = sizeof(tubuf);
4071 if ( checkTime( &bvtu, &thisUpdate ) ) {
4072 rc = LDAP_INVALID_SYNTAX;
4076 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4077 + issuer_dn.bv_len + thisUpdate.bv_len;
4078 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4080 p = normalized->bv_val;
4082 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4083 p = lutil_strbvcopy( p, &issuer_dn );
4084 p = lutil_strcopy( p, "\", thisUpdate \"" );
4085 p = lutil_strbvcopy( p, &thisUpdate );
4086 p = lutil_strcopy( p, /*{*/ "\" }" );
4091 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4092 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4094 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4099 /* X.509 PMI serialNumberAndIssuerSerialCheck
4101 AttributeCertificateExactAssertion ::= SEQUENCE {
4102 serialNumber CertificateSerialNumber,
4103 issuer AttCertIssuer }
4105 CertificateSerialNumber ::= INTEGER
4107 AttCertIssuer ::= [0] SEQUENCE {
4108 issuerName GeneralNames OPTIONAL,
4109 baseCertificateID [0] IssuerSerial OPTIONAL,
4110 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4111 -- At least one component shall be present
4113 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4115 GeneralName ::= CHOICE {
4116 otherName [0] INSTANCE OF OTHER-NAME,
4117 rfc822Name [1] IA5String,
4118 dNSName [2] IA5String,
4119 x400Address [3] ORAddress,
4120 directoryName [4] Name,
4121 ediPartyName [5] EDIPartyName,
4122 uniformResourceIdentifier [6] IA5String,
4123 iPAddress [7] OCTET STRING,
4124 registeredID [8] OBJECT IDENTIFIER }
4126 IssuerSerial ::= SEQUENCE {
4127 issuer GeneralNames,
4128 serial CertificateSerialNumber,
4129 issuerUID UniqueIdentifier OPTIONAL }
4131 ObjectDigestInfo ::= SEQUENCE {
4132 digestedObjectType ENUMERATED {
4135 otherObjectTypes (2) },
4136 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4137 digestAlgorithm AlgorithmIdentifier,
4138 objectDigest BIT STRING }
4140 * The way I interpret it, an assertion should look like
4142 { serialNumber 'dd'H,
4143 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4144 baseCertificateID { serial '1d'H,
4145 issuer { directoryName:rdnSequence:"cn=zzz" },
4146 issuerUID <value> -- optional
4148 objectDigestInfo { ... } -- optional
4152 * with issuerName, baseCertificateID and objectDigestInfo optional,
4153 * at least one present; the way it's currently implemented, it is
4155 { serialNumber 'dd'H,
4156 issuer { baseCertificateID { serial '1d'H,
4157 issuer { directoryName:rdnSequence:"cn=zzz" }
4162 * with all the above parts mandatory.
4165 serialNumberAndIssuerSerialCheck(
4169 struct berval *i_sn, /* contain serial of baseCertificateID */
4172 /* Parse GSER format */
4177 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4178 } have = HAVE_NONE, have2 = HAVE_NONE;
4180 struct berval x = *in;
4183 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4186 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4193 /* eat leading spaces */
4194 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4198 /* should be at issuer or serialNumber NamedValue */
4199 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4200 if ( have & HAVE_ISSUER ) {
4201 return LDAP_INVALID_SYNTAX;
4204 /* parse IssuerSerial */
4205 x.bv_val += STRLENOF("issuer");
4206 x.bv_len -= STRLENOF("issuer");
4208 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4212 /* eat leading spaces */
4213 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4217 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4221 /* eat leading spaces */
4222 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4226 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4227 return LDAP_INVALID_SYNTAX;
4229 x.bv_val += STRLENOF("baseCertificateID ");
4230 x.bv_len -= STRLENOF("baseCertificateID ");
4232 /* eat leading spaces */
4233 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4237 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4242 /* eat leading spaces */
4243 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4247 /* parse issuer of baseCertificateID */
4248 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4249 if ( have2 & HAVE_ISSUER ) {
4250 return LDAP_INVALID_SYNTAX;
4253 x.bv_val += STRLENOF("issuer ");
4254 x.bv_len -= STRLENOF("issuer ");
4256 /* eat leading spaces */
4257 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4261 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4265 /* eat leading spaces */
4266 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4270 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4271 return LDAP_INVALID_SYNTAX;
4273 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4274 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4276 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4280 is->bv_val = x.bv_val;
4283 for ( ; is->bv_len < x.bv_len; ) {
4284 if ( is->bv_val[is->bv_len] != '"' ) {
4288 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4295 x.bv_val += is->bv_len + 1;
4296 x.bv_len -= is->bv_len + 1;
4298 /* eat leading spaces */
4299 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4303 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4307 have2 |= HAVE_ISSUER;
4309 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4310 if ( have2 & HAVE_SN ) {
4311 return LDAP_INVALID_SYNTAX;
4314 x.bv_val += STRLENOF("serial ");
4315 x.bv_len -= STRLENOF("serial ");
4317 /* eat leading spaces */
4318 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4322 if ( checkNum( &x, i_sn ) ) {
4323 return LDAP_INVALID_SYNTAX;
4326 x.bv_val += i_sn->bv_len;
4327 x.bv_len -= i_sn->bv_len;
4332 return LDAP_INVALID_SYNTAX;
4335 /* eat leading spaces */
4336 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4340 if ( have2 == HAVE_ALL ) {
4344 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4349 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4353 /* eat leading spaces */
4354 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4358 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4362 have |= HAVE_ISSUER;
4364 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4365 if ( have & HAVE_SN ) {
4366 return LDAP_INVALID_SYNTAX;
4369 /* parse serialNumber */
4370 x.bv_val += STRLENOF("serialNumber");
4371 x.bv_len -= STRLENOF("serialNumber");
4373 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4377 /* eat leading spaces */
4378 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4382 if ( checkNum( &x, sn ) ) {
4383 return LDAP_INVALID_SYNTAX;
4386 x.bv_val += sn->bv_len;
4387 x.bv_len -= sn->bv_len;
4392 return LDAP_INVALID_SYNTAX;
4396 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4400 if ( have == HAVE_ALL ) {
4404 if ( x.bv_val[0] != ',' ) {
4405 return LDAP_INVALID_SYNTAX;
4411 /* should have no characters left... */
4412 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4414 if ( numdquotes == 0 ) {
4415 ber_dupbv_x( &ni, is, ctx );
4420 ni.bv_len = is->bv_len - numdquotes;
4421 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4422 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4423 if ( is->bv_val[src] == '"' ) {
4426 ni.bv_val[dst] = is->bv_val[src];
4428 ni.bv_val[dst] = '\0';
4433 /* need to handle double dquotes here */
4437 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4439 serialNumberAndIssuerSerialValidate(
4444 struct berval sn, i, i_sn;
4446 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4449 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4454 /* validate DN -- doesn't handle double dquote */
4455 rc = dnValidate( NULL, &i );
4457 rc = LDAP_INVALID_SYNTAX;
4460 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4461 slap_sl_free( i.bv_val, NULL );
4465 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4466 in->bv_val, rc, 0 );
4471 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4473 serialNumberAndIssuerSerialPretty(
4479 struct berval sn, i, i_sn, ni = BER_BVNULL;
4483 assert( in != NULL );
4484 assert( out != NULL );
4486 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4489 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4494 rc = dnPretty( syntax, &i, &ni, ctx );
4496 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4497 slap_sl_free( i.bv_val, ctx );
4501 rc = LDAP_INVALID_SYNTAX;
4505 /* make room from sn + "$" */
4506 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4507 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4508 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4510 if ( out->bv_val == NULL ) {
4517 p = lutil_strcopy( p, "{ serialNumber " );
4518 p = lutil_strbvcopy( p, &sn );
4519 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4520 p = lutil_strbvcopy( p, &ni );
4521 p = lutil_strcopy( p, "\" }, serial " );
4522 p = lutil_strbvcopy( p, &i_sn );
4523 p = lutil_strcopy( p, " } } }" );
4525 assert( p == &out->bv_val[out->bv_len] );
4528 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4529 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4531 slap_sl_free( ni.bv_val, ctx );
4536 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4538 * This routine is called by attributeCertificateExactNormalize
4539 * when attributeCertificateExactNormalize receives a search
4540 * string instead of a attribute certificate. This routine
4541 * checks if the search value is valid and then returns the
4545 serialNumberAndIssuerSerialNormalize(
4553 struct berval i, ni = BER_BVNULL,
4554 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4555 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4556 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4557 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4561 assert( in != NULL );
4562 assert( out != NULL );
4564 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4567 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4572 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4574 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4575 slap_sl_free( i.bv_val, ctx );
4579 rc = LDAP_INVALID_SYNTAX;
4583 /* Convert sn to canonical hex */
4585 sn2.bv_len = sn.bv_len;
4586 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4587 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4589 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4590 rc = LDAP_INVALID_SYNTAX;
4594 /* Convert i_sn to canonical hex */
4595 i_sn2.bv_val = i_sbuf2;
4596 i_sn2.bv_len = i_sn.bv_len;
4597 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4598 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4600 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4601 rc = LDAP_INVALID_SYNTAX;
4606 sn3.bv_len = sizeof(sbuf3);
4607 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4608 rc = LDAP_INVALID_SYNTAX;
4612 i_sn3.bv_val = i_sbuf3;
4613 i_sn3.bv_len = sizeof(i_sbuf3);
4614 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4615 rc = LDAP_INVALID_SYNTAX;
4619 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4620 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4621 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4623 if ( out->bv_val == NULL ) {
4631 p = lutil_strcopy( p, "{ serialNumber " );
4632 p = lutil_strbvcopy( p, &sn3 );
4633 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4634 p = lutil_strbvcopy( p, &ni );
4635 p = lutil_strcopy( p, "\" }, serial " );
4636 p = lutil_strbvcopy( p, &i_sn3 );
4637 p = lutil_strcopy( p, " } } }" );
4639 assert( p == &out->bv_val[out->bv_len] );
4642 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4643 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4645 if ( sn2.bv_val != sbuf2 ) {
4646 slap_sl_free( sn2.bv_val, ctx );
4649 if ( i_sn2.bv_val != i_sbuf2 ) {
4650 slap_sl_free( i_sn2.bv_val, ctx );
4653 if ( sn3.bv_val != sbuf3 ) {
4654 slap_sl_free( sn3.bv_val, ctx );
4657 if ( i_sn3.bv_val != i_sbuf3 ) {
4658 slap_sl_free( i_sn3.bv_val, ctx );
4661 slap_sl_free( ni.bv_val, ctx );
4666 /* X.509 PMI attributeCertificateExactNormalize */
4668 attributeCertificateExactNormalize(
4673 struct berval *normalized,
4676 BerElementBuffer berbuf;
4677 BerElement *ber = (BerElement *)&berbuf;
4680 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4681 struct berval sn, i_sn, sn2, i_sn2;
4682 struct berval issuer_dn = BER_BVNULL, bvdn;
4684 int rc = LDAP_INVALID_SYNTAX;
4686 if ( BER_BVISEMPTY( val ) ) {
4690 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4691 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4694 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4696 ber_init2( ber, val, LBER_USE_DER );
4697 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4698 tag = ber_skip_tag( ber, &len ); /* Sequence */
4699 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4700 ber_skip_data( ber, len );
4701 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4702 ber_skip_data( ber, len );
4705 tag = ber_skip_tag( ber, &len ); /* Sequence */
4706 /* issuerName (GeneralNames sequence; optional)? */
4707 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4708 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4709 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4710 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4711 rc = LDAP_INVALID_SYNTAX;
4714 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4715 len = ber_ptrlen( ber );
4716 bvdn.bv_val = val->bv_val + len;
4717 bvdn.bv_len = val->bv_len - len;
4718 rc = dnX509normalize( &bvdn, &issuer_dn );
4719 if ( rc != LDAP_SUCCESS ) goto done;
4721 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4722 ber_skip_data( ber, len );
4723 tag = ber_skip_tag( ber, &len ); /* serial number */
4724 if ( tag != LBER_INTEGER ) {
4725 rc = LDAP_INVALID_SYNTAX;
4728 i_sn.bv_val = (char *)ber->ber_ptr;
4730 i_sn2.bv_val = issuer_serialbuf;
4731 i_sn2.bv_len = sizeof(issuer_serialbuf);
4732 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4733 rc = LDAP_INVALID_SYNTAX;
4736 ber_skip_data( ber, len );
4738 /* issuerUID (bitstring; optional)? */
4739 /* objectDigestInfo (sequence; optional)? */
4741 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4742 ber_skip_data( ber, len );
4743 tag = ber_skip_tag( ber, &len ); /* serial number */
4744 if ( tag != LBER_INTEGER ) {
4745 rc = LDAP_INVALID_SYNTAX;
4748 sn.bv_val = (char *)ber->ber_ptr;
4750 sn2.bv_val = serialbuf;
4751 sn2.bv_len = sizeof(serialbuf);
4752 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4753 rc = LDAP_INVALID_SYNTAX;
4756 ber_skip_data( ber, len );
4758 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4759 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4760 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4762 p = normalized->bv_val;
4764 p = lutil_strcopy( p, "{ serialNumber " );
4765 p = lutil_strbvcopy( p, &sn2 );
4766 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4767 p = lutil_strbvcopy( p, &issuer_dn );
4768 p = lutil_strcopy( p, "\" }, serial " );
4769 p = lutil_strbvcopy( p, &i_sn2 );
4770 p = lutil_strcopy( p, " } } }" );
4772 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4773 normalized->bv_val, NULL, NULL );
4778 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4779 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4780 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4793 assert( in != NULL );
4794 assert( !BER_BVISNULL( in ) );
4796 for ( i = 0; i < in->bv_len; i++ ) {
4797 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4798 return LDAP_INVALID_SYNTAX;
4802 return LDAP_SUCCESS;
4805 /* Normalize a SID as used inside a CSN:
4806 * three-digit numeric string */
4813 struct berval *normalized,
4818 assert( val != NULL );
4819 assert( normalized != NULL );
4821 ber_dupbv_x( normalized, val, ctx );
4823 for ( i = 0; i < normalized->bv_len; i++ ) {
4824 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4825 ber_memfree_x( normalized->bv_val, ctx );
4826 BER_BVZERO( normalized );
4827 return LDAP_INVALID_SYNTAX;
4830 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4833 return LDAP_SUCCESS;
4841 assert( in != NULL );
4842 assert( !BER_BVISNULL( in ) );
4844 if ( in->bv_len != 3 ) {
4845 return LDAP_INVALID_SYNTAX;
4848 return hexValidate( NULL, in );
4851 /* Normalize a SID as used inside a CSN:
4852 * three-digit numeric string */
4859 struct berval *normalized,
4862 if ( val->bv_len != 3 ) {
4863 return LDAP_INVALID_SYNTAX;
4866 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4876 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4879 /* Normalize a SID as used inside a CSN, either as-is
4880 * (assertion value) or extracted from the CSN
4881 * (attribute value) */
4888 struct berval *normalized,
4896 if ( BER_BVISEMPTY( val ) ) {
4897 return LDAP_INVALID_SYNTAX;
4900 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4901 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4904 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4906 ptr = ber_bvchr( val, '#' );
4907 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4908 return LDAP_INVALID_SYNTAX;
4911 bv.bv_val = ptr + 1;
4912 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4914 ptr = ber_bvchr( &bv, '#' );
4915 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4916 return LDAP_INVALID_SYNTAX;
4919 bv.bv_val = ptr + 1;
4920 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4922 ptr = ber_bvchr( &bv, '#' );
4923 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4924 return LDAP_INVALID_SYNTAX;
4927 bv.bv_len = ptr - bv.bv_val;
4929 if ( bv.bv_len == 2 ) {
4930 /* OpenLDAP 2.3 SID */
4932 buf[ 1 ] = bv.bv_val[ 0 ];
4933 buf[ 2 ] = bv.bv_val[ 1 ];
4940 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4952 assert( in != NULL );
4953 assert( !BER_BVISNULL( in ) );
4955 if ( BER_BVISEMPTY( in ) ) {
4956 return LDAP_INVALID_SYNTAX;
4961 ptr = ber_bvchr( &bv, '#' );
4962 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4963 return LDAP_INVALID_SYNTAX;
4966 bv.bv_len = ptr - bv.bv_val;
4967 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4968 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4970 return LDAP_INVALID_SYNTAX;
4973 rc = generalizedTimeValidate( NULL, &bv );
4974 if ( rc != LDAP_SUCCESS ) {
4978 bv.bv_val = ptr + 1;
4979 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4981 ptr = ber_bvchr( &bv, '#' );
4982 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4983 return LDAP_INVALID_SYNTAX;
4986 bv.bv_len = ptr - bv.bv_val;
4987 if ( bv.bv_len != 6 ) {
4988 return LDAP_INVALID_SYNTAX;
4991 rc = hexValidate( NULL, &bv );
4992 if ( rc != LDAP_SUCCESS ) {
4996 bv.bv_val = ptr + 1;
4997 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4999 ptr = ber_bvchr( &bv, '#' );
5000 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5001 return LDAP_INVALID_SYNTAX;
5004 bv.bv_len = ptr - bv.bv_val;
5005 if ( bv.bv_len == 2 ) {
5006 /* tolerate old 2-digit replica-id */
5007 rc = hexValidate( NULL, &bv );
5010 rc = sidValidate( NULL, &bv );
5012 if ( rc != LDAP_SUCCESS ) {
5016 bv.bv_val = ptr + 1;
5017 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5019 if ( bv.bv_len != 6 ) {
5020 return LDAP_INVALID_SYNTAX;
5023 return hexValidate( NULL, &bv );
5026 /* Normalize a CSN in OpenLDAP 2.1 format */
5033 struct berval *normalized,
5036 struct berval gt, cnt, sid, mod;
5038 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5042 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5043 assert( !BER_BVISEMPTY( val ) );
5047 ptr = ber_bvchr( >, '#' );
5048 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5049 return LDAP_INVALID_SYNTAX;
5052 gt.bv_len = ptr - gt.bv_val;
5053 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5054 return LDAP_INVALID_SYNTAX;
5057 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5058 return LDAP_INVALID_SYNTAX;
5061 cnt.bv_val = ptr + 1;
5062 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5064 ptr = ber_bvchr( &cnt, '#' );
5065 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5066 return LDAP_INVALID_SYNTAX;
5069 cnt.bv_len = ptr - cnt.bv_val;
5070 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5071 return LDAP_INVALID_SYNTAX;
5074 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5075 return LDAP_INVALID_SYNTAX;
5078 cnt.bv_val += STRLENOF( "0x" );
5079 cnt.bv_len -= STRLENOF( "0x" );
5081 sid.bv_val = ptr + 1;
5082 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5084 ptr = ber_bvchr( &sid, '#' );
5085 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5086 return LDAP_INVALID_SYNTAX;
5089 sid.bv_len = ptr - sid.bv_val;
5090 if ( sid.bv_len != STRLENOF( "0" ) ) {
5091 return LDAP_INVALID_SYNTAX;
5094 mod.bv_val = ptr + 1;
5095 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5096 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5097 return LDAP_INVALID_SYNTAX;
5100 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5104 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5105 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5107 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5109 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5110 ptr = lutil_strbvcopy( ptr, &cnt );
5114 *ptr++ = sid.bv_val[ 0 ];
5118 for ( i = 0; i < mod.bv_len; i++ ) {
5119 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5123 assert( ptr == &bv.bv_val[bv.bv_len] );
5125 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5126 return LDAP_INVALID_SYNTAX;
5129 ber_dupbv_x( normalized, &bv, ctx );
5131 return LDAP_SUCCESS;
5134 /* Normalize a CSN in OpenLDAP 2.3 format */
5141 struct berval *normalized,
5144 struct berval gt, cnt, sid, mod;
5146 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5150 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5151 assert( !BER_BVISEMPTY( val ) );
5155 ptr = ber_bvchr( >, '#' );
5156 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5157 return LDAP_INVALID_SYNTAX;
5160 gt.bv_len = ptr - gt.bv_val;
5161 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5162 return LDAP_INVALID_SYNTAX;
5165 cnt.bv_val = ptr + 1;
5166 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5168 ptr = ber_bvchr( &cnt, '#' );
5169 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5170 return LDAP_INVALID_SYNTAX;
5173 cnt.bv_len = ptr - cnt.bv_val;
5174 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5175 return LDAP_INVALID_SYNTAX;
5178 sid.bv_val = ptr + 1;
5179 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5181 ptr = ber_bvchr( &sid, '#' );
5182 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5183 return LDAP_INVALID_SYNTAX;
5186 sid.bv_len = ptr - sid.bv_val;
5187 if ( sid.bv_len != STRLENOF( "00" ) ) {
5188 return LDAP_INVALID_SYNTAX;
5191 mod.bv_val = ptr + 1;
5192 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5193 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5194 return LDAP_INVALID_SYNTAX;
5197 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5201 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5202 ptr = lutil_strcopy( ptr, ".000000Z#" );
5203 ptr = lutil_strbvcopy( ptr, &cnt );
5206 for ( i = 0; i < sid.bv_len; i++ ) {
5207 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5210 for ( i = 0; i < mod.bv_len; i++ ) {
5211 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5215 assert( ptr == &bv.bv_val[bv.bv_len] );
5216 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5217 return LDAP_INVALID_SYNTAX;
5220 ber_dupbv_x( normalized, &bv, ctx );
5222 return LDAP_SUCCESS;
5225 /* Normalize a CSN */
5232 struct berval *normalized,
5235 struct berval cnt, sid, mod;
5239 assert( val != NULL );
5240 assert( normalized != NULL );
5242 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5244 if ( BER_BVISEMPTY( val ) ) {
5245 return LDAP_INVALID_SYNTAX;
5248 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5249 /* Openldap <= 2.3 */
5251 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5254 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5257 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5260 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5261 return LDAP_INVALID_SYNTAX;
5264 ptr = ber_bvchr( val, '#' );
5265 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5266 return LDAP_INVALID_SYNTAX;
5269 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5270 return LDAP_INVALID_SYNTAX;
5273 cnt.bv_val = ptr + 1;
5274 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5276 ptr = ber_bvchr( &cnt, '#' );
5277 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5278 return LDAP_INVALID_SYNTAX;
5281 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5282 return LDAP_INVALID_SYNTAX;
5285 sid.bv_val = ptr + 1;
5286 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5288 ptr = ber_bvchr( &sid, '#' );
5289 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5290 return LDAP_INVALID_SYNTAX;
5293 sid.bv_len = ptr - sid.bv_val;
5294 if ( sid.bv_len != STRLENOF( "000" ) ) {
5295 return LDAP_INVALID_SYNTAX;
5298 mod.bv_val = ptr + 1;
5299 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5301 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5302 return LDAP_INVALID_SYNTAX;
5305 ber_dupbv_x( normalized, val, ctx );
5307 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5308 i < normalized->bv_len; i++ )
5310 /* assume it's already validated that's all hex digits */
5311 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5314 return LDAP_SUCCESS;
5324 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5327 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5328 /* slight optimization - does not need the start parameter */
5329 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5334 check_time_syntax (struct berval *val,
5337 struct berval *fraction)
5340 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5341 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5342 * GeneralizedTime supports leap seconds, UTCTime does not.
5344 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5345 static const int mdays[2][12] = {
5346 /* non-leap years */
5347 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5349 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5352 int part, c, c1, c2, tzoffset, leapyear = 0;
5355 e = p + val->bv_len;
5357 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5358 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5360 for (part = start; part < 7 && p < e; part++) {
5362 if (!ASCII_DIGIT(c1)) {
5367 return LDAP_INVALID_SYNTAX;
5370 if (!ASCII_DIGIT(c)) {
5371 return LDAP_INVALID_SYNTAX;
5373 c += c1 * 10 - '0' * 11;
5374 if ((part | 1) == 3) {
5377 return LDAP_INVALID_SYNTAX;
5380 if (c >= ceiling[part]) {
5381 if (! (c == 60 && part == 6 && start == 0))
5382 return LDAP_INVALID_SYNTAX;
5386 if (part < 5 + start) {
5387 return LDAP_INVALID_SYNTAX;
5389 for (; part < 9; part++) {
5393 /* leapyear check for the Gregorian calendar (year>1581) */
5394 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5398 if (parts[3] >= mdays[leapyear][parts[2]]) {
5399 return LDAP_INVALID_SYNTAX;
5403 fraction->bv_val = p;
5404 fraction->bv_len = 0;
5405 if (p < e && (*p == '.' || *p == ',')) {
5407 while (++p < e && ASCII_DIGIT(*p)) {
5410 if (p - fraction->bv_val == 1) {
5411 return LDAP_INVALID_SYNTAX;
5413 for (end_num = p; end_num[-1] == '0'; --end_num) {
5416 c = end_num - fraction->bv_val;
5417 if (c != 1) fraction->bv_len = c;
5423 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5429 return LDAP_INVALID_SYNTAX;
5435 for (part = 7; part < 9 && p < e; part++) {
5437 if (!ASCII_DIGIT(c1)) {
5442 return LDAP_INVALID_SYNTAX;
5445 if (!ASCII_DIGIT(c2)) {
5446 return LDAP_INVALID_SYNTAX;
5448 parts[part] = c1 * 10 + c2 - '0' * 11;
5449 if (parts[part] >= ceiling[part]) {
5450 return LDAP_INVALID_SYNTAX;
5453 if (part < 8 + start) {
5454 return LDAP_INVALID_SYNTAX;
5457 if (tzoffset == '-') {
5458 /* negative offset to UTC, ie west of Greenwich */
5459 parts[4] += parts[7];
5460 parts[5] += parts[8];
5461 /* offset is just hhmm, no seconds */
5462 for (part = 6; --part >= 0; ) {
5466 c = mdays[leapyear][parts[2]];
5468 if (parts[part] >= c) {
5470 return LDAP_INVALID_SYNTAX;
5475 } else if (part != 5) {
5480 /* positive offset to UTC, ie east of Greenwich */
5481 parts[4] -= parts[7];
5482 parts[5] -= parts[8];
5483 for (part = 6; --part >= 0; ) {
5484 if (parts[part] < 0) {
5486 return LDAP_INVALID_SYNTAX;
5491 /* make first arg to % non-negative */
5492 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5497 } else if (part != 5) {
5504 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5507 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5514 struct berval *normalized )
5518 rc = check_time_syntax(val, 1, parts, NULL);
5519 if (rc != LDAP_SUCCESS) {
5523 normalized->bv_val = ch_malloc( 14 );
5524 if ( normalized->bv_val == NULL ) {
5525 return LBER_ERROR_MEMORY;
5528 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5529 parts[1], parts[2] + 1, parts[3] + 1,
5530 parts[4], parts[5], parts[6] );
5531 normalized->bv_len = 13;
5533 return LDAP_SUCCESS;
5543 return check_time_syntax(in, 1, parts, NULL);
5546 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5549 generalizedTimeValidate(
5554 struct berval fraction;
5555 return check_time_syntax(in, 0, parts, &fraction);
5559 generalizedTimeNormalize(
5564 struct berval *normalized,
5569 struct berval fraction;
5571 rc = check_time_syntax(val, 0, parts, &fraction);
5572 if (rc != LDAP_SUCCESS) {
5576 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5577 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5578 if ( BER_BVISNULL( normalized ) ) {
5579 return LBER_ERROR_MEMORY;
5582 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5583 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5584 parts[4], parts[5], parts[6] );
5585 if ( !BER_BVISEMPTY( &fraction ) ) {
5586 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5587 fraction.bv_val, fraction.bv_len );
5588 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5590 strcpy( normalized->bv_val + len-1, "Z" );
5591 normalized->bv_len = len;
5593 return LDAP_SUCCESS;
5597 generalizedTimeOrderingMatch(
5602 struct berval *value,
5603 void *assertedValue )
5605 struct berval *asserted = (struct berval *) assertedValue;
5606 ber_len_t v_len = value->bv_len;
5607 ber_len_t av_len = asserted->bv_len;
5609 /* ignore trailing 'Z' when comparing */
5610 int match = memcmp( value->bv_val, asserted->bv_val,
5611 (v_len < av_len ? v_len : av_len) - 1 );
5612 if ( match == 0 ) match = v_len - av_len;
5615 return LDAP_SUCCESS;
5618 /* Index generation function */
5619 int generalizedTimeIndexer(
5624 struct berval *prefix,
5632 BerValue bvtmp; /* 40 bit index */
5634 struct lutil_timet tt;
5636 bvtmp.bv_len = sizeof(tmp);
5638 for( i=0; values[i].bv_val != NULL; i++ ) {
5639 /* just count them */
5642 /* we should have at least one value at this point */
5645 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5647 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5648 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5649 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5650 /* Use 40 bits of time for key */
5651 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5652 lutil_tm2time( &tm, &tt );
5653 tmp[0] = tt.tt_gsec & 0xff;
5654 tmp[4] = tt.tt_sec & 0xff;
5656 tmp[3] = tt.tt_sec & 0xff;
5658 tmp[2] = tt.tt_sec & 0xff;
5660 tmp[1] = tt.tt_sec & 0xff;
5662 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5666 keys[j].bv_val = NULL;
5671 return LDAP_SUCCESS;
5674 /* Index generation function */
5675 int generalizedTimeFilter(
5680 struct berval *prefix,
5681 void * assertedValue,
5687 BerValue bvtmp; /* 40 bit index */
5688 BerValue *value = (BerValue *) assertedValue;
5690 struct lutil_timet tt;
5692 bvtmp.bv_len = sizeof(tmp);
5694 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5695 /* Use 40 bits of time for key */
5696 if ( value->bv_val && value->bv_len >= 10 &&
5697 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5699 lutil_tm2time( &tm, &tt );
5700 tmp[0] = tt.tt_gsec & 0xff;
5701 tmp[4] = tt.tt_sec & 0xff;
5703 tmp[3] = tt.tt_sec & 0xff;
5705 tmp[2] = tt.tt_sec & 0xff;
5707 tmp[1] = tt.tt_sec & 0xff;
5709 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5710 ber_dupbv_x(keys, &bvtmp, ctx );
5711 keys[1].bv_val = NULL;
5719 return LDAP_SUCCESS;
5723 deliveryMethodValidate(
5725 struct berval *val )
5728 #define LENOF(s) (sizeof(s)-1)
5729 struct berval tmp = *val;
5731 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5732 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5733 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5736 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5738 switch( tmp.bv_val[0] ) {
5741 if(( tmp.bv_len >= LENOF("any") ) &&
5742 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5744 tmp.bv_len -= LENOF("any");
5745 tmp.bv_val += LENOF("any");
5748 return LDAP_INVALID_SYNTAX;
5752 if(( tmp.bv_len >= LENOF("mhs") ) &&
5753 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5755 tmp.bv_len -= LENOF("mhs");
5756 tmp.bv_val += LENOF("mhs");
5759 return LDAP_INVALID_SYNTAX;
5763 if(( tmp.bv_len >= LENOF("physical") ) &&
5764 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5766 tmp.bv_len -= LENOF("physical");
5767 tmp.bv_val += LENOF("physical");
5770 return LDAP_INVALID_SYNTAX;
5773 case 'T': /* telex or teletex or telephone */
5774 if(( tmp.bv_len >= LENOF("telex") ) &&
5775 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5777 tmp.bv_len -= LENOF("telex");
5778 tmp.bv_val += LENOF("telex");
5781 if(( tmp.bv_len >= LENOF("teletex") ) &&
5782 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5784 tmp.bv_len -= LENOF("teletex");
5785 tmp.bv_val += LENOF("teletex");
5788 if(( tmp.bv_len >= LENOF("telephone") ) &&
5789 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5791 tmp.bv_len -= LENOF("telephone");
5792 tmp.bv_val += LENOF("telephone");
5795 return LDAP_INVALID_SYNTAX;
5798 case 'G': /* g3fax or g4fax */
5799 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5800 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5801 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5803 tmp.bv_len -= LENOF("g3fax");
5804 tmp.bv_val += LENOF("g3fax");
5807 return LDAP_INVALID_SYNTAX;
5811 if(( tmp.bv_len >= LENOF("ia5") ) &&
5812 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5814 tmp.bv_len -= LENOF("ia5");
5815 tmp.bv_val += LENOF("ia5");
5818 return LDAP_INVALID_SYNTAX;
5822 if(( tmp.bv_len >= LENOF("videotex") ) &&
5823 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5825 tmp.bv_len -= LENOF("videotex");
5826 tmp.bv_val += LENOF("videotex");
5829 return LDAP_INVALID_SYNTAX;
5832 return LDAP_INVALID_SYNTAX;
5835 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5837 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5841 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5845 return LDAP_INVALID_SYNTAX;
5847 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5856 nisNetgroupTripleValidate(
5858 struct berval *val )
5863 if ( BER_BVISEMPTY( val ) ) {
5864 return LDAP_INVALID_SYNTAX;
5867 p = (char *)val->bv_val;
5868 e = p + val->bv_len;
5870 if ( *p != '(' /*')'*/ ) {
5871 return LDAP_INVALID_SYNTAX;
5874 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5878 return LDAP_INVALID_SYNTAX;
5881 } else if ( !AD_CHAR( *p ) ) {
5882 return LDAP_INVALID_SYNTAX;
5886 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5887 return LDAP_INVALID_SYNTAX;
5893 return LDAP_INVALID_SYNTAX;
5896 return LDAP_SUCCESS;
5900 bootParameterValidate(
5902 struct berval *val )
5906 if ( BER_BVISEMPTY( val ) ) {
5907 return LDAP_INVALID_SYNTAX;
5910 p = (char *)val->bv_val;
5911 e = p + val->bv_len;
5914 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5915 if ( !AD_CHAR( *p ) ) {
5916 return LDAP_INVALID_SYNTAX;
5921 return LDAP_INVALID_SYNTAX;
5925 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5926 if ( !AD_CHAR( *p ) ) {
5927 return LDAP_INVALID_SYNTAX;
5932 return LDAP_INVALID_SYNTAX;
5936 for ( p++; p < e; p++ ) {
5937 if ( !SLAP_PRINTABLE( *p ) ) {
5938 return LDAP_INVALID_SYNTAX;
5942 return LDAP_SUCCESS;
5946 firstComponentNormalize(
5951 struct berval *normalized,
5958 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5959 ber_dupbv_x( normalized, val, ctx );
5960 return LDAP_SUCCESS;
5963 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5965 if( ! ( val->bv_val[0] == '(' /*')'*/
5966 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5967 && ! ( val->bv_val[0] == '{' /*'}'*/
5968 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5970 return LDAP_INVALID_SYNTAX;
5973 /* trim leading white space */
5975 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5981 /* grab next word */
5982 comp.bv_val = &val->bv_val[len];
5983 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5984 for( comp.bv_len = 0;
5985 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5991 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5992 rc = numericoidValidate( NULL, &comp );
5993 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5994 rc = integerValidate( NULL, &comp );
5996 rc = LDAP_INVALID_SYNTAX;
6000 if( rc == LDAP_SUCCESS ) {
6001 ber_dupbv_x( normalized, &comp, ctx );
6007 static char *country_gen_syn[] = {
6008 "1.3.6.1.4.1.1466.115.121.1.15",
6009 "1.3.6.1.4.1.1466.115.121.1.26",
6010 "1.3.6.1.4.1.1466.115.121.1.44",
6014 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6015 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6017 static slap_syntax_defs_rec syntax_defs[] = {
6018 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6019 X_BINARY X_NOT_H_R ")",
6020 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6021 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6022 0, NULL, NULL, NULL},
6023 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6024 0, NULL, NULL, NULL},
6025 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6027 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6028 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6030 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6031 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6032 0, NULL, bitStringValidate, NULL },
6033 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6034 0, NULL, booleanValidate, NULL},
6035 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6036 X_BINARY X_NOT_H_R ")",
6037 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6038 NULL, certificateValidate, NULL},
6039 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6040 X_BINARY X_NOT_H_R ")",
6041 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6042 NULL, certificateListValidate, NULL},
6043 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6044 X_BINARY X_NOT_H_R ")",
6045 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6046 NULL, sequenceValidate, NULL},
6047 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6048 X_BINARY X_NOT_H_R ")",
6049 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6050 NULL, attributeCertificateValidate, NULL},
6051 #if 0 /* need to go __after__ printableString */
6052 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6053 0, "1.3.6.1.4.1.1466.115.121.1.44",
6054 countryStringValidate, NULL},
6056 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6057 0, NULL, dnValidate, dnPretty},
6058 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6059 0, NULL, rdnValidate, rdnPretty},
6060 #ifdef LDAP_COMP_MATCH
6061 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6062 0, NULL, allComponentsValidate, NULL},
6063 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6064 0, NULL, componentFilterValidate, NULL},
6066 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6067 0, NULL, NULL, NULL},
6068 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6069 0, NULL, deliveryMethodValidate, NULL},
6070 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6071 0, NULL, UTF8StringValidate, NULL},
6072 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6073 0, NULL, NULL, NULL},
6074 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6075 0, NULL, NULL, NULL},
6076 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6077 0, NULL, NULL, NULL},
6078 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6079 0, NULL, NULL, NULL},
6080 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6081 0, NULL, NULL, NULL},
6082 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6083 0, NULL, printablesStringValidate, NULL},
6084 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6085 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6086 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6087 0, NULL, generalizedTimeValidate, NULL},
6088 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6089 0, NULL, NULL, NULL},
6090 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6091 0, NULL, IA5StringValidate, NULL},
6092 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6093 0, NULL, integerValidate, NULL},
6094 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6095 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6096 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6097 0, NULL, NULL, NULL},
6098 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6099 0, NULL, NULL, NULL},
6100 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6101 0, NULL, NULL, NULL},
6102 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6103 0, NULL, NULL, NULL},
6104 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6105 0, NULL, NULL, NULL},
6106 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6107 0, NULL, nameUIDValidate, nameUIDPretty },
6108 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6109 0, NULL, NULL, NULL},
6110 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6111 0, NULL, numericStringValidate, NULL},
6112 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6113 0, NULL, NULL, NULL},
6114 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6115 0, NULL, numericoidValidate, NULL},
6116 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6117 0, NULL, IA5StringValidate, NULL},
6118 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6119 0, NULL, blobValidate, NULL},
6120 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6121 0, NULL, postalAddressValidate, NULL},
6122 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6123 0, NULL, NULL, NULL},
6124 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6125 0, NULL, NULL, NULL},
6126 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6127 0, NULL, printableStringValidate, NULL},
6128 /* moved here because now depends on Directory String, IA5 String
6129 * and Printable String */
6130 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6131 0, country_gen_syn, countryStringValidate, NULL},
6132 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6133 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6134 0, NULL, subtreeSpecificationValidate, NULL},
6135 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6136 X_BINARY X_NOT_H_R ")",
6137 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6138 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6139 0, NULL, printableStringValidate, NULL},
6140 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6141 0, NULL, NULL, NULL},
6142 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6143 0, NULL, printablesStringValidate, NULL},
6144 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6145 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6146 0, NULL, utcTimeValidate, NULL},
6148 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6149 0, NULL, NULL, NULL},
6150 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6151 0, NULL, NULL, NULL},
6152 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6153 0, NULL, NULL, NULL},
6154 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6155 0, NULL, NULL, NULL},
6156 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6157 0, NULL, NULL, NULL},
6159 /* RFC 2307 NIS Syntaxes */
6160 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6161 0, NULL, nisNetgroupTripleValidate, NULL},
6162 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6163 0, NULL, bootParameterValidate, NULL},
6165 /* draft-zeilenga-ldap-x509 */
6166 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6167 SLAP_SYNTAX_HIDE, NULL,
6168 serialNumberAndIssuerValidate,
6169 serialNumberAndIssuerPretty},
6170 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6171 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6172 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6173 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6174 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6175 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6176 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6177 SLAP_SYNTAX_HIDE, NULL,
6178 issuerAndThisUpdateValidate,
6179 issuerAndThisUpdatePretty},
6180 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6181 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6182 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6183 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6184 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6185 SLAP_SYNTAX_HIDE, NULL,
6186 serialNumberAndIssuerSerialValidate,
6187 serialNumberAndIssuerSerialPretty},
6188 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6189 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6191 #ifdef SLAPD_AUTHPASSWD
6192 /* needs updating */
6193 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6194 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6197 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6198 0, NULL, UUIDValidate, UUIDPretty},
6200 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6201 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6203 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6204 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6206 /* OpenLDAP Void Syntax */
6207 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6208 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6210 /* FIXME: OID is unused, but not registered yet */
6211 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6212 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6214 {NULL, 0, NULL, NULL, NULL}
6217 char *csnSIDMatchSyntaxes[] = {
6218 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6221 char *certificateExactMatchSyntaxes[] = {
6222 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6225 char *certificateListExactMatchSyntaxes[] = {
6226 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6229 char *attributeCertificateExactMatchSyntaxes[] = {
6230 attributeCertificateSyntaxOID /* attributeCertificate */,
6234 #ifdef LDAP_COMP_MATCH
6235 char *componentFilterMatchSyntaxes[] = {
6236 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6237 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6238 attributeCertificateSyntaxOID /* attributeCertificate */,
6243 char *directoryStringSyntaxes[] = {
6244 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6247 char *integerFirstComponentMatchSyntaxes[] = {
6248 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6249 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6252 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6253 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6254 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6255 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6256 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6257 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6258 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6259 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6260 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6265 * Other matching rules in X.520 that we do not use (yet):
6267 * 2.5.13.25 uTCTimeMatch
6268 * 2.5.13.26 uTCTimeOrderingMatch
6269 * 2.5.13.31* directoryStringFirstComponentMatch
6270 * 2.5.13.32* wordMatch
6271 * 2.5.13.33* keywordMatch
6272 * 2.5.13.36+ certificatePairExactMatch
6273 * 2.5.13.37+ certificatePairMatch
6274 * 2.5.13.40+ algorithmIdentifierMatch
6275 * 2.5.13.41* storedPrefixMatch
6276 * 2.5.13.42 attributeCertificateMatch
6277 * 2.5.13.43 readerAndKeyIDMatch
6278 * 2.5.13.44 attributeIntegrityMatch
6280 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6281 * (+) described in draft-zeilenga-ldap-x509
6283 static slap_mrule_defs_rec mrule_defs[] = {
6285 * EQUALITY matching rules must be listed after associated APPROX
6286 * matching rules. So, we list all APPROX matching rules first.
6288 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6289 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6290 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6291 NULL, NULL, directoryStringApproxMatch,
6292 directoryStringApproxIndexer, directoryStringApproxFilter,
6295 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6296 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6297 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6298 NULL, NULL, IA5StringApproxMatch,
6299 IA5StringApproxIndexer, IA5StringApproxFilter,
6303 * Other matching rules
6306 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6307 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6308 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6309 NULL, NULL, octetStringMatch,
6310 octetStringIndexer, octetStringFilter,
6313 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6314 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6315 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6316 NULL, dnNormalize, dnMatch,
6317 octetStringIndexer, octetStringFilter,
6320 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6321 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6322 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6323 NULL, dnNormalize, dnRelativeMatch,
6327 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6328 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6329 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6330 NULL, dnNormalize, dnRelativeMatch,
6334 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6335 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6336 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6337 NULL, dnNormalize, dnRelativeMatch,
6341 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6342 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6343 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6344 NULL, dnNormalize, dnRelativeMatch,
6348 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6349 "SYNTAX 1.2.36.79672281.1.5.0 )",
6350 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6351 NULL, rdnNormalize, rdnMatch,
6352 octetStringIndexer, octetStringFilter,
6355 #ifdef LDAP_COMP_MATCH
6356 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6357 "SYNTAX 1.2.36.79672281.1.5.2 )",
6358 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6359 NULL, NULL , componentFilterMatch,
6360 octetStringIndexer, octetStringFilter,
6363 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6364 "SYNTAX 1.2.36.79672281.1.5.3 )",
6365 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6366 NULL, NULL , allComponentsMatch,
6367 octetStringIndexer, octetStringFilter,
6370 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6371 "SYNTAX 1.2.36.79672281.1.5.3 )",
6372 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6373 NULL, NULL , directoryComponentsMatch,
6374 octetStringIndexer, octetStringFilter,
6378 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6379 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6380 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6381 NULL, UTF8StringNormalize, octetStringMatch,
6382 octetStringIndexer, octetStringFilter,
6383 directoryStringApproxMatchOID },
6385 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6386 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6387 SLAP_MR_ORDERING, directoryStringSyntaxes,
6388 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6390 "caseIgnoreMatch" },
6392 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6393 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6394 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6395 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6396 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6397 "caseIgnoreMatch" },
6399 {"( 2.5.13.5 NAME 'caseExactMatch' "
6400 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6401 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6402 NULL, UTF8StringNormalize, octetStringMatch,
6403 octetStringIndexer, octetStringFilter,
6404 directoryStringApproxMatchOID },
6406 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6407 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6408 SLAP_MR_ORDERING, directoryStringSyntaxes,
6409 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6413 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6414 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6415 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6416 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6417 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6420 {"( 2.5.13.8 NAME 'numericStringMatch' "
6421 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6422 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6423 NULL, numericStringNormalize, octetStringMatch,
6424 octetStringIndexer, octetStringFilter,
6427 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6428 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6429 SLAP_MR_ORDERING, NULL,
6430 NULL, numericStringNormalize, octetStringOrderingMatch,
6432 "numericStringMatch" },
6434 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6435 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6436 SLAP_MR_SUBSTR, NULL,
6437 NULL, numericStringNormalize, octetStringSubstringsMatch,
6438 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6439 "numericStringMatch" },
6441 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6442 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6443 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6444 NULL, postalAddressNormalize, octetStringMatch,
6445 octetStringIndexer, octetStringFilter,
6448 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6449 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6450 SLAP_MR_SUBSTR, NULL,
6451 NULL, NULL, NULL, NULL, NULL,
6452 "caseIgnoreListMatch" },
6454 {"( 2.5.13.13 NAME 'booleanMatch' "
6455 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6456 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6457 NULL, NULL, booleanMatch,
6458 octetStringIndexer, octetStringFilter,
6461 {"( 2.5.13.14 NAME 'integerMatch' "
6462 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6463 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6464 NULL, NULL, integerMatch,
6465 integerIndexer, integerFilter,
6468 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6470 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6471 NULL, NULL, integerMatch,
6475 {"( 2.5.13.16 NAME 'bitStringMatch' "
6476 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6477 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6478 NULL, NULL, octetStringMatch,
6479 octetStringIndexer, octetStringFilter,
6482 {"( 2.5.13.17 NAME 'octetStringMatch' "
6483 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6484 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6485 NULL, NULL, octetStringMatch,
6486 octetStringIndexer, octetStringFilter,
6489 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6490 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6491 SLAP_MR_ORDERING, NULL,
6492 NULL, NULL, octetStringOrderingMatch,
6494 "octetStringMatch" },
6496 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6497 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6498 SLAP_MR_SUBSTR, NULL,
6499 NULL, NULL, octetStringSubstringsMatch,
6500 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6501 "octetStringMatch" },
6503 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6504 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6505 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6507 telephoneNumberNormalize, octetStringMatch,
6508 octetStringIndexer, octetStringFilter,
6511 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6512 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6513 SLAP_MR_SUBSTR, NULL,
6514 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6515 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6516 "telephoneNumberMatch" },
6518 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6519 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6520 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6521 NULL, NULL, NULL, NULL, NULL, NULL },
6523 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6524 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6525 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6526 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6527 uniqueMemberIndexer, uniqueMemberFilter,
6530 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6531 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6532 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6533 NULL, NULL, NULL, NULL, NULL, NULL },
6535 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6536 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6537 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6538 NULL, generalizedTimeNormalize, octetStringMatch,
6539 generalizedTimeIndexer, generalizedTimeFilter,
6542 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6543 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6544 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6545 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6547 "generalizedTimeMatch" },
6549 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6550 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6551 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6552 integerFirstComponentMatchSyntaxes,
6553 NULL, firstComponentNormalize, integerMatch,
6554 octetStringIndexer, octetStringFilter,
6557 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6559 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6560 objectIdentifierFirstComponentMatchSyntaxes,
6561 NULL, firstComponentNormalize, octetStringMatch,
6562 octetStringIndexer, octetStringFilter,
6565 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6566 "SYNTAX 1.3.6.1.1.15.1 )",
6567 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6568 NULL, certificateExactNormalize, octetStringMatch,
6569 octetStringIndexer, octetStringFilter,
6572 {"( 2.5.13.35 NAME 'certificateMatch' "
6573 "SYNTAX 1.3.6.1.1.15.2 )",
6574 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6575 NULL, NULL, NULL, NULL, NULL,
6578 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6579 "SYNTAX 1.3.6.1.1.15.5 )",
6580 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6581 NULL, certificateListExactNormalize, octetStringMatch,
6582 octetStringIndexer, octetStringFilter,
6585 {"( 2.5.13.39 NAME 'certificateListMatch' "
6586 "SYNTAX 1.3.6.1.1.15.6 )",
6587 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6588 NULL, NULL, NULL, NULL, NULL,
6591 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6592 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6593 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6594 NULL, attributeCertificateExactNormalize, octetStringMatch,
6595 octetStringIndexer, octetStringFilter,
6598 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6599 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6600 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6601 NULL, NULL, NULL, NULL, NULL,
6604 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6605 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6606 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6607 NULL, IA5StringNormalize, octetStringMatch,
6608 octetStringIndexer, octetStringFilter,
6609 IA5StringApproxMatchOID },
6611 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6612 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6613 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6614 NULL, IA5StringNormalize, octetStringMatch,
6615 octetStringIndexer, octetStringFilter,
6616 IA5StringApproxMatchOID },
6618 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6619 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6620 SLAP_MR_SUBSTR, NULL,
6621 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6622 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6623 "caseIgnoreIA5Match" },
6625 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6626 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6627 SLAP_MR_SUBSTR, NULL,
6628 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6629 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6630 "caseExactIA5Match" },
6632 #ifdef SLAPD_AUTHPASSWD
6633 /* needs updating */
6634 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6635 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6636 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6637 NULL, NULL, authPasswordMatch,
6642 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6643 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6645 NULL, NULL, integerBitAndMatch,
6649 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6652 NULL, NULL, integerBitOrMatch,
6656 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6657 "SYNTAX 1.3.6.1.1.16.1 )",
6658 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6659 NULL, UUIDNormalize, octetStringMatch,
6660 octetStringIndexer, octetStringFilter,
6663 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6664 "SYNTAX 1.3.6.1.1.16.1 )",
6665 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6666 NULL, UUIDNormalize, octetStringOrderingMatch,
6667 octetStringIndexer, octetStringFilter,
6670 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6671 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6672 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6673 NULL, csnNormalize, csnMatch,
6674 csnIndexer, csnFilter,
6677 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6678 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6679 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6680 NULL, csnNormalize, csnOrderingMatch,
6684 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6685 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6686 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6687 NULL, csnSidNormalize, octetStringMatch,
6688 octetStringIndexer, octetStringFilter,
6691 /* FIXME: OID is unused, but not registered yet */
6692 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6693 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6694 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6695 NULL, authzNormalize, authzMatch,
6699 {NULL, SLAP_MR_NONE, NULL,
6700 NULL, NULL, NULL, NULL, NULL,
6705 slap_schema_init( void )
6710 /* we should only be called once (from main) */
6711 assert( schema_init_done == 0 );
6713 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6714 res = register_syntax( &syntax_defs[i] );
6717 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6718 syntax_defs[i].sd_desc );
6723 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6724 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6725 mrule_defs[i].mrd_compat_syntaxes == NULL )
6728 "slap_schema_init: Ignoring unusable matching rule %s\n",
6729 mrule_defs[i].mrd_desc );
6733 res = register_matching_rule( &mrule_defs[i] );
6737 "slap_schema_init: Error registering matching rule %s\n",
6738 mrule_defs[i].mrd_desc );
6743 res = slap_schema_load();
6744 schema_init_done = 1;
6749 schema_destroy( void )
6758 if( schema_init_done ) {
6759 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6760 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );