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_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2274 assert( p == &normalized->bv_val[normalized->bv_len] );
2277 if ( nlines != NULL ) {
2278 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2279 slap_sl_free( nlines[l].bv_val, ctx );
2282 slap_sl_free( lines, ctx );
2293 struct berval val = *in;
2295 if( BER_BVISEMPTY( &val ) ) {
2296 /* disallow empty strings */
2297 return LDAP_INVALID_SYNTAX;
2300 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2301 if ( val.bv_len == 1 ) {
2302 return LDAP_SUCCESS;
2305 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2312 while ( OID_LEADCHAR( val.bv_val[0] )) {
2316 if ( val.bv_len == 0 ) {
2317 return LDAP_SUCCESS;
2321 if( !OID_SEPARATOR( val.bv_val[0] )) {
2329 return LDAP_INVALID_SYNTAX;
2338 struct berval val = *in;
2340 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2342 if ( val.bv_val[0] == '-' ) {
2346 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2347 return LDAP_INVALID_SYNTAX;
2350 if( val.bv_val[0] == '0' ) { /* "-0" */
2351 return LDAP_INVALID_SYNTAX;
2354 } else if ( val.bv_val[0] == '0' ) {
2355 if( val.bv_len > 1 ) { /* "0<more>" */
2356 return LDAP_INVALID_SYNTAX;
2359 return LDAP_SUCCESS;
2362 for( i=0; i < val.bv_len; i++ ) {
2363 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2364 return LDAP_INVALID_SYNTAX;
2368 return LDAP_SUCCESS;
2377 struct berval *value,
2378 void *assertedValue )
2380 struct berval *asserted = (struct berval *) assertedValue;
2381 int vsign = 1, asign = 1; /* default sign = '+' */
2386 if( v.bv_val[0] == '-' ) {
2392 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2395 if( a.bv_val[0] == '-' ) {
2401 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2403 match = vsign - asign;
2405 match = ( v.bv_len != a.bv_len
2406 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2407 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2408 if( vsign < 0 ) match = -match;
2412 return LDAP_SUCCESS;
2415 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2416 #define INDEX_INTLEN_CHOP 7
2417 #define INDEX_INTLEN_CHOPBYTES 3
2427 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2428 * two's complement value (sign-extended or chopped as needed),
2429 * however the top <number of exponent-bytes + 1> bits of first byte
2430 * above is the inverse sign. The next bit is the sign as delimiter.
2432 ber_slen_t k = index_intlen_strlen;
2434 unsigned signmask = ~0x7fU;
2435 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2436 struct berval val = *in, itmp = *tmp;
2438 if ( val.bv_val[0] != '-' ) {
2443 /* Chop least significant digits, increase length instead */
2444 if ( val.bv_len > (ber_len_t) k ) {
2445 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2446 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2447 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2450 if ( lutil_str2bin( &val, &itmp, ctx )) {
2451 return LDAP_INVALID_SYNTAX;
2454 /* Omit leading sign byte */
2455 if ( itmp.bv_val[0] == neg ) {
2460 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2462 assert( chop == 0 );
2463 memset( key->bv_val, neg, k ); /* sign-extend */
2464 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2465 lenp = lenbuf + sizeof(lenbuf);
2466 chop = - (ber_len_t) k;
2468 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2470 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2471 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2472 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2473 k = (lenbuf + sizeof(lenbuf)) - lenp;
2474 if ( k > (ber_slen_t) index_intlen )
2476 memcpy( key->bv_val, lenp, k );
2477 itmp.bv_len = index_intlen - k;
2479 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2480 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2484 /* Index generation function */
2491 struct berval *prefix,
2501 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2503 /* count the values and find max needed length */
2505 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2506 if ( vlen < values[i].bv_len )
2507 vlen = values[i].bv_len;
2509 if ( vlen > maxstrlen )
2512 /* we should have at least one value at this point */
2515 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2516 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2517 keys[i].bv_len = index_intlen;
2518 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2521 keys[i].bv_val = NULL;
2523 if ( vlen > sizeof(ibuf) ) {
2524 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2528 itmp.bv_len = sizeof(ibuf);
2530 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2531 if ( itmp.bv_val != ibuf ) {
2532 itmp.bv_len = values[i].bv_len;
2533 if ( itmp.bv_len <= sizeof(ibuf) )
2534 itmp.bv_len = sizeof(ibuf);
2535 else if ( itmp.bv_len > maxstrlen )
2536 itmp.bv_len = maxstrlen;
2538 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2544 if ( itmp.bv_val != ibuf ) {
2545 slap_sl_free( itmp.bv_val, ctx );
2550 /* Index generation function */
2557 struct berval *prefix,
2558 void * assertedValue,
2565 struct berval *value;
2568 value = (struct berval *) assertedValue;
2570 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2572 keys[0].bv_len = index_intlen;
2573 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2575 keys[1].bv_val = NULL;
2577 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2578 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2579 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2580 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2583 iv.bv_len = sizeof(ibuf);
2586 rc = integerVal2Key( value, keys, &iv, ctx );
2590 if ( iv.bv_val != ibuf ) {
2591 slap_sl_free( iv.bv_val, ctx );
2597 countryStringValidate(
2599 struct berval *val )
2601 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2603 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2604 return LDAP_INVALID_SYNTAX;
2606 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2607 return LDAP_INVALID_SYNTAX;
2610 return LDAP_SUCCESS;
2614 printableStringValidate(
2616 struct berval *val )
2620 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2622 for(i=0; i < val->bv_len; i++) {
2623 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2624 return LDAP_INVALID_SYNTAX;
2628 return LDAP_SUCCESS;
2632 printablesStringValidate(
2634 struct berval *val )
2638 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2640 for(i=0,len=0; i < val->bv_len; i++) {
2641 int c = val->bv_val[i];
2645 return LDAP_INVALID_SYNTAX;
2649 } else if ( SLAP_PRINTABLE(c) ) {
2652 return LDAP_INVALID_SYNTAX;
2657 return LDAP_INVALID_SYNTAX;
2660 return LDAP_SUCCESS;
2666 struct berval *val )
2670 for(i=0; i < val->bv_len; i++) {
2671 if( !LDAP_ASCII(val->bv_val[i]) ) {
2672 return LDAP_INVALID_SYNTAX;
2676 return LDAP_SUCCESS;
2685 struct berval *normalized,
2689 int casefold = !SLAP_MR_ASSOCIATED( mr,
2690 slap_schema.si_mr_caseExactIA5Match );
2692 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2696 /* Ignore initial whitespace */
2697 while ( ASCII_SPACE( *p ) ) p++;
2699 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2700 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2701 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2702 normalized->bv_val[normalized->bv_len] = '\0';
2704 p = q = normalized->bv_val;
2707 if ( ASCII_SPACE( *p ) ) {
2710 /* Ignore the extra whitespace */
2711 while ( ASCII_SPACE( *p ) ) {
2715 } else if ( casefold ) {
2716 /* Most IA5 rules require casefolding */
2717 *q++ = TOLOWER(*p); p++;
2724 assert( normalized->bv_val <= p );
2728 * If the string ended in space, backup the pointer one
2729 * position. One is enough because the above loop collapsed
2730 * all whitespace to a single space.
2732 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2734 /* null terminate */
2737 normalized->bv_len = q - normalized->bv_val;
2739 return LDAP_SUCCESS;
2748 if( in->bv_len != 36 ) {
2749 return LDAP_INVALID_SYNTAX;
2752 for( i=0; i<36; i++ ) {
2758 if( in->bv_val[i] != '-' ) {
2759 return LDAP_INVALID_SYNTAX;
2763 if( !ASCII_HEX( in->bv_val[i]) ) {
2764 return LDAP_INVALID_SYNTAX;
2769 return LDAP_SUCCESS;
2780 int rc=LDAP_INVALID_SYNTAX;
2782 assert( in != NULL );
2783 assert( out != NULL );
2785 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2788 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2790 for( i=0; i<36; i++ ) {
2796 if( in->bv_val[i] != '-' ) {
2799 out->bv_val[i] = '-';
2803 if( !ASCII_HEX( in->bv_val[i]) ) {
2806 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2811 out->bv_val[ out->bv_len ] = '\0';
2815 slap_sl_free( out->bv_val, ctx );
2828 struct berval *normalized,
2831 unsigned char octet = '\0';
2835 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2836 /* NOTE: must be a normalized UUID */
2837 assert( val->bv_len == 16 );
2839 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2840 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2841 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2842 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2844 return LDAP_SUCCESS;
2847 normalized->bv_len = 16;
2848 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2850 for( i=0, j=0; i<36; i++ ) {
2851 unsigned char nibble;
2852 if( val->bv_val[i] == '-' ) {
2855 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2856 nibble = val->bv_val[i] - '0';
2858 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2859 nibble = val->bv_val[i] - ('a'-10);
2861 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2862 nibble = val->bv_val[i] - ('A'-10);
2865 slap_sl_free( normalized->bv_val, ctx );
2866 BER_BVZERO( normalized );
2867 return LDAP_INVALID_SYNTAX;
2872 normalized->bv_val[j>>1] = octet;
2874 octet = nibble << 4;
2879 normalized->bv_val[normalized->bv_len] = 0;
2880 return LDAP_SUCCESS;
2886 numericStringValidate(
2892 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2894 for(i=0; i < in->bv_len; i++) {
2895 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2896 return LDAP_INVALID_SYNTAX;
2900 return LDAP_SUCCESS;
2904 numericStringNormalize(
2909 struct berval *normalized,
2912 /* removal all spaces */
2915 assert( !BER_BVISEMPTY( val ) );
2917 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2920 q = normalized->bv_val;
2923 if ( ASCII_SPACE( *p ) ) {
2924 /* Ignore whitespace */
2931 /* we should have copied no more than is in val */
2932 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2934 /* null terminate */
2937 normalized->bv_len = q - normalized->bv_val;
2939 if( BER_BVISEMPTY( normalized ) ) {
2940 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2941 normalized->bv_val[0] = ' ';
2942 normalized->bv_val[1] = '\0';
2943 normalized->bv_len = 1;
2946 return LDAP_SUCCESS;
2950 * Integer conversion macros that will use the largest available
2953 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2954 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2955 # define SLAP_LONG long long
2957 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2958 # define SLAP_LONG long
2959 #endif /* HAVE_STRTOLL ... */
2967 struct berval *value,
2968 void *assertedValue )
2970 SLAP_LONG lValue, lAssertedValue;
2973 /* safe to assume integers are NUL terminated? */
2974 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2975 if( errno == ERANGE )
2977 return LDAP_CONSTRAINT_VIOLATION;
2980 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2982 if( errno == ERANGE )
2984 return LDAP_CONSTRAINT_VIOLATION;
2987 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2988 return LDAP_SUCCESS;
2997 struct berval *value,
2998 void *assertedValue )
3000 SLAP_LONG lValue, lAssertedValue;
3003 /* safe to assume integers are NUL terminated? */
3004 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
3005 if( errno == ERANGE )
3007 return LDAP_CONSTRAINT_VIOLATION;
3010 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
3012 if( errno == ERANGE )
3014 return LDAP_CONSTRAINT_VIOLATION;
3017 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
3018 return LDAP_SUCCESS;
3022 checkNum( struct berval *in, struct berval *out )
3024 /* parse serialNumber */
3025 ber_len_t neg = 0, extra = 0;
3028 out->bv_val = in->bv_val;
3031 if ( out->bv_val[0] == '-' ) {
3036 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3037 first = out->bv_val[2];
3040 out->bv_len += STRLENOF("0x");
3041 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3042 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3045 } else if ( out->bv_val[0] == '\'' ) {
3046 first = out->bv_val[1];
3049 out->bv_len += STRLENOF("'");
3051 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3052 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3054 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3057 out->bv_len += STRLENOF("'H");
3060 first = out->bv_val[0];
3061 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3062 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3066 if ( !( out->bv_len > neg ) ) {
3070 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3078 serialNumberAndIssuerCheck(
3086 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3088 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3089 /* Parse old format */
3090 is->bv_val = ber_bvchr( in, '$' );
3091 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3093 sn->bv_val = in->bv_val;
3094 sn->bv_len = is->bv_val - in->bv_val;
3097 is->bv_len = in->bv_len - (sn->bv_len + 1);
3099 /* eat leading zeros */
3100 for( n=0; n < (sn->bv_len-1); n++ ) {
3101 if( sn->bv_val[n] != '0' ) break;
3106 for( n=0; n < sn->bv_len; n++ ) {
3107 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3111 /* Parse GSER format */
3116 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3120 struct berval x = *in;
3126 /* eat leading spaces */
3127 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3131 /* should be at issuer or serialNumber NamedValue */
3132 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3133 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3136 x.bv_val += STRLENOF("issuer");
3137 x.bv_len -= STRLENOF("issuer");
3139 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3143 /* eat leading spaces */
3144 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3148 /* For backward compatibility, this part is optional */
3149 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3150 x.bv_val += STRLENOF("rdnSequence:");
3151 x.bv_len -= STRLENOF("rdnSequence:");
3154 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3158 is->bv_val = x.bv_val;
3161 for ( ; is->bv_len < x.bv_len; ) {
3162 if ( is->bv_val[is->bv_len] != '"' ) {
3166 if ( is->bv_val[is->bv_len+1] == '"' ) {
3173 x.bv_val += is->bv_len + 1;
3174 x.bv_len -= is->bv_len + 1;
3176 have |= HAVE_ISSUER;
3178 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3180 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3182 /* parse serialNumber */
3183 x.bv_val += STRLENOF("serialNumber");
3184 x.bv_len -= STRLENOF("serialNumber");
3186 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3190 /* eat leading spaces */
3191 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3195 if ( checkNum( &x, sn ) ) {
3196 return LDAP_INVALID_SYNTAX;
3199 x.bv_val += sn->bv_len;
3200 x.bv_len -= sn->bv_len;
3205 return LDAP_INVALID_SYNTAX;
3208 /* eat leading spaces */
3209 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3213 if ( have == HAVE_ALL ) {
3217 if ( x.bv_val[0] != ',' ) {
3218 return LDAP_INVALID_SYNTAX;
3225 /* should have no characters left... */
3226 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3228 if ( numdquotes == 0 ) {
3229 ber_dupbv_x( &ni, is, ctx );
3234 ni.bv_len = is->bv_len - numdquotes;
3235 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3236 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3237 if ( is->bv_val[src] == '"' ) {
3240 ni.bv_val[dst] = is->bv_val[src];
3242 ni.bv_val[dst] = '\0';
3252 serialNumberAndIssuerValidate(
3257 struct berval sn, i;
3259 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3262 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3267 /* validate DN -- doesn't handle double dquote */
3268 rc = dnValidate( NULL, &i );
3270 rc = LDAP_INVALID_SYNTAX;
3273 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3274 slap_sl_free( i.bv_val, NULL );
3277 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3278 in->bv_val, rc, 0 );
3285 serialNumberAndIssuerPretty(
3292 struct berval sn, i, ni = BER_BVNULL;
3295 assert( in != NULL );
3296 assert( out != NULL );
3300 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3303 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3308 rc = dnPretty( syntax, &i, &ni, ctx );
3310 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3311 slap_sl_free( i.bv_val, ctx );
3315 rc = LDAP_INVALID_SYNTAX;
3319 /* make room from sn + "$" */
3320 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3321 + sn.bv_len + ni.bv_len;
3322 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3324 if ( out->bv_val == NULL ) {
3331 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3332 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3333 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3334 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3335 p = lutil_strcopy( p, /*{*/ "\" }" );
3337 assert( p == &out->bv_val[out->bv_len] );
3340 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3341 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3343 slap_sl_free( ni.bv_val, ctx );
3345 return LDAP_SUCCESS;
3355 /* Use hex format. '123456789abcdef'H */
3356 unsigned char *ptr, zero = '\0';
3359 ber_len_t i, len, nlen;
3361 assert( in != NULL );
3362 assert( !BER_BVISNULL( in ) );
3363 assert( out != NULL );
3364 assert( !BER_BVISNULL( out ) );
3366 ptr = (unsigned char *)in->bv_val;
3369 /* Check for minimal encodings */
3371 if ( ptr[0] & 0x80 ) {
3372 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3376 } else if ( ptr[0] == 0 ) {
3377 if ( !( ptr[1] & 0x80 ) ) {
3384 } else if ( len == 0 ) {
3385 /* FIXME: this should not be possible,
3386 * since a value of zero would have length 1 */
3391 first = !( ptr[0] & 0xf0U );
3392 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3393 if ( nlen >= out->bv_len ) {
3394 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3400 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3404 for ( ; i < len; i++ ) {
3405 sprintf( sptr, "%02X", ptr[i] );
3412 assert( sptr == &out->bv_val[nlen] );
3419 #define SLAP_SN_BUFLEN (64)
3422 * This routine is called by certificateExactNormalize when
3423 * certificateExactNormalize receives a search string instead of
3424 * a certificate. This routine checks if the search value is valid
3425 * and then returns the normalized value
3428 serialNumberAndIssuerNormalize(
3436 struct berval sn, sn2, sn3, i, ni;
3437 char sbuf2[SLAP_SN_BUFLEN];
3438 char sbuf3[SLAP_SN_BUFLEN];
3442 assert( in != NULL );
3443 assert( out != NULL );
3445 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3448 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3453 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3455 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3456 slap_sl_free( i.bv_val, ctx );
3460 return LDAP_INVALID_SYNTAX;
3463 /* Convert sn to canonical hex */
3465 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3466 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3468 sn2.bv_len = sn.bv_len;
3469 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3470 rc = LDAP_INVALID_SYNTAX;
3475 sn3.bv_len = sizeof(sbuf3);
3476 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3477 rc = LDAP_INVALID_SYNTAX;
3481 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3482 + sn3.bv_len + ni.bv_len;
3483 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3485 if ( out->bv_val == NULL ) {
3493 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3494 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3495 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3496 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3497 p = lutil_strcopy( p, /*{*/ "\" }" );
3499 assert( p == &out->bv_val[out->bv_len] );
3502 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3503 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3505 if ( sn2.bv_val != sbuf2 ) {
3506 slap_sl_free( sn2.bv_val, ctx );
3509 if ( sn3.bv_val != sbuf3 ) {
3510 slap_sl_free( sn3.bv_val, ctx );
3513 slap_sl_free( ni.bv_val, ctx );
3519 certificateExactNormalize(
3524 struct berval *normalized,
3527 BerElementBuffer berbuf;
3528 BerElement *ber = (BerElement *)&berbuf;
3532 char serialbuf2[SLAP_SN_BUFLEN];
3533 struct berval sn, sn2 = BER_BVNULL;
3534 struct berval issuer_dn = BER_BVNULL, bvdn;
3536 int rc = LDAP_INVALID_SYNTAX;
3538 assert( val != NULL );
3540 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3541 val->bv_val, val->bv_len, 0 );
3543 if ( BER_BVISEMPTY( val ) ) goto done;
3545 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3546 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3549 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3551 ber_init2( ber, val, LBER_USE_DER );
3552 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3553 tag = ber_skip_tag( ber, &len ); /* Sequence */
3554 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3555 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3556 tag = ber_skip_tag( ber, &len );
3557 tag = ber_get_int( ber, &i ); /* version */
3560 /* NOTE: move the test here from certificateValidate,
3561 * so that we can validate certs with serial longer
3562 * than sizeof(ber_int_t) */
3563 tag = ber_skip_tag( ber, &len ); /* serial */
3565 sn.bv_val = (char *)ber->ber_ptr;
3566 sn2.bv_val = serialbuf2;
3567 sn2.bv_len = sizeof(serialbuf2);
3568 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3569 rc = LDAP_INVALID_SYNTAX;
3572 ber_skip_data( ber, len );
3574 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3575 ber_skip_data( ber, len );
3576 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3577 len = ber_ptrlen( ber );
3578 bvdn.bv_val = val->bv_val + len;
3579 bvdn.bv_len = val->bv_len - len;
3581 rc = dnX509normalize( &bvdn, &issuer_dn );
3582 if ( rc != LDAP_SUCCESS ) goto done;
3584 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3585 + sn2.bv_len + issuer_dn.bv_len;
3586 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3588 p = normalized->bv_val;
3590 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3591 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3592 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3593 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3594 p = lutil_strcopy( p, /*{*/ "\" }" );
3599 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3600 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3602 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3603 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3608 /* X.509 PKI certificateList stuff */
3610 checkTime( struct berval *in, struct berval *out )
3614 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3617 assert( in != NULL );
3618 assert( !BER_BVISNULL( in ) );
3619 assert( !BER_BVISEMPTY( in ) );
3621 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3625 if ( out != NULL ) {
3626 assert( !BER_BVISNULL( out ) );
3627 assert( out->bv_len >= sizeof( buf ) );
3628 bv.bv_val = out->bv_val;
3634 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3635 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3638 if ( in->bv_val[i] != 'Z' ) {
3643 if ( i != in->bv_len ) {
3647 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3648 lutil_strncopy( bv.bv_val, in->bv_val, i );
3651 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3652 char *p = bv.bv_val;
3653 if ( in->bv_val[0] < '7' ) {
3654 p = lutil_strcopy( p, "20" );
3657 p = lutil_strcopy( p, "19" );
3659 lutil_strncopy( p, in->bv_val, i );
3666 rc = generalizedTimeValidate( NULL, &bv );
3667 if ( rc == LDAP_SUCCESS && out != NULL ) {
3668 if ( out->bv_len > bv.bv_len ) {
3669 out->bv_val[ bv.bv_len ] = '\0';
3671 out->bv_len = bv.bv_len;
3674 return rc != LDAP_SUCCESS;
3678 issuerAndThisUpdateCheck(
3685 struct berval x = *in;
3686 struct berval ni = BER_BVNULL;
3687 /* Parse GSER format */
3691 HAVE_THISUPDATE = 0x2,
3692 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3696 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3698 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3699 return LDAP_INVALID_SYNTAX;
3703 x.bv_len -= STRLENOF("{}");
3706 /* eat leading spaces */
3707 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3711 /* should be at issuer or thisUpdate */
3712 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3713 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3716 x.bv_val += STRLENOF("issuer");
3717 x.bv_len -= STRLENOF("issuer");
3719 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3723 /* eat leading spaces */
3724 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3728 /* For backward compatibility, this part is optional */
3729 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3730 return LDAP_INVALID_SYNTAX;
3732 x.bv_val += STRLENOF("rdnSequence:");
3733 x.bv_len -= STRLENOF("rdnSequence:");
3735 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3739 is->bv_val = x.bv_val;
3742 for ( ; is->bv_len < x.bv_len; ) {
3743 if ( is->bv_val[is->bv_len] != '"' ) {
3747 if ( is->bv_val[is->bv_len+1] == '"' ) {
3754 x.bv_val += is->bv_len + 1;
3755 x.bv_len -= is->bv_len + 1;
3757 have |= HAVE_ISSUER;
3759 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3761 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3763 /* parse thisUpdate */
3764 x.bv_val += STRLENOF("thisUpdate");
3765 x.bv_len -= STRLENOF("thisUpdate");
3767 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3771 /* eat leading spaces */
3772 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3776 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3780 tu->bv_val = x.bv_val;
3783 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3784 if ( tu->bv_val[tu->bv_len] == '"' ) {
3788 x.bv_val += tu->bv_len + 1;
3789 x.bv_len -= tu->bv_len + 1;
3791 have |= HAVE_THISUPDATE;
3794 return LDAP_INVALID_SYNTAX;
3797 /* eat leading spaces */
3798 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3802 if ( have == HAVE_ALL ) {
3806 if ( x.bv_val[0] != ',' ) {
3807 return LDAP_INVALID_SYNTAX;
3814 /* should have no characters left... */
3815 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3817 if ( numdquotes == 0 ) {
3818 ber_dupbv_x( &ni, is, ctx );
3823 ni.bv_len = is->bv_len - numdquotes;
3824 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3825 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3826 if ( is->bv_val[src] == '"' ) {
3829 ni.bv_val[dst] = is->bv_val[src];
3831 ni.bv_val[dst] = '\0';
3840 issuerAndThisUpdateValidate(
3845 struct berval i, tu;
3847 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3850 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3855 /* validate DN -- doesn't handle double dquote */
3856 rc = dnValidate( NULL, &i );
3858 rc = LDAP_INVALID_SYNTAX;
3860 } else if ( checkTime( &tu, NULL ) ) {
3861 rc = LDAP_INVALID_SYNTAX;
3864 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3865 slap_sl_free( i.bv_val, NULL );
3868 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3869 in->bv_val, rc, 0 );
3876 issuerAndThisUpdatePretty(
3883 struct berval i, tu, ni = BER_BVNULL;
3886 assert( in != NULL );
3887 assert( out != NULL );
3891 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3894 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3899 rc = dnPretty( syntax, &i, &ni, ctx );
3901 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3902 slap_sl_free( i.bv_val, ctx );
3905 if ( rc || checkTime( &tu, NULL ) ) {
3906 rc = LDAP_INVALID_SYNTAX;
3911 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3912 + ni.bv_len + tu.bv_len;
3913 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3915 if ( out->bv_val == NULL ) {
3922 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3923 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3924 p = lutil_strcopy( p, "\", thisUpdate \"" );
3925 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3926 p = lutil_strcopy( p, /*{*/ "\" }" );
3928 assert( p == &out->bv_val[out->bv_len] );
3931 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3932 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3934 slap_sl_free( ni.bv_val, ctx );
3940 issuerAndThisUpdateNormalize(
3948 struct berval i, ni, tu, tu2;
3949 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3953 assert( in != NULL );
3954 assert( out != NULL );
3956 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3959 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3964 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3966 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3967 slap_sl_free( i.bv_val, ctx );
3971 tu2.bv_len = sizeof( sbuf );
3972 if ( rc || checkTime( &tu, &tu2 ) ) {
3973 return LDAP_INVALID_SYNTAX;
3976 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3977 + ni.bv_len + tu2.bv_len;
3978 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3980 if ( out->bv_val == NULL ) {
3988 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3989 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3990 p = lutil_strcopy( p, "\", thisUpdate \"" );
3991 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3992 p = lutil_strcopy( p, /*{*/ "\" }" );
3994 assert( p == &out->bv_val[out->bv_len] );
3997 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3998 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4000 slap_sl_free( ni.bv_val, ctx );
4006 certificateListExactNormalize(
4011 struct berval *normalized,
4014 BerElementBuffer berbuf;
4015 BerElement *ber = (BerElement *)&berbuf;
4019 struct berval issuer_dn = BER_BVNULL, bvdn,
4021 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
4022 int rc = LDAP_INVALID_SYNTAX;
4024 assert( val != NULL );
4026 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
4027 val->bv_val, val->bv_len, 0 );
4029 if ( BER_BVISEMPTY( val ) ) goto done;
4031 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4032 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4035 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4037 ber_init2( ber, val, LBER_USE_DER );
4038 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4039 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4040 tag = ber_skip_tag( ber, &len ); /* Sequence */
4041 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4042 tag = ber_peek_tag( ber, &len );
4043 /* Optional version */
4044 if ( tag == LBER_INTEGER ) {
4045 tag = ber_get_int( ber, &version );
4046 assert( tag == LBER_INTEGER );
4047 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4049 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4050 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4051 ber_skip_data( ber, len );
4053 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4054 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4055 len = ber_ptrlen( ber );
4056 bvdn.bv_val = val->bv_val + len;
4057 bvdn.bv_len = val->bv_len - len;
4058 tag = ber_skip_tag( ber, &len );
4059 ber_skip_data( ber, len );
4061 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4062 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4063 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4064 bvtu.bv_val = (char *)ber->ber_ptr;
4067 rc = dnX509normalize( &bvdn, &issuer_dn );
4068 if ( rc != LDAP_SUCCESS ) goto done;
4070 thisUpdate.bv_val = tubuf;
4071 thisUpdate.bv_len = sizeof(tubuf);
4072 if ( checkTime( &bvtu, &thisUpdate ) ) {
4073 rc = LDAP_INVALID_SYNTAX;
4077 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4078 + issuer_dn.bv_len + thisUpdate.bv_len;
4079 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4081 p = normalized->bv_val;
4083 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4084 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4085 p = lutil_strcopy( p, "\", thisUpdate \"" );
4086 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
4087 p = lutil_strcopy( p, /*{*/ "\" }" );
4092 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4093 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4095 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4100 /* X.509 PMI serialNumberAndIssuerSerialCheck
4102 AttributeCertificateExactAssertion ::= SEQUENCE {
4103 serialNumber CertificateSerialNumber,
4104 issuer AttCertIssuer }
4106 CertificateSerialNumber ::= INTEGER
4108 AttCertIssuer ::= [0] SEQUENCE {
4109 issuerName GeneralNames OPTIONAL,
4110 baseCertificateID [0] IssuerSerial OPTIONAL,
4111 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4112 -- At least one component shall be present
4114 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4116 GeneralName ::= CHOICE {
4117 otherName [0] INSTANCE OF OTHER-NAME,
4118 rfc822Name [1] IA5String,
4119 dNSName [2] IA5String,
4120 x400Address [3] ORAddress,
4121 directoryName [4] Name,
4122 ediPartyName [5] EDIPartyName,
4123 uniformResourceIdentifier [6] IA5String,
4124 iPAddress [7] OCTET STRING,
4125 registeredID [8] OBJECT IDENTIFIER }
4127 IssuerSerial ::= SEQUENCE {
4128 issuer GeneralNames,
4129 serial CertificateSerialNumber,
4130 issuerUID UniqueIdentifier OPTIONAL }
4132 ObjectDigestInfo ::= SEQUENCE {
4133 digestedObjectType ENUMERATED {
4136 otherObjectTypes (2) },
4137 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4138 digestAlgorithm AlgorithmIdentifier,
4139 objectDigest BIT STRING }
4141 * The way I interpret it, an assertion should look like
4143 { serialNumber 'dd'H,
4144 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4145 baseCertificateID { serial '1d'H,
4146 issuer { directoryName:rdnSequence:"cn=zzz" },
4147 issuerUID <value> -- optional
4149 objectDigestInfo { ... } -- optional
4153 * with issuerName, baseCertificateID and objectDigestInfo optional,
4154 * at least one present; the way it's currently implemented, it is
4156 { serialNumber 'dd'H,
4157 issuer { baseCertificateID { serial '1d'H,
4158 issuer { directoryName:rdnSequence:"cn=zzz" }
4163 * with all the above parts mandatory.
4166 serialNumberAndIssuerSerialCheck(
4170 struct berval *i_sn, /* contain serial of baseCertificateID */
4173 /* Parse GSER format */
4178 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4179 } have = HAVE_NONE, have2 = HAVE_NONE;
4181 struct berval x = *in;
4184 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4187 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4194 /* eat leading spaces */
4195 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4199 /* should be at issuer or serialNumber NamedValue */
4200 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4201 if ( have & HAVE_ISSUER ) {
4202 return LDAP_INVALID_SYNTAX;
4205 /* parse IssuerSerial */
4206 x.bv_val += STRLENOF("issuer");
4207 x.bv_len -= STRLENOF("issuer");
4209 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4213 /* eat leading spaces */
4214 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4218 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4222 /* eat leading spaces */
4223 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4227 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4228 return LDAP_INVALID_SYNTAX;
4230 x.bv_val += STRLENOF("baseCertificateID ");
4231 x.bv_len -= STRLENOF("baseCertificateID ");
4233 /* eat leading spaces */
4234 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4238 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4243 /* eat leading spaces */
4244 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4248 /* parse issuer of baseCertificateID */
4249 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4250 if ( have2 & HAVE_ISSUER ) {
4251 return LDAP_INVALID_SYNTAX;
4254 x.bv_val += STRLENOF("issuer ");
4255 x.bv_len -= STRLENOF("issuer ");
4257 /* eat leading spaces */
4258 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4262 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4266 /* eat leading spaces */
4267 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4271 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4272 return LDAP_INVALID_SYNTAX;
4274 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4275 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4277 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4281 is->bv_val = x.bv_val;
4284 for ( ; is->bv_len < x.bv_len; ) {
4285 if ( is->bv_val[is->bv_len] != '"' ) {
4289 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4296 x.bv_val += is->bv_len + 1;
4297 x.bv_len -= is->bv_len + 1;
4299 /* eat leading spaces */
4300 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4304 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4308 have2 |= HAVE_ISSUER;
4310 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4311 if ( have2 & HAVE_SN ) {
4312 return LDAP_INVALID_SYNTAX;
4315 x.bv_val += STRLENOF("serial ");
4316 x.bv_len -= STRLENOF("serial ");
4318 /* eat leading spaces */
4319 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4323 if ( checkNum( &x, i_sn ) ) {
4324 return LDAP_INVALID_SYNTAX;
4327 x.bv_val += i_sn->bv_len;
4328 x.bv_len -= i_sn->bv_len;
4333 return LDAP_INVALID_SYNTAX;
4336 /* eat leading spaces */
4337 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4341 if ( have2 == HAVE_ALL ) {
4345 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4350 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4354 /* eat leading spaces */
4355 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4359 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4363 have |= HAVE_ISSUER;
4365 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4366 if ( have & HAVE_SN ) {
4367 return LDAP_INVALID_SYNTAX;
4370 /* parse serialNumber */
4371 x.bv_val += STRLENOF("serialNumber");
4372 x.bv_len -= STRLENOF("serialNumber");
4374 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4378 /* eat leading spaces */
4379 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4383 if ( checkNum( &x, sn ) ) {
4384 return LDAP_INVALID_SYNTAX;
4387 x.bv_val += sn->bv_len;
4388 x.bv_len -= sn->bv_len;
4393 return LDAP_INVALID_SYNTAX;
4397 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4401 if ( have == HAVE_ALL ) {
4405 if ( x.bv_val[0] != ',' ) {
4406 return LDAP_INVALID_SYNTAX;
4412 /* should have no characters left... */
4413 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4415 if ( numdquotes == 0 ) {
4416 ber_dupbv_x( &ni, is, ctx );
4421 ni.bv_len = is->bv_len - numdquotes;
4422 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4423 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4424 if ( is->bv_val[src] == '"' ) {
4427 ni.bv_val[dst] = is->bv_val[src];
4429 ni.bv_val[dst] = '\0';
4434 /* need to handle double dquotes here */
4438 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4440 serialNumberAndIssuerSerialValidate(
4445 struct berval sn, i, i_sn;
4447 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4450 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4455 /* validate DN -- doesn't handle double dquote */
4456 rc = dnValidate( NULL, &i );
4458 rc = LDAP_INVALID_SYNTAX;
4461 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4462 slap_sl_free( i.bv_val, NULL );
4466 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4467 in->bv_val, rc, 0 );
4472 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4474 serialNumberAndIssuerSerialPretty(
4480 struct berval sn, i, i_sn, ni = BER_BVNULL;
4484 assert( in != NULL );
4485 assert( out != NULL );
4487 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4490 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4495 rc = dnPretty( syntax, &i, &ni, ctx );
4497 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4498 slap_sl_free( i.bv_val, ctx );
4502 rc = LDAP_INVALID_SYNTAX;
4506 /* make room from sn + "$" */
4507 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4508 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4509 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4511 if ( out->bv_val == NULL ) {
4518 p = lutil_strcopy( p, "{ serialNumber " );
4519 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
4520 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4521 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4522 p = lutil_strcopy( p, "\" }, serial " );
4523 p = lutil_strncopy( p, i_sn.bv_val, i_sn.bv_len );
4524 p = lutil_strcopy( p, " } } }" );
4526 assert( p == &out->bv_val[out->bv_len] );
4529 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4530 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4532 slap_sl_free( ni.bv_val, ctx );
4537 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4539 * This routine is called by attributeCertificateExactNormalize
4540 * when attributeCertificateExactNormalize receives a search
4541 * string instead of a attribute certificate. This routine
4542 * checks if the search value is valid and then returns the
4546 serialNumberAndIssuerSerialNormalize(
4554 struct berval i, ni = BER_BVNULL,
4555 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4556 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4557 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4558 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4562 assert( in != NULL );
4563 assert( out != NULL );
4565 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4568 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4573 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4575 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4576 slap_sl_free( i.bv_val, ctx );
4580 rc = LDAP_INVALID_SYNTAX;
4584 /* Convert sn to canonical hex */
4586 sn2.bv_len = sn.bv_len;
4587 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4588 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4590 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4591 rc = LDAP_INVALID_SYNTAX;
4595 /* Convert i_sn to canonical hex */
4596 i_sn2.bv_val = i_sbuf2;
4597 i_sn2.bv_len = i_sn.bv_len;
4598 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4599 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4601 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4602 rc = LDAP_INVALID_SYNTAX;
4607 sn3.bv_len = sizeof(sbuf3);
4608 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4609 rc = LDAP_INVALID_SYNTAX;
4613 i_sn3.bv_val = i_sbuf3;
4614 i_sn3.bv_len = sizeof(i_sbuf3);
4615 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4616 rc = LDAP_INVALID_SYNTAX;
4620 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4621 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4622 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4624 if ( out->bv_val == NULL ) {
4632 p = lutil_strcopy( p, "{ serialNumber " );
4633 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
4634 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4635 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4636 p = lutil_strcopy( p, "\" }, serial " );
4637 p = lutil_strncopy( p, i_sn3.bv_val, i_sn3.bv_len );
4638 p = lutil_strcopy( p, " } } }" );
4640 assert( p == &out->bv_val[out->bv_len] );
4643 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4644 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4646 if ( sn2.bv_val != sbuf2 ) {
4647 slap_sl_free( sn2.bv_val, ctx );
4650 if ( i_sn2.bv_val != i_sbuf2 ) {
4651 slap_sl_free( i_sn2.bv_val, ctx );
4654 if ( sn3.bv_val != sbuf3 ) {
4655 slap_sl_free( sn3.bv_val, ctx );
4658 if ( i_sn3.bv_val != i_sbuf3 ) {
4659 slap_sl_free( i_sn3.bv_val, ctx );
4662 slap_sl_free( ni.bv_val, ctx );
4667 /* X.509 PMI attributeCertificateExactNormalize */
4669 attributeCertificateExactNormalize(
4674 struct berval *normalized,
4677 BerElementBuffer berbuf;
4678 BerElement *ber = (BerElement *)&berbuf;
4681 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4682 struct berval sn, i_sn, sn2, i_sn2;
4683 struct berval issuer_dn = BER_BVNULL, bvdn;
4685 int rc = LDAP_INVALID_SYNTAX;
4687 if ( BER_BVISEMPTY( val ) ) {
4691 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4692 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4695 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4697 ber_init2( ber, val, LBER_USE_DER );
4698 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4699 tag = ber_skip_tag( ber, &len ); /* Sequence */
4700 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4701 ber_skip_data( ber, len );
4702 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4703 ber_skip_data( ber, len );
4706 tag = ber_skip_tag( ber, &len ); /* Sequence */
4707 /* issuerName (GeneralNames sequence; optional)? */
4708 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4709 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4710 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4711 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4712 rc = LDAP_INVALID_SYNTAX;
4715 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4716 len = ber_ptrlen( ber );
4717 bvdn.bv_val = val->bv_val + len;
4718 bvdn.bv_len = val->bv_len - len;
4719 rc = dnX509normalize( &bvdn, &issuer_dn );
4720 if ( rc != LDAP_SUCCESS ) goto done;
4722 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4723 ber_skip_data( ber, len );
4724 tag = ber_skip_tag( ber, &len ); /* serial number */
4725 if ( tag != LBER_INTEGER ) {
4726 rc = LDAP_INVALID_SYNTAX;
4729 i_sn.bv_val = (char *)ber->ber_ptr;
4731 i_sn2.bv_val = issuer_serialbuf;
4732 i_sn2.bv_len = sizeof(issuer_serialbuf);
4733 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4734 rc = LDAP_INVALID_SYNTAX;
4737 ber_skip_data( ber, len );
4739 /* issuerUID (bitstring; optional)? */
4740 /* objectDigestInfo (sequence; optional)? */
4742 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4743 ber_skip_data( ber, len );
4744 tag = ber_skip_tag( ber, &len ); /* serial number */
4745 if ( tag != LBER_INTEGER ) {
4746 rc = LDAP_INVALID_SYNTAX;
4749 sn.bv_val = (char *)ber->ber_ptr;
4751 sn2.bv_val = serialbuf;
4752 sn2.bv_len = sizeof(serialbuf);
4753 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4754 rc = LDAP_INVALID_SYNTAX;
4757 ber_skip_data( ber, len );
4759 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4760 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4761 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4763 p = normalized->bv_val;
4765 p = lutil_strcopy( p, "{ serialNumber " );
4766 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
4767 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4768 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4769 p = lutil_strcopy( p, "\" }, serial " );
4770 p = lutil_strncopy( p, i_sn2.bv_val, i_sn2.bv_len );
4771 p = lutil_strcopy( p, " } } }" );
4773 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4774 normalized->bv_val, NULL, NULL );
4779 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4780 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4781 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4794 assert( in != NULL );
4795 assert( !BER_BVISNULL( in ) );
4797 for ( i = 0; i < in->bv_len; i++ ) {
4798 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4799 return LDAP_INVALID_SYNTAX;
4803 return LDAP_SUCCESS;
4806 /* Normalize a SID as used inside a CSN:
4807 * three-digit numeric string */
4814 struct berval *normalized,
4819 assert( val != NULL );
4820 assert( normalized != NULL );
4822 ber_dupbv_x( normalized, val, ctx );
4824 for ( i = 0; i < normalized->bv_len; i++ ) {
4825 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4826 ber_memfree_x( normalized->bv_val, ctx );
4827 BER_BVZERO( normalized );
4828 return LDAP_INVALID_SYNTAX;
4831 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4834 return LDAP_SUCCESS;
4842 assert( in != NULL );
4843 assert( !BER_BVISNULL( in ) );
4845 if ( in->bv_len != 3 ) {
4846 return LDAP_INVALID_SYNTAX;
4849 return hexValidate( NULL, in );
4852 /* Normalize a SID as used inside a CSN:
4853 * three-digit numeric string */
4860 struct berval *normalized,
4863 if ( val->bv_len != 3 ) {
4864 return LDAP_INVALID_SYNTAX;
4867 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4877 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4880 /* Normalize a SID as used inside a CSN, either as-is
4881 * (assertion value) or extracted from the CSN
4882 * (attribute value) */
4889 struct berval *normalized,
4897 if ( BER_BVISEMPTY( val ) ) {
4898 return LDAP_INVALID_SYNTAX;
4901 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4902 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4905 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4907 ptr = ber_bvchr( val, '#' );
4908 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4909 return LDAP_INVALID_SYNTAX;
4912 bv.bv_val = ptr + 1;
4913 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4915 ptr = ber_bvchr( &bv, '#' );
4916 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4917 return LDAP_INVALID_SYNTAX;
4920 bv.bv_val = ptr + 1;
4921 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4923 ptr = ber_bvchr( &bv, '#' );
4924 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4925 return LDAP_INVALID_SYNTAX;
4928 bv.bv_len = ptr - bv.bv_val;
4930 if ( bv.bv_len == 2 ) {
4931 /* OpenLDAP 2.3 SID */
4933 buf[ 1 ] = bv.bv_val[ 0 ];
4934 buf[ 2 ] = bv.bv_val[ 1 ];
4941 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4953 assert( in != NULL );
4954 assert( !BER_BVISNULL( in ) );
4956 if ( BER_BVISEMPTY( in ) ) {
4957 return LDAP_INVALID_SYNTAX;
4962 ptr = ber_bvchr( &bv, '#' );
4963 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4964 return LDAP_INVALID_SYNTAX;
4967 bv.bv_len = ptr - bv.bv_val;
4968 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4969 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4971 return LDAP_INVALID_SYNTAX;
4974 rc = generalizedTimeValidate( NULL, &bv );
4975 if ( rc != LDAP_SUCCESS ) {
4979 bv.bv_val = ptr + 1;
4980 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4982 ptr = ber_bvchr( &bv, '#' );
4983 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4984 return LDAP_INVALID_SYNTAX;
4987 bv.bv_len = ptr - bv.bv_val;
4988 if ( bv.bv_len != 6 ) {
4989 return LDAP_INVALID_SYNTAX;
4992 rc = hexValidate( NULL, &bv );
4993 if ( rc != LDAP_SUCCESS ) {
4997 bv.bv_val = ptr + 1;
4998 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5000 ptr = ber_bvchr( &bv, '#' );
5001 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
5002 return LDAP_INVALID_SYNTAX;
5005 bv.bv_len = ptr - bv.bv_val;
5006 if ( bv.bv_len == 2 ) {
5007 /* tolerate old 2-digit replica-id */
5008 rc = hexValidate( NULL, &bv );
5011 rc = sidValidate( NULL, &bv );
5013 if ( rc != LDAP_SUCCESS ) {
5017 bv.bv_val = ptr + 1;
5018 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
5020 if ( bv.bv_len != 6 ) {
5021 return LDAP_INVALID_SYNTAX;
5024 return hexValidate( NULL, &bv );
5027 /* Normalize a CSN in OpenLDAP 2.1 format */
5034 struct berval *normalized,
5037 struct berval gt, cnt, sid, mod;
5039 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5043 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5044 assert( !BER_BVISEMPTY( val ) );
5048 ptr = ber_bvchr( >, '#' );
5049 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5050 return LDAP_INVALID_SYNTAX;
5053 gt.bv_len = ptr - gt.bv_val;
5054 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5055 return LDAP_INVALID_SYNTAX;
5058 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5059 return LDAP_INVALID_SYNTAX;
5062 cnt.bv_val = ptr + 1;
5063 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5065 ptr = ber_bvchr( &cnt, '#' );
5066 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5067 return LDAP_INVALID_SYNTAX;
5070 cnt.bv_len = ptr - cnt.bv_val;
5071 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5072 return LDAP_INVALID_SYNTAX;
5075 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5076 return LDAP_INVALID_SYNTAX;
5079 cnt.bv_val += STRLENOF( "0x" );
5080 cnt.bv_len -= STRLENOF( "0x" );
5082 sid.bv_val = ptr + 1;
5083 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5085 ptr = ber_bvchr( &sid, '#' );
5086 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5087 return LDAP_INVALID_SYNTAX;
5090 sid.bv_len = ptr - sid.bv_val;
5091 if ( sid.bv_len != STRLENOF( "0" ) ) {
5092 return LDAP_INVALID_SYNTAX;
5095 mod.bv_val = ptr + 1;
5096 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5097 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5098 return LDAP_INVALID_SYNTAX;
5101 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5105 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5106 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5108 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5110 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5111 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5115 *ptr++ = sid.bv_val[ 0 ];
5119 for ( i = 0; i < mod.bv_len; i++ ) {
5120 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5124 assert( ptr == &bv.bv_val[bv.bv_len] );
5126 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5127 return LDAP_INVALID_SYNTAX;
5130 ber_dupbv_x( normalized, &bv, ctx );
5132 return LDAP_SUCCESS;
5135 /* Normalize a CSN in OpenLDAP 2.3 format */
5142 struct berval *normalized,
5145 struct berval gt, cnt, sid, mod;
5147 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5151 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5152 assert( !BER_BVISEMPTY( val ) );
5156 ptr = ber_bvchr( >, '#' );
5157 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5158 return LDAP_INVALID_SYNTAX;
5161 gt.bv_len = ptr - gt.bv_val;
5162 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5163 return LDAP_INVALID_SYNTAX;
5166 cnt.bv_val = ptr + 1;
5167 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5169 ptr = ber_bvchr( &cnt, '#' );
5170 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5171 return LDAP_INVALID_SYNTAX;
5174 cnt.bv_len = ptr - cnt.bv_val;
5175 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5176 return LDAP_INVALID_SYNTAX;
5179 sid.bv_val = ptr + 1;
5180 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5182 ptr = ber_bvchr( &sid, '#' );
5183 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5184 return LDAP_INVALID_SYNTAX;
5187 sid.bv_len = ptr - sid.bv_val;
5188 if ( sid.bv_len != STRLENOF( "00" ) ) {
5189 return LDAP_INVALID_SYNTAX;
5192 mod.bv_val = ptr + 1;
5193 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5194 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5195 return LDAP_INVALID_SYNTAX;
5198 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5202 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5203 ptr = lutil_strcopy( ptr, ".000000Z#" );
5204 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5207 for ( i = 0; i < sid.bv_len; i++ ) {
5208 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5211 for ( i = 0; i < mod.bv_len; i++ ) {
5212 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5216 assert( ptr == &bv.bv_val[bv.bv_len] );
5217 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5218 return LDAP_INVALID_SYNTAX;
5221 ber_dupbv_x( normalized, &bv, ctx );
5223 return LDAP_SUCCESS;
5226 /* Normalize a CSN */
5233 struct berval *normalized,
5236 struct berval cnt, sid, mod;
5240 assert( val != NULL );
5241 assert( normalized != NULL );
5243 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5245 if ( BER_BVISEMPTY( val ) ) {
5246 return LDAP_INVALID_SYNTAX;
5249 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5250 /* Openldap <= 2.3 */
5252 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5255 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5258 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5261 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5262 return LDAP_INVALID_SYNTAX;
5265 ptr = ber_bvchr( val, '#' );
5266 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5267 return LDAP_INVALID_SYNTAX;
5270 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5271 return LDAP_INVALID_SYNTAX;
5274 cnt.bv_val = ptr + 1;
5275 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5277 ptr = ber_bvchr( &cnt, '#' );
5278 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5279 return LDAP_INVALID_SYNTAX;
5282 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5283 return LDAP_INVALID_SYNTAX;
5286 sid.bv_val = ptr + 1;
5287 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5289 ptr = ber_bvchr( &sid, '#' );
5290 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5291 return LDAP_INVALID_SYNTAX;
5294 sid.bv_len = ptr - sid.bv_val;
5295 if ( sid.bv_len != STRLENOF( "000" ) ) {
5296 return LDAP_INVALID_SYNTAX;
5299 mod.bv_val = ptr + 1;
5300 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5302 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5303 return LDAP_INVALID_SYNTAX;
5306 ber_dupbv_x( normalized, val, ctx );
5308 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5309 i < normalized->bv_len; i++ )
5311 /* assume it's already validated that's all hex digits */
5312 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5315 return LDAP_SUCCESS;
5325 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5328 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5329 /* slight optimization - does not need the start parameter */
5330 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5335 check_time_syntax (struct berval *val,
5338 struct berval *fraction)
5341 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5342 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5343 * GeneralizedTime supports leap seconds, UTCTime does not.
5345 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5346 static const int mdays[2][12] = {
5347 /* non-leap years */
5348 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5350 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5353 int part, c, c1, c2, tzoffset, leapyear = 0;
5356 e = p + val->bv_len;
5358 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5359 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5361 for (part = start; part < 7 && p < e; part++) {
5363 if (!ASCII_DIGIT(c1)) {
5368 return LDAP_INVALID_SYNTAX;
5371 if (!ASCII_DIGIT(c)) {
5372 return LDAP_INVALID_SYNTAX;
5374 c += c1 * 10 - '0' * 11;
5375 if ((part | 1) == 3) {
5378 return LDAP_INVALID_SYNTAX;
5381 if (c >= ceiling[part]) {
5382 if (! (c == 60 && part == 6 && start == 0))
5383 return LDAP_INVALID_SYNTAX;
5387 if (part < 5 + start) {
5388 return LDAP_INVALID_SYNTAX;
5390 for (; part < 9; part++) {
5394 /* leapyear check for the Gregorian calendar (year>1581) */
5395 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5399 if (parts[3] >= mdays[leapyear][parts[2]]) {
5400 return LDAP_INVALID_SYNTAX;
5404 fraction->bv_val = p;
5405 fraction->bv_len = 0;
5406 if (p < e && (*p == '.' || *p == ',')) {
5408 while (++p < e && ASCII_DIGIT(*p)) {
5411 if (p - fraction->bv_val == 1) {
5412 return LDAP_INVALID_SYNTAX;
5414 for (end_num = p; end_num[-1] == '0'; --end_num) {
5417 c = end_num - fraction->bv_val;
5418 if (c != 1) fraction->bv_len = c;
5424 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5430 return LDAP_INVALID_SYNTAX;
5436 for (part = 7; part < 9 && p < e; part++) {
5438 if (!ASCII_DIGIT(c1)) {
5443 return LDAP_INVALID_SYNTAX;
5446 if (!ASCII_DIGIT(c2)) {
5447 return LDAP_INVALID_SYNTAX;
5449 parts[part] = c1 * 10 + c2 - '0' * 11;
5450 if (parts[part] >= ceiling[part]) {
5451 return LDAP_INVALID_SYNTAX;
5454 if (part < 8 + start) {
5455 return LDAP_INVALID_SYNTAX;
5458 if (tzoffset == '-') {
5459 /* negative offset to UTC, ie west of Greenwich */
5460 parts[4] += parts[7];
5461 parts[5] += parts[8];
5462 /* offset is just hhmm, no seconds */
5463 for (part = 6; --part >= 0; ) {
5467 c = mdays[leapyear][parts[2]];
5469 if (parts[part] >= c) {
5471 return LDAP_INVALID_SYNTAX;
5476 } else if (part != 5) {
5481 /* positive offset to UTC, ie east of Greenwich */
5482 parts[4] -= parts[7];
5483 parts[5] -= parts[8];
5484 for (part = 6; --part >= 0; ) {
5485 if (parts[part] < 0) {
5487 return LDAP_INVALID_SYNTAX;
5492 /* make first arg to % non-negative */
5493 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5498 } else if (part != 5) {
5505 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5508 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5515 struct berval *normalized )
5519 rc = check_time_syntax(val, 1, parts, NULL);
5520 if (rc != LDAP_SUCCESS) {
5524 normalized->bv_val = ch_malloc( 14 );
5525 if ( normalized->bv_val == NULL ) {
5526 return LBER_ERROR_MEMORY;
5529 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5530 parts[1], parts[2] + 1, parts[3] + 1,
5531 parts[4], parts[5], parts[6] );
5532 normalized->bv_len = 13;
5534 return LDAP_SUCCESS;
5544 return check_time_syntax(in, 1, parts, NULL);
5547 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5550 generalizedTimeValidate(
5555 struct berval fraction;
5556 return check_time_syntax(in, 0, parts, &fraction);
5560 generalizedTimeNormalize(
5565 struct berval *normalized,
5570 struct berval fraction;
5572 rc = check_time_syntax(val, 0, parts, &fraction);
5573 if (rc != LDAP_SUCCESS) {
5577 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5578 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5579 if ( BER_BVISNULL( normalized ) ) {
5580 return LBER_ERROR_MEMORY;
5583 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5584 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5585 parts[4], parts[5], parts[6] );
5586 if ( !BER_BVISEMPTY( &fraction ) ) {
5587 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5588 fraction.bv_val, fraction.bv_len );
5589 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5591 strcpy( normalized->bv_val + len-1, "Z" );
5592 normalized->bv_len = len;
5594 return LDAP_SUCCESS;
5598 generalizedTimeOrderingMatch(
5603 struct berval *value,
5604 void *assertedValue )
5606 struct berval *asserted = (struct berval *) assertedValue;
5607 ber_len_t v_len = value->bv_len;
5608 ber_len_t av_len = asserted->bv_len;
5610 /* ignore trailing 'Z' when comparing */
5611 int match = memcmp( value->bv_val, asserted->bv_val,
5612 (v_len < av_len ? v_len : av_len) - 1 );
5613 if ( match == 0 ) match = v_len - av_len;
5616 return LDAP_SUCCESS;
5619 /* Index generation function */
5620 int generalizedTimeIndexer(
5625 struct berval *prefix,
5633 BerValue bvtmp; /* 40 bit index */
5635 struct lutil_timet tt;
5637 bvtmp.bv_len = sizeof(tmp);
5639 for( i=0; values[i].bv_val != NULL; i++ ) {
5640 /* just count them */
5643 /* we should have at least one value at this point */
5646 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5648 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5649 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5650 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5651 /* Use 40 bits of time for key */
5652 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5653 lutil_tm2time( &tm, &tt );
5654 tmp[0] = tt.tt_gsec & 0xff;
5655 tmp[4] = tt.tt_sec & 0xff;
5657 tmp[3] = tt.tt_sec & 0xff;
5659 tmp[2] = tt.tt_sec & 0xff;
5661 tmp[1] = tt.tt_sec & 0xff;
5663 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5667 keys[j].bv_val = NULL;
5672 return LDAP_SUCCESS;
5675 /* Index generation function */
5676 int generalizedTimeFilter(
5681 struct berval *prefix,
5682 void * assertedValue,
5688 BerValue bvtmp; /* 40 bit index */
5689 BerValue *value = (BerValue *) assertedValue;
5691 struct lutil_timet tt;
5693 bvtmp.bv_len = sizeof(tmp);
5695 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5696 /* Use 40 bits of time for key */
5697 if ( value->bv_val && value->bv_len >= 10 &&
5698 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5700 lutil_tm2time( &tm, &tt );
5701 tmp[0] = tt.tt_gsec & 0xff;
5702 tmp[4] = tt.tt_sec & 0xff;
5704 tmp[3] = tt.tt_sec & 0xff;
5706 tmp[2] = tt.tt_sec & 0xff;
5708 tmp[1] = tt.tt_sec & 0xff;
5710 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5711 ber_dupbv_x(keys, &bvtmp, ctx );
5712 keys[1].bv_val = NULL;
5720 return LDAP_SUCCESS;
5724 deliveryMethodValidate(
5726 struct berval *val )
5729 #define LENOF(s) (sizeof(s)-1)
5730 struct berval tmp = *val;
5732 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5733 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5734 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5737 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5739 switch( tmp.bv_val[0] ) {
5742 if(( tmp.bv_len >= LENOF("any") ) &&
5743 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5745 tmp.bv_len -= LENOF("any");
5746 tmp.bv_val += LENOF("any");
5749 return LDAP_INVALID_SYNTAX;
5753 if(( tmp.bv_len >= LENOF("mhs") ) &&
5754 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5756 tmp.bv_len -= LENOF("mhs");
5757 tmp.bv_val += LENOF("mhs");
5760 return LDAP_INVALID_SYNTAX;
5764 if(( tmp.bv_len >= LENOF("physical") ) &&
5765 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5767 tmp.bv_len -= LENOF("physical");
5768 tmp.bv_val += LENOF("physical");
5771 return LDAP_INVALID_SYNTAX;
5774 case 'T': /* telex or teletex or telephone */
5775 if(( tmp.bv_len >= LENOF("telex") ) &&
5776 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5778 tmp.bv_len -= LENOF("telex");
5779 tmp.bv_val += LENOF("telex");
5782 if(( tmp.bv_len >= LENOF("teletex") ) &&
5783 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5785 tmp.bv_len -= LENOF("teletex");
5786 tmp.bv_val += LENOF("teletex");
5789 if(( tmp.bv_len >= LENOF("telephone") ) &&
5790 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5792 tmp.bv_len -= LENOF("telephone");
5793 tmp.bv_val += LENOF("telephone");
5796 return LDAP_INVALID_SYNTAX;
5799 case 'G': /* g3fax or g4fax */
5800 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5801 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5802 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5804 tmp.bv_len -= LENOF("g3fax");
5805 tmp.bv_val += LENOF("g3fax");
5808 return LDAP_INVALID_SYNTAX;
5812 if(( tmp.bv_len >= LENOF("ia5") ) &&
5813 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5815 tmp.bv_len -= LENOF("ia5");
5816 tmp.bv_val += LENOF("ia5");
5819 return LDAP_INVALID_SYNTAX;
5823 if(( tmp.bv_len >= LENOF("videotex") ) &&
5824 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5826 tmp.bv_len -= LENOF("videotex");
5827 tmp.bv_val += LENOF("videotex");
5830 return LDAP_INVALID_SYNTAX;
5833 return LDAP_INVALID_SYNTAX;
5836 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5838 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5842 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5846 return LDAP_INVALID_SYNTAX;
5848 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5857 nisNetgroupTripleValidate(
5859 struct berval *val )
5864 if ( BER_BVISEMPTY( val ) ) {
5865 return LDAP_INVALID_SYNTAX;
5868 p = (char *)val->bv_val;
5869 e = p + val->bv_len;
5871 if ( *p != '(' /*')'*/ ) {
5872 return LDAP_INVALID_SYNTAX;
5875 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5879 return LDAP_INVALID_SYNTAX;
5882 } else if ( !AD_CHAR( *p ) ) {
5883 return LDAP_INVALID_SYNTAX;
5887 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5888 return LDAP_INVALID_SYNTAX;
5894 return LDAP_INVALID_SYNTAX;
5897 return LDAP_SUCCESS;
5901 bootParameterValidate(
5903 struct berval *val )
5907 if ( BER_BVISEMPTY( val ) ) {
5908 return LDAP_INVALID_SYNTAX;
5911 p = (char *)val->bv_val;
5912 e = p + val->bv_len;
5915 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5916 if ( !AD_CHAR( *p ) ) {
5917 return LDAP_INVALID_SYNTAX;
5922 return LDAP_INVALID_SYNTAX;
5926 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5927 if ( !AD_CHAR( *p ) ) {
5928 return LDAP_INVALID_SYNTAX;
5933 return LDAP_INVALID_SYNTAX;
5937 for ( p++; p < e; p++ ) {
5938 if ( !SLAP_PRINTABLE( *p ) ) {
5939 return LDAP_INVALID_SYNTAX;
5943 return LDAP_SUCCESS;
5947 firstComponentNormalize(
5952 struct berval *normalized,
5959 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5960 ber_dupbv_x( normalized, val, ctx );
5961 return LDAP_SUCCESS;
5964 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5966 if( ! ( val->bv_val[0] == '(' /*')'*/
5967 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5968 && ! ( val->bv_val[0] == '{' /*'}'*/
5969 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5971 return LDAP_INVALID_SYNTAX;
5974 /* trim leading white space */
5976 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5982 /* grab next word */
5983 comp.bv_val = &val->bv_val[len];
5984 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5985 for( comp.bv_len = 0;
5986 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5992 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5993 rc = numericoidValidate( NULL, &comp );
5994 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5995 rc = integerValidate( NULL, &comp );
5997 rc = LDAP_INVALID_SYNTAX;
6001 if( rc == LDAP_SUCCESS ) {
6002 ber_dupbv_x( normalized, &comp, ctx );
6008 static char *country_gen_syn[] = {
6009 "1.3.6.1.4.1.1466.115.121.1.15",
6010 "1.3.6.1.4.1.1466.115.121.1.26",
6011 "1.3.6.1.4.1.1466.115.121.1.44",
6015 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
6016 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
6018 static slap_syntax_defs_rec syntax_defs[] = {
6019 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
6020 X_BINARY X_NOT_H_R ")",
6021 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
6022 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
6023 0, NULL, NULL, NULL},
6024 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
6025 0, NULL, NULL, NULL},
6026 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
6028 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6029 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6031 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6032 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6033 0, NULL, bitStringValidate, NULL },
6034 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6035 0, NULL, booleanValidate, NULL},
6036 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6037 X_BINARY X_NOT_H_R ")",
6038 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6039 NULL, certificateValidate, NULL},
6040 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6041 X_BINARY X_NOT_H_R ")",
6042 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6043 NULL, certificateListValidate, NULL},
6044 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6045 X_BINARY X_NOT_H_R ")",
6046 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6047 NULL, sequenceValidate, NULL},
6048 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6049 X_BINARY X_NOT_H_R ")",
6050 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6051 NULL, attributeCertificateValidate, NULL},
6052 #if 0 /* need to go __after__ printableString */
6053 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6054 0, "1.3.6.1.4.1.1466.115.121.1.44",
6055 countryStringValidate, NULL},
6057 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6058 0, NULL, dnValidate, dnPretty},
6059 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6060 0, NULL, rdnValidate, rdnPretty},
6061 #ifdef LDAP_COMP_MATCH
6062 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6063 0, NULL, allComponentsValidate, NULL},
6064 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6065 0, NULL, componentFilterValidate, NULL},
6067 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6068 0, NULL, NULL, NULL},
6069 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6070 0, NULL, deliveryMethodValidate, NULL},
6071 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6072 0, NULL, UTF8StringValidate, NULL},
6073 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6074 0, NULL, NULL, NULL},
6075 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6076 0, NULL, NULL, NULL},
6077 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6078 0, NULL, NULL, NULL},
6079 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6080 0, NULL, NULL, NULL},
6081 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6082 0, NULL, NULL, NULL},
6083 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6084 0, NULL, printablesStringValidate, NULL},
6085 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6086 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6087 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6088 0, NULL, generalizedTimeValidate, NULL},
6089 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6090 0, NULL, NULL, NULL},
6091 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6092 0, NULL, IA5StringValidate, NULL},
6093 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6094 0, NULL, integerValidate, NULL},
6095 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6096 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6097 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6098 0, NULL, NULL, NULL},
6099 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6100 0, NULL, NULL, NULL},
6101 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6102 0, NULL, NULL, NULL},
6103 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6104 0, NULL, NULL, NULL},
6105 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6106 0, NULL, NULL, NULL},
6107 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6108 0, NULL, nameUIDValidate, nameUIDPretty },
6109 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6110 0, NULL, NULL, NULL},
6111 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6112 0, NULL, numericStringValidate, NULL},
6113 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6114 0, NULL, NULL, NULL},
6115 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6116 0, NULL, numericoidValidate, NULL},
6117 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6118 0, NULL, IA5StringValidate, NULL},
6119 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6120 0, NULL, blobValidate, NULL},
6121 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6122 0, NULL, postalAddressValidate, NULL},
6123 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6124 0, NULL, NULL, NULL},
6125 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6126 0, NULL, NULL, NULL},
6127 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6128 0, NULL, printableStringValidate, NULL},
6129 /* moved here because now depends on Directory String, IA5 String
6130 * and Printable String */
6131 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6132 0, country_gen_syn, countryStringValidate, NULL},
6133 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6134 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6135 0, NULL, subtreeSpecificationValidate, NULL},
6136 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6137 X_BINARY X_NOT_H_R ")",
6138 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6139 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6140 0, NULL, printableStringValidate, NULL},
6141 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6142 0, NULL, NULL, NULL},
6143 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6144 0, NULL, printablesStringValidate, NULL},
6145 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6146 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6147 0, NULL, utcTimeValidate, NULL},
6149 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6150 0, NULL, NULL, NULL},
6151 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6152 0, NULL, NULL, NULL},
6153 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6154 0, NULL, NULL, NULL},
6155 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6156 0, NULL, NULL, NULL},
6157 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6158 0, NULL, NULL, NULL},
6160 /* RFC 2307 NIS Syntaxes */
6161 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6162 0, NULL, nisNetgroupTripleValidate, NULL},
6163 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6164 0, NULL, bootParameterValidate, NULL},
6166 /* draft-zeilenga-ldap-x509 */
6167 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6168 SLAP_SYNTAX_HIDE, NULL,
6169 serialNumberAndIssuerValidate,
6170 serialNumberAndIssuerPretty},
6171 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6172 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6173 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6174 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6175 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6176 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6177 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6178 SLAP_SYNTAX_HIDE, NULL,
6179 issuerAndThisUpdateValidate,
6180 issuerAndThisUpdatePretty},
6181 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6182 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6183 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6184 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6185 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6186 SLAP_SYNTAX_HIDE, NULL,
6187 serialNumberAndIssuerSerialValidate,
6188 serialNumberAndIssuerSerialPretty},
6189 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6190 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6192 #ifdef SLAPD_AUTHPASSWD
6193 /* needs updating */
6194 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6195 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6198 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6199 0, NULL, UUIDValidate, UUIDPretty},
6201 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6202 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6204 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6205 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6207 /* OpenLDAP Void Syntax */
6208 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6209 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6211 /* FIXME: OID is unused, but not registered yet */
6212 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6213 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6215 {NULL, 0, NULL, NULL, NULL}
6218 char *csnSIDMatchSyntaxes[] = {
6219 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6222 char *certificateExactMatchSyntaxes[] = {
6223 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6226 char *certificateListExactMatchSyntaxes[] = {
6227 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6230 char *attributeCertificateExactMatchSyntaxes[] = {
6231 attributeCertificateSyntaxOID /* attributeCertificate */,
6235 #ifdef LDAP_COMP_MATCH
6236 char *componentFilterMatchSyntaxes[] = {
6237 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6238 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6239 attributeCertificateSyntaxOID /* attributeCertificate */,
6244 char *directoryStringSyntaxes[] = {
6245 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6248 char *integerFirstComponentMatchSyntaxes[] = {
6249 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6250 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6253 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6254 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6255 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6256 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6257 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6258 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6259 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6260 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6261 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6266 * Other matching rules in X.520 that we do not use (yet):
6268 * 2.5.13.25 uTCTimeMatch
6269 * 2.5.13.26 uTCTimeOrderingMatch
6270 * 2.5.13.31* directoryStringFirstComponentMatch
6271 * 2.5.13.32* wordMatch
6272 * 2.5.13.33* keywordMatch
6273 * 2.5.13.36+ certificatePairExactMatch
6274 * 2.5.13.37+ certificatePairMatch
6275 * 2.5.13.40+ algorithmIdentifierMatch
6276 * 2.5.13.41* storedPrefixMatch
6277 * 2.5.13.42 attributeCertificateMatch
6278 * 2.5.13.43 readerAndKeyIDMatch
6279 * 2.5.13.44 attributeIntegrityMatch
6281 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6282 * (+) described in draft-zeilenga-ldap-x509
6284 static slap_mrule_defs_rec mrule_defs[] = {
6286 * EQUALITY matching rules must be listed after associated APPROX
6287 * matching rules. So, we list all APPROX matching rules first.
6289 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6290 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6291 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6292 NULL, NULL, directoryStringApproxMatch,
6293 directoryStringApproxIndexer, directoryStringApproxFilter,
6296 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6297 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6298 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6299 NULL, NULL, IA5StringApproxMatch,
6300 IA5StringApproxIndexer, IA5StringApproxFilter,
6304 * Other matching rules
6307 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6308 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6309 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6310 NULL, NULL, octetStringMatch,
6311 octetStringIndexer, octetStringFilter,
6314 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6315 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6316 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6317 NULL, dnNormalize, dnMatch,
6318 octetStringIndexer, octetStringFilter,
6321 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6322 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6323 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6324 NULL, dnNormalize, dnRelativeMatch,
6328 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6329 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6330 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6331 NULL, dnNormalize, dnRelativeMatch,
6335 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6336 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6337 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6338 NULL, dnNormalize, dnRelativeMatch,
6342 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6343 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6344 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6345 NULL, dnNormalize, dnRelativeMatch,
6349 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6350 "SYNTAX 1.2.36.79672281.1.5.0 )",
6351 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6352 NULL, rdnNormalize, rdnMatch,
6353 octetStringIndexer, octetStringFilter,
6356 #ifdef LDAP_COMP_MATCH
6357 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6358 "SYNTAX 1.2.36.79672281.1.5.2 )",
6359 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6360 NULL, NULL , componentFilterMatch,
6361 octetStringIndexer, octetStringFilter,
6364 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6365 "SYNTAX 1.2.36.79672281.1.5.3 )",
6366 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6367 NULL, NULL , allComponentsMatch,
6368 octetStringIndexer, octetStringFilter,
6371 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6372 "SYNTAX 1.2.36.79672281.1.5.3 )",
6373 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6374 NULL, NULL , directoryComponentsMatch,
6375 octetStringIndexer, octetStringFilter,
6379 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6380 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6381 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6382 NULL, UTF8StringNormalize, octetStringMatch,
6383 octetStringIndexer, octetStringFilter,
6384 directoryStringApproxMatchOID },
6386 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6387 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6388 SLAP_MR_ORDERING, directoryStringSyntaxes,
6389 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6391 "caseIgnoreMatch" },
6393 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6394 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6395 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6396 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6397 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6398 "caseIgnoreMatch" },
6400 {"( 2.5.13.5 NAME 'caseExactMatch' "
6401 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6402 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6403 NULL, UTF8StringNormalize, octetStringMatch,
6404 octetStringIndexer, octetStringFilter,
6405 directoryStringApproxMatchOID },
6407 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6408 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6409 SLAP_MR_ORDERING, directoryStringSyntaxes,
6410 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6414 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6415 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6416 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6417 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6418 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6421 {"( 2.5.13.8 NAME 'numericStringMatch' "
6422 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6423 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6424 NULL, numericStringNormalize, octetStringMatch,
6425 octetStringIndexer, octetStringFilter,
6428 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6429 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6430 SLAP_MR_ORDERING, NULL,
6431 NULL, numericStringNormalize, octetStringOrderingMatch,
6433 "numericStringMatch" },
6435 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6436 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6437 SLAP_MR_SUBSTR, NULL,
6438 NULL, numericStringNormalize, octetStringSubstringsMatch,
6439 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6440 "numericStringMatch" },
6442 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6443 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6444 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6445 NULL, postalAddressNormalize, octetStringMatch,
6446 octetStringIndexer, octetStringFilter,
6449 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6450 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6451 SLAP_MR_SUBSTR, NULL,
6452 NULL, NULL, NULL, NULL, NULL,
6453 "caseIgnoreListMatch" },
6455 {"( 2.5.13.13 NAME 'booleanMatch' "
6456 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6457 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6458 NULL, NULL, booleanMatch,
6459 octetStringIndexer, octetStringFilter,
6462 {"( 2.5.13.14 NAME 'integerMatch' "
6463 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6464 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6465 NULL, NULL, integerMatch,
6466 integerIndexer, integerFilter,
6469 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6470 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6471 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6472 NULL, NULL, integerMatch,
6476 {"( 2.5.13.16 NAME 'bitStringMatch' "
6477 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6478 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6479 NULL, NULL, octetStringMatch,
6480 octetStringIndexer, octetStringFilter,
6483 {"( 2.5.13.17 NAME 'octetStringMatch' "
6484 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6485 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6486 NULL, NULL, octetStringMatch,
6487 octetStringIndexer, octetStringFilter,
6490 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6492 SLAP_MR_ORDERING, NULL,
6493 NULL, NULL, octetStringOrderingMatch,
6495 "octetStringMatch" },
6497 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6498 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6499 SLAP_MR_SUBSTR, NULL,
6500 NULL, NULL, octetStringSubstringsMatch,
6501 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6502 "octetStringMatch" },
6504 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6505 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6506 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6508 telephoneNumberNormalize, octetStringMatch,
6509 octetStringIndexer, octetStringFilter,
6512 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6514 SLAP_MR_SUBSTR, NULL,
6515 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6516 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6517 "telephoneNumberMatch" },
6519 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6520 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6521 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6522 NULL, NULL, NULL, NULL, NULL, NULL },
6524 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6525 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6526 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6527 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6528 uniqueMemberIndexer, uniqueMemberFilter,
6531 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6532 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6533 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6534 NULL, NULL, NULL, NULL, NULL, NULL },
6536 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6538 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6539 NULL, generalizedTimeNormalize, octetStringMatch,
6540 generalizedTimeIndexer, generalizedTimeFilter,
6543 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6545 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6546 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6548 "generalizedTimeMatch" },
6550 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6552 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6553 integerFirstComponentMatchSyntaxes,
6554 NULL, firstComponentNormalize, integerMatch,
6555 octetStringIndexer, octetStringFilter,
6558 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6559 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6560 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6561 objectIdentifierFirstComponentMatchSyntaxes,
6562 NULL, firstComponentNormalize, octetStringMatch,
6563 octetStringIndexer, octetStringFilter,
6566 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6567 "SYNTAX 1.3.6.1.1.15.1 )",
6568 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6569 NULL, certificateExactNormalize, octetStringMatch,
6570 octetStringIndexer, octetStringFilter,
6573 {"( 2.5.13.35 NAME 'certificateMatch' "
6574 "SYNTAX 1.3.6.1.1.15.2 )",
6575 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6576 NULL, NULL, NULL, NULL, NULL,
6579 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6580 "SYNTAX 1.3.6.1.1.15.5 )",
6581 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6582 NULL, certificateListExactNormalize, octetStringMatch,
6583 octetStringIndexer, octetStringFilter,
6586 {"( 2.5.13.39 NAME 'certificateListMatch' "
6587 "SYNTAX 1.3.6.1.1.15.6 )",
6588 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6589 NULL, NULL, NULL, NULL, NULL,
6592 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6593 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6594 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6595 NULL, attributeCertificateExactNormalize, octetStringMatch,
6596 octetStringIndexer, octetStringFilter,
6599 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6600 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6601 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6602 NULL, NULL, NULL, NULL, NULL,
6605 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6606 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6607 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6608 NULL, IA5StringNormalize, octetStringMatch,
6609 octetStringIndexer, octetStringFilter,
6610 IA5StringApproxMatchOID },
6612 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6613 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6614 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6615 NULL, IA5StringNormalize, octetStringMatch,
6616 octetStringIndexer, octetStringFilter,
6617 IA5StringApproxMatchOID },
6619 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6621 SLAP_MR_SUBSTR, NULL,
6622 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6623 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6624 "caseIgnoreIA5Match" },
6626 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6628 SLAP_MR_SUBSTR, NULL,
6629 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6630 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6631 "caseExactIA5Match" },
6633 #ifdef SLAPD_AUTHPASSWD
6634 /* needs updating */
6635 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6636 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6637 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6638 NULL, NULL, authPasswordMatch,
6643 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6644 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6646 NULL, NULL, integerBitAndMatch,
6650 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6651 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6653 NULL, NULL, integerBitOrMatch,
6657 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6658 "SYNTAX 1.3.6.1.1.16.1 )",
6659 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6660 NULL, UUIDNormalize, octetStringMatch,
6661 octetStringIndexer, octetStringFilter,
6664 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6665 "SYNTAX 1.3.6.1.1.16.1 )",
6666 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6667 NULL, UUIDNormalize, octetStringOrderingMatch,
6668 octetStringIndexer, octetStringFilter,
6671 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6672 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6673 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6674 NULL, csnNormalize, csnMatch,
6675 csnIndexer, csnFilter,
6678 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6679 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6680 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6681 NULL, csnNormalize, csnOrderingMatch,
6685 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6686 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6687 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6688 NULL, csnSidNormalize, octetStringMatch,
6689 octetStringIndexer, octetStringFilter,
6692 /* FIXME: OID is unused, but not registered yet */
6693 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6694 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6695 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6696 NULL, authzNormalize, authzMatch,
6700 {NULL, SLAP_MR_NONE, NULL,
6701 NULL, NULL, NULL, NULL, NULL,
6706 slap_schema_init( void )
6711 /* we should only be called once (from main) */
6712 assert( schema_init_done == 0 );
6714 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6715 res = register_syntax( &syntax_defs[i] );
6718 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6719 syntax_defs[i].sd_desc );
6724 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6725 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6726 mrule_defs[i].mrd_compat_syntaxes == NULL )
6729 "slap_schema_init: Ignoring unusable matching rule %s\n",
6730 mrule_defs[i].mrd_desc );
6734 res = register_matching_rule( &mrule_defs[i] );
6738 "slap_schema_init: Error registering matching rule %s\n",
6739 mrule_defs[i].mrd_desc );
6744 res = slap_schema_load();
6745 schema_init_done = 1;
6750 schema_destroy( void )
6759 if( schema_init_done ) {
6760 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6761 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );