1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 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 = SLAP_X509_OPTION + 1,
160 SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 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 */
323 if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */
324 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
325 tag = ber_skip_tag( ber, &len );
326 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
327 ber_skip_data( ber, len );
328 tag = ber_skip_tag( ber, &len );
330 /* signatureAlgorithm */
331 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
332 ber_skip_data( ber, len );
333 tag = ber_skip_tag( ber, &len );
335 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
336 ber_skip_data( ber, len );
337 tag = ber_skip_tag( ber, &len );
338 /* Must be at end now */
339 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
343 /* X.509 PMI Attribute Certificate Validate */
345 attributeCertificateValidate( Syntax *syntax, struct berval *in )
347 BerElementBuffer berbuf;
348 BerElement *ber = (BerElement *)&berbuf;
354 ber_init2( ber, in, LBER_USE_DER );
356 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
357 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
359 tag = ber_skip_tag( ber, &len ); /* Sequence */
360 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
362 tag = ber_peek_tag( ber, &len ); /* Version */
363 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
364 tag = ber_get_int( ber, &version ); /* X.509 only allows v2 */
365 if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
367 tag = ber_skip_tag( ber, &len ); /* Holder */
368 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
369 ber_skip_data( ber, len );
371 tag = ber_skip_tag( ber, &len ); /* Issuer */
372 if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
373 ber_skip_data( ber, len );
375 tag = ber_skip_tag( ber, &len ); /* Signature */
376 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
377 ber_skip_data( ber, len );
379 tag = ber_skip_tag( ber, &len ); /* Serial number */
380 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
381 ber_skip_data( ber, len );
383 tag = ber_skip_tag( ber, &len ); /* AttCertValidityPeriod */
384 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
385 ber_skip_data( ber, len );
387 tag = ber_skip_tag( ber, &len ); /* Attributes */
388 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
389 ber_skip_data( ber, len );
391 ber_peek_tag( ber, &len );
393 if ( tag == LBER_BITSTRING ) { /* issuerUniqueID */
394 tag = ber_skip_tag( ber, &len );
395 ber_skip_data( ber, len );
396 tag = ber_peek_tag( ber, &len );
399 if ( tag == LBER_SEQUENCE ) { /* extensions or signatureAlgorithm */
400 tag = ber_skip_tag( ber, &len );
401 ber_skip_data( ber, len );
403 tag = ber_peek_tag( ber, &len );
406 if ( tag == LBER_SEQUENCE ) { /* signatureAlgorithm */
407 tag = ber_skip_tag( ber, &len );
408 ber_skip_data( ber, len );
410 tag = ber_peek_tag( ber, &len );
413 if ( tag == LBER_BITSTRING ) { /* Signature */
414 tag = ber_skip_tag( ber, &len );
415 ber_skip_data( ber, len );
417 tag = ber_peek_tag( ber, &len );
420 /* Must be at end now */
421 if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
432 struct berval *value,
433 void *assertedValue )
435 struct berval *asserted = (struct berval *) assertedValue;
436 int match = value->bv_len - asserted->bv_len;
439 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
447 octetStringOrderingMatch(
452 struct berval *value,
453 void *assertedValue )
455 struct berval *asserted = (struct berval *) assertedValue;
456 ber_len_t v_len = value->bv_len;
457 ber_len_t av_len = asserted->bv_len;
459 int match = memcmp( value->bv_val, asserted->bv_val,
460 (v_len < av_len ? v_len : av_len) );
462 if( match == 0 ) match = v_len - av_len;
470 HASH_CONTEXT *HASHcontext,
471 struct berval *prefix,
476 HASH_Init(HASHcontext);
477 if(prefix && prefix->bv_len > 0) {
478 HASH_Update(HASHcontext,
479 (unsigned char *)prefix->bv_val, prefix->bv_len);
481 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
482 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
483 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
489 HASH_CONTEXT *HASHcontext,
490 unsigned char *HASHdigest,
491 unsigned char *value,
494 HASH_CONTEXT ctx = *HASHcontext;
495 HASH_Update( &ctx, value, len );
496 HASH_Final( HASHdigest, &ctx );
499 /* Index generation function */
500 int octetStringIndexer(
505 struct berval *prefix,
513 HASH_CONTEXT HASHcontext;
514 unsigned char HASHdigest[HASH_BYTES];
515 struct berval digest;
516 digest.bv_val = (char *)HASHdigest;
517 digest.bv_len = sizeof(HASHdigest);
519 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
520 /* just count them */
523 /* we should have at least one value at this point */
526 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
528 slen = syntax->ssyn_oidlen;
529 mlen = mr->smr_oidlen;
531 hashPreset( &HASHcontext, prefix, 0, syntax, mr);
532 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
533 hashIter( &HASHcontext, HASHdigest,
534 (unsigned char *)values[i].bv_val, values[i].bv_len );
535 ber_dupbv_x( &keys[i], &digest, ctx );
538 BER_BVZERO( &keys[i] );
545 /* Index generation function */
546 int octetStringFilter(
551 struct berval *prefix,
552 void * assertedValue,
558 HASH_CONTEXT HASHcontext;
559 unsigned char HASHdigest[HASH_BYTES];
560 struct berval *value = (struct berval *) assertedValue;
561 struct berval digest;
562 digest.bv_val = (char *)HASHdigest;
563 digest.bv_len = sizeof(HASHdigest);
565 slen = syntax->ssyn_oidlen;
566 mlen = mr->smr_oidlen;
568 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
570 hashPreset( &HASHcontext, prefix, 0, syntax, mr );
571 hashIter( &HASHcontext, HASHdigest,
572 (unsigned char *)value->bv_val, value->bv_len );
574 ber_dupbv_x( keys, &digest, ctx );
575 BER_BVZERO( &keys[1] );
583 octetStringSubstringsMatch(
588 struct berval *value,
589 void *assertedValue )
592 SubstringsAssertion *sub = assertedValue;
593 struct berval left = *value;
597 /* Add up asserted input length */
598 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
599 inlen += sub->sa_initial.bv_len;
602 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
603 inlen += sub->sa_any[i].bv_len;
606 if ( !BER_BVISNULL( &sub->sa_final ) ) {
607 inlen += sub->sa_final.bv_len;
610 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
611 if ( inlen > left.bv_len ) {
616 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
617 sub->sa_initial.bv_len );
623 left.bv_val += sub->sa_initial.bv_len;
624 left.bv_len -= sub->sa_initial.bv_len;
625 inlen -= sub->sa_initial.bv_len;
628 if ( !BER_BVISNULL( &sub->sa_final ) ) {
629 if ( inlen > left.bv_len ) {
634 match = memcmp( sub->sa_final.bv_val,
635 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
636 sub->sa_final.bv_len );
642 left.bv_len -= sub->sa_final.bv_len;
643 inlen -= sub->sa_final.bv_len;
647 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
652 if ( inlen > left.bv_len ) {
653 /* not enough length */
658 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
662 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
669 idx = p - left.bv_val;
671 if ( idx >= left.bv_len ) {
672 /* this shouldn't happen */
679 if ( sub->sa_any[i].bv_len > left.bv_len ) {
680 /* not enough left */
685 match = memcmp( left.bv_val,
686 sub->sa_any[i].bv_val,
687 sub->sa_any[i].bv_len );
695 left.bv_val += sub->sa_any[i].bv_len;
696 left.bv_len -= sub->sa_any[i].bv_len;
697 inlen -= sub->sa_any[i].bv_len;
706 /* Substrings Index generation function */
708 octetStringSubstringsIndexer(
713 struct berval *prefix,
722 HASH_CONTEXT HCany, HCini, HCfin;
723 unsigned char HASHdigest[HASH_BYTES];
724 struct berval digest;
725 digest.bv_val = (char *)HASHdigest;
726 digest.bv_len = sizeof(HASHdigest);
730 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
731 /* count number of indices to generate */
732 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
733 if( values[i].bv_len >= index_substr_if_maxlen ) {
734 nkeys += index_substr_if_maxlen -
735 (index_substr_if_minlen - 1);
736 } else if( values[i].bv_len >= index_substr_if_minlen ) {
737 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
741 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
742 if( values[i].bv_len >= index_substr_any_len ) {
743 nkeys += values[i].bv_len - (index_substr_any_len - 1);
747 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
748 if( values[i].bv_len >= index_substr_if_maxlen ) {
749 nkeys += index_substr_if_maxlen -
750 (index_substr_if_minlen - 1);
751 } else if( values[i].bv_len >= index_substr_if_minlen ) {
752 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
758 /* no keys to generate */
763 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
765 slen = syntax->ssyn_oidlen;
766 mlen = mr->smr_oidlen;
768 if ( flags & SLAP_INDEX_SUBSTR_ANY )
769 hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
770 if( flags & SLAP_INDEX_SUBSTR_INITIAL )
771 hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
772 if( flags & SLAP_INDEX_SUBSTR_FINAL )
773 hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
776 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
779 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
780 ( values[i].bv_len >= index_substr_any_len ) )
782 max = values[i].bv_len - (index_substr_any_len - 1);
784 for( j=0; j<max; j++ ) {
785 hashIter( &HCany, HASHdigest,
786 (unsigned char *)&values[i].bv_val[j],
787 index_substr_any_len );
788 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
792 /* skip if too short */
793 if( values[i].bv_len < index_substr_if_minlen ) continue;
795 max = index_substr_if_maxlen < values[i].bv_len
796 ? index_substr_if_maxlen : values[i].bv_len;
798 for( j=index_substr_if_minlen; j<=max; j++ ) {
800 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
801 hashIter( &HCini, HASHdigest,
802 (unsigned char *)values[i].bv_val, j );
803 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
806 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
807 hashIter( &HCfin, HASHdigest,
808 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
809 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
816 BER_BVZERO( &keys[nkeys] );
827 octetStringSubstringsFilter (
832 struct berval *prefix,
833 void * assertedValue,
837 SubstringsAssertion *sa;
840 size_t slen, mlen, klen;
842 HASH_CONTEXT HASHcontext;
843 unsigned char HASHdigest[HASH_BYTES];
844 struct berval *value;
845 struct berval digest;
847 sa = (SubstringsAssertion *) assertedValue;
849 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
850 !BER_BVISNULL( &sa->sa_initial ) &&
851 sa->sa_initial.bv_len >= index_substr_if_minlen )
854 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
855 ( flags & SLAP_INDEX_SUBSTR_ANY ))
857 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
861 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
863 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
864 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
865 /* don't bother accounting with stepping */
866 nkeys += sa->sa_any[i].bv_len -
867 ( index_substr_any_len - 1 );
872 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
873 !BER_BVISNULL( &sa->sa_final ) &&
874 sa->sa_final.bv_len >= index_substr_if_minlen )
877 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
878 ( flags & SLAP_INDEX_SUBSTR_ANY ))
880 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
889 digest.bv_val = (char *)HASHdigest;
890 digest.bv_len = sizeof(HASHdigest);
892 slen = syntax->ssyn_oidlen;
893 mlen = mr->smr_oidlen;
895 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
898 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
899 !BER_BVISNULL( &sa->sa_initial ) &&
900 sa->sa_initial.bv_len >= index_substr_if_minlen )
902 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
903 value = &sa->sa_initial;
905 klen = index_substr_if_maxlen < value->bv_len
906 ? index_substr_if_maxlen : value->bv_len;
908 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
909 hashIter( &HASHcontext, HASHdigest,
910 (unsigned char *)value->bv_val, klen );
911 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
913 /* If initial is too long and we have subany indexed, use it
914 * to match the excess...
916 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
919 pre = SLAP_INDEX_SUBSTR_PREFIX;
920 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
921 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
923 hashIter( &HASHcontext, HASHdigest,
924 (unsigned char *)&value->bv_val[j], index_substr_any_len );
925 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
930 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
932 pre = SLAP_INDEX_SUBSTR_PREFIX;
933 klen = index_substr_any_len;
935 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
936 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
940 value = &sa->sa_any[i];
942 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
944 j <= value->bv_len - index_substr_any_len;
945 j += index_substr_any_step )
947 hashIter( &HASHcontext, HASHdigest,
948 (unsigned char *)&value->bv_val[j], klen );
949 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
954 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
955 !BER_BVISNULL( &sa->sa_final ) &&
956 sa->sa_final.bv_len >= index_substr_if_minlen )
958 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
959 value = &sa->sa_final;
961 klen = index_substr_if_maxlen < value->bv_len
962 ? index_substr_if_maxlen : value->bv_len;
964 hashPreset( &HASHcontext, prefix, pre, syntax, mr );
965 hashIter( &HASHcontext, HASHdigest,
966 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
967 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
969 /* If final is too long and we have subany indexed, use it
970 * to match the excess...
972 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
975 pre = SLAP_INDEX_SUBSTR_PREFIX;
976 hashPreset( &HASHcontext, prefix, pre, syntax, mr);
977 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
979 hashIter( &HASHcontext, HASHdigest,
980 (unsigned char *)&value->bv_val[j], index_substr_any_len );
981 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
987 BER_BVZERO( &keys[nkeys] );
1004 /* very unforgiving validation, requires no normalization
1005 * before simplistic matching
1007 if( in->bv_len < 3 ) {
1008 return LDAP_INVALID_SYNTAX;
1011 /* RFC 4517 Section 3.3.2 Bit String:
1012 * BitString = SQUOTE *binary-digit SQUOTE "B"
1013 * binary-digit = "0" / "1"
1015 * where SQUOTE [RFC4512] is
1016 * SQUOTE = %x27 ; single quote ("'")
1018 * Example: '0101111101'B
1021 if( in->bv_val[0] != '\'' ||
1022 in->bv_val[in->bv_len - 2] != '\'' ||
1023 in->bv_val[in->bv_len - 1] != 'B' )
1025 return LDAP_INVALID_SYNTAX;
1028 for( i = in->bv_len - 3; i > 0; i-- ) {
1029 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
1030 return LDAP_INVALID_SYNTAX;
1034 return LDAP_SUCCESS;
1038 * Syntaxes from RFC 4517
1043 A value of the Bit String syntax is a sequence of binary digits. The
1044 LDAP-specific encoding of a value of this syntax is defined by the
1047 BitString = SQUOTE *binary-digit SQUOTE "B"
1049 binary-digit = "0" / "1"
1051 The <SQUOTE> rule is defined in [MODELS].
1056 The LDAP definition for the Bit String syntax is:
1058 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
1060 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
1064 3.3.21. Name and Optional UID
1066 A value of the Name and Optional UID syntax is the distinguished name
1067 [MODELS] of an entity optionally accompanied by a unique identifier
1068 that serves to differentiate the entity from others with an identical
1071 The LDAP-specific encoding of a value of this syntax is defined by
1074 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
1076 The <BitString> rule is defined in Section 3.3.2. The
1077 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
1078 defined in [MODELS].
1080 Note that although the '#' character may occur in the string
1081 representation of a distinguished name, no additional escaping of
1082 this character is performed when a <distinguishedName> is encoded in
1083 a <NameAndOptionalUID>.
1086 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
1088 The LDAP definition for the Name and Optional UID syntax is:
1090 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
1092 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
1099 1.4. Common ABNF Productions
1102 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
1104 SQUOTE = %x27 ; single quote ("'")
1108 * Note: normalization strips any leading "0"s, unless the
1109 * bit string is exactly "'0'B", so the normalized example,
1110 * in slapd, would result in
1112 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
1114 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1115 * be escaped except when at the beginning of a value, the
1116 * definition of Name and Optional UID appears to be flawed,
1117 * because there is no clear means to determine whether the
1118 * UID part is present or not.
1122 * cn=Someone,dc=example,dc=com#'1'B
1124 * could be either a NameAndOptionalUID with trailing UID, i.e.
1126 * DN = "cn=Someone,dc=example,dc=com"
1129 * or a NameAndOptionalUID with no trailing UID, and the AVA
1130 * in the last RDN made of
1132 * attributeType = dc
1133 * attributeValue = com#'1'B
1135 * in fact "com#'1'B" is a valid IA5 string.
1137 * As a consequence, current slapd code assumes that the
1138 * presence of portions of a BitString at the end of the string
1139 * representation of a NameAndOptionalUID means a BitString
1140 * is expected, and cause an error otherwise. This is quite
1141 * arbitrary, and might change in the future.
1151 struct berval dn, uid;
1153 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1155 ber_dupbv( &dn, in );
1156 if( !dn.bv_val ) return LDAP_OTHER;
1158 /* if there's a "#", try bitStringValidate()... */
1159 uid.bv_val = strrchr( dn.bv_val, '#' );
1160 if ( !BER_BVISNULL( &uid ) ) {
1162 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1164 rc = bitStringValidate( NULL, &uid );
1165 if ( rc == LDAP_SUCCESS ) {
1166 /* in case of success, trim the UID,
1167 * otherwise treat it as part of the DN */
1168 dn.bv_len -= uid.bv_len + 1;
1169 uid.bv_val[-1] = '\0';
1173 rc = dnValidate( NULL, &dn );
1175 ber_memfree( dn.bv_val );
1186 assert( val != NULL );
1187 assert( out != NULL );
1190 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1192 if( BER_BVISEMPTY( val ) ) {
1193 ber_dupbv_x( out, val, ctx );
1195 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1196 return LDAP_INVALID_SYNTAX;
1200 struct berval dnval = *val;
1201 struct berval uidval = BER_BVNULL;
1203 uidval.bv_val = strrchr( val->bv_val, '#' );
1204 if ( !BER_BVISNULL( &uidval ) ) {
1206 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1208 rc = bitStringValidate( NULL, &uidval );
1210 if ( rc == LDAP_SUCCESS ) {
1211 ber_dupbv_x( &dnval, val, ctx );
1212 dnval.bv_len -= uidval.bv_len + 1;
1213 dnval.bv_val[dnval.bv_len] = '\0';
1216 BER_BVZERO( &uidval );
1220 rc = dnPretty( syntax, &dnval, out, ctx );
1221 if ( dnval.bv_val != val->bv_val ) {
1222 slap_sl_free( dnval.bv_val, ctx );
1224 if( rc != LDAP_SUCCESS ) {
1228 if( !BER_BVISNULL( &uidval ) ) {
1232 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1233 + STRLENOF( "#" ) + uidval.bv_len + 1,
1236 ber_memfree_x( out->bv_val, ctx );
1240 out->bv_val[out->bv_len++] = '#';
1241 out->bv_val[out->bv_len++] = '\'';
1243 got1 = uidval.bv_len < sizeof("'0'B");
1244 for( i = 1; i < uidval.bv_len - 2; i++ ) {
1245 c = uidval.bv_val[i];
1248 if( got1 ) out->bv_val[out->bv_len++] = c;
1252 out->bv_val[out->bv_len++] = c;
1257 out->bv_val[out->bv_len++] = '\'';
1258 out->bv_val[out->bv_len++] = 'B';
1259 out->bv_val[out->bv_len] = '\0';
1263 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1265 return LDAP_SUCCESS;
1269 uniqueMemberNormalize(
1274 struct berval *normalized,
1280 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1282 ber_dupbv_x( &out, val, ctx );
1283 if ( BER_BVISEMPTY( &out ) ) {
1287 struct berval uid = BER_BVNULL;
1289 uid.bv_val = strrchr( out.bv_val, '#' );
1290 if ( !BER_BVISNULL( &uid ) ) {
1292 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1294 rc = bitStringValidate( NULL, &uid );
1295 if ( rc == LDAP_SUCCESS ) {
1296 uid.bv_val[-1] = '\0';
1297 out.bv_len -= uid.bv_len + 1;
1303 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1305 if( rc != LDAP_SUCCESS ) {
1306 slap_sl_free( out.bv_val, ctx );
1307 return LDAP_INVALID_SYNTAX;
1310 if( !BER_BVISNULL( &uid ) ) {
1313 tmp = ch_realloc( normalized->bv_val,
1314 normalized->bv_len + uid.bv_len
1315 + STRLENOF("#") + 1 );
1316 if ( tmp == NULL ) {
1317 ber_memfree_x( normalized->bv_val, ctx );
1321 normalized->bv_val = tmp;
1323 /* insert the separator */
1324 normalized->bv_val[normalized->bv_len++] = '#';
1326 /* append the UID */
1327 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1328 uid.bv_val, uid.bv_len );
1329 normalized->bv_len += uid.bv_len;
1332 normalized->bv_val[normalized->bv_len] = '\0';
1335 slap_sl_free( out.bv_val, ctx );
1338 return LDAP_SUCCESS;
1347 struct berval *value,
1348 void *assertedValue )
1351 struct berval *asserted = (struct berval *) assertedValue;
1352 struct berval assertedDN = *asserted;
1353 struct berval assertedUID = BER_BVNULL;
1354 struct berval valueDN = *value;
1355 struct berval valueUID = BER_BVNULL;
1356 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1358 if ( !BER_BVISEMPTY( asserted ) ) {
1359 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1360 if ( !BER_BVISNULL( &assertedUID ) ) {
1361 assertedUID.bv_val++;
1362 assertedUID.bv_len = assertedDN.bv_len
1363 - ( assertedUID.bv_val - assertedDN.bv_val );
1365 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1366 assertedDN.bv_len -= assertedUID.bv_len + 1;
1369 BER_BVZERO( &assertedUID );
1374 if ( !BER_BVISEMPTY( value ) ) {
1376 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1377 if ( !BER_BVISNULL( &valueUID ) ) {
1379 valueUID.bv_len = valueDN.bv_len
1380 - ( valueUID.bv_val - valueDN.bv_val );
1382 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1383 valueDN.bv_len -= valueUID.bv_len + 1;
1386 BER_BVZERO( &valueUID );
1391 if( valueUID.bv_len && assertedUID.bv_len ) {
1392 match = valueUID.bv_len - assertedUID.bv_len;
1395 return LDAP_SUCCESS;
1398 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1401 return LDAP_SUCCESS;
1404 } else if ( !approx && valueUID.bv_len ) {
1407 return LDAP_SUCCESS;
1409 } else if ( !approx && assertedUID.bv_len ) {
1412 return LDAP_SUCCESS;
1415 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1419 uniqueMemberIndexer(
1424 struct berval *prefix,
1432 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1433 /* just count them */
1437 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1439 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1440 struct berval assertedDN = values[i];
1441 struct berval assertedUID = BER_BVNULL;
1443 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1444 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1445 if ( !BER_BVISNULL( &assertedUID ) ) {
1446 assertedUID.bv_val++;
1447 assertedUID.bv_len = assertedDN.bv_len
1448 - ( assertedUID.bv_val - assertedDN.bv_val );
1450 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1451 assertedDN.bv_len -= assertedUID.bv_len + 1;
1454 BER_BVZERO( &assertedUID );
1459 dnvalues[i] = assertedDN;
1461 BER_BVZERO( &dnvalues[i] );
1463 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1464 dnvalues, keysp, ctx );
1466 slap_sl_free( dnvalues, ctx );
1476 struct berval *prefix,
1477 void * assertedValue,
1481 struct berval *asserted = (struct berval *) assertedValue;
1482 struct berval assertedDN = *asserted;
1483 struct berval assertedUID = BER_BVNULL;
1485 if ( !BER_BVISEMPTY( asserted ) ) {
1486 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1487 if ( !BER_BVISNULL( &assertedUID ) ) {
1488 assertedUID.bv_val++;
1489 assertedUID.bv_len = assertedDN.bv_len
1490 - ( assertedUID.bv_val - assertedDN.bv_val );
1492 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1493 assertedDN.bv_len -= assertedUID.bv_len + 1;
1496 BER_BVZERO( &assertedUID );
1501 return octetStringFilter( use, flags, syntax, mr, prefix,
1502 &assertedDN, keysp, ctx );
1507 * Handling boolean syntax and matching is quite rigid.
1508 * A more flexible approach would be to allow a variety
1509 * of strings to be normalized and prettied into TRUE
1517 /* very unforgiving validation, requires no normalization
1518 * before simplistic matching
1521 if( in->bv_len == 4 ) {
1522 if( bvmatch( in, &slap_true_bv ) ) {
1523 return LDAP_SUCCESS;
1525 } else if( in->bv_len == 5 ) {
1526 if( bvmatch( in, &slap_false_bv ) ) {
1527 return LDAP_SUCCESS;
1531 return LDAP_INVALID_SYNTAX;
1540 struct berval *value,
1541 void *assertedValue )
1543 /* simplistic matching allowed by rigid validation */
1544 struct berval *asserted = (struct berval *) assertedValue;
1545 *matchp = value->bv_len != asserted->bv_len;
1546 return LDAP_SUCCESS;
1549 /*-------------------------------------------------------------------
1550 LDAP/X.500 string syntax / matching rules have a few oddities. This
1551 comment attempts to detail how slapd(8) treats them.
1554 StringSyntax X.500 LDAP Matching/Comments
1555 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1556 PrintableString subset subset i/e + ignore insignificant spaces
1557 PrintableString subset subset i/e + ignore insignificant spaces
1558 NumericString subset subset ignore all spaces
1559 IA5String ASCII ASCII i/e + ignore insignificant spaces
1560 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1562 TelephoneNumber subset subset i + ignore all spaces and "-"
1564 See RFC 4518 for details.
1568 In X.500(93), a directory string can be either a PrintableString,
1569 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1570 In later versions, more CHOICEs were added. In all cases the string
1573 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1574 A directory string cannot be zero length.
1576 For matching, there are both case ignore and exact rules. Both
1577 also require that "insignificant" spaces be ignored.
1578 spaces before the first non-space are ignored;
1579 spaces after the last non-space are ignored;
1580 spaces after a space are ignored.
1581 Note: by these rules (and as clarified in X.520), a string of only
1582 spaces is to be treated as if held one space, not empty (which
1583 would be a syntax error).
1586 In ASN.1, numeric string is just a string of digits and spaces
1587 and could be empty. However, in X.500, all attribute values of
1588 numeric string carry a non-empty constraint. For example:
1590 internationalISDNNumber ATTRIBUTE ::= {
1591 WITH SYNTAX InternationalISDNNumber
1592 EQUALITY MATCHING RULE numericStringMatch
1593 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1594 ID id-at-internationalISDNNumber }
1595 InternationalISDNNumber ::=
1596 NumericString (SIZE(1..ub-international-isdn-number))
1598 Unforunately, some assertion values are don't carry the same
1599 constraint (but its unclear how such an assertion could ever
1600 be true). In LDAP, there is one syntax (numericString) not two
1601 (numericString with constraint, numericString without constraint).
1602 This should be treated as numericString with non-empty constraint.
1603 Note that while someone may have no ISDN number, there are no ISDN
1604 numbers which are zero length.
1606 In matching, spaces are ignored.
1609 In ASN.1, Printable string is just a string of printable characters
1610 and can be empty. In X.500, semantics much like NumericString (see
1611 serialNumber for a like example) excepting uses insignificant space
1612 handling instead of ignore all spaces. They must be non-empty.
1615 Basically same as PrintableString. There are no examples in X.500,
1616 but same logic applies. Empty strings are allowed.
1618 -------------------------------------------------------------------*/
1627 unsigned char *u = (unsigned char *)in->bv_val;
1629 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1630 /* directory strings cannot be empty */
1631 return LDAP_INVALID_SYNTAX;
1634 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1635 /* get the length indicated by the first byte */
1636 len = LDAP_UTF8_CHARLEN2( u, len );
1638 /* very basic checks */
1641 if( (u[5] & 0xC0) != 0x80 ) {
1642 return LDAP_INVALID_SYNTAX;
1645 if( (u[4] & 0xC0) != 0x80 ) {
1646 return LDAP_INVALID_SYNTAX;
1649 if( (u[3] & 0xC0) != 0x80 ) {
1650 return LDAP_INVALID_SYNTAX;
1653 if( (u[2] & 0xC0 )!= 0x80 ) {
1654 return LDAP_INVALID_SYNTAX;
1657 if( (u[1] & 0xC0) != 0x80 ) {
1658 return LDAP_INVALID_SYNTAX;
1661 /* CHARLEN already validated it */
1664 return LDAP_INVALID_SYNTAX;
1667 /* make sure len corresponds with the offset
1668 to the next character */
1669 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1673 return LDAP_INVALID_SYNTAX;
1676 return LDAP_SUCCESS;
1680 UTF8StringNormalize(
1685 struct berval *normalized,
1688 struct berval tmp, nvalue;
1689 int flags, wasspace;
1692 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1694 if( BER_BVISNULL( val ) ) {
1695 /* assume we're dealing with a syntax (e.g., UTF8String)
1696 * which allows empty strings
1698 BER_BVZERO( normalized );
1699 return LDAP_SUCCESS;
1702 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1703 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1704 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1705 ? LDAP_UTF8_APPROX : 0;
1707 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1712 /* collapse spaces (in place) */
1714 nvalue.bv_val = tmp.bv_val;
1716 /* trim leading spaces? */
1717 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1718 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1720 for( i = 0; i < tmp.bv_len; i++) {
1721 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1722 if( wasspace++ == 0 ) {
1723 /* trim repeated spaces */
1724 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1728 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1732 if( !BER_BVISEMPTY( &nvalue ) ) {
1733 /* trim trailing space? */
1735 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1736 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1740 nvalue.bv_val[nvalue.bv_len] = '\0';
1743 /* string of all spaces is treated as one space */
1744 nvalue.bv_val[0] = ' ';
1745 nvalue.bv_val[1] = '\0';
1749 *normalized = nvalue;
1750 return LDAP_SUCCESS;
1754 directoryStringSubstringsMatch(
1759 struct berval *value,
1760 void *assertedValue )
1763 SubstringsAssertion *sub = assertedValue;
1764 struct berval left = *value;
1768 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1769 if ( sub->sa_initial.bv_len > left.bv_len ) {
1770 /* not enough left */
1775 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1776 sub->sa_initial.bv_len );
1782 left.bv_val += sub->sa_initial.bv_len;
1783 left.bv_len -= sub->sa_initial.bv_len;
1785 priorspace = ASCII_SPACE(
1786 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1789 if ( sub->sa_any ) {
1790 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1794 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1795 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1797 /* allow next space to match */
1804 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1808 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1809 /* not enough left */
1814 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1821 idx = p - left.bv_val;
1823 if ( idx >= left.bv_len ) {
1824 /* this shouldn't happen */
1831 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1832 /* not enough left */
1837 match = memcmp( left.bv_val,
1838 sub->sa_any[i].bv_val,
1839 sub->sa_any[i].bv_len );
1847 left.bv_val += sub->sa_any[i].bv_len;
1848 left.bv_len -= sub->sa_any[i].bv_len;
1850 priorspace = ASCII_SPACE(
1851 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1855 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1856 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1857 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1859 /* allow next space to match */
1864 if ( sub->sa_final.bv_len > left.bv_len ) {
1865 /* not enough left */
1870 match = memcmp( sub->sa_final.bv_val,
1871 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1872 sub->sa_final.bv_len );
1881 return LDAP_SUCCESS;
1884 #if defined(SLAPD_APPROX_INITIALS)
1885 # define SLAPD_APPROX_DELIMITER "._ "
1886 # define SLAPD_APPROX_WORDLEN 2
1888 # define SLAPD_APPROX_DELIMITER " "
1889 # define SLAPD_APPROX_WORDLEN 1
1898 struct berval *value,
1899 void *assertedValue )
1901 struct berval *nval, *assertv;
1902 char *val, **values, **words, *c;
1903 int i, count, len, nextchunk=0, nextavail=0;
1905 /* Yes, this is necessary */
1906 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1907 if( nval == NULL ) {
1909 return LDAP_SUCCESS;
1912 /* Yes, this is necessary */
1913 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1914 NULL, LDAP_UTF8_APPROX, NULL );
1915 if( assertv == NULL ) {
1918 return LDAP_SUCCESS;
1921 /* Isolate how many words there are */
1922 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1923 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1924 if ( c == NULL ) break;
1929 /* Get a phonetic copy of each word */
1930 words = (char **)ch_malloc( count * sizeof(char *) );
1931 values = (char **)ch_malloc( count * sizeof(char *) );
1932 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1934 values[i] = phonetic(c);
1937 /* Work through the asserted value's words, to see if at least some
1938 * of the words are there, in the same order. */
1940 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1941 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1946 #if defined(SLAPD_APPROX_INITIALS)
1947 else if( len == 1 ) {
1948 /* Single letter words need to at least match one word's initial */
1949 for( i=nextavail; i<count; i++ )
1950 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1957 /* Isolate the next word in the asserted value and phonetic it */
1958 assertv->bv_val[nextchunk+len] = '\0';
1959 val = phonetic( assertv->bv_val + nextchunk );
1961 /* See if this phonetic chunk is in the remaining words of *value */
1962 for( i=nextavail; i<count; i++ ){
1963 if( !strcmp( val, values[i] ) ){
1971 /* This chunk in the asserted value was NOT within the *value. */
1977 /* Go on to the next word in the asserted value */
1981 /* If some of the words were seen, call it a match */
1982 if( nextavail > 0 ) {
1989 /* Cleanup allocs */
1990 ber_bvfree( assertv );
1991 for( i=0; i<count; i++ ) {
1992 ch_free( values[i] );
1998 return LDAP_SUCCESS;
2007 struct berval *prefix,
2013 int i,j, len, wordcount, keycount=0;
2014 struct berval *newkeys;
2015 BerVarray keys=NULL;
2017 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
2018 struct berval val = BER_BVNULL;
2019 /* Yes, this is necessary */
2020 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
2021 assert( !BER_BVISNULL( &val ) );
2023 /* Isolate how many words there are. There will be a key for each */
2024 for( wordcount = 0, c = val.bv_val; *c; c++) {
2025 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2026 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2028 if (*c == '\0') break;
2032 /* Allocate/increase storage to account for new keys */
2033 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2034 * sizeof(struct berval) );
2035 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2036 if( keys ) ch_free( keys );
2039 /* Get a phonetic copy of each word */
2040 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2042 if( len < SLAPD_APPROX_WORDLEN ) continue;
2043 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2048 ber_memfree( val.bv_val );
2050 BER_BVZERO( &keys[keycount] );
2053 return LDAP_SUCCESS;
2062 struct berval *prefix,
2063 void * assertedValue,
2072 /* Yes, this is necessary */
2073 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2074 NULL, LDAP_UTF8_APPROX, NULL );
2075 if( val == NULL || BER_BVISNULL( val ) ) {
2076 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2077 BER_BVZERO( &keys[0] );
2080 return LDAP_SUCCESS;
2083 /* Isolate how many words there are. There will be a key for each */
2084 for( count = 0,c = val->bv_val; *c; c++) {
2085 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2086 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2088 if (*c == '\0') break;
2092 /* Allocate storage for new keys */
2093 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2095 /* Get a phonetic copy of each word */
2096 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2098 if( len < SLAPD_APPROX_WORDLEN ) continue;
2099 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2105 BER_BVZERO( &keys[count] );
2108 return LDAP_SUCCESS;
2111 /* Remove all spaces and '-' characters */
2113 telephoneNumberNormalize(
2118 struct berval *normalized,
2123 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2125 /* validator should have refused an empty string */
2126 assert( !BER_BVISEMPTY( val ) );
2128 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2130 for( p = val->bv_val; *p; p++ ) {
2131 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2137 normalized->bv_len = q - normalized->bv_val;
2139 if( BER_BVISEMPTY( normalized ) ) {
2140 slap_sl_free( normalized->bv_val, ctx );
2141 BER_BVZERO( normalized );
2142 return LDAP_INVALID_SYNTAX;
2145 return LDAP_SUCCESS;
2149 postalAddressValidate(
2153 struct berval bv = *in;
2156 for ( c = 0; c < in->bv_len; c++ ) {
2157 if ( in->bv_val[c] == '\\' ) {
2159 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2160 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2162 return LDAP_INVALID_SYNTAX;
2167 if ( in->bv_val[c] == '$' ) {
2168 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2169 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2170 return LDAP_INVALID_SYNTAX;
2172 bv.bv_val = &in->bv_val[c] + 1;
2176 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2177 return UTF8StringValidate( NULL, &bv );
2181 postalAddressNormalize(
2186 struct berval *normalized,
2189 BerVarray lines = NULL, nlines = NULL;
2191 int rc = LDAP_SUCCESS;
2192 MatchingRule *xmr = NULL;
2195 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2196 xmr = slap_schema.si_mr_caseIgnoreMatch;
2199 xmr = slap_schema.si_mr_caseExactMatch;
2202 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2203 if ( val->bv_val[c] == '$' ) {
2208 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2209 nlines = &lines[l + 2];
2211 lines[0].bv_val = val->bv_val;
2212 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2213 if ( val->bv_val[c] == '$' ) {
2214 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2216 lines[l].bv_val = &val->bv_val[c + 1];
2219 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2221 normalized->bv_len = l;
2223 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2224 /* NOTE: we directly normalize each line,
2225 * without unescaping the values, since the special
2226 * values '\24' ('$') and '\5C' ('\') are not affected
2227 * by normalization */
2228 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2229 if ( rc != LDAP_SUCCESS ) {
2230 rc = LDAP_INVALID_SYNTAX;
2234 normalized->bv_len += nlines[l].bv_len;
2237 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2239 p = normalized->bv_val;
2240 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2241 p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2247 assert( p == &normalized->bv_val[normalized->bv_len] );
2250 if ( nlines != NULL ) {
2251 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2252 slap_sl_free( nlines[l].bv_val, ctx );
2255 slap_sl_free( lines, ctx );
2266 struct berval val = *in;
2268 if( BER_BVISEMPTY( &val ) ) {
2269 /* disallow empty strings */
2270 return LDAP_INVALID_SYNTAX;
2273 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2274 if ( val.bv_len == 1 ) {
2275 return LDAP_SUCCESS;
2278 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2285 while ( OID_LEADCHAR( val.bv_val[0] )) {
2289 if ( val.bv_len == 0 ) {
2290 return LDAP_SUCCESS;
2294 if( !OID_SEPARATOR( val.bv_val[0] )) {
2302 return LDAP_INVALID_SYNTAX;
2311 struct berval val = *in;
2313 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2315 if ( val.bv_val[0] == '-' ) {
2319 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2320 return LDAP_INVALID_SYNTAX;
2323 if( val.bv_val[0] == '0' ) { /* "-0" */
2324 return LDAP_INVALID_SYNTAX;
2327 } else if ( val.bv_val[0] == '0' ) {
2328 if( val.bv_len > 1 ) { /* "0<more>" */
2329 return LDAP_INVALID_SYNTAX;
2332 return LDAP_SUCCESS;
2335 for( i=0; i < val.bv_len; i++ ) {
2336 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2337 return LDAP_INVALID_SYNTAX;
2341 return LDAP_SUCCESS;
2350 struct berval *value,
2351 void *assertedValue )
2353 struct berval *asserted = (struct berval *) assertedValue;
2354 int vsign = 1, asign = 1; /* default sign = '+' */
2359 if( v.bv_val[0] == '-' ) {
2365 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2368 if( a.bv_val[0] == '-' ) {
2374 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2376 match = vsign - asign;
2378 match = ( v.bv_len != a.bv_len
2379 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2380 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2381 if( vsign < 0 ) match = -match;
2385 return LDAP_SUCCESS;
2388 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2389 #define INDEX_INTLEN_CHOP 7
2390 #define INDEX_INTLEN_CHOPBYTES 3
2400 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2401 * two's complement value (sign-extended or chopped as needed),
2402 * however the top <number of exponent-bytes + 1> bits of first byte
2403 * above is the inverse sign. The next bit is the sign as delimiter.
2405 ber_slen_t k = index_intlen_strlen;
2407 unsigned signmask = ~0x7fU;
2408 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2409 struct berval val = *in, itmp = *tmp;
2411 if ( val.bv_val[0] != '-' ) {
2416 /* Chop least significant digits, increase length instead */
2417 if ( val.bv_len > (ber_len_t) k ) {
2418 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2419 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2420 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2423 if ( lutil_str2bin( &val, &itmp, ctx )) {
2424 return LDAP_INVALID_SYNTAX;
2427 /* Omit leading sign byte */
2428 if ( itmp.bv_val[0] == neg ) {
2433 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2435 assert( chop == 0 );
2436 memset( key->bv_val, neg, k ); /* sign-extend */
2437 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2438 lenp = lenbuf + sizeof(lenbuf);
2439 chop = - (ber_len_t) k;
2441 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2443 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2444 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2445 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2446 k = (lenbuf + sizeof(lenbuf)) - lenp;
2447 if ( k > (ber_slen_t) index_intlen )
2449 memcpy( key->bv_val, lenp, k );
2450 itmp.bv_len = index_intlen - k;
2452 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2453 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2457 /* Index generation function */
2464 struct berval *prefix,
2474 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2476 /* count the values and find max needed length */
2478 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2479 if ( vlen < values[i].bv_len )
2480 vlen = values[i].bv_len;
2482 if ( vlen > maxstrlen )
2485 /* we should have at least one value at this point */
2488 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2489 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2490 keys[i].bv_len = index_intlen;
2491 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2494 keys[i].bv_val = NULL;
2496 if ( vlen > sizeof(ibuf) ) {
2497 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2501 itmp.bv_len = sizeof(ibuf);
2503 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2504 if ( itmp.bv_val != ibuf ) {
2505 itmp.bv_len = values[i].bv_len;
2506 if ( itmp.bv_len <= sizeof(ibuf) )
2507 itmp.bv_len = sizeof(ibuf);
2508 else if ( itmp.bv_len > maxstrlen )
2509 itmp.bv_len = maxstrlen;
2511 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2517 if ( itmp.bv_val != ibuf ) {
2518 slap_sl_free( itmp.bv_val, ctx );
2523 /* Index generation function */
2530 struct berval *prefix,
2531 void * assertedValue,
2538 struct berval *value;
2541 value = (struct berval *) assertedValue;
2543 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2545 keys[0].bv_len = index_intlen;
2546 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2548 keys[1].bv_val = NULL;
2550 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2551 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2552 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2553 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2556 iv.bv_len = sizeof(ibuf);
2559 rc = integerVal2Key( value, keys, &iv, ctx );
2563 if ( iv.bv_val != ibuf ) {
2564 slap_sl_free( iv.bv_val, ctx );
2570 countryStringValidate(
2572 struct berval *val )
2574 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2576 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2577 return LDAP_INVALID_SYNTAX;
2579 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2580 return LDAP_INVALID_SYNTAX;
2583 return LDAP_SUCCESS;
2587 printableStringValidate(
2589 struct berval *val )
2593 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2595 for(i=0; i < val->bv_len; i++) {
2596 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2597 return LDAP_INVALID_SYNTAX;
2601 return LDAP_SUCCESS;
2605 printablesStringValidate(
2607 struct berval *val )
2611 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2613 for(i=0,len=0; i < val->bv_len; i++) {
2614 int c = val->bv_val[i];
2618 return LDAP_INVALID_SYNTAX;
2622 } else if ( SLAP_PRINTABLE(c) ) {
2625 return LDAP_INVALID_SYNTAX;
2630 return LDAP_INVALID_SYNTAX;
2633 return LDAP_SUCCESS;
2639 struct berval *val )
2643 for(i=0; i < val->bv_len; i++) {
2644 if( !LDAP_ASCII(val->bv_val[i]) ) {
2645 return LDAP_INVALID_SYNTAX;
2649 return LDAP_SUCCESS;
2658 struct berval *normalized,
2662 int casefold = !SLAP_MR_ASSOCIATED( mr,
2663 slap_schema.si_mr_caseExactIA5Match );
2665 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2669 /* Ignore initial whitespace */
2670 while ( ASCII_SPACE( *p ) ) p++;
2672 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2673 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2674 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2675 normalized->bv_val[normalized->bv_len] = '\0';
2677 p = q = normalized->bv_val;
2680 if ( ASCII_SPACE( *p ) ) {
2683 /* Ignore the extra whitespace */
2684 while ( ASCII_SPACE( *p ) ) {
2688 } else if ( casefold ) {
2689 /* Most IA5 rules require casefolding */
2690 *q++ = TOLOWER(*p); p++;
2697 assert( normalized->bv_val <= p );
2701 * If the string ended in space, backup the pointer one
2702 * position. One is enough because the above loop collapsed
2703 * all whitespace to a single space.
2705 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2707 /* null terminate */
2710 normalized->bv_len = q - normalized->bv_val;
2712 return LDAP_SUCCESS;
2721 if( in->bv_len != 36 ) {
2722 return LDAP_INVALID_SYNTAX;
2725 for( i=0; i<36; i++ ) {
2731 if( in->bv_val[i] != '-' ) {
2732 return LDAP_INVALID_SYNTAX;
2736 if( !ASCII_HEX( in->bv_val[i]) ) {
2737 return LDAP_INVALID_SYNTAX;
2742 return LDAP_SUCCESS;
2753 int rc=LDAP_INVALID_SYNTAX;
2755 assert( in != NULL );
2756 assert( out != NULL );
2758 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2761 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2763 for( i=0; i<36; i++ ) {
2769 if( in->bv_val[i] != '-' ) {
2772 out->bv_val[i] = '-';
2776 if( !ASCII_HEX( in->bv_val[i]) ) {
2779 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2784 out->bv_val[ out->bv_len ] = '\0';
2788 slap_sl_free( out->bv_val, ctx );
2801 struct berval *normalized,
2804 unsigned char octet = '\0';
2808 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2809 /* NOTE: must be a normalized UUID */
2810 assert( val->bv_len == 16 );
2812 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2813 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2814 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2815 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2817 return LDAP_SUCCESS;
2820 normalized->bv_len = 16;
2821 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2823 for( i=0, j=0; i<36; i++ ) {
2824 unsigned char nibble;
2825 if( val->bv_val[i] == '-' ) {
2828 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2829 nibble = val->bv_val[i] - '0';
2831 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2832 nibble = val->bv_val[i] - ('a'-10);
2834 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2835 nibble = val->bv_val[i] - ('A'-10);
2838 slap_sl_free( normalized->bv_val, ctx );
2839 return LDAP_INVALID_SYNTAX;
2844 normalized->bv_val[j>>1] = octet;
2846 octet = nibble << 4;
2851 normalized->bv_val[normalized->bv_len] = 0;
2852 return LDAP_SUCCESS;
2858 numericStringValidate(
2864 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2866 for(i=0; i < in->bv_len; i++) {
2867 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2868 return LDAP_INVALID_SYNTAX;
2872 return LDAP_SUCCESS;
2876 numericStringNormalize(
2881 struct berval *normalized,
2884 /* removal all spaces */
2887 assert( !BER_BVISEMPTY( val ) );
2889 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2892 q = normalized->bv_val;
2895 if ( ASCII_SPACE( *p ) ) {
2896 /* Ignore whitespace */
2903 /* we should have copied no more than is in val */
2904 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2906 /* null terminate */
2909 normalized->bv_len = q - normalized->bv_val;
2911 if( BER_BVISEMPTY( normalized ) ) {
2912 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2913 normalized->bv_val[0] = ' ';
2914 normalized->bv_val[1] = '\0';
2915 normalized->bv_len = 1;
2918 return LDAP_SUCCESS;
2922 * Integer conversion macros that will use the largest available
2925 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2926 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2927 # define SLAP_LONG long long
2929 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2930 # define SLAP_LONG long
2931 #endif /* HAVE_STRTOLL ... */
2939 struct berval *value,
2940 void *assertedValue )
2942 SLAP_LONG lValue, lAssertedValue;
2945 /* safe to assume integers are NUL terminated? */
2946 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2947 if( errno == ERANGE )
2949 return LDAP_CONSTRAINT_VIOLATION;
2952 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2954 if( errno == ERANGE )
2956 return LDAP_CONSTRAINT_VIOLATION;
2959 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2960 return LDAP_SUCCESS;
2969 struct berval *value,
2970 void *assertedValue )
2972 SLAP_LONG lValue, lAssertedValue;
2975 /* safe to assume integers are NUL terminated? */
2976 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2977 if( errno == ERANGE )
2979 return LDAP_CONSTRAINT_VIOLATION;
2982 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2984 if( errno == ERANGE )
2986 return LDAP_CONSTRAINT_VIOLATION;
2989 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2990 return LDAP_SUCCESS;
2994 checkNum( struct berval *in, struct berval *out )
2996 /* parse serialNumber */
2997 ber_len_t neg = 0, extra = 0;
3000 out->bv_val = in->bv_val;
3003 if ( out->bv_val[0] == '-' ) {
3008 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
3009 first = out->bv_val[2];
3012 out->bv_len += STRLENOF("0x");
3013 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3014 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3017 } else if ( out->bv_val[0] == '\'' ) {
3018 first = out->bv_val[1];
3021 out->bv_len += STRLENOF("'");
3023 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3024 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3026 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3029 out->bv_len += STRLENOF("'H");
3032 first = out->bv_val[0];
3033 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3034 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3038 if ( !( out->bv_len > neg ) ) {
3042 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3050 serialNumberAndIssuerCheck(
3058 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3060 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3061 /* Parse old format */
3062 is->bv_val = ber_bvchr( in, '$' );
3063 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3065 sn->bv_val = in->bv_val;
3066 sn->bv_len = is->bv_val - in->bv_val;
3069 is->bv_len = in->bv_len - (sn->bv_len + 1);
3071 /* eat leading zeros */
3072 for( n=0; n < (sn->bv_len-1); n++ ) {
3073 if( sn->bv_val[n] != '0' ) break;
3078 for( n=0; n < sn->bv_len; n++ ) {
3079 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3083 /* Parse GSER format */
3088 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3092 struct berval x = *in;
3098 /* eat leading spaces */
3099 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3103 /* should be at issuer or serialNumber NamedValue */
3104 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3105 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3108 x.bv_val += STRLENOF("issuer");
3109 x.bv_len -= STRLENOF("issuer");
3111 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3115 /* eat leading spaces */
3116 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3120 /* For backward compatibility, this part is optional */
3121 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3122 x.bv_val += STRLENOF("rdnSequence:");
3123 x.bv_len -= STRLENOF("rdnSequence:");
3126 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3130 is->bv_val = x.bv_val;
3133 for ( ; is->bv_len < x.bv_len; ) {
3134 if ( is->bv_val[is->bv_len] != '"' ) {
3138 if ( is->bv_val[is->bv_len+1] == '"' ) {
3145 x.bv_val += is->bv_len + 1;
3146 x.bv_len -= is->bv_len + 1;
3148 have |= HAVE_ISSUER;
3150 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3152 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3154 /* parse serialNumber */
3155 x.bv_val += STRLENOF("serialNumber");
3156 x.bv_len -= STRLENOF("serialNumber");
3158 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3162 /* eat leading spaces */
3163 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3167 if ( checkNum( &x, sn ) ) {
3168 return LDAP_INVALID_SYNTAX;
3171 x.bv_val += sn->bv_len;
3172 x.bv_len -= sn->bv_len;
3177 return LDAP_INVALID_SYNTAX;
3180 /* eat leading spaces */
3181 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3185 if ( have == HAVE_ALL ) {
3189 if ( x.bv_val[0] != ',' ) {
3190 return LDAP_INVALID_SYNTAX;
3197 /* should have no characters left... */
3198 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3200 if ( numdquotes == 0 ) {
3201 ber_dupbv_x( &ni, is, ctx );
3206 ni.bv_len = is->bv_len - numdquotes;
3207 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3208 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3209 if ( is->bv_val[src] == '"' ) {
3212 ni.bv_val[dst] = is->bv_val[src];
3214 ni.bv_val[dst] = '\0';
3224 serialNumberAndIssuerValidate(
3229 struct berval sn, i;
3231 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3234 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3239 /* validate DN -- doesn't handle double dquote */
3240 rc = dnValidate( NULL, &i );
3242 rc = LDAP_INVALID_SYNTAX;
3245 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3246 slap_sl_free( i.bv_val, NULL );
3249 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3250 in->bv_val, rc, 0 );
3257 serialNumberAndIssuerPretty(
3264 struct berval sn, i, ni = BER_BVNULL;
3267 assert( in != NULL );
3268 assert( out != NULL );
3272 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3275 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3280 rc = dnPretty( syntax, &i, &ni, ctx );
3282 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3283 slap_sl_free( i.bv_val, ctx );
3287 rc = LDAP_INVALID_SYNTAX;
3291 /* make room from sn + "$" */
3292 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3293 + sn.bv_len + ni.bv_len;
3294 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3296 if ( out->bv_val == NULL ) {
3303 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3304 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3305 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3306 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3307 p = lutil_strcopy( p, /*{*/ "\" }" );
3309 assert( p == &out->bv_val[out->bv_len] );
3312 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3313 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3315 slap_sl_free( ni.bv_val, ctx );
3317 return LDAP_SUCCESS;
3327 /* Use hex format. '123456789abcdef'H */
3328 unsigned char *ptr, zero = '\0';
3331 ber_len_t i, len, nlen;
3333 assert( in != NULL );
3334 assert( !BER_BVISNULL( in ) );
3335 assert( out != NULL );
3336 assert( !BER_BVISNULL( out ) );
3338 ptr = (unsigned char *)in->bv_val;
3341 /* Check for minimal encodings */
3343 if ( ptr[0] & 0x80 ) {
3344 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3348 } else if ( ptr[0] == 0 ) {
3349 if ( !( ptr[1] & 0x80 ) ) {
3356 } else if ( len == 0 ) {
3357 /* FIXME: this should not be possible,
3358 * since a value of zero would have length 1 */
3363 first = !( ptr[0] & 0xf0U );
3364 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3365 if ( nlen >= out->bv_len ) {
3366 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3372 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3376 for ( ; i < len; i++ ) {
3377 sprintf( sptr, "%02X", ptr[i] );
3384 assert( sptr == &out->bv_val[nlen] );
3391 #define SLAP_SN_BUFLEN (64)
3394 * This routine is called by certificateExactNormalize when
3395 * certificateExactNormalize receives a search string instead of
3396 * a certificate. This routine checks if the search value is valid
3397 * and then returns the normalized value
3400 serialNumberAndIssuerNormalize(
3408 struct berval sn, sn2, sn3, i, ni;
3409 char sbuf2[SLAP_SN_BUFLEN];
3410 char sbuf3[SLAP_SN_BUFLEN];
3414 assert( in != NULL );
3415 assert( out != NULL );
3417 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3420 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3425 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3427 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3428 slap_sl_free( i.bv_val, ctx );
3432 return LDAP_INVALID_SYNTAX;
3435 /* Convert sn to canonical hex */
3437 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3438 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3440 sn2.bv_len = sn.bv_len;
3441 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3442 rc = LDAP_INVALID_SYNTAX;
3447 sn3.bv_len = sizeof(sbuf3);
3448 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3449 rc = LDAP_INVALID_SYNTAX;
3453 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3454 + sn3.bv_len + ni.bv_len;
3455 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3457 if ( out->bv_val == NULL ) {
3465 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3466 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3467 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3468 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3469 p = lutil_strcopy( p, /*{*/ "\" }" );
3471 assert( p == &out->bv_val[out->bv_len] );
3474 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3475 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3477 if ( sn2.bv_val != sbuf2 ) {
3478 slap_sl_free( sn2.bv_val, ctx );
3481 if ( sn3.bv_val != sbuf3 ) {
3482 slap_sl_free( sn3.bv_val, ctx );
3485 slap_sl_free( ni.bv_val, ctx );
3491 certificateExactNormalize(
3496 struct berval *normalized,
3499 BerElementBuffer berbuf;
3500 BerElement *ber = (BerElement *)&berbuf;
3504 char serialbuf2[SLAP_SN_BUFLEN];
3505 struct berval sn, sn2 = BER_BVNULL;
3506 struct berval issuer_dn = BER_BVNULL, bvdn;
3508 int rc = LDAP_INVALID_SYNTAX;
3510 assert( val != NULL );
3512 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3513 val->bv_val, val->bv_len, 0 );
3515 if ( BER_BVISEMPTY( val ) ) goto done;
3517 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3518 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3521 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3523 ber_init2( ber, val, LBER_USE_DER );
3524 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3525 tag = ber_skip_tag( ber, &len ); /* Sequence */
3526 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3527 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3528 tag = ber_skip_tag( ber, &len );
3529 tag = ber_get_int( ber, &i ); /* version */
3532 /* NOTE: move the test here from certificateValidate,
3533 * so that we can validate certs with serial longer
3534 * than sizeof(ber_int_t) */
3535 tag = ber_skip_tag( ber, &len ); /* serial */
3537 sn.bv_val = (char *)ber->ber_ptr;
3538 sn2.bv_val = serialbuf2;
3539 sn2.bv_len = sizeof(serialbuf2);
3540 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3541 rc = LDAP_INVALID_SYNTAX;
3544 ber_skip_data( ber, len );
3546 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3547 ber_skip_data( ber, len );
3548 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3549 len = ber_ptrlen( ber );
3550 bvdn.bv_val = val->bv_val + len;
3551 bvdn.bv_len = val->bv_len - len;
3553 rc = dnX509normalize( &bvdn, &issuer_dn );
3554 if ( rc != LDAP_SUCCESS ) goto done;
3556 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3557 + sn2.bv_len + issuer_dn.bv_len;
3558 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3560 p = normalized->bv_val;
3562 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3563 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3564 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3565 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3566 p = lutil_strcopy( p, /*{*/ "\" }" );
3571 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3572 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3574 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3575 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3580 /* X.509 PKI certificateList stuff */
3582 checkTime( struct berval *in, struct berval *out )
3586 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3589 assert( in != NULL );
3590 assert( !BER_BVISNULL( in ) );
3591 assert( !BER_BVISEMPTY( in ) );
3593 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3597 if ( out != NULL ) {
3598 assert( !BER_BVISNULL( out ) );
3599 assert( out->bv_len >= sizeof( buf ) );
3600 bv.bv_val = out->bv_val;
3606 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3607 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3610 if ( in->bv_val[i] != 'Z' ) {
3615 if ( i != in->bv_len ) {
3619 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3620 lutil_strncopy( bv.bv_val, in->bv_val, i );
3623 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3624 char *p = bv.bv_val;
3625 if ( in->bv_val[0] < '7' ) {
3626 p = lutil_strcopy( p, "20" );
3629 p = lutil_strcopy( p, "19" );
3631 lutil_strncopy( p, in->bv_val, i );
3638 rc = generalizedTimeValidate( NULL, &bv );
3639 if ( rc == LDAP_SUCCESS && out != NULL ) {
3640 out->bv_len = bv.bv_len;
3643 return rc != LDAP_SUCCESS;
3647 issuerAndThisUpdateCheck(
3654 struct berval x = *in;
3655 struct berval ni = BER_BVNULL;
3656 /* Parse GSER format */
3660 HAVE_THISUPDATE = 0x2,
3661 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3665 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3667 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3668 return LDAP_INVALID_SYNTAX;
3672 x.bv_len -= STRLENOF("{}");
3675 /* eat leading spaces */
3676 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3680 /* should be at issuer or thisUpdate */
3681 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3682 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3685 x.bv_val += STRLENOF("issuer");
3686 x.bv_len -= STRLENOF("issuer");
3688 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3692 /* eat leading spaces */
3693 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3697 /* For backward compatibility, this part is optional */
3698 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3699 return LDAP_INVALID_SYNTAX;
3701 x.bv_val += STRLENOF("rdnSequence:");
3702 x.bv_len -= STRLENOF("rdnSequence:");
3704 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3708 is->bv_val = x.bv_val;
3711 for ( ; is->bv_len < x.bv_len; ) {
3712 if ( is->bv_val[is->bv_len] != '"' ) {
3716 if ( is->bv_val[is->bv_len+1] == '"' ) {
3723 x.bv_val += is->bv_len + 1;
3724 x.bv_len -= is->bv_len + 1;
3726 have |= HAVE_ISSUER;
3728 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3730 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3732 /* parse thisUpdate */
3733 x.bv_val += STRLENOF("thisUpdate");
3734 x.bv_len -= STRLENOF("thisUpdate");
3736 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3740 /* eat leading spaces */
3741 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3745 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3749 tu->bv_val = x.bv_val;
3752 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3753 if ( tu->bv_val[tu->bv_len] == '"' ) {
3757 x.bv_val += tu->bv_len + 1;
3758 x.bv_len -= tu->bv_len + 1;
3760 have |= HAVE_THISUPDATE;
3763 return LDAP_INVALID_SYNTAX;
3766 /* eat leading spaces */
3767 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3771 if ( have == HAVE_ALL ) {
3775 if ( x.bv_val[0] != ',' ) {
3776 return LDAP_INVALID_SYNTAX;
3783 /* should have no characters left... */
3784 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3786 if ( numdquotes == 0 ) {
3787 ber_dupbv_x( &ni, is, ctx );
3792 ni.bv_len = is->bv_len - numdquotes;
3793 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3794 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3795 if ( is->bv_val[src] == '"' ) {
3798 ni.bv_val[dst] = is->bv_val[src];
3800 ni.bv_val[dst] = '\0';
3809 issuerAndThisUpdateValidate(
3814 struct berval i, tu;
3816 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3819 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3824 /* validate DN -- doesn't handle double dquote */
3825 rc = dnValidate( NULL, &i );
3827 rc = LDAP_INVALID_SYNTAX;
3829 } else if ( checkTime( &tu, NULL ) ) {
3830 rc = LDAP_INVALID_SYNTAX;
3833 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3834 slap_sl_free( i.bv_val, NULL );
3837 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3838 in->bv_val, rc, 0 );
3845 issuerAndThisUpdatePretty(
3852 struct berval i, tu, ni = BER_BVNULL;
3855 assert( in != NULL );
3856 assert( out != NULL );
3860 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3863 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3868 rc = dnPretty( syntax, &i, &ni, ctx );
3870 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3871 slap_sl_free( i.bv_val, ctx );
3874 if ( rc || checkTime( &tu, NULL ) ) {
3875 rc = LDAP_INVALID_SYNTAX;
3880 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3881 + ni.bv_len + tu.bv_len;
3882 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3884 if ( out->bv_val == NULL ) {
3891 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3892 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3893 p = lutil_strcopy( p, "\", thisUpdate \"" );
3894 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3895 p = lutil_strcopy( p, /*{*/ "\" }" );
3897 assert( p == &out->bv_val[out->bv_len] );
3900 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3901 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3903 slap_sl_free( ni.bv_val, ctx );
3909 issuerAndThisUpdateNormalize(
3917 struct berval i, ni, tu, tu2;
3918 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3922 assert( in != NULL );
3923 assert( out != NULL );
3925 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3928 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3933 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3935 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3936 slap_sl_free( i.bv_val, ctx );
3940 tu2.bv_len = sizeof( sbuf );
3941 if ( rc || checkTime( &tu, &tu2 ) ) {
3942 return LDAP_INVALID_SYNTAX;
3945 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3946 + ni.bv_len + tu2.bv_len;
3947 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3949 if ( out->bv_val == NULL ) {
3957 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3958 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3959 p = lutil_strcopy( p, "\", thisUpdate \"" );
3960 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3961 p = lutil_strcopy( p, /*{*/ "\" }" );
3963 assert( p == &out->bv_val[out->bv_len] );
3966 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3967 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3969 slap_sl_free( ni.bv_val, ctx );
3975 certificateListExactNormalize(
3980 struct berval *normalized,
3983 BerElementBuffer berbuf;
3984 BerElement *ber = (BerElement *)&berbuf;
3988 struct berval issuer_dn = BER_BVNULL, bvdn,
3990 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3991 int rc = LDAP_INVALID_SYNTAX;
3993 assert( val != NULL );
3995 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
3996 val->bv_val, val->bv_len, 0 );
3998 if ( BER_BVISEMPTY( val ) ) goto done;
4000 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4001 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
4004 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4006 ber_init2( ber, val, LBER_USE_DER );
4007 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
4008 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4009 tag = ber_skip_tag( ber, &len ); /* Sequence */
4010 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4011 tag = ber_peek_tag( ber, &len );
4012 /* Optional version */
4013 if ( tag == LBER_INTEGER ) {
4014 tag = ber_get_int( ber, &version );
4015 assert( tag == LBER_INTEGER );
4016 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
4018 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
4019 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4020 ber_skip_data( ber, len );
4022 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4023 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4024 len = ber_ptrlen( ber );
4025 bvdn.bv_val = val->bv_val + len;
4026 bvdn.bv_len = val->bv_len - len;
4027 tag = ber_skip_tag( ber, &len );
4028 ber_skip_data( ber, len );
4030 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4031 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4032 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4033 bvtu.bv_val = (char *)ber->ber_ptr;
4036 rc = dnX509normalize( &bvdn, &issuer_dn );
4037 if ( rc != LDAP_SUCCESS ) goto done;
4039 thisUpdate.bv_val = tubuf;
4040 thisUpdate.bv_len = sizeof(tubuf);
4041 if ( checkTime( &bvtu, &thisUpdate ) ) {
4042 rc = LDAP_INVALID_SYNTAX;
4046 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4047 + issuer_dn.bv_len + thisUpdate.bv_len;
4048 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4050 p = normalized->bv_val;
4052 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4053 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4054 p = lutil_strcopy( p, "\", thisUpdate \"" );
4055 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
4056 p = lutil_strcopy( p, /*{*/ "\" }" );
4061 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4062 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4064 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4069 /* X.509 PMI serialNumberAndIssuerSerialCheck
4071 AttributeCertificateExactAssertion ::= SEQUENCE {
4072 serialNumber CertificateSerialNumber,
4073 issuer AttCertIssuer }
4075 CertificateSerialNumber ::= INTEGER
4077 AttCertIssuer ::= [0] SEQUENCE {
4078 issuerName GeneralNames OPTIONAL,
4079 baseCertificateID [0] IssuerSerial OPTIONAL,
4080 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4081 -- At least one component shall be present
4083 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4085 GeneralName ::= CHOICE {
4086 otherName [0] INSTANCE OF OTHER-NAME,
4087 rfc822Name [1] IA5String,
4088 dNSName [2] IA5String,
4089 x400Address [3] ORAddress,
4090 directoryName [4] Name,
4091 ediPartyName [5] EDIPartyName,
4092 uniformResourceIdentifier [6] IA5String,
4093 iPAddress [7] OCTET STRING,
4094 registeredID [8] OBJECT IDENTIFIER }
4096 IssuerSerial ::= SEQUENCE {
4097 issuer GeneralNames,
4098 serial CertificateSerialNumber,
4099 issuerUID UniqueIdentifier OPTIONAL }
4101 ObjectDigestInfo ::= SEQUENCE {
4102 digestedObjectType ENUMERATED {
4105 otherObjectTypes (2) },
4106 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4107 digestAlgorithm AlgorithmIdentifier,
4108 objectDigest BIT STRING }
4110 * The way I interpret it, an assertion should look like
4112 { serialNumber 'dd'H,
4113 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4114 baseCertificateID { serial '1d'H,
4115 issuer { directoryName:rdnSequence:"cn=zzz" },
4116 issuerUID <value> -- optional
4118 objectDigestInfo { ... } -- optional
4122 * with issuerName, baseCertificateID and objectDigestInfo optional,
4123 * at least one present; the way it's currently implemented, it is
4125 { serialNumber 'dd'H,
4126 issuer { baseCertificateID { serial '1d'H,
4127 issuer { directoryName:rdnSequence:"cn=zzz" }
4132 * with all the above parts mandatory.
4135 serialNumberAndIssuerSerialCheck(
4139 struct berval *i_sn, /* contain serial of baseCertificateID */
4142 /* Parse GSER format */
4147 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4148 } have = HAVE_NONE, have2 = HAVE_NONE;
4150 struct berval x = *in;
4153 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4156 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4163 /* eat leading spaces */
4164 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4168 /* should be at issuer or serialNumber NamedValue */
4169 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4170 if ( have & HAVE_ISSUER ) {
4171 return LDAP_INVALID_SYNTAX;
4174 /* parse IssuerSerial */
4175 x.bv_val += STRLENOF("issuer");
4176 x.bv_len -= STRLENOF("issuer");
4178 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
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;
4191 /* eat leading spaces */
4192 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4196 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4197 return LDAP_INVALID_SYNTAX;
4199 x.bv_val += STRLENOF("baseCertificateID ");
4200 x.bv_len -= STRLENOF("baseCertificateID ");
4202 /* eat leading spaces */
4203 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4207 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4212 /* eat leading spaces */
4213 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4217 /* parse issuer of baseCertificateID */
4218 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4219 if ( have2 & HAVE_ISSUER ) {
4220 return LDAP_INVALID_SYNTAX;
4223 x.bv_val += STRLENOF("issuer ");
4224 x.bv_len -= STRLENOF("issuer ");
4226 /* eat leading spaces */
4227 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4231 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4235 /* eat leading spaces */
4236 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4240 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4241 return LDAP_INVALID_SYNTAX;
4243 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4244 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4246 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4250 is->bv_val = x.bv_val;
4253 for ( ; is->bv_len < x.bv_len; ) {
4254 if ( is->bv_val[is->bv_len] != '"' ) {
4258 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4265 x.bv_val += is->bv_len + 1;
4266 x.bv_len -= is->bv_len + 1;
4268 /* eat leading spaces */
4269 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4273 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4277 have2 |= HAVE_ISSUER;
4279 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4280 if ( have2 & HAVE_SN ) {
4281 return LDAP_INVALID_SYNTAX;
4284 x.bv_val += STRLENOF("serial ");
4285 x.bv_len -= STRLENOF("serial ");
4287 /* eat leading spaces */
4288 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4292 if ( checkNum( &x, i_sn ) ) {
4293 return LDAP_INVALID_SYNTAX;
4296 x.bv_val += i_sn->bv_len;
4297 x.bv_len -= i_sn->bv_len;
4302 return LDAP_INVALID_SYNTAX;
4305 /* eat leading spaces */
4306 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4310 if ( have2 == HAVE_ALL ) {
4314 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4319 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4323 /* eat leading spaces */
4324 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4328 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4332 have |= HAVE_ISSUER;
4334 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4335 if ( have & HAVE_SN ) {
4336 return LDAP_INVALID_SYNTAX;
4339 /* parse serialNumber */
4340 x.bv_val += STRLENOF("serialNumber");
4341 x.bv_len -= STRLENOF("serialNumber");
4343 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4347 /* eat leading spaces */
4348 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4352 if ( checkNum( &x, sn ) ) {
4353 return LDAP_INVALID_SYNTAX;
4356 x.bv_val += sn->bv_len;
4357 x.bv_len -= sn->bv_len;
4362 return LDAP_INVALID_SYNTAX;
4366 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4370 if ( have == HAVE_ALL ) {
4374 if ( x.bv_val[0] != ',' ) {
4375 return LDAP_INVALID_SYNTAX;
4381 /* should have no characters left... */
4382 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4384 if ( numdquotes == 0 ) {
4385 ber_dupbv_x( &ni, is, ctx );
4390 ni.bv_len = is->bv_len - numdquotes;
4391 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4392 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4393 if ( is->bv_val[src] == '"' ) {
4396 ni.bv_val[dst] = is->bv_val[src];
4398 ni.bv_val[dst] = '\0';
4403 /* need to handle double dquotes here */
4407 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4409 serialNumberAndIssuerSerialValidate(
4414 struct berval sn, i, i_sn;
4416 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4419 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4424 /* validate DN -- doesn't handle double dquote */
4425 rc = dnValidate( NULL, &i );
4427 rc = LDAP_INVALID_SYNTAX;
4430 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4431 slap_sl_free( i.bv_val, NULL );
4435 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4436 in->bv_val, rc, 0 );
4441 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4443 serialNumberAndIssuerSerialPretty(
4449 struct berval sn, i, i_sn, ni = BER_BVNULL;
4453 assert( in != NULL );
4454 assert( out != NULL );
4456 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4459 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4464 rc = dnPretty( syntax, &i, &ni, ctx );
4466 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4467 slap_sl_free( i.bv_val, ctx );
4471 rc = LDAP_INVALID_SYNTAX;
4475 /* make room from sn + "$" */
4476 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4477 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4478 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4480 if ( out->bv_val == NULL ) {
4487 p = lutil_strcopy( p, "{ serialNumber " );
4488 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
4489 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4490 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4491 p = lutil_strcopy( p, "\" }, serial " );
4492 p = lutil_strncopy( p, i_sn.bv_val, i_sn.bv_len );
4493 p = lutil_strcopy( p, " } } }" );
4495 assert( p == &out->bv_val[out->bv_len] );
4498 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4499 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4501 slap_sl_free( ni.bv_val, ctx );
4506 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4508 * This routine is called by attributeCertificateExactNormalize
4509 * when attributeCertificateExactNormalize receives a search
4510 * string instead of a attribute certificate. This routine
4511 * checks if the search value is valid and then returns the
4515 serialNumberAndIssuerSerialNormalize(
4523 struct berval i, ni = BER_BVNULL,
4524 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4525 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4526 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4527 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4531 assert( in != NULL );
4532 assert( out != NULL );
4534 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4537 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4542 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4544 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4545 slap_sl_free( i.bv_val, ctx );
4549 rc = LDAP_INVALID_SYNTAX;
4553 /* Convert sn to canonical hex */
4555 sn2.bv_len = sn.bv_len;
4556 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4557 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4559 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4560 rc = LDAP_INVALID_SYNTAX;
4564 /* Convert i_sn to canonical hex */
4565 i_sn2.bv_val = i_sbuf2;
4566 i_sn2.bv_len = i_sn.bv_len;
4567 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4568 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4570 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4571 rc = LDAP_INVALID_SYNTAX;
4576 sn3.bv_len = sizeof(sbuf3);
4577 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4578 rc = LDAP_INVALID_SYNTAX;
4582 i_sn3.bv_val = i_sbuf3;
4583 i_sn3.bv_len = sizeof(i_sbuf3);
4584 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4585 rc = LDAP_INVALID_SYNTAX;
4589 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4590 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4591 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4593 if ( out->bv_val == NULL ) {
4601 p = lutil_strcopy( p, "{ serialNumber " );
4602 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
4603 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4604 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4605 p = lutil_strcopy( p, "\" }, serial " );
4606 p = lutil_strncopy( p, i_sn3.bv_val, i_sn3.bv_len );
4607 p = lutil_strcopy( p, " } } }" );
4609 assert( p == &out->bv_val[out->bv_len] );
4612 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4613 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4615 if ( sn2.bv_val != sbuf2 ) {
4616 slap_sl_free( sn2.bv_val, ctx );
4619 if ( i_sn2.bv_val != i_sbuf2 ) {
4620 slap_sl_free( i_sn2.bv_val, ctx );
4623 if ( sn3.bv_val != sbuf3 ) {
4624 slap_sl_free( sn3.bv_val, ctx );
4627 if ( i_sn3.bv_val != i_sbuf3 ) {
4628 slap_sl_free( i_sn3.bv_val, ctx );
4631 slap_sl_free( ni.bv_val, ctx );
4636 /* X.509 PMI attributeCertificateExactNormalize */
4638 attributeCertificateExactNormalize(
4643 struct berval *normalized,
4646 BerElementBuffer berbuf;
4647 BerElement *ber = (BerElement *)&berbuf;
4650 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4651 struct berval sn, i_sn, sn2, i_sn2;
4652 struct berval issuer_dn = BER_BVNULL, bvdn;
4654 int rc = LDAP_INVALID_SYNTAX;
4656 if ( BER_BVISEMPTY( val ) ) {
4660 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4661 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4664 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4666 ber_init2( ber, val, LBER_USE_DER );
4667 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4668 tag = ber_skip_tag( ber, &len ); /* Sequence */
4669 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4670 ber_skip_data( ber, len );
4671 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4672 ber_skip_data( ber, len );
4675 tag = ber_skip_tag( ber, &len ); /* Sequence */
4676 /* issuerName (GeneralNames sequence; optional)? */
4677 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4678 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4679 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4680 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4681 rc = LDAP_INVALID_SYNTAX;
4684 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4685 len = ber_ptrlen( ber );
4686 bvdn.bv_val = val->bv_val + len;
4687 bvdn.bv_len = val->bv_len - len;
4688 rc = dnX509normalize( &bvdn, &issuer_dn );
4689 if ( rc != LDAP_SUCCESS ) goto done;
4691 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
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 i_sn.bv_val = (char *)ber->ber_ptr;
4700 i_sn2.bv_val = issuer_serialbuf;
4701 i_sn2.bv_len = sizeof(issuer_serialbuf);
4702 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4703 rc = LDAP_INVALID_SYNTAX;
4706 ber_skip_data( ber, len );
4708 /* issuerUID (bitstring; optional)? */
4709 /* objectDigestInfo (sequence; optional)? */
4711 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4712 ber_skip_data( ber, len );
4713 tag = ber_skip_tag( ber, &len ); /* serial number */
4714 if ( tag != LBER_INTEGER ) {
4715 rc = LDAP_INVALID_SYNTAX;
4718 sn.bv_val = (char *)ber->ber_ptr;
4720 sn2.bv_val = serialbuf;
4721 sn2.bv_len = sizeof(serialbuf);
4722 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4723 rc = LDAP_INVALID_SYNTAX;
4726 ber_skip_data( ber, len );
4728 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4729 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4730 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4732 p = normalized->bv_val;
4734 p = lutil_strcopy( p, "{ serialNumber " );
4735 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
4736 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4737 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4738 p = lutil_strcopy( p, "\" }, serial " );
4739 p = lutil_strncopy( p, i_sn2.bv_val, i_sn2.bv_len );
4740 p = lutil_strcopy( p, " } } }" );
4742 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4743 normalized->bv_val, NULL, NULL );
4748 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4749 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4750 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4763 assert( in != NULL );
4764 assert( !BER_BVISNULL( in ) );
4766 for ( i = 0; i < in->bv_len; i++ ) {
4767 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4768 return LDAP_INVALID_SYNTAX;
4772 return LDAP_SUCCESS;
4775 /* Normalize a SID as used inside a CSN:
4776 * three-digit numeric string */
4783 struct berval *normalized,
4788 assert( val != NULL );
4789 assert( normalized != NULL );
4791 ber_dupbv_x( normalized, val, ctx );
4793 for ( i = 0; i < normalized->bv_len; i++ ) {
4794 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4795 ber_memfree_x( normalized->bv_val, ctx );
4796 BER_BVZERO( normalized );
4797 return LDAP_INVALID_SYNTAX;
4800 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4803 return LDAP_SUCCESS;
4811 assert( in != NULL );
4812 assert( !BER_BVISNULL( in ) );
4814 if ( in->bv_len != 3 ) {
4815 return LDAP_INVALID_SYNTAX;
4818 return hexValidate( NULL, in );
4821 /* Normalize a SID as used inside a CSN:
4822 * three-digit numeric string */
4829 struct berval *normalized,
4832 if ( val->bv_len != 3 ) {
4833 return LDAP_INVALID_SYNTAX;
4836 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4846 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4849 /* Normalize a SID as used inside a CSN, either as-is
4850 * (assertion value) or extracted from the CSN
4851 * (attribute value) */
4858 struct berval *normalized,
4866 if ( BER_BVISEMPTY( val ) ) {
4867 return LDAP_INVALID_SYNTAX;
4870 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4871 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4874 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4876 ptr = ber_bvchr( val, '#' );
4877 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4878 return LDAP_INVALID_SYNTAX;
4881 bv.bv_val = ptr + 1;
4882 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4884 ptr = ber_bvchr( &bv, '#' );
4885 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4886 return LDAP_INVALID_SYNTAX;
4889 bv.bv_val = ptr + 1;
4890 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4892 ptr = ber_bvchr( &bv, '#' );
4893 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4894 return LDAP_INVALID_SYNTAX;
4897 bv.bv_len = ptr - bv.bv_val;
4899 if ( bv.bv_len == 2 ) {
4900 /* OpenLDAP 2.3 SID */
4902 buf[ 1 ] = bv.bv_val[ 0 ];
4903 buf[ 2 ] = bv.bv_val[ 1 ];
4910 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4922 assert( in != NULL );
4923 assert( !BER_BVISNULL( in ) );
4925 if ( BER_BVISEMPTY( in ) ) {
4926 return LDAP_INVALID_SYNTAX;
4931 ptr = ber_bvchr( &bv, '#' );
4932 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4933 return LDAP_INVALID_SYNTAX;
4936 bv.bv_len = ptr - bv.bv_val;
4937 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4938 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4940 return LDAP_INVALID_SYNTAX;
4943 rc = generalizedTimeValidate( NULL, &bv );
4944 if ( rc != LDAP_SUCCESS ) {
4948 bv.bv_val = ptr + 1;
4949 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4951 ptr = ber_bvchr( &bv, '#' );
4952 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4953 return LDAP_INVALID_SYNTAX;
4956 bv.bv_len = ptr - bv.bv_val;
4957 if ( bv.bv_len != 6 ) {
4958 return LDAP_INVALID_SYNTAX;
4961 rc = hexValidate( 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 ptr = ber_bvchr( &bv, '#' );
4970 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4971 return LDAP_INVALID_SYNTAX;
4974 bv.bv_len = ptr - bv.bv_val;
4975 if ( bv.bv_len == 2 ) {
4976 /* tolerate old 2-digit replica-id */
4977 rc = hexValidate( NULL, &bv );
4980 rc = sidValidate( NULL, &bv );
4982 if ( rc != LDAP_SUCCESS ) {
4986 bv.bv_val = ptr + 1;
4987 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4989 if ( bv.bv_len != 6 ) {
4990 return LDAP_INVALID_SYNTAX;
4993 return hexValidate( NULL, &bv );
4996 /* Normalize a CSN in OpenLDAP 2.1 format */
5003 struct berval *normalized,
5006 struct berval gt, cnt, sid, mod;
5008 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5012 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5013 assert( !BER_BVISEMPTY( val ) );
5017 ptr = ber_bvchr( >, '#' );
5018 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5019 return LDAP_INVALID_SYNTAX;
5022 gt.bv_len = ptr - gt.bv_val;
5023 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5024 return LDAP_INVALID_SYNTAX;
5027 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5028 return LDAP_INVALID_SYNTAX;
5031 cnt.bv_val = ptr + 1;
5032 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5034 ptr = ber_bvchr( &cnt, '#' );
5035 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5036 return LDAP_INVALID_SYNTAX;
5039 cnt.bv_len = ptr - cnt.bv_val;
5040 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5041 return LDAP_INVALID_SYNTAX;
5044 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5045 return LDAP_INVALID_SYNTAX;
5048 cnt.bv_val += STRLENOF( "0x" );
5049 cnt.bv_len -= STRLENOF( "0x" );
5051 sid.bv_val = ptr + 1;
5052 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5054 ptr = ber_bvchr( &sid, '#' );
5055 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5056 return LDAP_INVALID_SYNTAX;
5059 sid.bv_len = ptr - sid.bv_val;
5060 if ( sid.bv_len != STRLENOF( "0" ) ) {
5061 return LDAP_INVALID_SYNTAX;
5064 mod.bv_val = ptr + 1;
5065 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5066 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5067 return LDAP_INVALID_SYNTAX;
5070 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5074 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5075 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5077 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5079 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5080 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5084 *ptr++ = sid.bv_val[ 0 ];
5088 for ( i = 0; i < mod.bv_len; i++ ) {
5089 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5093 assert( ptr == &bv.bv_val[bv.bv_len] );
5095 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5096 return LDAP_INVALID_SYNTAX;
5099 ber_dupbv_x( normalized, &bv, ctx );
5101 return LDAP_SUCCESS;
5104 /* Normalize a CSN in OpenLDAP 2.3 format */
5111 struct berval *normalized,
5114 struct berval gt, cnt, sid, mod;
5116 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5120 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5121 assert( !BER_BVISEMPTY( val ) );
5125 ptr = ber_bvchr( >, '#' );
5126 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5127 return LDAP_INVALID_SYNTAX;
5130 gt.bv_len = ptr - gt.bv_val;
5131 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5132 return LDAP_INVALID_SYNTAX;
5135 cnt.bv_val = ptr + 1;
5136 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5138 ptr = ber_bvchr( &cnt, '#' );
5139 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5140 return LDAP_INVALID_SYNTAX;
5143 cnt.bv_len = ptr - cnt.bv_val;
5144 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5145 return LDAP_INVALID_SYNTAX;
5148 sid.bv_val = ptr + 1;
5149 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5151 ptr = ber_bvchr( &sid, '#' );
5152 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5153 return LDAP_INVALID_SYNTAX;
5156 sid.bv_len = ptr - sid.bv_val;
5157 if ( sid.bv_len != STRLENOF( "00" ) ) {
5158 return LDAP_INVALID_SYNTAX;
5161 mod.bv_val = ptr + 1;
5162 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5163 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5164 return LDAP_INVALID_SYNTAX;
5167 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5171 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5172 ptr = lutil_strcopy( ptr, ".000000Z#" );
5173 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5176 for ( i = 0; i < sid.bv_len; i++ ) {
5177 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5180 for ( i = 0; i < mod.bv_len; i++ ) {
5181 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5185 assert( ptr == &bv.bv_val[bv.bv_len] );
5186 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5187 return LDAP_INVALID_SYNTAX;
5190 ber_dupbv_x( normalized, &bv, ctx );
5192 return LDAP_SUCCESS;
5195 /* Normalize a CSN */
5202 struct berval *normalized,
5205 struct berval cnt, sid, mod;
5209 assert( val != NULL );
5210 assert( normalized != NULL );
5212 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5214 if ( BER_BVISEMPTY( val ) ) {
5215 return LDAP_INVALID_SYNTAX;
5218 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5219 /* Openldap <= 2.3 */
5221 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5224 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5227 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5230 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5231 return LDAP_INVALID_SYNTAX;
5234 ptr = ber_bvchr( val, '#' );
5235 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5236 return LDAP_INVALID_SYNTAX;
5239 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5240 return LDAP_INVALID_SYNTAX;
5243 cnt.bv_val = ptr + 1;
5244 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5246 ptr = ber_bvchr( &cnt, '#' );
5247 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5248 return LDAP_INVALID_SYNTAX;
5251 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5252 return LDAP_INVALID_SYNTAX;
5255 sid.bv_val = ptr + 1;
5256 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5258 ptr = ber_bvchr( &sid, '#' );
5259 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5260 return LDAP_INVALID_SYNTAX;
5263 sid.bv_len = ptr - sid.bv_val;
5264 if ( sid.bv_len != STRLENOF( "000" ) ) {
5265 return LDAP_INVALID_SYNTAX;
5268 mod.bv_val = ptr + 1;
5269 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5271 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5272 return LDAP_INVALID_SYNTAX;
5275 ber_dupbv_x( normalized, val, ctx );
5277 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5278 i < normalized->bv_len; i++ )
5280 /* assume it's already validated that's all hex digits */
5281 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5284 return LDAP_SUCCESS;
5294 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5297 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5298 /* slight optimization - does not need the start parameter */
5299 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5304 check_time_syntax (struct berval *val,
5307 struct berval *fraction)
5310 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5311 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5312 * GeneralizedTime supports leap seconds, UTCTime does not.
5314 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5315 static const int mdays[2][12] = {
5316 /* non-leap years */
5317 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5319 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5322 int part, c, c1, c2, tzoffset, leapyear = 0;
5325 e = p + val->bv_len;
5327 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5328 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5330 for (part = start; part < 7 && p < e; part++) {
5332 if (!ASCII_DIGIT(c1)) {
5337 return LDAP_INVALID_SYNTAX;
5340 if (!ASCII_DIGIT(c)) {
5341 return LDAP_INVALID_SYNTAX;
5343 c += c1 * 10 - '0' * 11;
5344 if ((part | 1) == 3) {
5347 return LDAP_INVALID_SYNTAX;
5350 if (c >= ceiling[part]) {
5351 if (! (c == 60 && part == 6 && start == 0))
5352 return LDAP_INVALID_SYNTAX;
5356 if (part < 5 + start) {
5357 return LDAP_INVALID_SYNTAX;
5359 for (; part < 9; part++) {
5363 /* leapyear check for the Gregorian calendar (year>1581) */
5364 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5368 if (parts[3] >= mdays[leapyear][parts[2]]) {
5369 return LDAP_INVALID_SYNTAX;
5373 fraction->bv_val = p;
5374 fraction->bv_len = 0;
5375 if (p < e && (*p == '.' || *p == ',')) {
5377 while (++p < e && ASCII_DIGIT(*p)) {
5380 if (p - fraction->bv_val == 1) {
5381 return LDAP_INVALID_SYNTAX;
5383 for (end_num = p; end_num[-1] == '0'; --end_num) {
5386 c = end_num - fraction->bv_val;
5387 if (c != 1) fraction->bv_len = c;
5393 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5399 return LDAP_INVALID_SYNTAX;
5405 for (part = 7; part < 9 && p < e; part++) {
5407 if (!ASCII_DIGIT(c1)) {
5412 return LDAP_INVALID_SYNTAX;
5415 if (!ASCII_DIGIT(c2)) {
5416 return LDAP_INVALID_SYNTAX;
5418 parts[part] = c1 * 10 + c2 - '0' * 11;
5419 if (parts[part] >= ceiling[part]) {
5420 return LDAP_INVALID_SYNTAX;
5423 if (part < 8 + start) {
5424 return LDAP_INVALID_SYNTAX;
5427 if (tzoffset == '-') {
5428 /* negative offset to UTC, ie west of Greenwich */
5429 parts[4] += parts[7];
5430 parts[5] += parts[8];
5431 /* offset is just hhmm, no seconds */
5432 for (part = 6; --part >= 0; ) {
5436 c = mdays[leapyear][parts[2]];
5438 if (parts[part] >= c) {
5440 return LDAP_INVALID_SYNTAX;
5445 } else if (part != 5) {
5450 /* positive offset to UTC, ie east of Greenwich */
5451 parts[4] -= parts[7];
5452 parts[5] -= parts[8];
5453 for (part = 6; --part >= 0; ) {
5454 if (parts[part] < 0) {
5456 return LDAP_INVALID_SYNTAX;
5461 /* make first arg to % non-negative */
5462 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5467 } else if (part != 5) {
5474 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5477 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5484 struct berval *normalized )
5488 rc = check_time_syntax(val, 1, parts, NULL);
5489 if (rc != LDAP_SUCCESS) {
5493 normalized->bv_val = ch_malloc( 14 );
5494 if ( normalized->bv_val == NULL ) {
5495 return LBER_ERROR_MEMORY;
5498 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5499 parts[1], parts[2] + 1, parts[3] + 1,
5500 parts[4], parts[5], parts[6] );
5501 normalized->bv_len = 13;
5503 return LDAP_SUCCESS;
5513 return check_time_syntax(in, 1, parts, NULL);
5516 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5519 generalizedTimeValidate(
5524 struct berval fraction;
5525 return check_time_syntax(in, 0, parts, &fraction);
5529 generalizedTimeNormalize(
5534 struct berval *normalized,
5539 struct berval fraction;
5541 rc = check_time_syntax(val, 0, parts, &fraction);
5542 if (rc != LDAP_SUCCESS) {
5546 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5547 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5548 if ( BER_BVISNULL( normalized ) ) {
5549 return LBER_ERROR_MEMORY;
5552 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5553 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5554 parts[4], parts[5], parts[6] );
5555 if ( !BER_BVISEMPTY( &fraction ) ) {
5556 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5557 fraction.bv_val, fraction.bv_len );
5558 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5560 strcpy( normalized->bv_val + len-1, "Z" );
5561 normalized->bv_len = len;
5563 return LDAP_SUCCESS;
5567 generalizedTimeOrderingMatch(
5572 struct berval *value,
5573 void *assertedValue )
5575 struct berval *asserted = (struct berval *) assertedValue;
5576 ber_len_t v_len = value->bv_len;
5577 ber_len_t av_len = asserted->bv_len;
5579 /* ignore trailing 'Z' when comparing */
5580 int match = memcmp( value->bv_val, asserted->bv_val,
5581 (v_len < av_len ? v_len : av_len) - 1 );
5582 if ( match == 0 ) match = v_len - av_len;
5585 return LDAP_SUCCESS;
5588 /* Index generation function */
5589 int generalizedTimeIndexer(
5594 struct berval *prefix,
5602 BerValue bvtmp; /* 40 bit index */
5604 struct lutil_timet tt;
5606 bvtmp.bv_len = sizeof(tmp);
5608 for( i=0; values[i].bv_val != NULL; i++ ) {
5609 /* just count them */
5612 /* we should have at least one value at this point */
5615 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5617 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5618 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5619 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5620 /* Use 40 bits of time for key */
5621 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5622 lutil_tm2time( &tm, &tt );
5623 tmp[0] = tt.tt_gsec & 0xff;
5624 tmp[4] = tt.tt_sec & 0xff;
5626 tmp[3] = tt.tt_sec & 0xff;
5628 tmp[2] = tt.tt_sec & 0xff;
5630 tmp[1] = tt.tt_sec & 0xff;
5632 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5636 keys[j].bv_val = NULL;
5641 return LDAP_SUCCESS;
5644 /* Index generation function */
5645 int generalizedTimeFilter(
5650 struct berval *prefix,
5651 void * assertedValue,
5657 BerValue bvtmp; /* 40 bit index */
5658 BerValue *value = (BerValue *) assertedValue;
5660 struct lutil_timet tt;
5662 bvtmp.bv_len = sizeof(tmp);
5664 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5665 /* Use 40 bits of time for key */
5666 if ( value->bv_val && value->bv_len >= 10 &&
5667 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5669 lutil_tm2time( &tm, &tt );
5670 tmp[0] = tt.tt_gsec & 0xff;
5671 tmp[4] = tt.tt_sec & 0xff;
5673 tmp[3] = tt.tt_sec & 0xff;
5675 tmp[2] = tt.tt_sec & 0xff;
5677 tmp[1] = tt.tt_sec & 0xff;
5679 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5680 ber_dupbv_x(keys, &bvtmp, ctx );
5681 keys[1].bv_val = NULL;
5689 return LDAP_SUCCESS;
5693 deliveryMethodValidate(
5695 struct berval *val )
5698 #define LENOF(s) (sizeof(s)-1)
5699 struct berval tmp = *val;
5701 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5702 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5703 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5706 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5708 switch( tmp.bv_val[0] ) {
5711 if(( tmp.bv_len >= LENOF("any") ) &&
5712 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5714 tmp.bv_len -= LENOF("any");
5715 tmp.bv_val += LENOF("any");
5718 return LDAP_INVALID_SYNTAX;
5722 if(( tmp.bv_len >= LENOF("mhs") ) &&
5723 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5725 tmp.bv_len -= LENOF("mhs");
5726 tmp.bv_val += LENOF("mhs");
5729 return LDAP_INVALID_SYNTAX;
5733 if(( tmp.bv_len >= LENOF("physical") ) &&
5734 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5736 tmp.bv_len -= LENOF("physical");
5737 tmp.bv_val += LENOF("physical");
5740 return LDAP_INVALID_SYNTAX;
5743 case 'T': /* telex or teletex or telephone */
5744 if(( tmp.bv_len >= LENOF("telex") ) &&
5745 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5747 tmp.bv_len -= LENOF("telex");
5748 tmp.bv_val += LENOF("telex");
5751 if(( tmp.bv_len >= LENOF("teletex") ) &&
5752 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5754 tmp.bv_len -= LENOF("teletex");
5755 tmp.bv_val += LENOF("teletex");
5758 if(( tmp.bv_len >= LENOF("telephone") ) &&
5759 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5761 tmp.bv_len -= LENOF("telephone");
5762 tmp.bv_val += LENOF("telephone");
5765 return LDAP_INVALID_SYNTAX;
5768 case 'G': /* g3fax or g4fax */
5769 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5770 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5771 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5773 tmp.bv_len -= LENOF("g3fax");
5774 tmp.bv_val += LENOF("g3fax");
5777 return LDAP_INVALID_SYNTAX;
5781 if(( tmp.bv_len >= LENOF("ia5") ) &&
5782 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5784 tmp.bv_len -= LENOF("ia5");
5785 tmp.bv_val += LENOF("ia5");
5788 return LDAP_INVALID_SYNTAX;
5792 if(( tmp.bv_len >= LENOF("videotex") ) &&
5793 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5795 tmp.bv_len -= LENOF("videotex");
5796 tmp.bv_val += LENOF("videotex");
5799 return LDAP_INVALID_SYNTAX;
5802 return LDAP_INVALID_SYNTAX;
5805 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5807 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5811 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5815 return LDAP_INVALID_SYNTAX;
5817 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5826 nisNetgroupTripleValidate(
5828 struct berval *val )
5833 if ( BER_BVISEMPTY( val ) ) {
5834 return LDAP_INVALID_SYNTAX;
5837 p = (char *)val->bv_val;
5838 e = p + val->bv_len;
5840 if ( *p != '(' /*')'*/ ) {
5841 return LDAP_INVALID_SYNTAX;
5844 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5848 return LDAP_INVALID_SYNTAX;
5851 } else if ( !AD_CHAR( *p ) ) {
5852 return LDAP_INVALID_SYNTAX;
5856 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5857 return LDAP_INVALID_SYNTAX;
5863 return LDAP_INVALID_SYNTAX;
5866 return LDAP_SUCCESS;
5870 bootParameterValidate(
5872 struct berval *val )
5876 if ( BER_BVISEMPTY( val ) ) {
5877 return LDAP_INVALID_SYNTAX;
5880 p = (char *)val->bv_val;
5881 e = p + val->bv_len;
5884 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5885 if ( !AD_CHAR( *p ) ) {
5886 return LDAP_INVALID_SYNTAX;
5891 return LDAP_INVALID_SYNTAX;
5895 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5896 if ( !AD_CHAR( *p ) ) {
5897 return LDAP_INVALID_SYNTAX;
5902 return LDAP_INVALID_SYNTAX;
5906 for ( p++; p < e; p++ ) {
5907 if ( !SLAP_PRINTABLE( *p ) ) {
5908 return LDAP_INVALID_SYNTAX;
5912 return LDAP_SUCCESS;
5916 firstComponentNormalize(
5921 struct berval *normalized,
5928 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5929 ber_dupbv_x( normalized, val, ctx );
5930 return LDAP_SUCCESS;
5933 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5935 if( ! ( val->bv_val[0] == '(' /*')'*/
5936 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5937 && ! ( val->bv_val[0] == '{' /*'}'*/
5938 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5940 return LDAP_INVALID_SYNTAX;
5943 /* trim leading white space */
5945 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5951 /* grab next word */
5952 comp.bv_val = &val->bv_val[len];
5953 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5954 for( comp.bv_len = 0;
5955 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5961 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5962 rc = numericoidValidate( NULL, &comp );
5963 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5964 rc = integerValidate( NULL, &comp );
5966 rc = LDAP_INVALID_SYNTAX;
5970 if( rc == LDAP_SUCCESS ) {
5971 ber_dupbv_x( normalized, &comp, ctx );
5977 static char *country_gen_syn[] = {
5978 "1.3.6.1.4.1.1466.115.121.1.15",
5979 "1.3.6.1.4.1.1466.115.121.1.26",
5980 "1.3.6.1.4.1.1466.115.121.1.44",
5984 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
5985 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
5987 static slap_syntax_defs_rec syntax_defs[] = {
5988 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
5989 X_BINARY X_NOT_H_R ")",
5990 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
5991 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
5992 0, NULL, NULL, NULL},
5993 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
5994 0, NULL, NULL, NULL},
5995 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
5997 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5998 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
6000 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6001 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
6002 0, NULL, bitStringValidate, NULL },
6003 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
6004 0, NULL, booleanValidate, NULL},
6005 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
6006 X_BINARY X_NOT_H_R ")",
6007 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6008 NULL, certificateValidate, NULL},
6009 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
6010 X_BINARY X_NOT_H_R ")",
6011 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6012 NULL, certificateListValidate, NULL},
6013 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
6014 X_BINARY X_NOT_H_R ")",
6015 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6016 NULL, sequenceValidate, NULL},
6017 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
6018 X_BINARY X_NOT_H_R ")",
6019 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
6020 NULL, attributeCertificateValidate, NULL},
6021 #if 0 /* need to go __after__ printableString */
6022 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6023 0, "1.3.6.1.4.1.1466.115.121.1.44",
6024 countryStringValidate, NULL},
6026 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6027 0, NULL, dnValidate, dnPretty},
6028 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6029 0, NULL, rdnValidate, rdnPretty},
6030 #ifdef LDAP_COMP_MATCH
6031 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6032 0, NULL, allComponentsValidate, NULL},
6033 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6034 0, NULL, componentFilterValidate, NULL},
6036 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6037 0, NULL, NULL, NULL},
6038 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6039 0, NULL, deliveryMethodValidate, NULL},
6040 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6041 0, NULL, UTF8StringValidate, NULL},
6042 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6043 0, NULL, NULL, NULL},
6044 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6045 0, NULL, NULL, NULL},
6046 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6047 0, NULL, NULL, NULL},
6048 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6049 0, NULL, NULL, NULL},
6050 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6051 0, NULL, NULL, NULL},
6052 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6053 0, NULL, printablesStringValidate, NULL},
6054 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6055 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6056 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6057 0, NULL, generalizedTimeValidate, NULL},
6058 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6059 0, NULL, NULL, NULL},
6060 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6061 0, NULL, IA5StringValidate, NULL},
6062 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6063 0, NULL, integerValidate, NULL},
6064 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6065 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6066 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6067 0, NULL, NULL, NULL},
6068 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6069 0, NULL, NULL, NULL},
6070 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6071 0, NULL, NULL, NULL},
6072 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6073 0, NULL, NULL, NULL},
6074 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6075 0, NULL, NULL, NULL},
6076 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6077 0, NULL, nameUIDValidate, nameUIDPretty },
6078 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6079 0, NULL, NULL, NULL},
6080 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6081 0, NULL, numericStringValidate, NULL},
6082 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6083 0, NULL, NULL, NULL},
6084 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6085 0, NULL, numericoidValidate, NULL},
6086 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6087 0, NULL, IA5StringValidate, NULL},
6088 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6089 0, NULL, blobValidate, NULL},
6090 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6091 0, NULL, postalAddressValidate, NULL},
6092 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6093 0, NULL, NULL, NULL},
6094 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6095 0, NULL, NULL, NULL},
6096 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6097 0, NULL, printableStringValidate, NULL},
6098 /* moved here because now depends on Directory String, IA5 String
6099 * and Printable String */
6100 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6101 0, country_gen_syn, countryStringValidate, NULL},
6102 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6103 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6104 0, NULL, subtreeSpecificationValidate, NULL},
6105 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6106 X_BINARY X_NOT_H_R ")",
6107 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6108 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6109 0, NULL, printableStringValidate, NULL},
6110 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6111 0, NULL, NULL, NULL},
6112 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6113 0, NULL, printablesStringValidate, NULL},
6114 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6115 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6116 0, NULL, utcTimeValidate, NULL},
6118 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6119 0, NULL, NULL, NULL},
6120 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6121 0, NULL, NULL, NULL},
6122 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6123 0, NULL, NULL, NULL},
6124 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6125 0, NULL, NULL, NULL},
6126 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6127 0, NULL, NULL, NULL},
6129 /* RFC 2307 NIS Syntaxes */
6130 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6131 0, NULL, nisNetgroupTripleValidate, NULL},
6132 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6133 0, NULL, bootParameterValidate, NULL},
6135 /* draft-zeilenga-ldap-x509 */
6136 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6137 SLAP_SYNTAX_HIDE, NULL,
6138 serialNumberAndIssuerValidate,
6139 serialNumberAndIssuerPretty},
6140 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6141 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6142 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6143 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6144 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6145 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6146 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6147 SLAP_SYNTAX_HIDE, NULL,
6148 issuerAndThisUpdateValidate,
6149 issuerAndThisUpdatePretty},
6150 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6151 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6152 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6153 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6154 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6155 SLAP_SYNTAX_HIDE, NULL,
6156 serialNumberAndIssuerSerialValidate,
6157 serialNumberAndIssuerSerialPretty},
6158 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6159 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6161 #ifdef SLAPD_AUTHPASSWD
6162 /* needs updating */
6163 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6164 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6167 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6168 0, NULL, UUIDValidate, UUIDPretty},
6170 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6171 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6173 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6174 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6176 /* OpenLDAP Void Syntax */
6177 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6178 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6180 /* FIXME: OID is unused, but not registered yet */
6181 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6182 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6184 {NULL, 0, NULL, NULL, NULL}
6187 char *csnSIDMatchSyntaxes[] = {
6188 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6191 char *certificateExactMatchSyntaxes[] = {
6192 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6195 char *certificateListExactMatchSyntaxes[] = {
6196 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6199 char *attributeCertificateExactMatchSyntaxes[] = {
6200 attributeCertificateSyntaxOID /* attributeCertificate */,
6204 #ifdef LDAP_COMP_MATCH
6205 char *componentFilterMatchSyntaxes[] = {
6206 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6207 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6208 attributeCertificateSyntaxOID /* attributeCertificate */,
6213 char *directoryStringSyntaxes[] = {
6214 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6217 char *integerFirstComponentMatchSyntaxes[] = {
6218 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6219 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6222 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6223 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6224 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6225 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6226 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6227 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6228 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6229 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6230 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6235 * Other matching rules in X.520 that we do not use (yet):
6237 * 2.5.13.25 uTCTimeMatch
6238 * 2.5.13.26 uTCTimeOrderingMatch
6239 * 2.5.13.31* directoryStringFirstComponentMatch
6240 * 2.5.13.32* wordMatch
6241 * 2.5.13.33* keywordMatch
6242 * 2.5.13.36+ certificatePairExactMatch
6243 * 2.5.13.37+ certificatePairMatch
6244 * 2.5.13.40+ algorithmIdentifierMatch
6245 * 2.5.13.41* storedPrefixMatch
6246 * 2.5.13.42 attributeCertificateMatch
6247 * 2.5.13.43 readerAndKeyIDMatch
6248 * 2.5.13.44 attributeIntegrityMatch
6250 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6251 * (+) described in draft-zeilenga-ldap-x509
6253 static slap_mrule_defs_rec mrule_defs[] = {
6255 * EQUALITY matching rules must be listed after associated APPROX
6256 * matching rules. So, we list all APPROX matching rules first.
6258 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6259 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6260 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6261 NULL, NULL, directoryStringApproxMatch,
6262 directoryStringApproxIndexer, directoryStringApproxFilter,
6265 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6266 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6267 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6268 NULL, NULL, IA5StringApproxMatch,
6269 IA5StringApproxIndexer, IA5StringApproxFilter,
6273 * Other matching rules
6276 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6277 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6278 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6279 NULL, NULL, octetStringMatch,
6280 octetStringIndexer, octetStringFilter,
6283 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6284 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6285 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6286 NULL, dnNormalize, dnMatch,
6287 octetStringIndexer, octetStringFilter,
6290 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6291 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6292 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6293 NULL, dnNormalize, dnRelativeMatch,
6297 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6298 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6299 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6300 NULL, dnNormalize, dnRelativeMatch,
6304 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6305 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6306 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6307 NULL, dnNormalize, dnRelativeMatch,
6311 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6312 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6313 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6314 NULL, dnNormalize, dnRelativeMatch,
6318 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6319 "SYNTAX 1.2.36.79672281.1.5.0 )",
6320 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6321 NULL, rdnNormalize, rdnMatch,
6322 octetStringIndexer, octetStringFilter,
6325 #ifdef LDAP_COMP_MATCH
6326 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6327 "SYNTAX 1.2.36.79672281.1.5.2 )",
6328 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6329 NULL, NULL , componentFilterMatch,
6330 octetStringIndexer, octetStringFilter,
6333 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6334 "SYNTAX 1.2.36.79672281.1.5.3 )",
6335 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6336 NULL, NULL , allComponentsMatch,
6337 octetStringIndexer, octetStringFilter,
6340 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6341 "SYNTAX 1.2.36.79672281.1.5.3 )",
6342 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6343 NULL, NULL , directoryComponentsMatch,
6344 octetStringIndexer, octetStringFilter,
6348 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6349 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6350 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6351 NULL, UTF8StringNormalize, octetStringMatch,
6352 octetStringIndexer, octetStringFilter,
6353 directoryStringApproxMatchOID },
6355 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6356 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6357 SLAP_MR_ORDERING, directoryStringSyntaxes,
6358 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6360 "caseIgnoreMatch" },
6362 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6363 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6364 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6365 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6366 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6367 "caseIgnoreMatch" },
6369 {"( 2.5.13.5 NAME 'caseExactMatch' "
6370 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6371 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6372 NULL, UTF8StringNormalize, octetStringMatch,
6373 octetStringIndexer, octetStringFilter,
6374 directoryStringApproxMatchOID },
6376 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6377 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6378 SLAP_MR_ORDERING, directoryStringSyntaxes,
6379 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6383 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6384 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6385 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6386 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6387 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6390 {"( 2.5.13.8 NAME 'numericStringMatch' "
6391 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6392 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6393 NULL, numericStringNormalize, octetStringMatch,
6394 octetStringIndexer, octetStringFilter,
6397 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6398 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6399 SLAP_MR_ORDERING, NULL,
6400 NULL, numericStringNormalize, octetStringOrderingMatch,
6402 "numericStringMatch" },
6404 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6405 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6406 SLAP_MR_SUBSTR, NULL,
6407 NULL, numericStringNormalize, octetStringSubstringsMatch,
6408 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6409 "numericStringMatch" },
6411 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6412 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6413 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6414 NULL, postalAddressNormalize, octetStringMatch,
6415 octetStringIndexer, octetStringFilter,
6418 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6419 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6420 SLAP_MR_SUBSTR, NULL,
6421 NULL, NULL, NULL, NULL, NULL,
6422 "caseIgnoreListMatch" },
6424 {"( 2.5.13.13 NAME 'booleanMatch' "
6425 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6426 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6427 NULL, NULL, booleanMatch,
6428 octetStringIndexer, octetStringFilter,
6431 {"( 2.5.13.14 NAME 'integerMatch' "
6432 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6433 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6434 NULL, NULL, integerMatch,
6435 integerIndexer, integerFilter,
6438 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6439 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6440 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6441 NULL, NULL, integerMatch,
6445 {"( 2.5.13.16 NAME 'bitStringMatch' "
6446 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6447 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6448 NULL, NULL, octetStringMatch,
6449 octetStringIndexer, octetStringFilter,
6452 {"( 2.5.13.17 NAME 'octetStringMatch' "
6453 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6454 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6455 NULL, NULL, octetStringMatch,
6456 octetStringIndexer, octetStringFilter,
6459 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6460 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6461 SLAP_MR_ORDERING, NULL,
6462 NULL, NULL, octetStringOrderingMatch,
6464 "octetStringMatch" },
6466 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6468 SLAP_MR_SUBSTR, NULL,
6469 NULL, NULL, octetStringSubstringsMatch,
6470 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6471 "octetStringMatch" },
6473 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6475 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6477 telephoneNumberNormalize, octetStringMatch,
6478 octetStringIndexer, octetStringFilter,
6481 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6482 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6483 SLAP_MR_SUBSTR, NULL,
6484 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6485 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6486 "telephoneNumberMatch" },
6488 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6489 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6490 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6491 NULL, NULL, NULL, NULL, NULL, NULL },
6493 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6495 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6496 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6497 uniqueMemberIndexer, uniqueMemberFilter,
6500 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6501 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6502 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6503 NULL, NULL, NULL, NULL, NULL, NULL },
6505 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6507 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6508 NULL, generalizedTimeNormalize, octetStringMatch,
6509 generalizedTimeIndexer, generalizedTimeFilter,
6512 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6514 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6515 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6517 "generalizedTimeMatch" },
6519 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6520 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6521 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6522 integerFirstComponentMatchSyntaxes,
6523 NULL, firstComponentNormalize, integerMatch,
6524 octetStringIndexer, octetStringFilter,
6527 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6528 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6529 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6530 objectIdentifierFirstComponentMatchSyntaxes,
6531 NULL, firstComponentNormalize, octetStringMatch,
6532 octetStringIndexer, octetStringFilter,
6535 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6536 "SYNTAX 1.3.6.1.1.15.1 )",
6537 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6538 NULL, certificateExactNormalize, octetStringMatch,
6539 octetStringIndexer, octetStringFilter,
6542 {"( 2.5.13.35 NAME 'certificateMatch' "
6543 "SYNTAX 1.3.6.1.1.15.2 )",
6544 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6545 NULL, NULL, NULL, NULL, NULL,
6548 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6549 "SYNTAX 1.3.6.1.1.15.5 )",
6550 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6551 NULL, certificateListExactNormalize, octetStringMatch,
6552 octetStringIndexer, octetStringFilter,
6555 {"( 2.5.13.39 NAME 'certificateListMatch' "
6556 "SYNTAX 1.3.6.1.1.15.6 )",
6557 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6558 NULL, NULL, NULL, NULL, NULL,
6561 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6562 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6563 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6564 NULL, attributeCertificateExactNormalize, octetStringMatch,
6565 octetStringIndexer, octetStringFilter,
6568 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6569 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6570 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6571 NULL, NULL, NULL, NULL, NULL,
6574 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6575 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6576 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6577 NULL, IA5StringNormalize, octetStringMatch,
6578 octetStringIndexer, octetStringFilter,
6579 IA5StringApproxMatchOID },
6581 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6582 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6583 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6584 NULL, IA5StringNormalize, octetStringMatch,
6585 octetStringIndexer, octetStringFilter,
6586 IA5StringApproxMatchOID },
6588 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6589 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6590 SLAP_MR_SUBSTR, NULL,
6591 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6592 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6593 "caseIgnoreIA5Match" },
6595 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6596 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6597 SLAP_MR_SUBSTR, NULL,
6598 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6599 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6600 "caseExactIA5Match" },
6602 #ifdef SLAPD_AUTHPASSWD
6603 /* needs updating */
6604 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6605 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6606 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6607 NULL, NULL, authPasswordMatch,
6612 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6613 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6615 NULL, NULL, integerBitAndMatch,
6619 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6622 NULL, NULL, integerBitOrMatch,
6626 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6627 "SYNTAX 1.3.6.1.1.16.1 )",
6628 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6629 NULL, UUIDNormalize, octetStringMatch,
6630 octetStringIndexer, octetStringFilter,
6633 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6634 "SYNTAX 1.3.6.1.1.16.1 )",
6635 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6636 NULL, UUIDNormalize, octetStringOrderingMatch,
6637 octetStringIndexer, octetStringFilter,
6640 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6641 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6642 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6643 NULL, csnNormalize, csnMatch,
6644 csnIndexer, csnFilter,
6647 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6648 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6649 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6650 NULL, NULL, csnOrderingMatch,
6654 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6655 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6656 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6657 NULL, csnSidNormalize, octetStringMatch,
6658 octetStringIndexer, octetStringFilter,
6661 /* FIXME: OID is unused, but not registered yet */
6662 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6663 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6664 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6665 NULL, authzNormalize, authzMatch,
6669 {NULL, SLAP_MR_NONE, NULL,
6670 NULL, NULL, NULL, NULL, NULL,
6675 slap_schema_init( void )
6680 /* we should only be called once (from main) */
6681 assert( schema_init_done == 0 );
6683 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6684 res = register_syntax( &syntax_defs[i] );
6687 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6688 syntax_defs[i].sd_desc );
6693 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6694 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6695 mrule_defs[i].mrd_compat_syntaxes == NULL )
6698 "slap_schema_init: Ignoring unusable matching rule %s\n",
6699 mrule_defs[i].mrd_desc );
6703 res = register_matching_rule( &mrule_defs[i] );
6707 "slap_schema_init: Error registering matching rule %s\n",
6708 mrule_defs[i].mrd_desc );
6713 res = slap_schema_load();
6714 schema_init_done = 1;
6719 schema_destroy( void )
6728 if( schema_init_done ) {
6729 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6730 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );