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 certificateListValidate( Syntax *syntax, struct berval *in )
279 BerElementBuffer berbuf;
280 BerElement *ber = (BerElement *)&berbuf;
283 ber_int_t version = SLAP_X509_V1;
285 ber_init2( ber, in, LBER_USE_DER );
286 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
287 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
288 tag = ber_skip_tag( ber, &len ); /* Sequence */
289 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
290 tag = ber_peek_tag( ber, &len );
291 /* Optional version */
292 if ( tag == LBER_INTEGER ) {
293 tag = ber_get_int( ber, &version );
294 assert( tag == LBER_INTEGER );
295 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
297 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
298 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
299 ber_skip_data( ber, len );
300 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
301 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
302 ber_skip_data( ber, len );
303 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
304 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
305 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
306 ber_skip_data( ber, len );
307 /* Optional nextUpdate */
308 tag = ber_skip_tag( ber, &len );
309 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
310 ber_skip_data( ber, len );
311 tag = ber_skip_tag( ber, &len );
313 /* revokedCertificates - Sequence of Sequence, Optional */
314 if ( tag == LBER_SEQUENCE ) {
316 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
317 /* Should NOT be empty */
318 ber_skip_data( ber, len );
319 tag = ber_skip_tag( ber, &len );
322 /* Optional Extensions - Sequence of Sequence */
323 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
325 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
326 tag = ber_peek_tag( ber, &seqlen );
327 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
328 ber_skip_data( ber, len );
329 tag = ber_skip_tag( ber, &len );
331 /* signatureAlgorithm */
332 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
333 ber_skip_data( ber, len );
334 tag = ber_skip_tag( ber, &len );
336 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
337 ber_skip_data( ber, len );
338 tag = ber_skip_tag( ber, &len );
339 /* Must be at end now */
340 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
344 /* X.509 PMI Attribute Certificate Validate */
346 attributeCertificateValidate( Syntax *syntax, struct berval *in )
348 BerElementBuffer berbuf;
349 BerElement *ber = (BerElement *)&berbuf;
355 ber_init2( ber, in, LBER_USE_DER );
357 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
358 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
360 tag = ber_skip_tag( ber, &len ); /* Sequence */
361 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
363 tag = ber_peek_tag( ber, &len ); /* Version */
364 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
365 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
366 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
368 tag = ber_skip_tag( ber, &len ); /* Holder */
369 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
370 ber_skip_data( ber, len );
372 tag = ber_skip_tag( ber, &len ); /* Issuer */
373 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
374 ber_skip_data( ber, len );
376 tag = ber_skip_tag( ber, &len ); /* Signature */
377 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
378 ber_skip_data( ber, len );
380 tag = ber_skip_tag( ber, &len ); /* Serial number */
381 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
382 ber_skip_data( ber, len );
384 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
385 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
386 ber_skip_data( ber, len );
388 tag = ber_skip_tag( ber, &len ); /* Attributes */
389 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
390 ber_skip_data( ber, len );
392 tag = ber_peek_tag( ber, &len );
394 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
395 tag = ber_skip_tag( ber, &len );
396 ber_skip_data( ber, len );
397 tag = ber_peek_tag( ber, &len );
400 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
401 tag = ber_skip_tag( ber, &len );
402 ber_skip_data( ber, len );
404 tag = ber_peek_tag( ber, &len );
407 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
408 tag = ber_skip_tag( ber, &len );
409 ber_skip_data( ber, len );
411 tag = ber_peek_tag( ber, &len );
414 if ( tag == LBER_BITSTRING ) { /* Signature */
415 tag = ber_skip_tag( ber, &len );
416 ber_skip_data( ber, len );
418 tag = ber_peek_tag( ber, &len );
421 /* Must be at end now */
422 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
433 struct berval *value,
434 void *assertedValue )
436 struct berval *asserted = (struct berval *) assertedValue;
437 int match = value->bv_len - asserted->bv_len;
440 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
448 octetStringOrderingMatch(
453 struct berval *value,
454 void *assertedValue )
456 struct berval *asserted = (struct berval *) assertedValue;
457 ber_len_t v_len = value->bv_len;
458 ber_len_t av_len = asserted->bv_len;
460 int match = memcmp( value->bv_val, asserted->bv_val,
461 (v_len < av_len ? v_len : av_len) );
463 if( match == 0 ) match = v_len - av_len;
471 HASH_CONTEXT *HASHcontext,
472 struct berval *prefix,
477 HASH_Init(HASHcontext);
478 if(prefix && prefix->bv_len > 0) {
479 HASH_Update(HASHcontext,
480 (unsigned char *)prefix->bv_val, prefix->bv_len);
482 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
483 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
484 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
490 HASH_CONTEXT *HASHcontext,
491 unsigned char *HASHdigest,
492 unsigned char *value,
495 HASH_CONTEXT ctx = *HASHcontext;
496 HASH_Update( &ctx, value, len );
497 HASH_Final( HASHdigest, &ctx );
500 /* Index generation function */
501 int octetStringIndexer(
506 struct berval *prefix,
514 HASH_CONTEXT HASHcontext;
515 unsigned char HASHdigest[HASH_BYTES];
516 struct berval digest;
517 digest.bv_val = (char *)HASHdigest;
518 digest.bv_len = sizeof(HASHdigest);
520 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
521 /* just count them */
524 /* we should have at least one value at this point */
527 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
529 slen = syntax->ssyn_oidlen;
530 mlen = mr->smr_oidlen;
532 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
533 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
534 hashIter( &HASHcontext, HASHdigest,
535 (unsigned char *)values[i].bv_val, values[i].bv_len );
536 ber_dupbv_x( &keys[i], &digest, ctx );
539 BER_BVZERO( &keys[i] );
546 /* Index generation function */
547 int octetStringFilter(
552 struct berval *prefix,
553 void * assertedValue,
559 HASH_CONTEXT HASHcontext;
560 unsigned char HASHdigest[HASH_BYTES];
561 struct berval *value = (struct berval *) assertedValue;
562 struct berval digest;
563 digest.bv_val = (char *)HASHdigest;
564 digest.bv_len = sizeof(HASHdigest);
566 slen = syntax->ssyn_oidlen;
567 mlen = mr->smr_oidlen;
569 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
571 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
572 hashIter( &HASHcontext, HASHdigest,
573 (unsigned char *)value->bv_val, value->bv_len );
575 ber_dupbv_x( keys, &digest, ctx );
576 BER_BVZERO( &keys[1] );
584 octetStringSubstringsMatch(
589 struct berval *value,
590 void *assertedValue )
593 SubstringsAssertion *sub = assertedValue;
594 struct berval left = *value;
598 /* Add up asserted input length */
599 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
600 inlen += sub->sa_initial.bv_len;
603 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
604 inlen += sub->sa_any[i].bv_len;
607 if ( !BER_BVISNULL( &sub->sa_final ) ) {
608 inlen += sub->sa_final.bv_len;
611 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
612 if ( inlen > left.bv_len ) {
617 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
618 sub->sa_initial.bv_len );
624 left.bv_val += sub->sa_initial.bv_len;
625 left.bv_len -= sub->sa_initial.bv_len;
626 inlen -= sub->sa_initial.bv_len;
629 if ( !BER_BVISNULL( &sub->sa_final ) ) {
630 if ( inlen > left.bv_len ) {
635 match = memcmp( sub->sa_final.bv_val,
636 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
637 sub->sa_final.bv_len );
643 left.bv_len -= sub->sa_final.bv_len;
644 inlen -= sub->sa_final.bv_len;
648 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
653 if ( inlen > left.bv_len ) {
654 /* not enough length */
659 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
663 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
670 idx = p - left.bv_val;
672 if ( idx >= left.bv_len ) {
673 /* this shouldn't happen */
680 if ( sub->sa_any[i].bv_len > left.bv_len ) {
681 /* not enough left */
686 match = memcmp( left.bv_val,
687 sub->sa_any[i].bv_val,
688 sub->sa_any[i].bv_len );
696 left.bv_val += sub->sa_any[i].bv_len;
697 left.bv_len -= sub->sa_any[i].bv_len;
698 inlen -= sub->sa_any[i].bv_len;
707 /* Substrings Index generation function */
709 octetStringSubstringsIndexer(
714 struct berval *prefix,
723 HASH_CONTEXT HCany, HCini, HCfin;
724 unsigned char HASHdigest[HASH_BYTES];
725 struct berval digest;
726 digest.bv_val = (char *)HASHdigest;
727 digest.bv_len = sizeof(HASHdigest);
731 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
732 /* count number of indices to generate */
733 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
734 if( values[i].bv_len >= index_substr_if_maxlen ) {
735 nkeys += index_substr_if_maxlen -
736 (index_substr_if_minlen - 1);
737 } else if( values[i].bv_len >= index_substr_if_minlen ) {
738 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
742 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
743 if( values[i].bv_len >= index_substr_any_len ) {
744 nkeys += values[i].bv_len - (index_substr_any_len - 1);
748 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
749 if( values[i].bv_len >= index_substr_if_maxlen ) {
750 nkeys += index_substr_if_maxlen -
751 (index_substr_if_minlen - 1);
752 } else if( values[i].bv_len >= index_substr_if_minlen ) {
753 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
759 /* no keys to generate */
764 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
766 slen = syntax->ssyn_oidlen;
767 mlen = mr->smr_oidlen;
769 if ( flags & SLAP_INDEX_SUBSTR_ANY )
770 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
771 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
772 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
773 if( flags & SLAP_INDEX_SUBSTR_FINAL )
774 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
777 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
780 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
781 ( values[i].bv_len >= index_substr_any_len ) )
783 max = values[i].bv_len - (index_substr_any_len - 1);
785 for( j=0; j<max; j++ ) {
786 hashIter( &HCany, HASHdigest,
787 (unsigned char *)&values[i].bv_val[j],
788 index_substr_any_len );
789 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
793 /* skip if too short */
794 if( values[i].bv_len < index_substr_if_minlen ) continue;
796 max = index_substr_if_maxlen < values[i].bv_len
797 ? index_substr_if_maxlen : values[i].bv_len;
799 for( j=index_substr_if_minlen; j<=max; j++ ) {
801 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
802 hashIter( &HCini, HASHdigest,
803 (unsigned char *)values[i].bv_val, j );
804 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
807 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
808 hashIter( &HCfin, HASHdigest,
809 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
810 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
817 BER_BVZERO( &keys[nkeys] );
828 octetStringSubstringsFilter (
833 struct berval *prefix,
834 void * assertedValue,
838 SubstringsAssertion *sa;
841 size_t slen, mlen, klen;
843 HASH_CONTEXT HASHcontext;
844 unsigned char HASHdigest[HASH_BYTES];
845 struct berval *value;
846 struct berval digest;
848 sa = (SubstringsAssertion *) assertedValue;
850 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
851 !BER_BVISNULL( &sa->sa_initial ) &&
852 sa->sa_initial.bv_len >= index_substr_if_minlen )
855 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
856 ( flags & SLAP_INDEX_SUBSTR_ANY ))
858 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
862 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
864 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
865 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
866 /* don't bother accounting with stepping */
867 nkeys += sa->sa_any[i].bv_len -
868 ( index_substr_any_len - 1 );
873 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
874 !BER_BVISNULL( &sa->sa_final ) &&
875 sa->sa_final.bv_len >= index_substr_if_minlen )
878 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
879 ( flags & SLAP_INDEX_SUBSTR_ANY ))
881 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
890 digest.bv_val = (char *)HASHdigest;
891 digest.bv_len = sizeof(HASHdigest);
893 slen = syntax->ssyn_oidlen;
894 mlen = mr->smr_oidlen;
896 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
899 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
900 !BER_BVISNULL( &sa->sa_initial ) &&
901 sa->sa_initial.bv_len >= index_substr_if_minlen )
903 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
904 value = &sa->sa_initial;
906 klen = index_substr_if_maxlen < value->bv_len
907 ? index_substr_if_maxlen : value->bv_len;
909 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
910 hashIter( &HASHcontext, HASHdigest,
911 (unsigned char *)value->bv_val, klen );
912 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
914 /* If initial is too long and we have subany indexed, use it
915 * to match the excess...
917 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
920 pre = SLAP_INDEX_SUBSTR_PREFIX;
921 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
922 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
924 hashIter( &HASHcontext, HASHdigest,
925 (unsigned char *)&value->bv_val[j], index_substr_any_len );
926 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
931 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
933 pre = SLAP_INDEX_SUBSTR_PREFIX;
934 klen = index_substr_any_len;
936 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
937 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
941 value = &sa->sa_any[i];
943 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
945 j <= value->bv_len - index_substr_any_len;
946 j += index_substr_any_step )
948 hashIter( &HASHcontext, HASHdigest,
949 (unsigned char *)&value->bv_val[j], klen );
950 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
955 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
956 !BER_BVISNULL( &sa->sa_final ) &&
957 sa->sa_final.bv_len >= index_substr_if_minlen )
959 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
960 value = &sa->sa_final;
962 klen = index_substr_if_maxlen < value->bv_len
963 ? index_substr_if_maxlen : value->bv_len;
965 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
966 hashIter( &HASHcontext, HASHdigest,
967 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
968 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
970 /* If final is too long and we have subany indexed, use it
971 * to match the excess...
973 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
976 pre = SLAP_INDEX_SUBSTR_PREFIX;
977 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
978 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
980 hashIter( &HASHcontext, HASHdigest,
981 (unsigned char *)&value->bv_val[j], index_substr_any_len );
982 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
988 BER_BVZERO( &keys[nkeys] );
1005 /* very unforgiving validation, requires no normalization
1006 * before simplistic matching
1008 if( in->bv_len < 3 ) {
1009 return LDAP_INVALID_SYNTAX;
1012 /* RFC 4517 Section 3.3.2 Bit String:
1013 * BitString = SQUOTE *binary-digit SQUOTE "B"
1014 * binary-digit = "0" / "1"
1016 * where SQUOTE [RFC4512] is
1017 * SQUOTE = %x27 ; single quote ("'")
1019 * Example: '0101111101'B
1022 if( in->bv_val[0] != '\'' ||
1023 in->bv_val[in->bv_len - 2] != '\'' ||
1024 in->bv_val[in->bv_len - 1] != 'B' )
1026 return LDAP_INVALID_SYNTAX;
1029 for( i = in->bv_len - 3; i > 0; i-- ) {
1030 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1031 return LDAP_INVALID_SYNTAX;
1035 return LDAP_SUCCESS;
1039 * Syntaxes from RFC 4517
1044 A value of the Bit String syntax is a sequence of binary digits. The
1045 LDAP-specific encoding of a value of this syntax is defined by the
1048 BitString = SQUOTE *binary-digit SQUOTE "B"
1050 binary-digit = "0" / "1"
1052 The <SQUOTE> rule is defined in [MODELS].
1057 The LDAP definition for the Bit String syntax is:
1059 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1061 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1065 3.3.21. Name and Optional UID
1067 A value of the Name and Optional UID syntax is the distinguished name
1068 [MODELS] of an entity optionally accompanied by a unique identifier
1069 that serves to differentiate the entity from others with an identical
1072 The LDAP-specific encoding of a value of this syntax is defined by
1075 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1077 The <BitString> rule is defined in Section 3.3.2. The
1078 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1079 defined in [MODELS].
1081 Note that although the '#' character may occur in the string
1082 representation of a distinguished name, no additional escaping of
1083 this character is performed when a <distinguishedName> is encoded in
1084 a <NameAndOptionalUID>.
1087 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1089 The LDAP definition for the Name and Optional UID syntax is:
1091 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1093 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1100 1.4. Common ABNF Productions
1103 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1105 SQUOTE = %x27 ; single quote ("'")
1110 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1111 * be escaped except when at the beginning of a value, the
1112 * definition of Name and Optional UID appears to be flawed,
1113 * because there is no clear means to determine whether the
1114 * UID part is present or not.
1118 * cn=Someone,dc=example,dc=com#'1'B
1120 * could be either a NameAndOptionalUID with trailing UID, i.e.
1122 * DN = "cn=Someone,dc=example,dc=com"
1125 * or a NameAndOptionalUID with no trailing UID, and the AVA
1126 * in the last RDN made of
1128 * attributeType = dc
1129 * attributeValue = com#'1'B
1131 * in fact "com#'1'B" is a valid IA5 string.
1133 * As a consequence, current slapd code takes the presence of
1134 * #<valid BitString> at the end of the string representation
1135 * of a NameAndOptionalUID to mean this is indeed a BitString.
1136 * This is quite arbitrary - it has changed the past and might
1137 * change in the future.
1147 struct berval dn, uid;
1149 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1151 ber_dupbv( &dn, in );
1152 if( !dn.bv_val ) return LDAP_OTHER;
1154 /* if there's a "#", try bitStringValidate()... */
1155 uid.bv_val = strrchr( dn.bv_val, '#' );
1156 if ( !BER_BVISNULL( &uid ) ) {
1158 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1160 rc = bitStringValidate( NULL, &uid );
1161 if ( rc == LDAP_SUCCESS ) {
1162 /* in case of success, trim the UID,
1163 * otherwise treat it as part of the DN */
1164 dn.bv_len -= uid.bv_len + 1;
1165 uid.bv_val[-1] = '\0';
1169 rc = dnValidate( NULL, &dn );
1171 ber_memfree( dn.bv_val );
1182 assert( val != NULL );
1183 assert( out != NULL );
1186 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1188 if( BER_BVISEMPTY( val ) ) {
1189 ber_dupbv_x( out, val, ctx );
1191 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1192 return LDAP_INVALID_SYNTAX;
1196 struct berval dnval = *val;
1197 struct berval uidval = BER_BVNULL;
1199 uidval.bv_val = strrchr( val->bv_val, '#' );
1200 if ( !BER_BVISNULL( &uidval ) ) {
1202 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1204 rc = bitStringValidate( NULL, &uidval );
1206 if ( rc == LDAP_SUCCESS ) {
1207 ber_dupbv_x( &dnval, val, ctx );
1209 dnval.bv_len -= ++uidval.bv_len;
1210 dnval.bv_val[dnval.bv_len] = '\0';
1213 BER_BVZERO( &uidval );
1217 rc = dnPretty( syntax, &dnval, out, ctx );
1218 if ( dnval.bv_val != val->bv_val ) {
1219 slap_sl_free( dnval.bv_val, ctx );
1221 if( rc != LDAP_SUCCESS ) {
1225 if( !BER_BVISNULL( &uidval ) ) {
1228 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1229 + uidval.bv_len + 1,
1232 ber_memfree_x( out->bv_val, ctx );
1236 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1237 out->bv_len += uidval.bv_len;
1238 out->bv_val[out->bv_len] = '\0';
1242 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1244 return LDAP_SUCCESS;
1248 uniqueMemberNormalize(
1253 struct berval *normalized,
1259 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1261 ber_dupbv_x( &out, val, ctx );
1262 if ( BER_BVISEMPTY( &out ) ) {
1266 struct berval uid = BER_BVNULL;
1268 uid.bv_val = strrchr( out.bv_val, '#' );
1269 if ( !BER_BVISNULL( &uid ) ) {
1271 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1273 rc = bitStringValidate( NULL, &uid );
1274 if ( rc == LDAP_SUCCESS ) {
1275 uid.bv_val[-1] = '\0';
1276 out.bv_len -= uid.bv_len + 1;
1282 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1284 if( rc != LDAP_SUCCESS ) {
1285 slap_sl_free( out.bv_val, ctx );
1286 return LDAP_INVALID_SYNTAX;
1289 if( !BER_BVISNULL( &uid ) ) {
1292 tmp = ch_realloc( normalized->bv_val,
1293 normalized->bv_len + uid.bv_len
1294 + STRLENOF("#") + 1 );
1295 if ( tmp == NULL ) {
1296 ber_memfree_x( normalized->bv_val, ctx );
1300 normalized->bv_val = tmp;
1302 /* insert the separator */
1303 normalized->bv_val[normalized->bv_len++] = '#';
1305 /* append the UID */
1306 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1307 uid.bv_val, uid.bv_len );
1308 normalized->bv_len += uid.bv_len;
1311 normalized->bv_val[normalized->bv_len] = '\0';
1314 slap_sl_free( out.bv_val, ctx );
1317 return LDAP_SUCCESS;
1326 struct berval *value,
1327 void *assertedValue )
1330 struct berval *asserted = (struct berval *) assertedValue;
1331 struct berval assertedDN = *asserted;
1332 struct berval assertedUID = BER_BVNULL;
1333 struct berval valueDN = *value;
1334 struct berval valueUID = BER_BVNULL;
1335 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1337 if ( !BER_BVISEMPTY( asserted ) ) {
1338 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1339 if ( !BER_BVISNULL( &assertedUID ) ) {
1340 assertedUID.bv_val++;
1341 assertedUID.bv_len = assertedDN.bv_len
1342 - ( assertedUID.bv_val - assertedDN.bv_val );
1344 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1345 assertedDN.bv_len -= assertedUID.bv_len + 1;
1348 BER_BVZERO( &assertedUID );
1353 if ( !BER_BVISEMPTY( value ) ) {
1355 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1356 if ( !BER_BVISNULL( &valueUID ) ) {
1358 valueUID.bv_len = valueDN.bv_len
1359 - ( valueUID.bv_val - valueDN.bv_val );
1361 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1362 valueDN.bv_len -= valueUID.bv_len + 1;
1365 BER_BVZERO( &valueUID );
1370 if( valueUID.bv_len && assertedUID.bv_len ) {
1371 match = valueUID.bv_len - assertedUID.bv_len;
1374 return LDAP_SUCCESS;
1377 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1380 return LDAP_SUCCESS;
1383 } else if ( !approx && valueUID.bv_len ) {
1386 return LDAP_SUCCESS;
1388 } else if ( !approx && assertedUID.bv_len ) {
1391 return LDAP_SUCCESS;
1394 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1398 uniqueMemberIndexer(
1403 struct berval *prefix,
1411 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1412 /* just count them */
1416 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1418 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1419 struct berval assertedDN = values[i];
1420 struct berval assertedUID = BER_BVNULL;
1422 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1423 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1424 if ( !BER_BVISNULL( &assertedUID ) ) {
1425 assertedUID.bv_val++;
1426 assertedUID.bv_len = assertedDN.bv_len
1427 - ( assertedUID.bv_val - assertedDN.bv_val );
1429 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1430 assertedDN.bv_len -= assertedUID.bv_len + 1;
1433 BER_BVZERO( &assertedUID );
1438 dnvalues[i] = assertedDN;
1440 BER_BVZERO( &dnvalues[i] );
1442 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1443 dnvalues, keysp, ctx );
1445 slap_sl_free( dnvalues, ctx );
1455 struct berval *prefix,
1456 void * assertedValue,
1460 struct berval *asserted = (struct berval *) assertedValue;
1461 struct berval assertedDN = *asserted;
1462 struct berval assertedUID = BER_BVNULL;
1464 if ( !BER_BVISEMPTY( asserted ) ) {
1465 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1466 if ( !BER_BVISNULL( &assertedUID ) ) {
1467 assertedUID.bv_val++;
1468 assertedUID.bv_len = assertedDN.bv_len
1469 - ( assertedUID.bv_val - assertedDN.bv_val );
1471 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1472 assertedDN.bv_len -= assertedUID.bv_len + 1;
1475 BER_BVZERO( &assertedUID );
1480 return octetStringFilter( use, flags, syntax, mr, prefix,
1481 &assertedDN, keysp, ctx );
1486 * Handling boolean syntax and matching is quite rigid.
1487 * A more flexible approach would be to allow a variety
1488 * of strings to be normalized and prettied into TRUE
1496 /* very unforgiving validation, requires no normalization
1497 * before simplistic matching
1500 if( in->bv_len == 4 ) {
1501 if( bvmatch( in, &slap_true_bv ) ) {
1502 return LDAP_SUCCESS;
1504 } else if( in->bv_len == 5 ) {
1505 if( bvmatch( in, &slap_false_bv ) ) {
1506 return LDAP_SUCCESS;
1510 return LDAP_INVALID_SYNTAX;
1519 struct berval *value,
1520 void *assertedValue )
1522 /* simplistic matching allowed by rigid validation */
1523 struct berval *asserted = (struct berval *) assertedValue;
1524 *matchp = value->bv_len != asserted->bv_len;
1525 return LDAP_SUCCESS;
1528 /*-------------------------------------------------------------------
1529 LDAP/X.500 string syntax / matching rules have a few oddities. This
1530 comment attempts to detail how slapd(8) treats them.
1533 StringSyntax X.500 LDAP Matching/Comments
1534 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1535 PrintableString subset subset i/e + ignore insignificant spaces
1536 PrintableString subset subset i/e + ignore insignificant spaces
1537 NumericString subset subset ignore all spaces
1538 IA5String ASCII ASCII i/e + ignore insignificant spaces
1539 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1541 TelephoneNumber subset subset i + ignore all spaces and "-"
1543 See RFC 4518 for details.
1547 In X.500(93), a directory string can be either a PrintableString,
1548 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1549 In later versions, more CHOICEs were added. In all cases the string
1552 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1553 A directory string cannot be zero length.
1555 For matching, there are both case ignore and exact rules. Both
1556 also require that "insignificant" spaces be ignored.
1557 spaces before the first non-space are ignored;
1558 spaces after the last non-space are ignored;
1559 spaces after a space are ignored.
1560 Note: by these rules (and as clarified in X.520), a string of only
1561 spaces is to be treated as if held one space, not empty (which
1562 would be a syntax error).
1565 In ASN.1, numeric string is just a string of digits and spaces
1566 and could be empty. However, in X.500, all attribute values of
1567 numeric string carry a non-empty constraint. For example:
1569 internationalISDNNumber ATTRIBUTE ::= {
1570 WITH SYNTAX InternationalISDNNumber
1571 EQUALITY MATCHING RULE numericStringMatch
1572 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1573 ID id-at-internationalISDNNumber }
1574 InternationalISDNNumber ::=
1575 NumericString (SIZE(1..ub-international-isdn-number))
1577 Unforunately, some assertion values are don't carry the same
1578 constraint (but its unclear how such an assertion could ever
1579 be true). In LDAP, there is one syntax (numericString) not two
1580 (numericString with constraint, numericString without constraint).
1581 This should be treated as numericString with non-empty constraint.
1582 Note that while someone may have no ISDN number, there are no ISDN
1583 numbers which are zero length.
1585 In matching, spaces are ignored.
1588 In ASN.1, Printable string is just a string of printable characters
1589 and can be empty. In X.500, semantics much like NumericString (see
1590 serialNumber for a like example) excepting uses insignificant space
1591 handling instead of ignore all spaces. They must be non-empty.
1594 Basically same as PrintableString. There are no examples in X.500,
1595 but same logic applies. Empty strings are allowed.
1597 -------------------------------------------------------------------*/
1606 unsigned char *u = (unsigned char *)in->bv_val;
1608 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1609 /* directory strings cannot be empty */
1610 return LDAP_INVALID_SYNTAX;
1613 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1614 /* get the length indicated by the first byte */
1615 len = LDAP_UTF8_CHARLEN2( u, len );
1617 /* very basic checks */
1620 if( (u[5] & 0xC0) != 0x80 ) {
1621 return LDAP_INVALID_SYNTAX;
1624 if( (u[4] & 0xC0) != 0x80 ) {
1625 return LDAP_INVALID_SYNTAX;
1628 if( (u[3] & 0xC0) != 0x80 ) {
1629 return LDAP_INVALID_SYNTAX;
1632 if( (u[2] & 0xC0 )!= 0x80 ) {
1633 return LDAP_INVALID_SYNTAX;
1636 if( (u[1] & 0xC0) != 0x80 ) {
1637 return LDAP_INVALID_SYNTAX;
1640 /* CHARLEN already validated it */
1643 return LDAP_INVALID_SYNTAX;
1646 /* make sure len corresponds with the offset
1647 to the next character */
1648 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1652 return LDAP_INVALID_SYNTAX;
1655 return LDAP_SUCCESS;
1659 UTF8StringNormalize(
1664 struct berval *normalized,
1667 struct berval tmp, nvalue;
1668 int flags, wasspace;
1671 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1673 if( BER_BVISNULL( val ) ) {
1674 /* assume we're dealing with a syntax (e.g., UTF8String)
1675 * which allows empty strings
1677 BER_BVZERO( normalized );
1678 return LDAP_SUCCESS;
1681 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1682 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1683 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1684 ? LDAP_UTF8_APPROX : 0;
1686 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1691 /* collapse spaces (in place) */
1693 nvalue.bv_val = tmp.bv_val;
1695 /* trim leading spaces? */
1696 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1697 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1699 for( i = 0; i < tmp.bv_len; i++) {
1700 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1701 if( wasspace++ == 0 ) {
1702 /* trim repeated spaces */
1703 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1707 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1711 if( !BER_BVISEMPTY( &nvalue ) ) {
1712 /* trim trailing space? */
1714 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1715 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1719 nvalue.bv_val[nvalue.bv_len] = '\0';
1722 /* string of all spaces is treated as one space */
1723 nvalue.bv_val[0] = ' ';
1724 nvalue.bv_val[1] = '\0';
1728 *normalized = nvalue;
1729 return LDAP_SUCCESS;
1733 directoryStringSubstringsMatch(
1738 struct berval *value,
1739 void *assertedValue )
1742 SubstringsAssertion *sub = assertedValue;
1743 struct berval left = *value;
1747 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1748 if ( sub->sa_initial.bv_len > left.bv_len ) {
1749 /* not enough left */
1754 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1755 sub->sa_initial.bv_len );
1761 left.bv_val += sub->sa_initial.bv_len;
1762 left.bv_len -= sub->sa_initial.bv_len;
1764 priorspace = ASCII_SPACE(
1765 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1768 if ( sub->sa_any ) {
1769 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1773 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1774 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1776 /* allow next space to match */
1783 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1787 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1788 /* not enough left */
1793 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1800 idx = p - left.bv_val;
1802 if ( idx >= left.bv_len ) {
1803 /* this shouldn't happen */
1810 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1811 /* not enough left */
1816 match = memcmp( left.bv_val,
1817 sub->sa_any[i].bv_val,
1818 sub->sa_any[i].bv_len );
1826 left.bv_val += sub->sa_any[i].bv_len;
1827 left.bv_len -= sub->sa_any[i].bv_len;
1829 priorspace = ASCII_SPACE(
1830 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1834 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1835 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1836 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1838 /* allow next space to match */
1843 if ( sub->sa_final.bv_len > left.bv_len ) {
1844 /* not enough left */
1849 match = memcmp( sub->sa_final.bv_val,
1850 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1851 sub->sa_final.bv_len );
1860 return LDAP_SUCCESS;
1863 #if defined(SLAPD_APPROX_INITIALS)
1864 # define SLAPD_APPROX_DELIMITER "._ "
1865 # define SLAPD_APPROX_WORDLEN 2
1867 # define SLAPD_APPROX_DELIMITER " "
1868 # define SLAPD_APPROX_WORDLEN 1
1877 struct berval *value,
1878 void *assertedValue )
1880 struct berval *nval, *assertv;
1881 char *val, **values, **words, *c;
1882 int i, count, len, nextchunk=0, nextavail=0;
1884 /* Yes, this is necessary */
1885 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1886 if( nval == NULL ) {
1888 return LDAP_SUCCESS;
1891 /* Yes, this is necessary */
1892 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1893 NULL, LDAP_UTF8_APPROX, NULL );
1894 if( assertv == NULL ) {
1897 return LDAP_SUCCESS;
1900 /* Isolate how many words there are */
1901 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1902 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1903 if ( c == NULL ) break;
1908 /* Get a phonetic copy of each word */
1909 words = (char **)ch_malloc( count * sizeof(char *) );
1910 values = (char **)ch_malloc( count * sizeof(char *) );
1911 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1913 values[i] = phonetic(c);
1916 /* Work through the asserted value's words, to see if at least some
1917 * of the words are there, in the same order. */
1919 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1920 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1925 #if defined(SLAPD_APPROX_INITIALS)
1926 else if( len == 1 ) {
1927 /* Single letter words need to at least match one word's initial */
1928 for( i=nextavail; i<count; i++ )
1929 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1936 /* Isolate the next word in the asserted value and phonetic it */
1937 assertv->bv_val[nextchunk+len] = '\0';
1938 val = phonetic( assertv->bv_val + nextchunk );
1940 /* See if this phonetic chunk is in the remaining words of *value */
1941 for( i=nextavail; i<count; i++ ){
1942 if( !strcmp( val, values[i] ) ){
1950 /* This chunk in the asserted value was NOT within the *value. */
1956 /* Go on to the next word in the asserted value */
1960 /* If some of the words were seen, call it a match */
1961 if( nextavail > 0 ) {
1968 /* Cleanup allocs */
1969 ber_bvfree( assertv );
1970 for( i=0; i<count; i++ ) {
1971 ch_free( values[i] );
1977 return LDAP_SUCCESS;
1986 struct berval *prefix,
1992 int i,j, len, wordcount, keycount=0;
1993 struct berval *newkeys;
1994 BerVarray keys=NULL;
1996 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1997 struct berval val = BER_BVNULL;
1998 /* Yes, this is necessary */
1999 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2000 assert( !BER_BVISNULL( &val ) );
2002 /* Isolate how many words there are. There will be a key for each */
2003 for( wordcount = 0, c = val.bv_val; *c; c++) {
2004 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2005 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2007 if (*c == '\0') break;
2011 /* Allocate/increase storage to account for new keys */
2012 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2013 * sizeof(struct berval) );
2014 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2015 if( keys ) ch_free( keys );
2018 /* Get a phonetic copy of each word */
2019 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2021 if( len < SLAPD_APPROX_WORDLEN ) continue;
2022 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2027 ber_memfree( val.bv_val );
2029 BER_BVZERO( &keys[keycount] );
2032 return LDAP_SUCCESS;
2041 struct berval *prefix,
2042 void * assertedValue,
2051 /* Yes, this is necessary */
2052 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2053 NULL, LDAP_UTF8_APPROX, NULL );
2054 if( val == NULL || BER_BVISNULL( val ) ) {
2055 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2056 BER_BVZERO( &keys[0] );
2059 return LDAP_SUCCESS;
2062 /* Isolate how many words there are. There will be a key for each */
2063 for( count = 0,c = val->bv_val; *c; c++) {
2064 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2065 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2067 if (*c == '\0') break;
2071 /* Allocate storage for new keys */
2072 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2074 /* Get a phonetic copy of each word */
2075 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2077 if( len < SLAPD_APPROX_WORDLEN ) continue;
2078 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2084 BER_BVZERO( &keys[count] );
2087 return LDAP_SUCCESS;
2090 /* Remove all spaces and '-' characters */
2092 telephoneNumberNormalize(
2097 struct berval *normalized,
2102 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2104 /* validator should have refused an empty string */
2105 assert( !BER_BVISEMPTY( val ) );
2107 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2109 for( p = val->bv_val; *p; p++ ) {
2110 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2116 normalized->bv_len = q - normalized->bv_val;
2118 if( BER_BVISEMPTY( normalized ) ) {
2119 slap_sl_free( normalized->bv_val, ctx );
2120 BER_BVZERO( normalized );
2121 return LDAP_INVALID_SYNTAX;
2124 return LDAP_SUCCESS;
2128 postalAddressValidate(
2132 struct berval bv = *in;
2135 for ( c = 0; c < in->bv_len; c++ ) {
2136 if ( in->bv_val[c] == '\\' ) {
2138 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2139 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2141 return LDAP_INVALID_SYNTAX;
2146 if ( in->bv_val[c] == '$' ) {
2147 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2148 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2149 return LDAP_INVALID_SYNTAX;
2151 bv.bv_val = &in->bv_val[c] + 1;
2155 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2156 return UTF8StringValidate( NULL, &bv );
2160 postalAddressNormalize(
2165 struct berval *normalized,
2168 BerVarray lines = NULL, nlines = NULL;
2170 int rc = LDAP_SUCCESS;
2171 MatchingRule *xmr = NULL;
2174 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2175 xmr = slap_schema.si_mr_caseIgnoreMatch;
2178 xmr = slap_schema.si_mr_caseExactMatch;
2181 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2182 if ( val->bv_val[c] == '$' ) {
2187 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2188 nlines = &lines[l + 2];
2190 lines[0].bv_val = val->bv_val;
2191 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2192 if ( val->bv_val[c] == '$' ) {
2193 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2195 lines[l].bv_val = &val->bv_val[c + 1];
2198 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2200 normalized->bv_len = l;
2202 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2203 /* NOTE: we directly normalize each line,
2204 * without unescaping the values, since the special
2205 * values '\24' ('$') and '\5C' ('\') are not affected
2206 * by normalization */
2207 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2208 if ( rc != LDAP_SUCCESS ) {
2209 rc = LDAP_INVALID_SYNTAX;
2213 normalized->bv_len += nlines[l].bv_len;
2216 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2218 p = normalized->bv_val;
2219 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2220 p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2226 assert( p == &normalized->bv_val[normalized->bv_len] );
2229 if ( nlines != NULL ) {
2230 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2231 slap_sl_free( nlines[l].bv_val, ctx );
2234 slap_sl_free( lines, ctx );
2245 struct berval val = *in;
2247 if( BER_BVISEMPTY( &val ) ) {
2248 /* disallow empty strings */
2249 return LDAP_INVALID_SYNTAX;
2252 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2253 if ( val.bv_len == 1 ) {
2254 return LDAP_SUCCESS;
2257 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2264 while ( OID_LEADCHAR( val.bv_val[0] )) {
2268 if ( val.bv_len == 0 ) {
2269 return LDAP_SUCCESS;
2273 if( !OID_SEPARATOR( val.bv_val[0] )) {
2281 return LDAP_INVALID_SYNTAX;
2290 struct berval val = *in;
2292 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2294 if ( val.bv_val[0] == '-' ) {
2298 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2299 return LDAP_INVALID_SYNTAX;
2302 if( val.bv_val[0] == '0' ) { /* "-0" */
2303 return LDAP_INVALID_SYNTAX;
2306 } else if ( val.bv_val[0] == '0' ) {
2307 if( val.bv_len > 1 ) { /* "0<more>" */
2308 return LDAP_INVALID_SYNTAX;
2311 return LDAP_SUCCESS;
2314 for( i=0; i < val.bv_len; i++ ) {
2315 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2316 return LDAP_INVALID_SYNTAX;
2320 return LDAP_SUCCESS;
2329 struct berval *value,
2330 void *assertedValue )
2332 struct berval *asserted = (struct berval *) assertedValue;
2333 int vsign = 1, asign = 1; /* default sign = '+' */
2338 if( v.bv_val[0] == '-' ) {
2344 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2347 if( a.bv_val[0] == '-' ) {
2353 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2355 match = vsign - asign;
2357 match = ( v.bv_len != a.bv_len
2358 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2359 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2360 if( vsign < 0 ) match = -match;
2364 return LDAP_SUCCESS;
2367 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2368 #define INDEX_INTLEN_CHOP 7
2369 #define INDEX_INTLEN_CHOPBYTES 3
2379 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2380 * two's complement value (sign-extended or chopped as needed),
2381 * however the top <number of exponent-bytes + 1> bits of first byte
2382 * above is the inverse sign. The next bit is the sign as delimiter.
2384 ber_slen_t k = index_intlen_strlen;
2386 unsigned signmask = ~0x7fU;
2387 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2388 struct berval val = *in, itmp = *tmp;
2390 if ( val.bv_val[0] != '-' ) {
2395 /* Chop least significant digits, increase length instead */
2396 if ( val.bv_len > (ber_len_t) k ) {
2397 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2398 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2399 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2402 if ( lutil_str2bin( &val, &itmp, ctx )) {
2403 return LDAP_INVALID_SYNTAX;
2406 /* Omit leading sign byte */
2407 if ( itmp.bv_val[0] == neg ) {
2412 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2414 assert( chop == 0 );
2415 memset( key->bv_val, neg, k ); /* sign-extend */
2416 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2417 lenp = lenbuf + sizeof(lenbuf);
2418 chop = - (ber_len_t) k;
2420 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2422 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2423 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2424 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2425 k = (lenbuf + sizeof(lenbuf)) - lenp;
2426 if ( k > (ber_slen_t) index_intlen )
2428 memcpy( key->bv_val, lenp, k );
2429 itmp.bv_len = index_intlen - k;
2431 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2432 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2436 /* Index generation function */
2443 struct berval *prefix,
2453 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2455 /* count the values and find max needed length */
2457 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2458 if ( vlen < values[i].bv_len )
2459 vlen = values[i].bv_len;
2461 if ( vlen > maxstrlen )
2464 /* we should have at least one value at this point */
2467 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2468 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2469 keys[i].bv_len = index_intlen;
2470 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2473 keys[i].bv_val = NULL;
2475 if ( vlen > sizeof(ibuf) ) {
2476 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2480 itmp.bv_len = sizeof(ibuf);
2482 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2483 if ( itmp.bv_val != ibuf ) {
2484 itmp.bv_len = values[i].bv_len;
2485 if ( itmp.bv_len <= sizeof(ibuf) )
2486 itmp.bv_len = sizeof(ibuf);
2487 else if ( itmp.bv_len > maxstrlen )
2488 itmp.bv_len = maxstrlen;
2490 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2496 if ( itmp.bv_val != ibuf ) {
2497 slap_sl_free( itmp.bv_val, ctx );
2502 /* Index generation function */
2509 struct berval *prefix,
2510 void * assertedValue,
2517 struct berval *value;
2520 value = (struct berval *) assertedValue;
2522 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2524 keys[0].bv_len = index_intlen;
2525 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2527 keys[1].bv_val = NULL;
2529 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2530 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2531 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2532 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2535 iv.bv_len = sizeof(ibuf);
2538 rc = integerVal2Key( value, keys, &iv, ctx );
2542 if ( iv.bv_val != ibuf ) {
2543 slap_sl_free( iv.bv_val, ctx );
2549 countryStringValidate(
2551 struct berval *val )
2553 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2555 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2556 return LDAP_INVALID_SYNTAX;
2558 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2559 return LDAP_INVALID_SYNTAX;
2562 return LDAP_SUCCESS;
2566 printableStringValidate(
2568 struct berval *val )
2572 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2574 for(i=0; i < val->bv_len; i++) {
2575 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2576 return LDAP_INVALID_SYNTAX;
2580 return LDAP_SUCCESS;
2584 printablesStringValidate(
2586 struct berval *val )
2590 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2592 for(i=0,len=0; i < val->bv_len; i++) {
2593 int c = val->bv_val[i];
2597 return LDAP_INVALID_SYNTAX;
2601 } else if ( SLAP_PRINTABLE(c) ) {
2604 return LDAP_INVALID_SYNTAX;
2609 return LDAP_INVALID_SYNTAX;
2612 return LDAP_SUCCESS;
2618 struct berval *val )
2622 for(i=0; i < val->bv_len; i++) {
2623 if( !LDAP_ASCII(val->bv_val[i]) ) {
2624 return LDAP_INVALID_SYNTAX;
2628 return LDAP_SUCCESS;
2637 struct berval *normalized,
2641 int casefold = !SLAP_MR_ASSOCIATED( mr,
2642 slap_schema.si_mr_caseExactIA5Match );
2644 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2648 /* Ignore initial whitespace */
2649 while ( ASCII_SPACE( *p ) ) p++;
2651 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2652 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2653 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2654 normalized->bv_val[normalized->bv_len] = '\0';
2656 p = q = normalized->bv_val;
2659 if ( ASCII_SPACE( *p ) ) {
2662 /* Ignore the extra whitespace */
2663 while ( ASCII_SPACE( *p ) ) {
2667 } else if ( casefold ) {
2668 /* Most IA5 rules require casefolding */
2669 *q++ = TOLOWER(*p); p++;
2676 assert( normalized->bv_val <= p );
2680 * If the string ended in space, backup the pointer one
2681 * position. One is enough because the above loop collapsed
2682 * all whitespace to a single space.
2684 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2686 /* null terminate */
2689 normalized->bv_len = q - normalized->bv_val;
2691 return LDAP_SUCCESS;
2700 if( in->bv_len != 36 ) {
2701 return LDAP_INVALID_SYNTAX;
2704 for( i=0; i<36; i++ ) {
2710 if( in->bv_val[i] != '-' ) {
2711 return LDAP_INVALID_SYNTAX;
2715 if( !ASCII_HEX( in->bv_val[i]) ) {
2716 return LDAP_INVALID_SYNTAX;
2721 return LDAP_SUCCESS;
2732 int rc=LDAP_INVALID_SYNTAX;
2734 assert( in != NULL );
2735 assert( out != NULL );
2737 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2740 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2742 for( i=0; i<36; i++ ) {
2748 if( in->bv_val[i] != '-' ) {
2751 out->bv_val[i] = '-';
2755 if( !ASCII_HEX( in->bv_val[i]) ) {
2758 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2763 out->bv_val[ out->bv_len ] = '\0';
2767 slap_sl_free( out->bv_val, ctx );
2780 struct berval *normalized,
2783 unsigned char octet = '\0';
2787 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2788 /* NOTE: must be a normalized UUID */
2789 assert( val->bv_len == 16 );
2791 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2792 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2793 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2794 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2796 return LDAP_SUCCESS;
2799 normalized->bv_len = 16;
2800 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2802 for( i=0, j=0; i<36; i++ ) {
2803 unsigned char nibble;
2804 if( val->bv_val[i] == '-' ) {
2807 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2808 nibble = val->bv_val[i] - '0';
2810 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2811 nibble = val->bv_val[i] - ('a'-10);
2813 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2814 nibble = val->bv_val[i] - ('A'-10);
2817 slap_sl_free( normalized->bv_val, ctx );
2818 BER_BVZERO( normalized );
2819 return LDAP_INVALID_SYNTAX;
2824 normalized->bv_val[j>>1] = octet;
2826 octet = nibble << 4;
2831 normalized->bv_val[normalized->bv_len] = 0;
2832 return LDAP_SUCCESS;
2838 numericStringValidate(
2844 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2846 for(i=0; i < in->bv_len; i++) {
2847 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2848 return LDAP_INVALID_SYNTAX;
2852 return LDAP_SUCCESS;
2856 numericStringNormalize(
2861 struct berval *normalized,
2864 /* removal all spaces */
2867 assert( !BER_BVISEMPTY( val ) );
2869 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2872 q = normalized->bv_val;
2875 if ( ASCII_SPACE( *p ) ) {
2876 /* Ignore whitespace */
2883 /* we should have copied no more than is in val */
2884 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2886 /* null terminate */
2889 normalized->bv_len = q - normalized->bv_val;
2891 if( BER_BVISEMPTY( normalized ) ) {
2892 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2893 normalized->bv_val[0] = ' ';
2894 normalized->bv_val[1] = '\0';
2895 normalized->bv_len = 1;
2898 return LDAP_SUCCESS;
2902 * Integer conversion macros that will use the largest available
2905 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2906 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2907 # define SLAP_LONG long long
2909 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2910 # define SLAP_LONG long
2911 #endif /* HAVE_STRTOLL ... */
2919 struct berval *value,
2920 void *assertedValue )
2922 SLAP_LONG lValue, lAssertedValue;
2925 /* safe to assume integers are NUL terminated? */
2926 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2927 if( errno == ERANGE )
2929 return LDAP_CONSTRAINT_VIOLATION;
2932 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2934 if( errno == ERANGE )
2936 return LDAP_CONSTRAINT_VIOLATION;
2939 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2940 return LDAP_SUCCESS;
2949 struct berval *value,
2950 void *assertedValue )
2952 SLAP_LONG lValue, lAssertedValue;
2955 /* safe to assume integers are NUL terminated? */
2956 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2957 if( errno == ERANGE )
2959 return LDAP_CONSTRAINT_VIOLATION;
2962 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2964 if( errno == ERANGE )
2966 return LDAP_CONSTRAINT_VIOLATION;
2969 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2970 return LDAP_SUCCESS;
2974 checkNum( struct berval *in, struct berval *out )
2976 /* parse serialNumber */
2977 ber_len_t neg = 0, extra = 0;
2980 out->bv_val = in->bv_val;
2983 if ( out->bv_val[0] == '-' ) {
2988 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
2989 first = out->bv_val[2];
2992 out->bv_len += STRLENOF("0x");
2993 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2994 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2997 } else if ( out->bv_val[0] == '\'' ) {
2998 first = out->bv_val[1];
3001 out->bv_len += STRLENOF("'");
3003 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3004 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3006 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3009 out->bv_len += STRLENOF("'H");
3012 first = out->bv_val[0];
3013 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3014 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3018 if ( !( out->bv_len > neg ) ) {
3022 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3030 serialNumberAndIssuerCheck(
3038 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3040 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3041 /* Parse old format */
3042 is->bv_val = ber_bvchr( in, '$' );
3043 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3045 sn->bv_val = in->bv_val;
3046 sn->bv_len = is->bv_val - in->bv_val;
3049 is->bv_len = in->bv_len - (sn->bv_len + 1);
3051 /* eat leading zeros */
3052 for( n=0; n < (sn->bv_len-1); n++ ) {
3053 if( sn->bv_val[n] != '0' ) break;
3058 for( n=0; n < sn->bv_len; n++ ) {
3059 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3063 /* Parse GSER format */
3068 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3072 struct berval x = *in;
3078 /* eat leading spaces */
3079 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3083 /* should be at issuer or serialNumber NamedValue */
3084 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3085 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3088 x.bv_val += STRLENOF("issuer");
3089 x.bv_len -= STRLENOF("issuer");
3091 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3095 /* eat leading spaces */
3096 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3100 /* For backward compatibility, this part is optional */
3101 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3102 x.bv_val += STRLENOF("rdnSequence:");
3103 x.bv_len -= STRLENOF("rdnSequence:");
3106 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3110 is->bv_val = x.bv_val;
3113 for ( ; is->bv_len < x.bv_len; ) {
3114 if ( is->bv_val[is->bv_len] != '"' ) {
3118 if ( is->bv_val[is->bv_len+1] == '"' ) {
3125 x.bv_val += is->bv_len + 1;
3126 x.bv_len -= is->bv_len + 1;
3128 have |= HAVE_ISSUER;
3130 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3132 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3134 /* parse serialNumber */
3135 x.bv_val += STRLENOF("serialNumber");
3136 x.bv_len -= STRLENOF("serialNumber");
3138 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3142 /* eat leading spaces */
3143 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3147 if ( checkNum( &x, sn ) ) {
3148 return LDAP_INVALID_SYNTAX;
3151 x.bv_val += sn->bv_len;
3152 x.bv_len -= sn->bv_len;
3157 return LDAP_INVALID_SYNTAX;
3160 /* eat leading spaces */
3161 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3165 if ( have == HAVE_ALL ) {
3169 if ( x.bv_val[0] != ',' ) {
3170 return LDAP_INVALID_SYNTAX;
3177 /* should have no characters left... */
3178 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3180 if ( numdquotes == 0 ) {
3181 ber_dupbv_x( &ni, is, ctx );
3186 ni.bv_len = is->bv_len - numdquotes;
3187 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3188 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3189 if ( is->bv_val[src] == '"' ) {
3192 ni.bv_val[dst] = is->bv_val[src];
3194 ni.bv_val[dst] = '\0';
3204 serialNumberAndIssuerValidate(
3209 struct berval sn, i;
3211 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3214 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3219 /* validate DN -- doesn't handle double dquote */
3220 rc = dnValidate( NULL, &i );
3222 rc = LDAP_INVALID_SYNTAX;
3225 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3226 slap_sl_free( i.bv_val, NULL );
3229 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3230 in->bv_val, rc, 0 );
3237 serialNumberAndIssuerPretty(
3244 struct berval sn, i, ni = BER_BVNULL;
3247 assert( in != NULL );
3248 assert( out != NULL );
3252 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3255 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3260 rc = dnPretty( syntax, &i, &ni, ctx );
3262 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3263 slap_sl_free( i.bv_val, ctx );
3267 rc = LDAP_INVALID_SYNTAX;
3271 /* make room from sn + "$" */
3272 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3273 + sn.bv_len + ni.bv_len;
3274 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3276 if ( out->bv_val == NULL ) {
3283 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3284 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3285 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3286 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3287 p = lutil_strcopy( p, /*{*/ "\" }" );
3289 assert( p == &out->bv_val[out->bv_len] );
3292 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3293 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3295 slap_sl_free( ni.bv_val, ctx );
3297 return LDAP_SUCCESS;
3307 /* Use hex format. '123456789abcdef'H */
3308 unsigned char *ptr, zero = '\0';
3311 ber_len_t i, len, nlen;
3313 assert( in != NULL );
3314 assert( !BER_BVISNULL( in ) );
3315 assert( out != NULL );
3316 assert( !BER_BVISNULL( out ) );
3318 ptr = (unsigned char *)in->bv_val;
3321 /* Check for minimal encodings */
3323 if ( ptr[0] & 0x80 ) {
3324 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3328 } else if ( ptr[0] == 0 ) {
3329 if ( !( ptr[1] & 0x80 ) ) {
3336 } else if ( len == 0 ) {
3337 /* FIXME: this should not be possible,
3338 * since a value of zero would have length 1 */
3343 first = !( ptr[0] & 0xf0U );
3344 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3345 if ( nlen >= out->bv_len ) {
3346 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3352 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3356 for ( ; i < len; i++ ) {
3357 sprintf( sptr, "%02X", ptr[i] );
3364 assert( sptr == &out->bv_val[nlen] );
3371 #define SLAP_SN_BUFLEN (64)
3374 * This routine is called by certificateExactNormalize when
3375 * certificateExactNormalize receives a search string instead of
3376 * a certificate. This routine checks if the search value is valid
3377 * and then returns the normalized value
3380 serialNumberAndIssuerNormalize(
3388 struct berval sn, sn2, sn3, i, ni;
3389 char sbuf2[SLAP_SN_BUFLEN];
3390 char sbuf3[SLAP_SN_BUFLEN];
3394 assert( in != NULL );
3395 assert( out != NULL );
3397 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3400 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3405 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3407 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3408 slap_sl_free( i.bv_val, ctx );
3412 return LDAP_INVALID_SYNTAX;
3415 /* Convert sn to canonical hex */
3417 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3418 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3420 sn2.bv_len = sn.bv_len;
3421 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3422 rc = LDAP_INVALID_SYNTAX;
3427 sn3.bv_len = sizeof(sbuf3);
3428 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3429 rc = LDAP_INVALID_SYNTAX;
3433 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3434 + sn3.bv_len + ni.bv_len;
3435 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3437 if ( out->bv_val == NULL ) {
3445 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3446 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3447 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3448 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3449 p = lutil_strcopy( p, /*{*/ "\" }" );
3451 assert( p == &out->bv_val[out->bv_len] );
3454 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3455 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3457 if ( sn2.bv_val != sbuf2 ) {
3458 slap_sl_free( sn2.bv_val, ctx );
3461 if ( sn3.bv_val != sbuf3 ) {
3462 slap_sl_free( sn3.bv_val, ctx );
3465 slap_sl_free( ni.bv_val, ctx );
3471 certificateExactNormalize(
3476 struct berval *normalized,
3479 BerElementBuffer berbuf;
3480 BerElement *ber = (BerElement *)&berbuf;
3484 char serialbuf2[SLAP_SN_BUFLEN];
3485 struct berval sn, sn2 = BER_BVNULL;
3486 struct berval issuer_dn = BER_BVNULL, bvdn;
3488 int rc = LDAP_INVALID_SYNTAX;
3490 assert( val != NULL );
3492 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3493 val->bv_val, val->bv_len, 0 );
3495 if ( BER_BVISEMPTY( val ) ) goto done;
3497 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3498 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3501 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3503 ber_init2( ber, val, LBER_USE_DER );
3504 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3505 tag = ber_skip_tag( ber, &len ); /* Sequence */
3506 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3507 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3508 tag = ber_skip_tag( ber, &len );
3509 tag = ber_get_int( ber, &i ); /* version */
3512 /* NOTE: move the test here from certificateValidate,
3513 * so that we can validate certs with serial longer
3514 * than sizeof(ber_int_t) */
3515 tag = ber_skip_tag( ber, &len ); /* serial */
3517 sn.bv_val = (char *)ber->ber_ptr;
3518 sn2.bv_val = serialbuf2;
3519 sn2.bv_len = sizeof(serialbuf2);
3520 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3521 rc = LDAP_INVALID_SYNTAX;
3524 ber_skip_data( ber, len );
3526 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3527 ber_skip_data( ber, len );
3528 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3529 len = ber_ptrlen( ber );
3530 bvdn.bv_val = val->bv_val + len;
3531 bvdn.bv_len = val->bv_len - len;
3533 rc = dnX509normalize( &bvdn, &issuer_dn );
3534 if ( rc != LDAP_SUCCESS ) goto done;
3536 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3537 + sn2.bv_len + issuer_dn.bv_len;
3538 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3540 p = normalized->bv_val;
3542 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3543 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3544 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3545 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3546 p = lutil_strcopy( p, /*{*/ "\" }" );
3551 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3552 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3554 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3555 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3560 /* X.509 PKI certificateList stuff */
3562 checkTime( struct berval *in, struct berval *out )
3566 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3569 assert( in != NULL );
3570 assert( !BER_BVISNULL( in ) );
3571 assert( !BER_BVISEMPTY( in ) );
3573 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3577 if ( out != NULL ) {
3578 assert( !BER_BVISNULL( out ) );
3579 assert( out->bv_len >= sizeof( buf ) );
3580 bv.bv_val = out->bv_val;
3586 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3587 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3590 if ( in->bv_val[i] != 'Z' ) {
3595 if ( i != in->bv_len ) {
3599 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3600 lutil_strncopy( bv.bv_val, in->bv_val, i );
3603 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3604 char *p = bv.bv_val;
3605 if ( in->bv_val[0] < '7' ) {
3606 p = lutil_strcopy( p, "20" );
3609 p = lutil_strcopy( p, "19" );
3611 lutil_strncopy( p, in->bv_val, i );
3618 rc = generalizedTimeValidate( NULL, &bv );
3619 if ( rc == LDAP_SUCCESS && out != NULL ) {
3620 out->bv_len = bv.bv_len;
3623 return rc != LDAP_SUCCESS;
3627 issuerAndThisUpdateCheck(
3634 struct berval x = *in;
3635 struct berval ni = BER_BVNULL;
3636 /* Parse GSER format */
3640 HAVE_THISUPDATE = 0x2,
3641 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3645 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3647 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3648 return LDAP_INVALID_SYNTAX;
3652 x.bv_len -= STRLENOF("{}");
3655 /* eat leading spaces */
3656 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3660 /* should be at issuer or thisUpdate */
3661 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3662 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3665 x.bv_val += STRLENOF("issuer");
3666 x.bv_len -= STRLENOF("issuer");
3668 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3672 /* eat leading spaces */
3673 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3677 /* For backward compatibility, this part is optional */
3678 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3679 return LDAP_INVALID_SYNTAX;
3681 x.bv_val += STRLENOF("rdnSequence:");
3682 x.bv_len -= STRLENOF("rdnSequence:");
3684 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3688 is->bv_val = x.bv_val;
3691 for ( ; is->bv_len < x.bv_len; ) {
3692 if ( is->bv_val[is->bv_len] != '"' ) {
3696 if ( is->bv_val[is->bv_len+1] == '"' ) {
3703 x.bv_val += is->bv_len + 1;
3704 x.bv_len -= is->bv_len + 1;
3706 have |= HAVE_ISSUER;
3708 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3710 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3712 /* parse thisUpdate */
3713 x.bv_val += STRLENOF("thisUpdate");
3714 x.bv_len -= STRLENOF("thisUpdate");
3716 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3720 /* eat leading spaces */
3721 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3725 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3729 tu->bv_val = x.bv_val;
3732 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3733 if ( tu->bv_val[tu->bv_len] == '"' ) {
3737 x.bv_val += tu->bv_len + 1;
3738 x.bv_len -= tu->bv_len + 1;
3740 have |= HAVE_THISUPDATE;
3743 return LDAP_INVALID_SYNTAX;
3746 /* eat leading spaces */
3747 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3751 if ( have == HAVE_ALL ) {
3755 if ( x.bv_val[0] != ',' ) {
3756 return LDAP_INVALID_SYNTAX;
3763 /* should have no characters left... */
3764 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3766 if ( numdquotes == 0 ) {
3767 ber_dupbv_x( &ni, is, ctx );
3772 ni.bv_len = is->bv_len - numdquotes;
3773 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3774 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3775 if ( is->bv_val[src] == '"' ) {
3778 ni.bv_val[dst] = is->bv_val[src];
3780 ni.bv_val[dst] = '\0';
3789 issuerAndThisUpdateValidate(
3794 struct berval i, tu;
3796 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3799 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3804 /* validate DN -- doesn't handle double dquote */
3805 rc = dnValidate( NULL, &i );
3807 rc = LDAP_INVALID_SYNTAX;
3809 } else if ( checkTime( &tu, NULL ) ) {
3810 rc = LDAP_INVALID_SYNTAX;
3813 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3814 slap_sl_free( i.bv_val, NULL );
3817 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3818 in->bv_val, rc, 0 );
3825 issuerAndThisUpdatePretty(
3832 struct berval i, tu, ni = BER_BVNULL;
3835 assert( in != NULL );
3836 assert( out != NULL );
3840 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3843 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3848 rc = dnPretty( syntax, &i, &ni, ctx );
3850 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3851 slap_sl_free( i.bv_val, ctx );
3854 if ( rc || checkTime( &tu, NULL ) ) {
3855 rc = LDAP_INVALID_SYNTAX;
3860 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3861 + ni.bv_len + tu.bv_len;
3862 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3864 if ( out->bv_val == NULL ) {
3871 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3872 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3873 p = lutil_strcopy( p, "\", thisUpdate \"" );
3874 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3875 p = lutil_strcopy( p, /*{*/ "\" }" );
3877 assert( p == &out->bv_val[out->bv_len] );
3880 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3881 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3883 slap_sl_free( ni.bv_val, ctx );
3889 issuerAndThisUpdateNormalize(
3897 struct berval i, ni, tu, tu2;
3898 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3902 assert( in != NULL );
3903 assert( out != NULL );
3905 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3908 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3913 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3915 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3916 slap_sl_free( i.bv_val, ctx );
3920 tu2.bv_len = sizeof( sbuf );
3921 if ( rc || checkTime( &tu, &tu2 ) ) {
3922 return LDAP_INVALID_SYNTAX;
3925 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3926 + ni.bv_len + tu2.bv_len;
3927 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3929 if ( out->bv_val == NULL ) {
3937 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3938 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3939 p = lutil_strcopy( p, "\", thisUpdate \"" );
3940 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3941 p = lutil_strcopy( p, /*{*/ "\" }" );
3943 assert( p == &out->bv_val[out->bv_len] );
3946 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3947 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3949 slap_sl_free( ni.bv_val, ctx );
3955 certificateListExactNormalize(
3960 struct berval *normalized,
3963 BerElementBuffer berbuf;
3964 BerElement *ber = (BerElement *)&berbuf;
3968 struct berval issuer_dn = BER_BVNULL, bvdn,
3970 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3971 int rc = LDAP_INVALID_SYNTAX;
3973 assert( val != NULL );
3975 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
3976 val->bv_val, val->bv_len, 0 );
3978 if ( BER_BVISEMPTY( val ) ) goto done;
3980 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3981 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
3984 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3986 ber_init2( ber, val, LBER_USE_DER );
3987 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
3988 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3989 tag = ber_skip_tag( ber, &len ); /* Sequence */
3990 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3991 tag = ber_peek_tag( ber, &len );
3992 /* Optional version */
3993 if ( tag == LBER_INTEGER ) {
3994 tag = ber_get_int( ber, &version );
3995 assert( tag == LBER_INTEGER );
3996 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
3998 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
3999 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4000 ber_skip_data( ber, len );
4002 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4003 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4004 len = ber_ptrlen( ber );
4005 bvdn.bv_val = val->bv_val + len;
4006 bvdn.bv_len = val->bv_len - len;
4007 tag = ber_skip_tag( ber, &len );
4008 ber_skip_data( ber, len );
4010 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4011 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4012 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4013 bvtu.bv_val = (char *)ber->ber_ptr;
4016 rc = dnX509normalize( &bvdn, &issuer_dn );
4017 if ( rc != LDAP_SUCCESS ) goto done;
4019 thisUpdate.bv_val = tubuf;
4020 thisUpdate.bv_len = sizeof(tubuf);
4021 if ( checkTime( &bvtu, &thisUpdate ) ) {
4022 rc = LDAP_INVALID_SYNTAX;
4026 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4027 + issuer_dn.bv_len + thisUpdate.bv_len;
4028 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4030 p = normalized->bv_val;
4032 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4033 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4034 p = lutil_strcopy( p, "\", thisUpdate \"" );
4035 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
4036 p = lutil_strcopy( p, /*{*/ "\" }" );
4041 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4042 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4044 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4049 /* X.509 PMI serialNumberAndIssuerSerialCheck
4051 AttributeCertificateExactAssertion ::= SEQUENCE {
4052 serialNumber CertificateSerialNumber,
4053 issuer AttCertIssuer }
4055 CertificateSerialNumber ::= INTEGER
4057 AttCertIssuer ::= [0] SEQUENCE {
4058 issuerName GeneralNames OPTIONAL,
4059 baseCertificateID [0] IssuerSerial OPTIONAL,
4060 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4061 -- At least one component shall be present
4063 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4065 GeneralName ::= CHOICE {
4066 otherName [0] INSTANCE OF OTHER-NAME,
4067 rfc822Name [1] IA5String,
4068 dNSName [2] IA5String,
4069 x400Address [3] ORAddress,
4070 directoryName [4] Name,
4071 ediPartyName [5] EDIPartyName,
4072 uniformResourceIdentifier [6] IA5String,
4073 iPAddress [7] OCTET STRING,
4074 registeredID [8] OBJECT IDENTIFIER }
4076 IssuerSerial ::= SEQUENCE {
4077 issuer GeneralNames,
4078 serial CertificateSerialNumber,
4079 issuerUID UniqueIdentifier OPTIONAL }
4081 ObjectDigestInfo ::= SEQUENCE {
4082 digestedObjectType ENUMERATED {
4085 otherObjectTypes (2) },
4086 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4087 digestAlgorithm AlgorithmIdentifier,
4088 objectDigest BIT STRING }
4090 * The way I interpret it, an assertion should look like
4092 { serialNumber 'dd'H,
4093 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4094 baseCertificateID { serial '1d'H,
4095 issuer { directoryName:rdnSequence:"cn=zzz" },
4096 issuerUID <value> -- optional
4098 objectDigestInfo { ... } -- optional
4102 * with issuerName, baseCertificateID and objectDigestInfo optional,
4103 * at least one present; the way it's currently implemented, it is
4105 { serialNumber 'dd'H,
4106 issuer { baseCertificateID { serial '1d'H,
4107 issuer { directoryName:rdnSequence:"cn=zzz" }
4112 * with all the above parts mandatory.
4115 serialNumberAndIssuerSerialCheck(
4119 struct berval *i_sn, /* contain serial of baseCertificateID */
4122 /* Parse GSER format */
4127 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4128 } have = HAVE_NONE, have2 = HAVE_NONE;
4130 struct berval x = *in;
4133 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4136 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4143 /* eat leading spaces */
4144 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4148 /* should be at issuer or serialNumber NamedValue */
4149 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4150 if ( have & HAVE_ISSUER ) {
4151 return LDAP_INVALID_SYNTAX;
4154 /* parse IssuerSerial */
4155 x.bv_val += STRLENOF("issuer");
4156 x.bv_len -= STRLENOF("issuer");
4158 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4162 /* eat leading spaces */
4163 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4167 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4171 /* eat leading spaces */
4172 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4176 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4177 return LDAP_INVALID_SYNTAX;
4179 x.bv_val += STRLENOF("baseCertificateID ");
4180 x.bv_len -= STRLENOF("baseCertificateID ");
4182 /* eat leading spaces */
4183 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4187 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4192 /* eat leading spaces */
4193 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4197 /* parse issuer of baseCertificateID */
4198 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4199 if ( have2 & HAVE_ISSUER ) {
4200 return LDAP_INVALID_SYNTAX;
4203 x.bv_val += STRLENOF("issuer ");
4204 x.bv_len -= STRLENOF("issuer ");
4206 /* eat leading spaces */
4207 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4211 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4215 /* eat leading spaces */
4216 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4220 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4221 return LDAP_INVALID_SYNTAX;
4223 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4224 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4226 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4230 is->bv_val = x.bv_val;
4233 for ( ; is->bv_len < x.bv_len; ) {
4234 if ( is->bv_val[is->bv_len] != '"' ) {
4238 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4245 x.bv_val += is->bv_len + 1;
4246 x.bv_len -= is->bv_len + 1;
4248 /* eat leading spaces */
4249 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4253 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4257 have2 |= HAVE_ISSUER;
4259 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4260 if ( have2 & HAVE_SN ) {
4261 return LDAP_INVALID_SYNTAX;
4264 x.bv_val += STRLENOF("serial ");
4265 x.bv_len -= STRLENOF("serial ");
4267 /* eat leading spaces */
4268 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4272 if ( checkNum( &x, i_sn ) ) {
4273 return LDAP_INVALID_SYNTAX;
4276 x.bv_val += i_sn->bv_len;
4277 x.bv_len -= i_sn->bv_len;
4282 return LDAP_INVALID_SYNTAX;
4285 /* eat leading spaces */
4286 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4290 if ( have2 == HAVE_ALL ) {
4294 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4299 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4303 /* eat leading spaces */
4304 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4308 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4312 have |= HAVE_ISSUER;
4314 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4315 if ( have & HAVE_SN ) {
4316 return LDAP_INVALID_SYNTAX;
4319 /* parse serialNumber */
4320 x.bv_val += STRLENOF("serialNumber");
4321 x.bv_len -= STRLENOF("serialNumber");
4323 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4327 /* eat leading spaces */
4328 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4332 if ( checkNum( &x, sn ) ) {
4333 return LDAP_INVALID_SYNTAX;
4336 x.bv_val += sn->bv_len;
4337 x.bv_len -= sn->bv_len;
4342 return LDAP_INVALID_SYNTAX;
4346 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4350 if ( have == HAVE_ALL ) {
4354 if ( x.bv_val[0] != ',' ) {
4355 return LDAP_INVALID_SYNTAX;
4361 /* should have no characters left... */
4362 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4364 if ( numdquotes == 0 ) {
4365 ber_dupbv_x( &ni, is, ctx );
4370 ni.bv_len = is->bv_len - numdquotes;
4371 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4372 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4373 if ( is->bv_val[src] == '"' ) {
4376 ni.bv_val[dst] = is->bv_val[src];
4378 ni.bv_val[dst] = '\0';
4383 /* need to handle double dquotes here */
4387 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4389 serialNumberAndIssuerSerialValidate(
4394 struct berval sn, i, i_sn;
4396 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4399 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4404 /* validate DN -- doesn't handle double dquote */
4405 rc = dnValidate( NULL, &i );
4407 rc = LDAP_INVALID_SYNTAX;
4410 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4411 slap_sl_free( i.bv_val, NULL );
4415 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4416 in->bv_val, rc, 0 );
4421 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4423 serialNumberAndIssuerSerialPretty(
4429 struct berval sn, i, i_sn, ni = BER_BVNULL;
4433 assert( in != NULL );
4434 assert( out != NULL );
4436 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4439 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4444 rc = dnPretty( syntax, &i, &ni, ctx );
4446 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4447 slap_sl_free( i.bv_val, ctx );
4451 rc = LDAP_INVALID_SYNTAX;
4455 /* make room from sn + "$" */
4456 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4457 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4458 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4460 if ( out->bv_val == NULL ) {
4467 p = lutil_strcopy( p, "{ serialNumber " );
4468 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
4469 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4470 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4471 p = lutil_strcopy( p, "\" }, serial " );
4472 p = lutil_strncopy( p, i_sn.bv_val, i_sn.bv_len );
4473 p = lutil_strcopy( p, " } } }" );
4475 assert( p == &out->bv_val[out->bv_len] );
4478 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4479 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4481 slap_sl_free( ni.bv_val, ctx );
4486 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4488 * This routine is called by attributeCertificateExactNormalize
4489 * when attributeCertificateExactNormalize receives a search
4490 * string instead of a attribute certificate. This routine
4491 * checks if the search value is valid and then returns the
4495 serialNumberAndIssuerSerialNormalize(
4503 struct berval i, ni = BER_BVNULL,
4504 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4505 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4506 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4507 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4511 assert( in != NULL );
4512 assert( out != NULL );
4514 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4517 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4522 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4524 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4525 slap_sl_free( i.bv_val, ctx );
4529 rc = LDAP_INVALID_SYNTAX;
4533 /* Convert sn to canonical hex */
4535 sn2.bv_len = sn.bv_len;
4536 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4537 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4539 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4540 rc = LDAP_INVALID_SYNTAX;
4544 /* Convert i_sn to canonical hex */
4545 i_sn2.bv_val = i_sbuf2;
4546 i_sn2.bv_len = i_sn.bv_len;
4547 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4548 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4550 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4551 rc = LDAP_INVALID_SYNTAX;
4556 sn3.bv_len = sizeof(sbuf3);
4557 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4558 rc = LDAP_INVALID_SYNTAX;
4562 i_sn3.bv_val = i_sbuf3;
4563 i_sn3.bv_len = sizeof(i_sbuf3);
4564 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4565 rc = LDAP_INVALID_SYNTAX;
4569 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4570 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4571 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4573 if ( out->bv_val == NULL ) {
4581 p = lutil_strcopy( p, "{ serialNumber " );
4582 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
4583 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4584 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4585 p = lutil_strcopy( p, "\" }, serial " );
4586 p = lutil_strncopy( p, i_sn3.bv_val, i_sn3.bv_len );
4587 p = lutil_strcopy( p, " } } }" );
4589 assert( p == &out->bv_val[out->bv_len] );
4592 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4593 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4595 if ( sn2.bv_val != sbuf2 ) {
4596 slap_sl_free( sn2.bv_val, ctx );
4599 if ( i_sn2.bv_val != i_sbuf2 ) {
4600 slap_sl_free( i_sn2.bv_val, ctx );
4603 if ( sn3.bv_val != sbuf3 ) {
4604 slap_sl_free( sn3.bv_val, ctx );
4607 if ( i_sn3.bv_val != i_sbuf3 ) {
4608 slap_sl_free( i_sn3.bv_val, ctx );
4611 slap_sl_free( ni.bv_val, ctx );
4616 /* X.509 PMI attributeCertificateExactNormalize */
4618 attributeCertificateExactNormalize(
4623 struct berval *normalized,
4626 BerElementBuffer berbuf;
4627 BerElement *ber = (BerElement *)&berbuf;
4630 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4631 struct berval sn, i_sn, sn2, i_sn2;
4632 struct berval issuer_dn = BER_BVNULL, bvdn;
4634 int rc = LDAP_INVALID_SYNTAX;
4636 if ( BER_BVISEMPTY( val ) ) {
4640 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4641 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4644 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4646 ber_init2( ber, val, LBER_USE_DER );
4647 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4648 tag = ber_skip_tag( ber, &len ); /* Sequence */
4649 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4650 ber_skip_data( ber, len );
4651 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4652 ber_skip_data( ber, len );
4655 tag = ber_skip_tag( ber, &len ); /* Sequence */
4656 /* issuerName (GeneralNames sequence; optional)? */
4657 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4658 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4659 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4660 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4661 rc = LDAP_INVALID_SYNTAX;
4664 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4665 len = ber_ptrlen( ber );
4666 bvdn.bv_val = val->bv_val + len;
4667 bvdn.bv_len = val->bv_len - len;
4668 rc = dnX509normalize( &bvdn, &issuer_dn );
4669 if ( rc != LDAP_SUCCESS ) goto done;
4671 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4672 ber_skip_data( ber, len );
4673 tag = ber_skip_tag( ber, &len ); /* serial number */
4674 if ( tag != LBER_INTEGER ) {
4675 rc = LDAP_INVALID_SYNTAX;
4678 i_sn.bv_val = (char *)ber->ber_ptr;
4680 i_sn2.bv_val = issuer_serialbuf;
4681 i_sn2.bv_len = sizeof(issuer_serialbuf);
4682 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4683 rc = LDAP_INVALID_SYNTAX;
4686 ber_skip_data( ber, len );
4688 /* issuerUID (bitstring; optional)? */
4689 /* objectDigestInfo (sequence; optional)? */
4691 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4692 ber_skip_data( ber, len );
4693 tag = ber_skip_tag( ber, &len ); /* serial number */
4694 if ( tag != LBER_INTEGER ) {
4695 rc = LDAP_INVALID_SYNTAX;
4698 sn.bv_val = (char *)ber->ber_ptr;
4700 sn2.bv_val = serialbuf;
4701 sn2.bv_len = sizeof(serialbuf);
4702 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4703 rc = LDAP_INVALID_SYNTAX;
4706 ber_skip_data( ber, len );
4708 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4709 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4710 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4712 p = normalized->bv_val;
4714 p = lutil_strcopy( p, "{ serialNumber " );
4715 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
4716 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4717 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4718 p = lutil_strcopy( p, "\" }, serial " );
4719 p = lutil_strncopy( p, i_sn2.bv_val, i_sn2.bv_len );
4720 p = lutil_strcopy( p, " } } }" );
4722 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4723 normalized->bv_val, NULL, NULL );
4728 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4729 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4730 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4743 assert( in != NULL );
4744 assert( !BER_BVISNULL( in ) );
4746 for ( i = 0; i < in->bv_len; i++ ) {
4747 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4748 return LDAP_INVALID_SYNTAX;
4752 return LDAP_SUCCESS;
4755 /* Normalize a SID as used inside a CSN:
4756 * three-digit numeric string */
4763 struct berval *normalized,
4768 assert( val != NULL );
4769 assert( normalized != NULL );
4771 ber_dupbv_x( normalized, val, ctx );
4773 for ( i = 0; i < normalized->bv_len; i++ ) {
4774 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4775 ber_memfree_x( normalized->bv_val, ctx );
4776 BER_BVZERO( normalized );
4777 return LDAP_INVALID_SYNTAX;
4780 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4783 return LDAP_SUCCESS;
4791 assert( in != NULL );
4792 assert( !BER_BVISNULL( in ) );
4794 if ( in->bv_len != 3 ) {
4795 return LDAP_INVALID_SYNTAX;
4798 return hexValidate( NULL, in );
4801 /* Normalize a SID as used inside a CSN:
4802 * three-digit numeric string */
4809 struct berval *normalized,
4812 if ( val->bv_len != 3 ) {
4813 return LDAP_INVALID_SYNTAX;
4816 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4826 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4829 /* Normalize a SID as used inside a CSN, either as-is
4830 * (assertion value) or extracted from the CSN
4831 * (attribute value) */
4838 struct berval *normalized,
4846 if ( BER_BVISEMPTY( val ) ) {
4847 return LDAP_INVALID_SYNTAX;
4850 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4851 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4854 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4856 ptr = ber_bvchr( val, '#' );
4857 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4858 return LDAP_INVALID_SYNTAX;
4861 bv.bv_val = ptr + 1;
4862 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4864 ptr = ber_bvchr( &bv, '#' );
4865 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4866 return LDAP_INVALID_SYNTAX;
4869 bv.bv_val = ptr + 1;
4870 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4872 ptr = ber_bvchr( &bv, '#' );
4873 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4874 return LDAP_INVALID_SYNTAX;
4877 bv.bv_len = ptr - bv.bv_val;
4879 if ( bv.bv_len == 2 ) {
4880 /* OpenLDAP 2.3 SID */
4882 buf[ 1 ] = bv.bv_val[ 0 ];
4883 buf[ 2 ] = bv.bv_val[ 1 ];
4890 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4902 assert( in != NULL );
4903 assert( !BER_BVISNULL( in ) );
4905 if ( BER_BVISEMPTY( in ) ) {
4906 return LDAP_INVALID_SYNTAX;
4911 ptr = ber_bvchr( &bv, '#' );
4912 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4913 return LDAP_INVALID_SYNTAX;
4916 bv.bv_len = ptr - bv.bv_val;
4917 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4918 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4920 return LDAP_INVALID_SYNTAX;
4923 rc = generalizedTimeValidate( NULL, &bv );
4924 if ( rc != LDAP_SUCCESS ) {
4928 bv.bv_val = ptr + 1;
4929 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4931 ptr = ber_bvchr( &bv, '#' );
4932 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4933 return LDAP_INVALID_SYNTAX;
4936 bv.bv_len = ptr - bv.bv_val;
4937 if ( bv.bv_len != 6 ) {
4938 return LDAP_INVALID_SYNTAX;
4941 rc = hexValidate( NULL, &bv );
4942 if ( rc != LDAP_SUCCESS ) {
4946 bv.bv_val = ptr + 1;
4947 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4949 ptr = ber_bvchr( &bv, '#' );
4950 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4951 return LDAP_INVALID_SYNTAX;
4954 bv.bv_len = ptr - bv.bv_val;
4955 if ( bv.bv_len == 2 ) {
4956 /* tolerate old 2-digit replica-id */
4957 rc = hexValidate( NULL, &bv );
4960 rc = sidValidate( NULL, &bv );
4962 if ( rc != LDAP_SUCCESS ) {
4966 bv.bv_val = ptr + 1;
4967 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4969 if ( bv.bv_len != 6 ) {
4970 return LDAP_INVALID_SYNTAX;
4973 return hexValidate( NULL, &bv );
4976 /* Normalize a CSN in OpenLDAP 2.1 format */
4983 struct berval *normalized,
4986 struct berval gt, cnt, sid, mod;
4988 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4992 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4993 assert( !BER_BVISEMPTY( val ) );
4997 ptr = ber_bvchr( >, '#' );
4998 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
4999 return LDAP_INVALID_SYNTAX;
5002 gt.bv_len = ptr - gt.bv_val;
5003 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5004 return LDAP_INVALID_SYNTAX;
5007 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5008 return LDAP_INVALID_SYNTAX;
5011 cnt.bv_val = ptr + 1;
5012 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5014 ptr = ber_bvchr( &cnt, '#' );
5015 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5016 return LDAP_INVALID_SYNTAX;
5019 cnt.bv_len = ptr - cnt.bv_val;
5020 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5021 return LDAP_INVALID_SYNTAX;
5024 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5025 return LDAP_INVALID_SYNTAX;
5028 cnt.bv_val += STRLENOF( "0x" );
5029 cnt.bv_len -= STRLENOF( "0x" );
5031 sid.bv_val = ptr + 1;
5032 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5034 ptr = ber_bvchr( &sid, '#' );
5035 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5036 return LDAP_INVALID_SYNTAX;
5039 sid.bv_len = ptr - sid.bv_val;
5040 if ( sid.bv_len != STRLENOF( "0" ) ) {
5041 return LDAP_INVALID_SYNTAX;
5044 mod.bv_val = ptr + 1;
5045 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5046 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5047 return LDAP_INVALID_SYNTAX;
5050 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5054 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5055 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5057 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5059 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5060 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5064 *ptr++ = sid.bv_val[ 0 ];
5068 for ( i = 0; i < mod.bv_len; i++ ) {
5069 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5073 assert( ptr == &bv.bv_val[bv.bv_len] );
5075 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5076 return LDAP_INVALID_SYNTAX;
5079 ber_dupbv_x( normalized, &bv, ctx );
5081 return LDAP_SUCCESS;
5084 /* Normalize a CSN in OpenLDAP 2.3 format */
5091 struct berval *normalized,
5094 struct berval gt, cnt, sid, mod;
5096 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5100 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5101 assert( !BER_BVISEMPTY( val ) );
5105 ptr = ber_bvchr( >, '#' );
5106 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5107 return LDAP_INVALID_SYNTAX;
5110 gt.bv_len = ptr - gt.bv_val;
5111 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5112 return LDAP_INVALID_SYNTAX;
5115 cnt.bv_val = ptr + 1;
5116 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5118 ptr = ber_bvchr( &cnt, '#' );
5119 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5120 return LDAP_INVALID_SYNTAX;
5123 cnt.bv_len = ptr - cnt.bv_val;
5124 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5125 return LDAP_INVALID_SYNTAX;
5128 sid.bv_val = ptr + 1;
5129 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5131 ptr = ber_bvchr( &sid, '#' );
5132 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5133 return LDAP_INVALID_SYNTAX;
5136 sid.bv_len = ptr - sid.bv_val;
5137 if ( sid.bv_len != STRLENOF( "00" ) ) {
5138 return LDAP_INVALID_SYNTAX;
5141 mod.bv_val = ptr + 1;
5142 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5143 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5144 return LDAP_INVALID_SYNTAX;
5147 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5151 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5152 ptr = lutil_strcopy( ptr, ".000000Z#" );
5153 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5156 for ( i = 0; i < sid.bv_len; i++ ) {
5157 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5160 for ( i = 0; i < mod.bv_len; i++ ) {
5161 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5165 assert( ptr == &bv.bv_val[bv.bv_len] );
5166 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5167 return LDAP_INVALID_SYNTAX;
5170 ber_dupbv_x( normalized, &bv, ctx );
5172 return LDAP_SUCCESS;
5175 /* Normalize a CSN */
5182 struct berval *normalized,
5185 struct berval cnt, sid, mod;
5189 assert( val != NULL );
5190 assert( normalized != NULL );
5192 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5194 if ( BER_BVISEMPTY( val ) ) {
5195 return LDAP_INVALID_SYNTAX;
5198 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5199 /* Openldap <= 2.3 */
5201 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5204 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5207 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5210 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5211 return LDAP_INVALID_SYNTAX;
5214 ptr = ber_bvchr( val, '#' );
5215 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5216 return LDAP_INVALID_SYNTAX;
5219 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5220 return LDAP_INVALID_SYNTAX;
5223 cnt.bv_val = ptr + 1;
5224 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5226 ptr = ber_bvchr( &cnt, '#' );
5227 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5228 return LDAP_INVALID_SYNTAX;
5231 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5232 return LDAP_INVALID_SYNTAX;
5235 sid.bv_val = ptr + 1;
5236 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5238 ptr = ber_bvchr( &sid, '#' );
5239 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5240 return LDAP_INVALID_SYNTAX;
5243 sid.bv_len = ptr - sid.bv_val;
5244 if ( sid.bv_len != STRLENOF( "000" ) ) {
5245 return LDAP_INVALID_SYNTAX;
5248 mod.bv_val = ptr + 1;
5249 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5251 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5252 return LDAP_INVALID_SYNTAX;
5255 ber_dupbv_x( normalized, val, ctx );
5257 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5258 i < normalized->bv_len; i++ )
5260 /* assume it's already validated that's all hex digits */
5261 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5264 return LDAP_SUCCESS;
5274 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5277 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5278 /* slight optimization - does not need the start parameter */
5279 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5284 check_time_syntax (struct berval *val,
5287 struct berval *fraction)
5290 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5291 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5292 * GeneralizedTime supports leap seconds, UTCTime does not.
5294 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5295 static const int mdays[2][12] = {
5296 /* non-leap years */
5297 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5299 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5302 int part, c, c1, c2, tzoffset, leapyear = 0;
5305 e = p + val->bv_len;
5307 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5308 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5310 for (part = start; part < 7 && p < e; part++) {
5312 if (!ASCII_DIGIT(c1)) {
5317 return LDAP_INVALID_SYNTAX;
5320 if (!ASCII_DIGIT(c)) {
5321 return LDAP_INVALID_SYNTAX;
5323 c += c1 * 10 - '0' * 11;
5324 if ((part | 1) == 3) {
5327 return LDAP_INVALID_SYNTAX;
5330 if (c >= ceiling[part]) {
5331 if (! (c == 60 && part == 6 && start == 0))
5332 return LDAP_INVALID_SYNTAX;
5336 if (part < 5 + start) {
5337 return LDAP_INVALID_SYNTAX;
5339 for (; part < 9; part++) {
5343 /* leapyear check for the Gregorian calendar (year>1581) */
5344 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5348 if (parts[3] >= mdays[leapyear][parts[2]]) {
5349 return LDAP_INVALID_SYNTAX;
5353 fraction->bv_val = p;
5354 fraction->bv_len = 0;
5355 if (p < e && (*p == '.' || *p == ',')) {
5357 while (++p < e && ASCII_DIGIT(*p)) {
5360 if (p - fraction->bv_val == 1) {
5361 return LDAP_INVALID_SYNTAX;
5363 for (end_num = p; end_num[-1] == '0'; --end_num) {
5366 c = end_num - fraction->bv_val;
5367 if (c != 1) fraction->bv_len = c;
5373 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5379 return LDAP_INVALID_SYNTAX;
5385 for (part = 7; part < 9 && p < e; part++) {
5387 if (!ASCII_DIGIT(c1)) {
5392 return LDAP_INVALID_SYNTAX;
5395 if (!ASCII_DIGIT(c2)) {
5396 return LDAP_INVALID_SYNTAX;
5398 parts[part] = c1 * 10 + c2 - '0' * 11;
5399 if (parts[part] >= ceiling[part]) {
5400 return LDAP_INVALID_SYNTAX;
5403 if (part < 8 + start) {
5404 return LDAP_INVALID_SYNTAX;
5407 if (tzoffset == '-') {
5408 /* negative offset to UTC, ie west of Greenwich */
5409 parts[4] += parts[7];
5410 parts[5] += parts[8];
5411 /* offset is just hhmm, no seconds */
5412 for (part = 6; --part >= 0; ) {
5416 c = mdays[leapyear][parts[2]];
5418 if (parts[part] >= c) {
5420 return LDAP_INVALID_SYNTAX;
5425 } else if (part != 5) {
5430 /* positive offset to UTC, ie east of Greenwich */
5431 parts[4] -= parts[7];
5432 parts[5] -= parts[8];
5433 for (part = 6; --part >= 0; ) {
5434 if (parts[part] < 0) {
5436 return LDAP_INVALID_SYNTAX;
5441 /* make first arg to % non-negative */
5442 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5447 } else if (part != 5) {
5454 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5457 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5464 struct berval *normalized )
5468 rc = check_time_syntax(val, 1, parts, NULL);
5469 if (rc != LDAP_SUCCESS) {
5473 normalized->bv_val = ch_malloc( 14 );
5474 if ( normalized->bv_val == NULL ) {
5475 return LBER_ERROR_MEMORY;
5478 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5479 parts[1], parts[2] + 1, parts[3] + 1,
5480 parts[4], parts[5], parts[6] );
5481 normalized->bv_len = 13;
5483 return LDAP_SUCCESS;
5493 return check_time_syntax(in, 1, parts, NULL);
5496 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5499 generalizedTimeValidate(
5504 struct berval fraction;
5505 return check_time_syntax(in, 0, parts, &fraction);
5509 generalizedTimeNormalize(
5514 struct berval *normalized,
5519 struct berval fraction;
5521 rc = check_time_syntax(val, 0, parts, &fraction);
5522 if (rc != LDAP_SUCCESS) {
5526 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5527 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5528 if ( BER_BVISNULL( normalized ) ) {
5529 return LBER_ERROR_MEMORY;
5532 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5533 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5534 parts[4], parts[5], parts[6] );
5535 if ( !BER_BVISEMPTY( &fraction ) ) {
5536 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5537 fraction.bv_val, fraction.bv_len );
5538 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5540 strcpy( normalized->bv_val + len-1, "Z" );
5541 normalized->bv_len = len;
5543 return LDAP_SUCCESS;
5547 generalizedTimeOrderingMatch(
5552 struct berval *value,
5553 void *assertedValue )
5555 struct berval *asserted = (struct berval *) assertedValue;
5556 ber_len_t v_len = value->bv_len;
5557 ber_len_t av_len = asserted->bv_len;
5559 /* ignore trailing 'Z' when comparing */
5560 int match = memcmp( value->bv_val, asserted->bv_val,
5561 (v_len < av_len ? v_len : av_len) - 1 );
5562 if ( match == 0 ) match = v_len - av_len;
5565 return LDAP_SUCCESS;
5568 /* Index generation function */
5569 int generalizedTimeIndexer(
5574 struct berval *prefix,
5582 BerValue bvtmp; /* 40 bit index */
5584 struct lutil_timet tt;
5586 bvtmp.bv_len = sizeof(tmp);
5588 for( i=0; values[i].bv_val != NULL; i++ ) {
5589 /* just count them */
5592 /* we should have at least one value at this point */
5595 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5597 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5598 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5599 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5600 /* Use 40 bits of time for key */
5601 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5602 lutil_tm2time( &tm, &tt );
5603 tmp[0] = tt.tt_gsec & 0xff;
5604 tmp[4] = tt.tt_sec & 0xff;
5606 tmp[3] = tt.tt_sec & 0xff;
5608 tmp[2] = tt.tt_sec & 0xff;
5610 tmp[1] = tt.tt_sec & 0xff;
5612 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5616 keys[j].bv_val = NULL;
5621 return LDAP_SUCCESS;
5624 /* Index generation function */
5625 int generalizedTimeFilter(
5630 struct berval *prefix,
5631 void * assertedValue,
5637 BerValue bvtmp; /* 40 bit index */
5638 BerValue *value = (BerValue *) assertedValue;
5640 struct lutil_timet tt;
5642 bvtmp.bv_len = sizeof(tmp);
5644 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5645 /* Use 40 bits of time for key */
5646 if ( value->bv_val && value->bv_len >= 10 &&
5647 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5649 lutil_tm2time( &tm, &tt );
5650 tmp[0] = tt.tt_gsec & 0xff;
5651 tmp[4] = tt.tt_sec & 0xff;
5653 tmp[3] = tt.tt_sec & 0xff;
5655 tmp[2] = tt.tt_sec & 0xff;
5657 tmp[1] = tt.tt_sec & 0xff;
5659 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5660 ber_dupbv_x(keys, &bvtmp, ctx );
5661 keys[1].bv_val = NULL;
5669 return LDAP_SUCCESS;
5673 deliveryMethodValidate(
5675 struct berval *val )
5678 #define LENOF(s) (sizeof(s)-1)
5679 struct berval tmp = *val;
5681 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5682 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5683 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5686 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5688 switch( tmp.bv_val[0] ) {
5691 if(( tmp.bv_len >= LENOF("any") ) &&
5692 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5694 tmp.bv_len -= LENOF("any");
5695 tmp.bv_val += LENOF("any");
5698 return LDAP_INVALID_SYNTAX;
5702 if(( tmp.bv_len >= LENOF("mhs") ) &&
5703 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5705 tmp.bv_len -= LENOF("mhs");
5706 tmp.bv_val += LENOF("mhs");
5709 return LDAP_INVALID_SYNTAX;
5713 if(( tmp.bv_len >= LENOF("physical") ) &&
5714 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5716 tmp.bv_len -= LENOF("physical");
5717 tmp.bv_val += LENOF("physical");
5720 return LDAP_INVALID_SYNTAX;
5723 case 'T': /* telex or teletex or telephone */
5724 if(( tmp.bv_len >= LENOF("telex") ) &&
5725 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5727 tmp.bv_len -= LENOF("telex");
5728 tmp.bv_val += LENOF("telex");
5731 if(( tmp.bv_len >= LENOF("teletex") ) &&
5732 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5734 tmp.bv_len -= LENOF("teletex");
5735 tmp.bv_val += LENOF("teletex");
5738 if(( tmp.bv_len >= LENOF("telephone") ) &&
5739 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5741 tmp.bv_len -= LENOF("telephone");
5742 tmp.bv_val += LENOF("telephone");
5745 return LDAP_INVALID_SYNTAX;
5748 case 'G': /* g3fax or g4fax */
5749 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5750 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5751 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5753 tmp.bv_len -= LENOF("g3fax");
5754 tmp.bv_val += LENOF("g3fax");
5757 return LDAP_INVALID_SYNTAX;
5761 if(( tmp.bv_len >= LENOF("ia5") ) &&
5762 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5764 tmp.bv_len -= LENOF("ia5");
5765 tmp.bv_val += LENOF("ia5");
5768 return LDAP_INVALID_SYNTAX;
5772 if(( tmp.bv_len >= LENOF("videotex") ) &&
5773 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5775 tmp.bv_len -= LENOF("videotex");
5776 tmp.bv_val += LENOF("videotex");
5779 return LDAP_INVALID_SYNTAX;
5782 return LDAP_INVALID_SYNTAX;
5785 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5787 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5791 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5795 return LDAP_INVALID_SYNTAX;
5797 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5806 nisNetgroupTripleValidate(
5808 struct berval *val )
5813 if ( BER_BVISEMPTY( val ) ) {
5814 return LDAP_INVALID_SYNTAX;
5817 p = (char *)val->bv_val;
5818 e = p + val->bv_len;
5820 if ( *p != '(' /*')'*/ ) {
5821 return LDAP_INVALID_SYNTAX;
5824 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5828 return LDAP_INVALID_SYNTAX;
5831 } else if ( !AD_CHAR( *p ) ) {
5832 return LDAP_INVALID_SYNTAX;
5836 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5837 return LDAP_INVALID_SYNTAX;
5843 return LDAP_INVALID_SYNTAX;
5846 return LDAP_SUCCESS;
5850 bootParameterValidate(
5852 struct berval *val )
5856 if ( BER_BVISEMPTY( val ) ) {
5857 return LDAP_INVALID_SYNTAX;
5860 p = (char *)val->bv_val;
5861 e = p + val->bv_len;
5864 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5865 if ( !AD_CHAR( *p ) ) {
5866 return LDAP_INVALID_SYNTAX;
5871 return LDAP_INVALID_SYNTAX;
5875 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5876 if ( !AD_CHAR( *p ) ) {
5877 return LDAP_INVALID_SYNTAX;
5882 return LDAP_INVALID_SYNTAX;
5886 for ( p++; p < e; p++ ) {
5887 if ( !SLAP_PRINTABLE( *p ) ) {
5888 return LDAP_INVALID_SYNTAX;
5892 return LDAP_SUCCESS;
5896 firstComponentNormalize(
5901 struct berval *normalized,
5908 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5909 ber_dupbv_x( normalized, val, ctx );
5910 return LDAP_SUCCESS;
5913 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5915 if( ! ( val->bv_val[0] == '(' /*')'*/
5916 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5917 && ! ( val->bv_val[0] == '{' /*'}'*/
5918 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5920 return LDAP_INVALID_SYNTAX;
5923 /* trim leading white space */
5925 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5931 /* grab next word */
5932 comp.bv_val = &val->bv_val[len];
5933 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5934 for( comp.bv_len = 0;
5935 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5941 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5942 rc = numericoidValidate( NULL, &comp );
5943 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5944 rc = integerValidate( NULL, &comp );
5946 rc = LDAP_INVALID_SYNTAX;
5950 if( rc == LDAP_SUCCESS ) {
5951 ber_dupbv_x( normalized, &comp, ctx );
5957 static char *country_gen_syn[] = {
5958 "1.3.6.1.4.1.1466.115.121.1.15",
5959 "1.3.6.1.4.1.1466.115.121.1.26",
5960 "1.3.6.1.4.1.1466.115.121.1.44",
5964 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
5965 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
5967 static slap_syntax_defs_rec syntax_defs[] = {
5968 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
5969 X_BINARY X_NOT_H_R ")",
5970 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
5971 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
5972 0, NULL, NULL, NULL},
5973 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
5974 0, NULL, NULL, NULL},
5975 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
5977 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5978 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
5980 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5981 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
5982 0, NULL, bitStringValidate, NULL },
5983 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
5984 0, NULL, booleanValidate, NULL},
5985 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
5986 X_BINARY X_NOT_H_R ")",
5987 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5988 NULL, certificateValidate, NULL},
5989 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
5990 X_BINARY X_NOT_H_R ")",
5991 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5992 NULL, certificateListValidate, NULL},
5993 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
5994 X_BINARY X_NOT_H_R ")",
5995 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5996 NULL, sequenceValidate, NULL},
5997 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
5998 X_BINARY X_NOT_H_R ")",
5999 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6000 NULL, attributeCertificateValidate, NULL},
6001 #if 0 /* need to go __after__ printableString */
6002 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6003 0, "1.3.6.1.4.1.1466.115.121.1.44",
6004 countryStringValidate, NULL},
6006 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6007 0, NULL, dnValidate, dnPretty},
6008 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6009 0, NULL, rdnValidate, rdnPretty},
6010 #ifdef LDAP_COMP_MATCH
6011 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6012 0, NULL, allComponentsValidate, NULL},
6013 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6014 0, NULL, componentFilterValidate, NULL},
6016 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6017 0, NULL, NULL, NULL},
6018 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6019 0, NULL, deliveryMethodValidate, NULL},
6020 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6021 0, NULL, UTF8StringValidate, NULL},
6022 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6023 0, NULL, NULL, NULL},
6024 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6025 0, NULL, NULL, NULL},
6026 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6027 0, NULL, NULL, NULL},
6028 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6029 0, NULL, NULL, NULL},
6030 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6031 0, NULL, NULL, NULL},
6032 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6033 0, NULL, printablesStringValidate, NULL},
6034 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6035 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6036 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6037 0, NULL, generalizedTimeValidate, NULL},
6038 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6039 0, NULL, NULL, NULL},
6040 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6041 0, NULL, IA5StringValidate, NULL},
6042 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6043 0, NULL, integerValidate, NULL},
6044 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6045 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6046 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6047 0, NULL, NULL, NULL},
6048 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6049 0, NULL, NULL, NULL},
6050 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6051 0, NULL, NULL, NULL},
6052 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6053 0, NULL, NULL, NULL},
6054 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6055 0, NULL, NULL, NULL},
6056 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6057 0, NULL, nameUIDValidate, nameUIDPretty },
6058 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6059 0, NULL, NULL, NULL},
6060 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6061 0, NULL, numericStringValidate, NULL},
6062 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6063 0, NULL, NULL, NULL},
6064 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6065 0, NULL, numericoidValidate, NULL},
6066 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6067 0, NULL, IA5StringValidate, NULL},
6068 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6069 0, NULL, blobValidate, NULL},
6070 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6071 0, NULL, postalAddressValidate, NULL},
6072 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6073 0, NULL, NULL, NULL},
6074 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6075 0, NULL, NULL, NULL},
6076 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6077 0, NULL, printableStringValidate, NULL},
6078 /* moved here because now depends on Directory String, IA5 String
6079 * and Printable String */
6080 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6081 0, country_gen_syn, countryStringValidate, NULL},
6082 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6083 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6084 0, NULL, subtreeSpecificationValidate, NULL},
6085 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6086 X_BINARY X_NOT_H_R ")",
6087 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6088 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6089 0, NULL, printableStringValidate, NULL},
6090 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6091 0, NULL, NULL, NULL},
6092 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6093 0, NULL, printablesStringValidate, NULL},
6094 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6095 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6096 0, NULL, utcTimeValidate, NULL},
6098 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6099 0, NULL, NULL, NULL},
6100 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6101 0, NULL, NULL, NULL},
6102 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6103 0, NULL, NULL, NULL},
6104 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6105 0, NULL, NULL, NULL},
6106 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6107 0, NULL, NULL, NULL},
6109 /* RFC 2307 NIS Syntaxes */
6110 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6111 0, NULL, nisNetgroupTripleValidate, NULL},
6112 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6113 0, NULL, bootParameterValidate, NULL},
6115 /* draft-zeilenga-ldap-x509 */
6116 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6117 SLAP_SYNTAX_HIDE, NULL,
6118 serialNumberAndIssuerValidate,
6119 serialNumberAndIssuerPretty},
6120 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6121 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6122 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6123 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6124 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6125 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6126 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6127 SLAP_SYNTAX_HIDE, NULL,
6128 issuerAndThisUpdateValidate,
6129 issuerAndThisUpdatePretty},
6130 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6131 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6132 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6133 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6134 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6135 SLAP_SYNTAX_HIDE, NULL,
6136 serialNumberAndIssuerSerialValidate,
6137 serialNumberAndIssuerSerialPretty},
6138 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6139 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6141 #ifdef SLAPD_AUTHPASSWD
6142 /* needs updating */
6143 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6144 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6147 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6148 0, NULL, UUIDValidate, UUIDPretty},
6150 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6151 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6153 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6154 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6156 /* OpenLDAP Void Syntax */
6157 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6158 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6160 /* FIXME: OID is unused, but not registered yet */
6161 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6162 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6164 {NULL, 0, NULL, NULL, NULL}
6167 char *csnSIDMatchSyntaxes[] = {
6168 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6171 char *certificateExactMatchSyntaxes[] = {
6172 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6175 char *certificateListExactMatchSyntaxes[] = {
6176 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6179 char *attributeCertificateExactMatchSyntaxes[] = {
6180 attributeCertificateSyntaxOID /* attributeCertificate */,
6184 #ifdef LDAP_COMP_MATCH
6185 char *componentFilterMatchSyntaxes[] = {
6186 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6187 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6188 attributeCertificateSyntaxOID /* attributeCertificate */,
6193 char *directoryStringSyntaxes[] = {
6194 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6197 char *integerFirstComponentMatchSyntaxes[] = {
6198 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6199 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6202 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6203 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6204 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6205 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6206 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6207 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6208 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6209 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6210 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6215 * Other matching rules in X.520 that we do not use (yet):
6217 * 2.5.13.25 uTCTimeMatch
6218 * 2.5.13.26 uTCTimeOrderingMatch
6219 * 2.5.13.31* directoryStringFirstComponentMatch
6220 * 2.5.13.32* wordMatch
6221 * 2.5.13.33* keywordMatch
6222 * 2.5.13.36+ certificatePairExactMatch
6223 * 2.5.13.37+ certificatePairMatch
6224 * 2.5.13.40+ algorithmIdentifierMatch
6225 * 2.5.13.41* storedPrefixMatch
6226 * 2.5.13.42 attributeCertificateMatch
6227 * 2.5.13.43 readerAndKeyIDMatch
6228 * 2.5.13.44 attributeIntegrityMatch
6230 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6231 * (+) described in draft-zeilenga-ldap-x509
6233 static slap_mrule_defs_rec mrule_defs[] = {
6235 * EQUALITY matching rules must be listed after associated APPROX
6236 * matching rules. So, we list all APPROX matching rules first.
6238 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6239 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6240 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6241 NULL, NULL, directoryStringApproxMatch,
6242 directoryStringApproxIndexer, directoryStringApproxFilter,
6245 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6246 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6247 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6248 NULL, NULL, IA5StringApproxMatch,
6249 IA5StringApproxIndexer, IA5StringApproxFilter,
6253 * Other matching rules
6256 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6257 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6258 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6259 NULL, NULL, octetStringMatch,
6260 octetStringIndexer, octetStringFilter,
6263 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6264 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6265 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6266 NULL, dnNormalize, dnMatch,
6267 octetStringIndexer, octetStringFilter,
6270 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6271 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6272 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6273 NULL, dnNormalize, dnRelativeMatch,
6277 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6278 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6279 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6280 NULL, dnNormalize, dnRelativeMatch,
6284 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6285 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6286 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6287 NULL, dnNormalize, dnRelativeMatch,
6291 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6292 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6293 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6294 NULL, dnNormalize, dnRelativeMatch,
6298 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6299 "SYNTAX 1.2.36.79672281.1.5.0 )",
6300 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6301 NULL, rdnNormalize, rdnMatch,
6302 octetStringIndexer, octetStringFilter,
6305 #ifdef LDAP_COMP_MATCH
6306 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6307 "SYNTAX 1.2.36.79672281.1.5.2 )",
6308 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6309 NULL, NULL , componentFilterMatch,
6310 octetStringIndexer, octetStringFilter,
6313 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6314 "SYNTAX 1.2.36.79672281.1.5.3 )",
6315 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6316 NULL, NULL , allComponentsMatch,
6317 octetStringIndexer, octetStringFilter,
6320 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6321 "SYNTAX 1.2.36.79672281.1.5.3 )",
6322 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6323 NULL, NULL , directoryComponentsMatch,
6324 octetStringIndexer, octetStringFilter,
6328 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6329 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6330 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6331 NULL, UTF8StringNormalize, octetStringMatch,
6332 octetStringIndexer, octetStringFilter,
6333 directoryStringApproxMatchOID },
6335 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6336 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6337 SLAP_MR_ORDERING, directoryStringSyntaxes,
6338 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6340 "caseIgnoreMatch" },
6342 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6343 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6344 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6345 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6346 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6347 "caseIgnoreMatch" },
6349 {"( 2.5.13.5 NAME 'caseExactMatch' "
6350 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6351 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6352 NULL, UTF8StringNormalize, octetStringMatch,
6353 octetStringIndexer, octetStringFilter,
6354 directoryStringApproxMatchOID },
6356 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6357 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6358 SLAP_MR_ORDERING, directoryStringSyntaxes,
6359 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6363 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6364 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6365 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6366 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6367 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6370 {"( 2.5.13.8 NAME 'numericStringMatch' "
6371 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6372 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6373 NULL, numericStringNormalize, octetStringMatch,
6374 octetStringIndexer, octetStringFilter,
6377 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6378 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6379 SLAP_MR_ORDERING, NULL,
6380 NULL, numericStringNormalize, octetStringOrderingMatch,
6382 "numericStringMatch" },
6384 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6385 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6386 SLAP_MR_SUBSTR, NULL,
6387 NULL, numericStringNormalize, octetStringSubstringsMatch,
6388 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6389 "numericStringMatch" },
6391 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6392 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6393 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6394 NULL, postalAddressNormalize, octetStringMatch,
6395 octetStringIndexer, octetStringFilter,
6398 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6400 SLAP_MR_SUBSTR, NULL,
6401 NULL, NULL, NULL, NULL, NULL,
6402 "caseIgnoreListMatch" },
6404 {"( 2.5.13.13 NAME 'booleanMatch' "
6405 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6406 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6407 NULL, NULL, booleanMatch,
6408 octetStringIndexer, octetStringFilter,
6411 {"( 2.5.13.14 NAME 'integerMatch' "
6412 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6413 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6414 NULL, NULL, integerMatch,
6415 integerIndexer, integerFilter,
6418 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6419 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6420 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6421 NULL, NULL, integerMatch,
6425 {"( 2.5.13.16 NAME 'bitStringMatch' "
6426 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6427 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6428 NULL, NULL, octetStringMatch,
6429 octetStringIndexer, octetStringFilter,
6432 {"( 2.5.13.17 NAME 'octetStringMatch' "
6433 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6434 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6435 NULL, NULL, octetStringMatch,
6436 octetStringIndexer, octetStringFilter,
6439 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6440 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6441 SLAP_MR_ORDERING, NULL,
6442 NULL, NULL, octetStringOrderingMatch,
6444 "octetStringMatch" },
6446 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6447 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6448 SLAP_MR_SUBSTR, NULL,
6449 NULL, NULL, octetStringSubstringsMatch,
6450 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6451 "octetStringMatch" },
6453 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6454 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6455 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6457 telephoneNumberNormalize, octetStringMatch,
6458 octetStringIndexer, octetStringFilter,
6461 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6462 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6463 SLAP_MR_SUBSTR, NULL,
6464 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6465 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6466 "telephoneNumberMatch" },
6468 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6470 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6471 NULL, NULL, NULL, NULL, NULL, NULL },
6473 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6475 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6476 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6477 uniqueMemberIndexer, uniqueMemberFilter,
6480 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6481 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6482 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6483 NULL, NULL, NULL, NULL, NULL, NULL },
6485 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6486 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6487 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6488 NULL, generalizedTimeNormalize, octetStringMatch,
6489 generalizedTimeIndexer, generalizedTimeFilter,
6492 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6493 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6494 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6495 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6497 "generalizedTimeMatch" },
6499 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6500 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6501 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6502 integerFirstComponentMatchSyntaxes,
6503 NULL, firstComponentNormalize, integerMatch,
6504 octetStringIndexer, octetStringFilter,
6507 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6508 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6509 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6510 objectIdentifierFirstComponentMatchSyntaxes,
6511 NULL, firstComponentNormalize, octetStringMatch,
6512 octetStringIndexer, octetStringFilter,
6515 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6516 "SYNTAX 1.3.6.1.1.15.1 )",
6517 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6518 NULL, certificateExactNormalize, octetStringMatch,
6519 octetStringIndexer, octetStringFilter,
6522 {"( 2.5.13.35 NAME 'certificateMatch' "
6523 "SYNTAX 1.3.6.1.1.15.2 )",
6524 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6525 NULL, NULL, NULL, NULL, NULL,
6528 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6529 "SYNTAX 1.3.6.1.1.15.5 )",
6530 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6531 NULL, certificateListExactNormalize, octetStringMatch,
6532 octetStringIndexer, octetStringFilter,
6535 {"( 2.5.13.39 NAME 'certificateListMatch' "
6536 "SYNTAX 1.3.6.1.1.15.6 )",
6537 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6538 NULL, NULL, NULL, NULL, NULL,
6541 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6542 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6543 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6544 NULL, attributeCertificateExactNormalize, octetStringMatch,
6545 octetStringIndexer, octetStringFilter,
6548 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6549 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6550 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6551 NULL, NULL, NULL, NULL, NULL,
6554 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6555 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6556 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6557 NULL, IA5StringNormalize, octetStringMatch,
6558 octetStringIndexer, octetStringFilter,
6559 IA5StringApproxMatchOID },
6561 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6562 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6563 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6564 NULL, IA5StringNormalize, octetStringMatch,
6565 octetStringIndexer, octetStringFilter,
6566 IA5StringApproxMatchOID },
6568 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6570 SLAP_MR_SUBSTR, NULL,
6571 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6572 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6573 "caseIgnoreIA5Match" },
6575 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6577 SLAP_MR_SUBSTR, NULL,
6578 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6579 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6580 "caseExactIA5Match" },
6582 #ifdef SLAPD_AUTHPASSWD
6583 /* needs updating */
6584 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6585 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6586 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6587 NULL, NULL, authPasswordMatch,
6592 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6593 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6595 NULL, NULL, integerBitAndMatch,
6599 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6600 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6602 NULL, NULL, integerBitOrMatch,
6606 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6607 "SYNTAX 1.3.6.1.1.16.1 )",
6608 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6609 NULL, UUIDNormalize, octetStringMatch,
6610 octetStringIndexer, octetStringFilter,
6613 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6614 "SYNTAX 1.3.6.1.1.16.1 )",
6615 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6616 NULL, UUIDNormalize, octetStringOrderingMatch,
6617 octetStringIndexer, octetStringFilter,
6620 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6621 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6622 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6623 NULL, csnNormalize, csnMatch,
6624 csnIndexer, csnFilter,
6627 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6628 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6629 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6630 NULL, csnNormalize, csnOrderingMatch,
6634 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6635 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6636 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6637 NULL, csnSidNormalize, octetStringMatch,
6638 octetStringIndexer, octetStringFilter,
6641 /* FIXME: OID is unused, but not registered yet */
6642 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6643 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6644 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6645 NULL, authzNormalize, authzMatch,
6649 {NULL, SLAP_MR_NONE, NULL,
6650 NULL, NULL, NULL, NULL, NULL,
6655 slap_schema_init( void )
6660 /* we should only be called once (from main) */
6661 assert( schema_init_done == 0 );
6663 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6664 res = register_syntax( &syntax_defs[i] );
6667 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6668 syntax_defs[i].sd_desc );
6673 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6674 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6675 mrule_defs[i].mrd_compat_syntaxes == NULL )
6678 "slap_schema_init: Ignoring unusable matching rule %s\n",
6679 mrule_defs[i].mrd_desc );
6683 res = register_matching_rule( &mrule_defs[i] );
6687 "slap_schema_init: Error registering matching rule %s\n",
6688 mrule_defs[i].mrd_desc );
6693 res = slap_schema_load();
6694 schema_init_done = 1;
6699 schema_destroy( void )
6708 if( schema_init_done ) {
6709 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6710 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );