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 ("'")
1109 * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to
1110 * be escaped except when at the beginning of a value, the
1111 * definition of Name and Optional UID appears to be flawed,
1112 * because there is no clear means to determine whether the
1113 * UID part is present or not.
1117 * cn=Someone,dc=example,dc=com#'1'B
1119 * could be either a NameAndOptionalUID with trailing UID, i.e.
1121 * DN = "cn=Someone,dc=example,dc=com"
1124 * or a NameAndOptionalUID with no trailing UID, and the AVA
1125 * in the last RDN made of
1127 * attributeType = dc
1128 * attributeValue = com#'1'B
1130 * in fact "com#'1'B" is a valid IA5 string.
1132 * As a consequence, current slapd code takes the presence of
1133 * #<valid BitString> at the end of the string representation
1134 * of a NameAndOptionalUID to mean this is indeed a BitString.
1135 * This is quite arbitrary - it has changed the past and might
1136 * change in the future.
1146 struct berval dn, uid;
1148 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
1150 ber_dupbv( &dn, in );
1151 if( !dn.bv_val ) return LDAP_OTHER;
1153 /* if there's a "#", try bitStringValidate()... */
1154 uid.bv_val = strrchr( dn.bv_val, '#' );
1155 if ( !BER_BVISNULL( &uid ) ) {
1157 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
1159 rc = bitStringValidate( NULL, &uid );
1160 if ( rc == LDAP_SUCCESS ) {
1161 /* in case of success, trim the UID,
1162 * otherwise treat it as part of the DN */
1163 dn.bv_len -= uid.bv_len + 1;
1164 uid.bv_val[-1] = '\0';
1168 rc = dnValidate( NULL, &dn );
1170 ber_memfree( dn.bv_val );
1181 assert( val != NULL );
1182 assert( out != NULL );
1185 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
1187 if( BER_BVISEMPTY( val ) ) {
1188 ber_dupbv_x( out, val, ctx );
1190 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
1191 return LDAP_INVALID_SYNTAX;
1195 struct berval dnval = *val;
1196 struct berval uidval = BER_BVNULL;
1198 uidval.bv_val = strrchr( val->bv_val, '#' );
1199 if ( !BER_BVISNULL( &uidval ) ) {
1201 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
1203 rc = bitStringValidate( NULL, &uidval );
1205 if ( rc == LDAP_SUCCESS ) {
1206 ber_dupbv_x( &dnval, val, ctx );
1208 dnval.bv_len -= ++uidval.bv_len;
1209 dnval.bv_val[dnval.bv_len] = '\0';
1212 BER_BVZERO( &uidval );
1216 rc = dnPretty( syntax, &dnval, out, ctx );
1217 if ( dnval.bv_val != val->bv_val ) {
1218 slap_sl_free( dnval.bv_val, ctx );
1220 if( rc != LDAP_SUCCESS ) {
1224 if( !BER_BVISNULL( &uidval ) ) {
1227 tmp = slap_sl_realloc( out->bv_val, out->bv_len
1228 + uidval.bv_len + 1,
1231 ber_memfree_x( out->bv_val, ctx );
1235 memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
1236 out->bv_len += uidval.bv_len;
1237 out->bv_val[out->bv_len] = '\0';
1241 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1243 return LDAP_SUCCESS;
1247 uniqueMemberNormalize(
1252 struct berval *normalized,
1258 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
1260 ber_dupbv_x( &out, val, ctx );
1261 if ( BER_BVISEMPTY( &out ) ) {
1265 struct berval uid = BER_BVNULL;
1267 uid.bv_val = strrchr( out.bv_val, '#' );
1268 if ( !BER_BVISNULL( &uid ) ) {
1270 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1272 rc = bitStringValidate( NULL, &uid );
1273 if ( rc == LDAP_SUCCESS ) {
1274 uid.bv_val[-1] = '\0';
1275 out.bv_len -= uid.bv_len + 1;
1281 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1283 if( rc != LDAP_SUCCESS ) {
1284 slap_sl_free( out.bv_val, ctx );
1285 return LDAP_INVALID_SYNTAX;
1288 if( !BER_BVISNULL( &uid ) ) {
1291 tmp = ch_realloc( normalized->bv_val,
1292 normalized->bv_len + uid.bv_len
1293 + STRLENOF("#") + 1 );
1294 if ( tmp == NULL ) {
1295 ber_memfree_x( normalized->bv_val, ctx );
1299 normalized->bv_val = tmp;
1301 /* insert the separator */
1302 normalized->bv_val[normalized->bv_len++] = '#';
1304 /* append the UID */
1305 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1306 uid.bv_val, uid.bv_len );
1307 normalized->bv_len += uid.bv_len;
1310 normalized->bv_val[normalized->bv_len] = '\0';
1313 slap_sl_free( out.bv_val, ctx );
1316 return LDAP_SUCCESS;
1325 struct berval *value,
1326 void *assertedValue )
1329 struct berval *asserted = (struct berval *) assertedValue;
1330 struct berval assertedDN = *asserted;
1331 struct berval assertedUID = BER_BVNULL;
1332 struct berval valueDN = *value;
1333 struct berval valueUID = BER_BVNULL;
1334 int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
1336 if ( !BER_BVISEMPTY( asserted ) ) {
1337 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1338 if ( !BER_BVISNULL( &assertedUID ) ) {
1339 assertedUID.bv_val++;
1340 assertedUID.bv_len = assertedDN.bv_len
1341 - ( assertedUID.bv_val - assertedDN.bv_val );
1343 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1344 assertedDN.bv_len -= assertedUID.bv_len + 1;
1347 BER_BVZERO( &assertedUID );
1352 if ( !BER_BVISEMPTY( value ) ) {
1354 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1355 if ( !BER_BVISNULL( &valueUID ) ) {
1357 valueUID.bv_len = valueDN.bv_len
1358 - ( valueUID.bv_val - valueDN.bv_val );
1360 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1361 valueDN.bv_len -= valueUID.bv_len + 1;
1364 BER_BVZERO( &valueUID );
1369 if( valueUID.bv_len && assertedUID.bv_len ) {
1370 match = valueUID.bv_len - assertedUID.bv_len;
1373 return LDAP_SUCCESS;
1376 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1379 return LDAP_SUCCESS;
1382 } else if ( !approx && valueUID.bv_len ) {
1385 return LDAP_SUCCESS;
1387 } else if ( !approx && assertedUID.bv_len ) {
1390 return LDAP_SUCCESS;
1393 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1397 uniqueMemberIndexer(
1402 struct berval *prefix,
1410 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1411 /* just count them */
1415 dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
1417 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
1418 struct berval assertedDN = values[i];
1419 struct berval assertedUID = BER_BVNULL;
1421 if ( !BER_BVISEMPTY( &assertedDN ) ) {
1422 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1423 if ( !BER_BVISNULL( &assertedUID ) ) {
1424 assertedUID.bv_val++;
1425 assertedUID.bv_len = assertedDN.bv_len
1426 - ( assertedUID.bv_val - assertedDN.bv_val );
1428 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1429 assertedDN.bv_len -= assertedUID.bv_len + 1;
1432 BER_BVZERO( &assertedUID );
1437 dnvalues[i] = assertedDN;
1439 BER_BVZERO( &dnvalues[i] );
1441 rc = octetStringIndexer( use, flags, syntax, mr, prefix,
1442 dnvalues, keysp, ctx );
1444 slap_sl_free( dnvalues, ctx );
1454 struct berval *prefix,
1455 void * assertedValue,
1459 struct berval *asserted = (struct berval *) assertedValue;
1460 struct berval assertedDN = *asserted;
1461 struct berval assertedUID = BER_BVNULL;
1463 if ( !BER_BVISEMPTY( asserted ) ) {
1464 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1465 if ( !BER_BVISNULL( &assertedUID ) ) {
1466 assertedUID.bv_val++;
1467 assertedUID.bv_len = assertedDN.bv_len
1468 - ( assertedUID.bv_val - assertedDN.bv_val );
1470 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1471 assertedDN.bv_len -= assertedUID.bv_len + 1;
1474 BER_BVZERO( &assertedUID );
1479 return octetStringFilter( use, flags, syntax, mr, prefix,
1480 &assertedDN, keysp, ctx );
1485 * Handling boolean syntax and matching is quite rigid.
1486 * A more flexible approach would be to allow a variety
1487 * of strings to be normalized and prettied into TRUE
1495 /* very unforgiving validation, requires no normalization
1496 * before simplistic matching
1499 if( in->bv_len == 4 ) {
1500 if( bvmatch( in, &slap_true_bv ) ) {
1501 return LDAP_SUCCESS;
1503 } else if( in->bv_len == 5 ) {
1504 if( bvmatch( in, &slap_false_bv ) ) {
1505 return LDAP_SUCCESS;
1509 return LDAP_INVALID_SYNTAX;
1518 struct berval *value,
1519 void *assertedValue )
1521 /* simplistic matching allowed by rigid validation */
1522 struct berval *asserted = (struct berval *) assertedValue;
1523 *matchp = value->bv_len != asserted->bv_len;
1524 return LDAP_SUCCESS;
1527 /*-------------------------------------------------------------------
1528 LDAP/X.500 string syntax / matching rules have a few oddities. This
1529 comment attempts to detail how slapd(8) treats them.
1532 StringSyntax X.500 LDAP Matching/Comments
1533 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1534 PrintableString subset subset i/e + ignore insignificant spaces
1535 PrintableString subset subset i/e + ignore insignificant spaces
1536 NumericString subset subset ignore all spaces
1537 IA5String ASCII ASCII i/e + ignore insignificant spaces
1538 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1540 TelephoneNumber subset subset i + ignore all spaces and "-"
1542 See RFC 4518 for details.
1546 In X.500(93), a directory string can be either a PrintableString,
1547 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1548 In later versions, more CHOICEs were added. In all cases the string
1551 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1552 A directory string cannot be zero length.
1554 For matching, there are both case ignore and exact rules. Both
1555 also require that "insignificant" spaces be ignored.
1556 spaces before the first non-space are ignored;
1557 spaces after the last non-space are ignored;
1558 spaces after a space are ignored.
1559 Note: by these rules (and as clarified in X.520), a string of only
1560 spaces is to be treated as if held one space, not empty (which
1561 would be a syntax error).
1564 In ASN.1, numeric string is just a string of digits and spaces
1565 and could be empty. However, in X.500, all attribute values of
1566 numeric string carry a non-empty constraint. For example:
1568 internationalISDNNumber ATTRIBUTE ::= {
1569 WITH SYNTAX InternationalISDNNumber
1570 EQUALITY MATCHING RULE numericStringMatch
1571 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1572 ID id-at-internationalISDNNumber }
1573 InternationalISDNNumber ::=
1574 NumericString (SIZE(1..ub-international-isdn-number))
1576 Unforunately, some assertion values are don't carry the same
1577 constraint (but its unclear how such an assertion could ever
1578 be true). In LDAP, there is one syntax (numericString) not two
1579 (numericString with constraint, numericString without constraint).
1580 This should be treated as numericString with non-empty constraint.
1581 Note that while someone may have no ISDN number, there are no ISDN
1582 numbers which are zero length.
1584 In matching, spaces are ignored.
1587 In ASN.1, Printable string is just a string of printable characters
1588 and can be empty. In X.500, semantics much like NumericString (see
1589 serialNumber for a like example) excepting uses insignificant space
1590 handling instead of ignore all spaces. They must be non-empty.
1593 Basically same as PrintableString. There are no examples in X.500,
1594 but same logic applies. Empty strings are allowed.
1596 -------------------------------------------------------------------*/
1605 unsigned char *u = (unsigned char *)in->bv_val;
1607 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1608 /* directory strings cannot be empty */
1609 return LDAP_INVALID_SYNTAX;
1612 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1613 /* get the length indicated by the first byte */
1614 len = LDAP_UTF8_CHARLEN2( u, len );
1616 /* very basic checks */
1619 if( (u[5] & 0xC0) != 0x80 ) {
1620 return LDAP_INVALID_SYNTAX;
1623 if( (u[4] & 0xC0) != 0x80 ) {
1624 return LDAP_INVALID_SYNTAX;
1627 if( (u[3] & 0xC0) != 0x80 ) {
1628 return LDAP_INVALID_SYNTAX;
1631 if( (u[2] & 0xC0 )!= 0x80 ) {
1632 return LDAP_INVALID_SYNTAX;
1635 if( (u[1] & 0xC0) != 0x80 ) {
1636 return LDAP_INVALID_SYNTAX;
1639 /* CHARLEN already validated it */
1642 return LDAP_INVALID_SYNTAX;
1645 /* make sure len corresponds with the offset
1646 to the next character */
1647 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1651 return LDAP_INVALID_SYNTAX;
1654 return LDAP_SUCCESS;
1658 UTF8StringNormalize(
1663 struct berval *normalized,
1666 struct berval tmp, nvalue;
1667 int flags, wasspace;
1670 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
1672 if( BER_BVISNULL( val ) ) {
1673 /* assume we're dealing with a syntax (e.g., UTF8String)
1674 * which allows empty strings
1676 BER_BVZERO( normalized );
1677 return LDAP_SUCCESS;
1680 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1681 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1682 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1683 ? LDAP_UTF8_APPROX : 0;
1685 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1690 /* collapse spaces (in place) */
1692 nvalue.bv_val = tmp.bv_val;
1694 /* trim leading spaces? */
1695 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1696 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1698 for( i = 0; i < tmp.bv_len; i++) {
1699 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1700 if( wasspace++ == 0 ) {
1701 /* trim repeated spaces */
1702 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1706 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1710 if( !BER_BVISEMPTY( &nvalue ) ) {
1711 /* trim trailing space? */
1713 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1714 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1718 nvalue.bv_val[nvalue.bv_len] = '\0';
1721 /* string of all spaces is treated as one space */
1722 nvalue.bv_val[0] = ' ';
1723 nvalue.bv_val[1] = '\0';
1727 *normalized = nvalue;
1728 return LDAP_SUCCESS;
1732 directoryStringSubstringsMatch(
1737 struct berval *value,
1738 void *assertedValue )
1741 SubstringsAssertion *sub = assertedValue;
1742 struct berval left = *value;
1746 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1747 if ( sub->sa_initial.bv_len > left.bv_len ) {
1748 /* not enough left */
1753 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1754 sub->sa_initial.bv_len );
1760 left.bv_val += sub->sa_initial.bv_len;
1761 left.bv_len -= sub->sa_initial.bv_len;
1763 priorspace = ASCII_SPACE(
1764 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1767 if ( sub->sa_any ) {
1768 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1772 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1773 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1775 /* allow next space to match */
1782 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1786 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1787 /* not enough left */
1792 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1799 idx = p - left.bv_val;
1801 if ( idx >= left.bv_len ) {
1802 /* this shouldn't happen */
1809 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1810 /* not enough left */
1815 match = memcmp( left.bv_val,
1816 sub->sa_any[i].bv_val,
1817 sub->sa_any[i].bv_len );
1825 left.bv_val += sub->sa_any[i].bv_len;
1826 left.bv_len -= sub->sa_any[i].bv_len;
1828 priorspace = ASCII_SPACE(
1829 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1833 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1834 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1835 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1837 /* allow next space to match */
1842 if ( sub->sa_final.bv_len > left.bv_len ) {
1843 /* not enough left */
1848 match = memcmp( sub->sa_final.bv_val,
1849 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1850 sub->sa_final.bv_len );
1859 return LDAP_SUCCESS;
1862 #if defined(SLAPD_APPROX_INITIALS)
1863 # define SLAPD_APPROX_DELIMITER "._ "
1864 # define SLAPD_APPROX_WORDLEN 2
1866 # define SLAPD_APPROX_DELIMITER " "
1867 # define SLAPD_APPROX_WORDLEN 1
1876 struct berval *value,
1877 void *assertedValue )
1879 struct berval *nval, *assertv;
1880 char *val, **values, **words, *c;
1881 int i, count, len, nextchunk=0, nextavail=0;
1883 /* Yes, this is necessary */
1884 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1885 if( nval == NULL ) {
1887 return LDAP_SUCCESS;
1890 /* Yes, this is necessary */
1891 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1892 NULL, LDAP_UTF8_APPROX, NULL );
1893 if( assertv == NULL ) {
1896 return LDAP_SUCCESS;
1899 /* Isolate how many words there are */
1900 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1901 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1902 if ( c == NULL ) break;
1907 /* Get a phonetic copy of each word */
1908 words = (char **)ch_malloc( count * sizeof(char *) );
1909 values = (char **)ch_malloc( count * sizeof(char *) );
1910 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1912 values[i] = phonetic(c);
1915 /* Work through the asserted value's words, to see if at least some
1916 * of the words are there, in the same order. */
1918 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1919 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1924 #if defined(SLAPD_APPROX_INITIALS)
1925 else if( len == 1 ) {
1926 /* Single letter words need to at least match one word's initial */
1927 for( i=nextavail; i<count; i++ )
1928 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1935 /* Isolate the next word in the asserted value and phonetic it */
1936 assertv->bv_val[nextchunk+len] = '\0';
1937 val = phonetic( assertv->bv_val + nextchunk );
1939 /* See if this phonetic chunk is in the remaining words of *value */
1940 for( i=nextavail; i<count; i++ ){
1941 if( !strcmp( val, values[i] ) ){
1949 /* This chunk in the asserted value was NOT within the *value. */
1955 /* Go on to the next word in the asserted value */
1959 /* If some of the words were seen, call it a match */
1960 if( nextavail > 0 ) {
1967 /* Cleanup allocs */
1968 ber_bvfree( assertv );
1969 for( i=0; i<count; i++ ) {
1970 ch_free( values[i] );
1976 return LDAP_SUCCESS;
1985 struct berval *prefix,
1991 int i,j, len, wordcount, keycount=0;
1992 struct berval *newkeys;
1993 BerVarray keys=NULL;
1995 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1996 struct berval val = BER_BVNULL;
1997 /* Yes, this is necessary */
1998 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1999 assert( !BER_BVISNULL( &val ) );
2001 /* Isolate how many words there are. There will be a key for each */
2002 for( wordcount = 0, c = val.bv_val; *c; c++) {
2003 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2004 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
2006 if (*c == '\0') break;
2010 /* Allocate/increase storage to account for new keys */
2011 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
2012 * sizeof(struct berval) );
2013 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
2014 if( keys ) ch_free( keys );
2017 /* Get a phonetic copy of each word */
2018 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
2020 if( len < SLAPD_APPROX_WORDLEN ) continue;
2021 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
2026 ber_memfree( val.bv_val );
2028 BER_BVZERO( &keys[keycount] );
2031 return LDAP_SUCCESS;
2040 struct berval *prefix,
2041 void * assertedValue,
2050 /* Yes, this is necessary */
2051 val = UTF8bvnormalize( ((struct berval *)assertedValue),
2052 NULL, LDAP_UTF8_APPROX, NULL );
2053 if( val == NULL || BER_BVISNULL( val ) ) {
2054 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
2055 BER_BVZERO( &keys[0] );
2058 return LDAP_SUCCESS;
2061 /* Isolate how many words there are. There will be a key for each */
2062 for( count = 0,c = val->bv_val; *c; c++) {
2063 len = strcspn(c, SLAPD_APPROX_DELIMITER);
2064 if( len >= SLAPD_APPROX_WORDLEN ) count++;
2066 if (*c == '\0') break;
2070 /* Allocate storage for new keys */
2071 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
2073 /* Get a phonetic copy of each word */
2074 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
2076 if( len < SLAPD_APPROX_WORDLEN ) continue;
2077 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
2083 BER_BVZERO( &keys[count] );
2086 return LDAP_SUCCESS;
2089 /* Remove all spaces and '-' characters */
2091 telephoneNumberNormalize(
2096 struct berval *normalized,
2101 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
2103 /* validator should have refused an empty string */
2104 assert( !BER_BVISEMPTY( val ) );
2106 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2108 for( p = val->bv_val; *p; p++ ) {
2109 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
2115 normalized->bv_len = q - normalized->bv_val;
2117 if( BER_BVISEMPTY( normalized ) ) {
2118 slap_sl_free( normalized->bv_val, ctx );
2119 BER_BVZERO( normalized );
2120 return LDAP_INVALID_SYNTAX;
2123 return LDAP_SUCCESS;
2127 postalAddressValidate(
2131 struct berval bv = *in;
2134 for ( c = 0; c < in->bv_len; c++ ) {
2135 if ( in->bv_val[c] == '\\' ) {
2137 if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
2138 && strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
2140 return LDAP_INVALID_SYNTAX;
2145 if ( in->bv_val[c] == '$' ) {
2146 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2147 if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
2148 return LDAP_INVALID_SYNTAX;
2150 bv.bv_val = &in->bv_val[c] + 1;
2154 bv.bv_len = &in->bv_val[c] - bv.bv_val;
2155 return UTF8StringValidate( NULL, &bv );
2159 postalAddressNormalize(
2164 struct berval *normalized,
2167 BerVarray lines = NULL, nlines = NULL;
2169 int rc = LDAP_SUCCESS;
2170 MatchingRule *xmr = NULL;
2173 if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
2174 xmr = slap_schema.si_mr_caseIgnoreMatch;
2177 xmr = slap_schema.si_mr_caseExactMatch;
2180 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2181 if ( val->bv_val[c] == '$' ) {
2186 lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
2187 nlines = &lines[l + 2];
2189 lines[0].bv_val = val->bv_val;
2190 for ( l = 0, c = 0; c < val->bv_len; c++ ) {
2191 if ( val->bv_val[c] == '$' ) {
2192 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2194 lines[l].bv_val = &val->bv_val[c + 1];
2197 lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
2199 normalized->bv_len = l;
2201 for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
2202 /* NOTE: we directly normalize each line,
2203 * without unescaping the values, since the special
2204 * values '\24' ('$') and '\5C' ('\') are not affected
2205 * by normalization */
2206 rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
2207 if ( rc != LDAP_SUCCESS ) {
2208 rc = LDAP_INVALID_SYNTAX;
2212 normalized->bv_len += nlines[l].bv_len;
2215 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2217 p = normalized->bv_val;
2218 for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
2219 p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
2225 assert( p == &normalized->bv_val[normalized->bv_len] );
2228 if ( nlines != NULL ) {
2229 for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
2230 slap_sl_free( nlines[l].bv_val, ctx );
2233 slap_sl_free( lines, ctx );
2244 struct berval val = *in;
2246 if( BER_BVISEMPTY( &val ) ) {
2247 /* disallow empty strings */
2248 return LDAP_INVALID_SYNTAX;
2251 while( OID_LEADCHAR( val.bv_val[0] ) ) {
2252 if ( val.bv_len == 1 ) {
2253 return LDAP_SUCCESS;
2256 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
2263 while ( OID_LEADCHAR( val.bv_val[0] )) {
2267 if ( val.bv_len == 0 ) {
2268 return LDAP_SUCCESS;
2272 if( !OID_SEPARATOR( val.bv_val[0] )) {
2280 return LDAP_INVALID_SYNTAX;
2289 struct berval val = *in;
2291 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
2293 if ( val.bv_val[0] == '-' ) {
2297 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
2298 return LDAP_INVALID_SYNTAX;
2301 if( val.bv_val[0] == '0' ) { /* "-0" */
2302 return LDAP_INVALID_SYNTAX;
2305 } else if ( val.bv_val[0] == '0' ) {
2306 if( val.bv_len > 1 ) { /* "0<more>" */
2307 return LDAP_INVALID_SYNTAX;
2310 return LDAP_SUCCESS;
2313 for( i=0; i < val.bv_len; i++ ) {
2314 if( !ASCII_DIGIT(val.bv_val[i]) ) {
2315 return LDAP_INVALID_SYNTAX;
2319 return LDAP_SUCCESS;
2328 struct berval *value,
2329 void *assertedValue )
2331 struct berval *asserted = (struct berval *) assertedValue;
2332 int vsign = 1, asign = 1; /* default sign = '+' */
2337 if( v.bv_val[0] == '-' ) {
2343 if( BER_BVISEMPTY( &v ) ) vsign = 0;
2346 if( a.bv_val[0] == '-' ) {
2352 if( BER_BVISEMPTY( &a ) ) vsign = 0;
2354 match = vsign - asign;
2356 match = ( v.bv_len != a.bv_len
2357 ? ( v.bv_len < a.bv_len ? -1 : 1 )
2358 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
2359 if( vsign < 0 ) match = -match;
2363 return LDAP_SUCCESS;
2366 /* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */
2367 #define INDEX_INTLEN_CHOP 7
2368 #define INDEX_INTLEN_CHOPBYTES 3
2378 * only if too large: one's complement <sign*exponent (chopped bytes)>,
2379 * two's complement value (sign-extended or chopped as needed),
2380 * however the top <number of exponent-bytes + 1> bits of first byte
2381 * above is the inverse sign. The next bit is the sign as delimiter.
2383 ber_slen_t k = index_intlen_strlen;
2385 unsigned signmask = ~0x7fU;
2386 unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
2387 struct berval val = *in, itmp = *tmp;
2389 if ( val.bv_val[0] != '-' ) {
2394 /* Chop least significant digits, increase length instead */
2395 if ( val.bv_len > (ber_len_t) k ) {
2396 chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */
2397 val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */
2398 chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */
2401 if ( lutil_str2bin( &val, &itmp, ctx )) {
2402 return LDAP_INVALID_SYNTAX;
2405 /* Omit leading sign byte */
2406 if ( itmp.bv_val[0] == neg ) {
2411 k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
2413 assert( chop == 0 );
2414 memset( key->bv_val, neg, k ); /* sign-extend */
2415 } else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
2416 lenp = lenbuf + sizeof(lenbuf);
2417 chop = - (ber_len_t) k;
2419 *--lenp = ((unsigned char) chop & 0xff) ^ neg;
2421 } while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
2422 /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
2423 * are 1, and the top n+2 bits of lenp[] are the sign bit. */
2424 k = (lenbuf + sizeof(lenbuf)) - lenp;
2425 if ( k > (ber_slen_t) index_intlen )
2427 memcpy( key->bv_val, lenp, k );
2428 itmp.bv_len = index_intlen - k;
2430 memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
2431 key->bv_val[0] ^= (unsigned char) signmask & 0xff; /* invert sign */
2435 /* Index generation function */
2442 struct berval *prefix,
2452 unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2454 /* count the values and find max needed length */
2456 for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2457 if ( vlen < values[i].bv_len )
2458 vlen = values[i].bv_len;
2460 if ( vlen > maxstrlen )
2463 /* we should have at least one value at this point */
2466 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2467 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
2468 keys[i].bv_len = index_intlen;
2469 keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
2472 keys[i].bv_val = NULL;
2474 if ( vlen > sizeof(ibuf) ) {
2475 itmp.bv_val = slap_sl_malloc( vlen, ctx );
2479 itmp.bv_len = sizeof(ibuf);
2481 for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
2482 if ( itmp.bv_val != ibuf ) {
2483 itmp.bv_len = values[i].bv_len;
2484 if ( itmp.bv_len <= sizeof(ibuf) )
2485 itmp.bv_len = sizeof(ibuf);
2486 else if ( itmp.bv_len > maxstrlen )
2487 itmp.bv_len = maxstrlen;
2489 rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
2495 if ( itmp.bv_val != ibuf ) {
2496 slap_sl_free( itmp.bv_val, ctx );
2501 /* Index generation function */
2508 struct berval *prefix,
2509 void * assertedValue,
2516 struct berval *value;
2519 value = (struct berval *) assertedValue;
2521 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2523 keys[0].bv_len = index_intlen;
2524 keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
2526 keys[1].bv_val = NULL;
2528 iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
2529 ? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
2530 if ( iv.bv_len > (int) sizeof(ibuf) ) {
2531 iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
2534 iv.bv_len = sizeof(ibuf);
2537 rc = integerVal2Key( value, keys, &iv, ctx );
2541 if ( iv.bv_val != ibuf ) {
2542 slap_sl_free( iv.bv_val, ctx );
2548 countryStringValidate(
2550 struct berval *val )
2552 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2554 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2555 return LDAP_INVALID_SYNTAX;
2557 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2558 return LDAP_INVALID_SYNTAX;
2561 return LDAP_SUCCESS;
2565 printableStringValidate(
2567 struct berval *val )
2571 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2573 for(i=0; i < val->bv_len; i++) {
2574 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2575 return LDAP_INVALID_SYNTAX;
2579 return LDAP_SUCCESS;
2583 printablesStringValidate(
2585 struct berval *val )
2589 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
2591 for(i=0,len=0; i < val->bv_len; i++) {
2592 int c = val->bv_val[i];
2596 return LDAP_INVALID_SYNTAX;
2600 } else if ( SLAP_PRINTABLE(c) ) {
2603 return LDAP_INVALID_SYNTAX;
2608 return LDAP_INVALID_SYNTAX;
2611 return LDAP_SUCCESS;
2617 struct berval *val )
2621 for(i=0; i < val->bv_len; i++) {
2622 if( !LDAP_ASCII(val->bv_val[i]) ) {
2623 return LDAP_INVALID_SYNTAX;
2627 return LDAP_SUCCESS;
2636 struct berval *normalized,
2640 int casefold = !SLAP_MR_ASSOCIATED( mr,
2641 slap_schema.si_mr_caseExactIA5Match );
2643 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
2647 /* Ignore initial whitespace */
2648 while ( ASCII_SPACE( *p ) ) p++;
2650 normalized->bv_len = val->bv_len - ( p - val->bv_val );
2651 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2652 AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
2653 normalized->bv_val[normalized->bv_len] = '\0';
2655 p = q = normalized->bv_val;
2658 if ( ASCII_SPACE( *p ) ) {
2661 /* Ignore the extra whitespace */
2662 while ( ASCII_SPACE( *p ) ) {
2666 } else if ( casefold ) {
2667 /* Most IA5 rules require casefolding */
2668 *q++ = TOLOWER(*p); p++;
2675 assert( normalized->bv_val <= p );
2679 * If the string ended in space, backup the pointer one
2680 * position. One is enough because the above loop collapsed
2681 * all whitespace to a single space.
2683 if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
2685 /* null terminate */
2688 normalized->bv_len = q - normalized->bv_val;
2690 return LDAP_SUCCESS;
2699 if( in->bv_len != 36 ) {
2700 return LDAP_INVALID_SYNTAX;
2703 for( i=0; i<36; i++ ) {
2709 if( in->bv_val[i] != '-' ) {
2710 return LDAP_INVALID_SYNTAX;
2714 if( !ASCII_HEX( in->bv_val[i]) ) {
2715 return LDAP_INVALID_SYNTAX;
2720 return LDAP_SUCCESS;
2731 int rc=LDAP_INVALID_SYNTAX;
2733 assert( in != NULL );
2734 assert( out != NULL );
2736 if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
2739 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
2741 for( i=0; i<36; i++ ) {
2747 if( in->bv_val[i] != '-' ) {
2750 out->bv_val[i] = '-';
2754 if( !ASCII_HEX( in->bv_val[i]) ) {
2757 out->bv_val[i] = TOLOWER( in->bv_val[i] );
2762 out->bv_val[ out->bv_len ] = '\0';
2766 slap_sl_free( out->bv_val, ctx );
2779 struct berval *normalized,
2782 unsigned char octet = '\0';
2786 if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
2787 /* NOTE: must be a normalized UUID */
2788 assert( val->bv_len == 16 );
2790 normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
2791 normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
2792 val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
2793 assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
2795 return LDAP_SUCCESS;
2798 normalized->bv_len = 16;
2799 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2801 for( i=0, j=0; i<36; i++ ) {
2802 unsigned char nibble;
2803 if( val->bv_val[i] == '-' ) {
2806 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2807 nibble = val->bv_val[i] - '0';
2809 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2810 nibble = val->bv_val[i] - ('a'-10);
2812 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2813 nibble = val->bv_val[i] - ('A'-10);
2816 slap_sl_free( normalized->bv_val, ctx );
2817 return LDAP_INVALID_SYNTAX;
2822 normalized->bv_val[j>>1] = octet;
2824 octet = nibble << 4;
2829 normalized->bv_val[normalized->bv_len] = 0;
2830 return LDAP_SUCCESS;
2836 numericStringValidate(
2842 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2844 for(i=0; i < in->bv_len; i++) {
2845 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2846 return LDAP_INVALID_SYNTAX;
2850 return LDAP_SUCCESS;
2854 numericStringNormalize(
2859 struct berval *normalized,
2862 /* removal all spaces */
2865 assert( !BER_BVISEMPTY( val ) );
2867 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2870 q = normalized->bv_val;
2873 if ( ASCII_SPACE( *p ) ) {
2874 /* Ignore whitespace */
2881 /* we should have copied no more than is in val */
2882 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2884 /* null terminate */
2887 normalized->bv_len = q - normalized->bv_val;
2889 if( BER_BVISEMPTY( normalized ) ) {
2890 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2891 normalized->bv_val[0] = ' ';
2892 normalized->bv_val[1] = '\0';
2893 normalized->bv_len = 1;
2896 return LDAP_SUCCESS;
2900 * Integer conversion macros that will use the largest available
2903 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2904 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2905 # define SLAP_LONG long long
2907 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2908 # define SLAP_LONG long
2909 #endif /* HAVE_STRTOLL ... */
2917 struct berval *value,
2918 void *assertedValue )
2920 SLAP_LONG lValue, lAssertedValue;
2923 /* safe to assume integers are NUL terminated? */
2924 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2925 if( errno == ERANGE )
2927 return LDAP_CONSTRAINT_VIOLATION;
2930 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2932 if( errno == ERANGE )
2934 return LDAP_CONSTRAINT_VIOLATION;
2937 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2938 return LDAP_SUCCESS;
2947 struct berval *value,
2948 void *assertedValue )
2950 SLAP_LONG lValue, lAssertedValue;
2953 /* safe to assume integers are NUL terminated? */
2954 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2955 if( errno == ERANGE )
2957 return LDAP_CONSTRAINT_VIOLATION;
2960 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2962 if( errno == ERANGE )
2964 return LDAP_CONSTRAINT_VIOLATION;
2967 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2968 return LDAP_SUCCESS;
2972 checkNum( struct berval *in, struct berval *out )
2974 /* parse serialNumber */
2975 ber_len_t neg = 0, extra = 0;
2978 out->bv_val = in->bv_val;
2981 if ( out->bv_val[0] == '-' ) {
2986 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
2987 first = out->bv_val[2];
2990 out->bv_len += STRLENOF("0x");
2991 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2992 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2995 } else if ( out->bv_val[0] == '\'' ) {
2996 first = out->bv_val[1];
2999 out->bv_len += STRLENOF("'");
3001 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3002 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3004 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3007 out->bv_len += STRLENOF("'H");
3010 first = out->bv_val[0];
3011 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3012 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3016 if ( !( out->bv_len > neg ) ) {
3020 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3028 serialNumberAndIssuerCheck(
3036 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3038 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3039 /* Parse old format */
3040 is->bv_val = ber_bvchr( in, '$' );
3041 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3043 sn->bv_val = in->bv_val;
3044 sn->bv_len = is->bv_val - in->bv_val;
3047 is->bv_len = in->bv_len - (sn->bv_len + 1);
3049 /* eat leading zeros */
3050 for( n=0; n < (sn->bv_len-1); n++ ) {
3051 if( sn->bv_val[n] != '0' ) break;
3056 for( n=0; n < sn->bv_len; n++ ) {
3057 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3061 /* Parse GSER format */
3066 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3070 struct berval x = *in;
3076 /* eat leading spaces */
3077 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3081 /* should be at issuer or serialNumber NamedValue */
3082 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3083 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3086 x.bv_val += STRLENOF("issuer");
3087 x.bv_len -= STRLENOF("issuer");
3089 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3093 /* eat leading spaces */
3094 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3098 /* For backward compatibility, this part is optional */
3099 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3100 x.bv_val += STRLENOF("rdnSequence:");
3101 x.bv_len -= STRLENOF("rdnSequence:");
3104 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3108 is->bv_val = x.bv_val;
3111 for ( ; is->bv_len < x.bv_len; ) {
3112 if ( is->bv_val[is->bv_len] != '"' ) {
3116 if ( is->bv_val[is->bv_len+1] == '"' ) {
3123 x.bv_val += is->bv_len + 1;
3124 x.bv_len -= is->bv_len + 1;
3126 have |= HAVE_ISSUER;
3128 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3130 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3132 /* parse serialNumber */
3133 x.bv_val += STRLENOF("serialNumber");
3134 x.bv_len -= STRLENOF("serialNumber");
3136 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3140 /* eat leading spaces */
3141 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3145 if ( checkNum( &x, sn ) ) {
3146 return LDAP_INVALID_SYNTAX;
3149 x.bv_val += sn->bv_len;
3150 x.bv_len -= sn->bv_len;
3155 return LDAP_INVALID_SYNTAX;
3158 /* eat leading spaces */
3159 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3163 if ( have == HAVE_ALL ) {
3167 if ( x.bv_val[0] != ',' ) {
3168 return LDAP_INVALID_SYNTAX;
3175 /* should have no characters left... */
3176 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3178 if ( numdquotes == 0 ) {
3179 ber_dupbv_x( &ni, is, ctx );
3184 ni.bv_len = is->bv_len - numdquotes;
3185 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3186 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3187 if ( is->bv_val[src] == '"' ) {
3190 ni.bv_val[dst] = is->bv_val[src];
3192 ni.bv_val[dst] = '\0';
3202 serialNumberAndIssuerValidate(
3207 struct berval sn, i;
3209 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3212 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3217 /* validate DN -- doesn't handle double dquote */
3218 rc = dnValidate( NULL, &i );
3220 rc = LDAP_INVALID_SYNTAX;
3223 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3224 slap_sl_free( i.bv_val, NULL );
3227 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3228 in->bv_val, rc, 0 );
3235 serialNumberAndIssuerPretty(
3242 struct berval sn, i, ni = BER_BVNULL;
3245 assert( in != NULL );
3246 assert( out != NULL );
3250 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3253 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3258 rc = dnPretty( syntax, &i, &ni, ctx );
3260 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3261 slap_sl_free( i.bv_val, ctx );
3265 rc = LDAP_INVALID_SYNTAX;
3269 /* make room from sn + "$" */
3270 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3271 + sn.bv_len + ni.bv_len;
3272 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3274 if ( out->bv_val == NULL ) {
3281 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3282 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3283 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3284 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3285 p = lutil_strcopy( p, /*{*/ "\" }" );
3287 assert( p == &out->bv_val[out->bv_len] );
3290 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3291 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3293 slap_sl_free( ni.bv_val, ctx );
3295 return LDAP_SUCCESS;
3305 /* Use hex format. '123456789abcdef'H */
3306 unsigned char *ptr, zero = '\0';
3309 ber_len_t i, len, nlen;
3311 assert( in != NULL );
3312 assert( !BER_BVISNULL( in ) );
3313 assert( out != NULL );
3314 assert( !BER_BVISNULL( out ) );
3316 ptr = (unsigned char *)in->bv_val;
3319 /* Check for minimal encodings */
3321 if ( ptr[0] & 0x80 ) {
3322 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3326 } else if ( ptr[0] == 0 ) {
3327 if ( !( ptr[1] & 0x80 ) ) {
3334 } else if ( len == 0 ) {
3335 /* FIXME: this should not be possible,
3336 * since a value of zero would have length 1 */
3341 first = !( ptr[0] & 0xf0U );
3342 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3343 if ( nlen >= out->bv_len ) {
3344 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3350 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3354 for ( ; i < len; i++ ) {
3355 sprintf( sptr, "%02X", ptr[i] );
3362 assert( sptr == &out->bv_val[nlen] );
3369 #define SLAP_SN_BUFLEN (64)
3372 * This routine is called by certificateExactNormalize when
3373 * certificateExactNormalize receives a search string instead of
3374 * a certificate. This routine checks if the search value is valid
3375 * and then returns the normalized value
3378 serialNumberAndIssuerNormalize(
3386 struct berval sn, sn2, sn3, i, ni;
3387 char sbuf2[SLAP_SN_BUFLEN];
3388 char sbuf3[SLAP_SN_BUFLEN];
3392 assert( in != NULL );
3393 assert( out != NULL );
3395 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3398 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3403 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3405 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3406 slap_sl_free( i.bv_val, ctx );
3410 return LDAP_INVALID_SYNTAX;
3413 /* Convert sn to canonical hex */
3415 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3416 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3418 sn2.bv_len = sn.bv_len;
3419 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3420 rc = LDAP_INVALID_SYNTAX;
3425 sn3.bv_len = sizeof(sbuf3);
3426 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3427 rc = LDAP_INVALID_SYNTAX;
3431 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3432 + sn3.bv_len + ni.bv_len;
3433 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3435 if ( out->bv_val == NULL ) {
3443 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3444 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3445 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3446 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3447 p = lutil_strcopy( p, /*{*/ "\" }" );
3449 assert( p == &out->bv_val[out->bv_len] );
3452 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3453 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3455 if ( sn2.bv_val != sbuf2 ) {
3456 slap_sl_free( sn2.bv_val, ctx );
3459 if ( sn3.bv_val != sbuf3 ) {
3460 slap_sl_free( sn3.bv_val, ctx );
3463 slap_sl_free( ni.bv_val, ctx );
3469 certificateExactNormalize(
3474 struct berval *normalized,
3477 BerElementBuffer berbuf;
3478 BerElement *ber = (BerElement *)&berbuf;
3482 char serialbuf2[SLAP_SN_BUFLEN];
3483 struct berval sn, sn2 = BER_BVNULL;
3484 struct berval issuer_dn = BER_BVNULL, bvdn;
3486 int rc = LDAP_INVALID_SYNTAX;
3488 assert( val != NULL );
3490 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3491 val->bv_val, val->bv_len, 0 );
3493 if ( BER_BVISEMPTY( val ) ) goto done;
3495 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3496 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3499 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3501 ber_init2( ber, val, LBER_USE_DER );
3502 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3503 tag = ber_skip_tag( ber, &len ); /* Sequence */
3504 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3505 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3506 tag = ber_skip_tag( ber, &len );
3507 tag = ber_get_int( ber, &i ); /* version */
3510 /* NOTE: move the test here from certificateValidate,
3511 * so that we can validate certs with serial longer
3512 * than sizeof(ber_int_t) */
3513 tag = ber_skip_tag( ber, &len ); /* serial */
3515 sn.bv_val = (char *)ber->ber_ptr;
3516 sn2.bv_val = serialbuf2;
3517 sn2.bv_len = sizeof(serialbuf2);
3518 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3519 rc = LDAP_INVALID_SYNTAX;
3522 ber_skip_data( ber, len );
3524 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3525 ber_skip_data( ber, len );
3526 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3527 len = ber_ptrlen( ber );
3528 bvdn.bv_val = val->bv_val + len;
3529 bvdn.bv_len = val->bv_len - len;
3531 rc = dnX509normalize( &bvdn, &issuer_dn );
3532 if ( rc != LDAP_SUCCESS ) goto done;
3534 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3535 + sn2.bv_len + issuer_dn.bv_len;
3536 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3538 p = normalized->bv_val;
3540 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3541 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3542 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3543 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3544 p = lutil_strcopy( p, /*{*/ "\" }" );
3549 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3550 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3552 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3553 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3558 /* X.509 PKI certificateList stuff */
3560 checkTime( struct berval *in, struct berval *out )
3564 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3567 assert( in != NULL );
3568 assert( !BER_BVISNULL( in ) );
3569 assert( !BER_BVISEMPTY( in ) );
3571 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3575 if ( out != NULL ) {
3576 assert( !BER_BVISNULL( out ) );
3577 assert( out->bv_len >= sizeof( buf ) );
3578 bv.bv_val = out->bv_val;
3584 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3585 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3588 if ( in->bv_val[i] != 'Z' ) {
3593 if ( i != in->bv_len ) {
3597 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3598 lutil_strncopy( bv.bv_val, in->bv_val, i );
3601 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3602 char *p = bv.bv_val;
3603 if ( in->bv_val[0] < '7' ) {
3604 p = lutil_strcopy( p, "20" );
3607 p = lutil_strcopy( p, "19" );
3609 lutil_strncopy( p, in->bv_val, i );
3616 rc = generalizedTimeValidate( NULL, &bv );
3617 if ( rc == LDAP_SUCCESS && out != NULL ) {
3618 out->bv_len = bv.bv_len;
3621 return rc != LDAP_SUCCESS;
3625 issuerAndThisUpdateCheck(
3632 struct berval x = *in;
3633 struct berval ni = BER_BVNULL;
3634 /* Parse GSER format */
3638 HAVE_THISUPDATE = 0x2,
3639 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3643 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3645 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3646 return LDAP_INVALID_SYNTAX;
3650 x.bv_len -= STRLENOF("{}");
3653 /* eat leading spaces */
3654 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3658 /* should be at issuer or thisUpdate */
3659 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3660 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3663 x.bv_val += STRLENOF("issuer");
3664 x.bv_len -= STRLENOF("issuer");
3666 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3670 /* eat leading spaces */
3671 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3675 /* For backward compatibility, this part is optional */
3676 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3677 return LDAP_INVALID_SYNTAX;
3679 x.bv_val += STRLENOF("rdnSequence:");
3680 x.bv_len -= STRLENOF("rdnSequence:");
3682 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3686 is->bv_val = x.bv_val;
3689 for ( ; is->bv_len < x.bv_len; ) {
3690 if ( is->bv_val[is->bv_len] != '"' ) {
3694 if ( is->bv_val[is->bv_len+1] == '"' ) {
3701 x.bv_val += is->bv_len + 1;
3702 x.bv_len -= is->bv_len + 1;
3704 have |= HAVE_ISSUER;
3706 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3708 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3710 /* parse thisUpdate */
3711 x.bv_val += STRLENOF("thisUpdate");
3712 x.bv_len -= STRLENOF("thisUpdate");
3714 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3718 /* eat leading spaces */
3719 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3723 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3727 tu->bv_val = x.bv_val;
3730 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3731 if ( tu->bv_val[tu->bv_len] == '"' ) {
3735 x.bv_val += tu->bv_len + 1;
3736 x.bv_len -= tu->bv_len + 1;
3738 have |= HAVE_THISUPDATE;
3741 return LDAP_INVALID_SYNTAX;
3744 /* eat leading spaces */
3745 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3749 if ( have == HAVE_ALL ) {
3753 if ( x.bv_val[0] != ',' ) {
3754 return LDAP_INVALID_SYNTAX;
3761 /* should have no characters left... */
3762 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3764 if ( numdquotes == 0 ) {
3765 ber_dupbv_x( &ni, is, ctx );
3770 ni.bv_len = is->bv_len - numdquotes;
3771 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3772 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3773 if ( is->bv_val[src] == '"' ) {
3776 ni.bv_val[dst] = is->bv_val[src];
3778 ni.bv_val[dst] = '\0';
3787 issuerAndThisUpdateValidate(
3792 struct berval i, tu;
3794 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3797 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3802 /* validate DN -- doesn't handle double dquote */
3803 rc = dnValidate( NULL, &i );
3805 rc = LDAP_INVALID_SYNTAX;
3807 } else if ( checkTime( &tu, NULL ) ) {
3808 rc = LDAP_INVALID_SYNTAX;
3811 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3812 slap_sl_free( i.bv_val, NULL );
3815 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3816 in->bv_val, rc, 0 );
3823 issuerAndThisUpdatePretty(
3830 struct berval i, tu, ni = BER_BVNULL;
3833 assert( in != NULL );
3834 assert( out != NULL );
3838 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3841 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3846 rc = dnPretty( syntax, &i, &ni, ctx );
3848 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3849 slap_sl_free( i.bv_val, ctx );
3852 if ( rc || checkTime( &tu, NULL ) ) {
3853 rc = LDAP_INVALID_SYNTAX;
3858 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3859 + ni.bv_len + tu.bv_len;
3860 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3862 if ( out->bv_val == NULL ) {
3869 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3870 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3871 p = lutil_strcopy( p, "\", thisUpdate \"" );
3872 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3873 p = lutil_strcopy( p, /*{*/ "\" }" );
3875 assert( p == &out->bv_val[out->bv_len] );
3878 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3879 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3881 slap_sl_free( ni.bv_val, ctx );
3887 issuerAndThisUpdateNormalize(
3895 struct berval i, ni, tu, tu2;
3896 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3900 assert( in != NULL );
3901 assert( out != NULL );
3903 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3906 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3911 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3913 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3914 slap_sl_free( i.bv_val, ctx );
3918 tu2.bv_len = sizeof( sbuf );
3919 if ( rc || checkTime( &tu, &tu2 ) ) {
3920 return LDAP_INVALID_SYNTAX;
3923 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3924 + ni.bv_len + tu2.bv_len;
3925 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3927 if ( out->bv_val == NULL ) {
3935 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3936 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3937 p = lutil_strcopy( p, "\", thisUpdate \"" );
3938 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3939 p = lutil_strcopy( p, /*{*/ "\" }" );
3941 assert( p == &out->bv_val[out->bv_len] );
3944 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3945 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3947 slap_sl_free( ni.bv_val, ctx );
3953 certificateListExactNormalize(
3958 struct berval *normalized,
3961 BerElementBuffer berbuf;
3962 BerElement *ber = (BerElement *)&berbuf;
3966 struct berval issuer_dn = BER_BVNULL, bvdn,
3968 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3969 int rc = LDAP_INVALID_SYNTAX;
3971 assert( val != NULL );
3973 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
3974 val->bv_val, val->bv_len, 0 );
3976 if ( BER_BVISEMPTY( val ) ) goto done;
3978 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3979 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
3982 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3984 ber_init2( ber, val, LBER_USE_DER );
3985 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
3986 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3987 tag = ber_skip_tag( ber, &len ); /* Sequence */
3988 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3989 tag = ber_peek_tag( ber, &len );
3990 /* Optional version */
3991 if ( tag == LBER_INTEGER ) {
3992 tag = ber_get_int( ber, &version );
3993 assert( tag == LBER_INTEGER );
3994 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
3996 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
3997 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3998 ber_skip_data( ber, len );
4000 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4001 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4002 len = ber_ptrlen( ber );
4003 bvdn.bv_val = val->bv_val + len;
4004 bvdn.bv_len = val->bv_len - len;
4005 tag = ber_skip_tag( ber, &len );
4006 ber_skip_data( ber, len );
4008 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4009 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4010 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4011 bvtu.bv_val = (char *)ber->ber_ptr;
4014 rc = dnX509normalize( &bvdn, &issuer_dn );
4015 if ( rc != LDAP_SUCCESS ) goto done;
4017 thisUpdate.bv_val = tubuf;
4018 thisUpdate.bv_len = sizeof(tubuf);
4019 if ( checkTime( &bvtu, &thisUpdate ) ) {
4020 rc = LDAP_INVALID_SYNTAX;
4024 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4025 + issuer_dn.bv_len + thisUpdate.bv_len;
4026 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4028 p = normalized->bv_val;
4030 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4031 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4032 p = lutil_strcopy( p, "\", thisUpdate \"" );
4033 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
4034 p = lutil_strcopy( p, /*{*/ "\" }" );
4039 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4040 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4042 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4047 /* X.509 PMI serialNumberAndIssuerSerialCheck
4049 AttributeCertificateExactAssertion ::= SEQUENCE {
4050 serialNumber CertificateSerialNumber,
4051 issuer AttCertIssuer }
4053 CertificateSerialNumber ::= INTEGER
4055 AttCertIssuer ::= [0] SEQUENCE {
4056 issuerName GeneralNames OPTIONAL,
4057 baseCertificateID [0] IssuerSerial OPTIONAL,
4058 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4059 -- At least one component shall be present
4061 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4063 GeneralName ::= CHOICE {
4064 otherName [0] INSTANCE OF OTHER-NAME,
4065 rfc822Name [1] IA5String,
4066 dNSName [2] IA5String,
4067 x400Address [3] ORAddress,
4068 directoryName [4] Name,
4069 ediPartyName [5] EDIPartyName,
4070 uniformResourceIdentifier [6] IA5String,
4071 iPAddress [7] OCTET STRING,
4072 registeredID [8] OBJECT IDENTIFIER }
4074 IssuerSerial ::= SEQUENCE {
4075 issuer GeneralNames,
4076 serial CertificateSerialNumber,
4077 issuerUID UniqueIdentifier OPTIONAL }
4079 ObjectDigestInfo ::= SEQUENCE {
4080 digestedObjectType ENUMERATED {
4083 otherObjectTypes (2) },
4084 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4085 digestAlgorithm AlgorithmIdentifier,
4086 objectDigest BIT STRING }
4088 * The way I interpret it, an assertion should look like
4090 { serialNumber 'dd'H,
4091 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4092 baseCertificateID { serial '1d'H,
4093 issuer { directoryName:rdnSequence:"cn=zzz" },
4094 issuerUID <value> -- optional
4096 objectDigestInfo { ... } -- optional
4100 * with issuerName, baseCertificateID and objectDigestInfo optional,
4101 * at least one present; the way it's currently implemented, it is
4103 { serialNumber 'dd'H,
4104 issuer { baseCertificateID { serial '1d'H,
4105 issuer { directoryName:rdnSequence:"cn=zzz" }
4110 * with all the above parts mandatory.
4113 serialNumberAndIssuerSerialCheck(
4117 struct berval *i_sn, /* contain serial of baseCertificateID */
4120 /* Parse GSER format */
4125 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4126 } have = HAVE_NONE, have2 = HAVE_NONE;
4128 struct berval x = *in;
4131 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4134 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4141 /* eat leading spaces */
4142 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4146 /* should be at issuer or serialNumber NamedValue */
4147 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4148 if ( have & HAVE_ISSUER ) {
4149 return LDAP_INVALID_SYNTAX;
4152 /* parse IssuerSerial */
4153 x.bv_val += STRLENOF("issuer");
4154 x.bv_len -= STRLENOF("issuer");
4156 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4160 /* eat leading spaces */
4161 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4165 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4169 /* eat leading spaces */
4170 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4174 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4175 return LDAP_INVALID_SYNTAX;
4177 x.bv_val += STRLENOF("baseCertificateID ");
4178 x.bv_len -= STRLENOF("baseCertificateID ");
4180 /* eat leading spaces */
4181 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4185 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4190 /* eat leading spaces */
4191 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4195 /* parse issuer of baseCertificateID */
4196 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4197 if ( have2 & HAVE_ISSUER ) {
4198 return LDAP_INVALID_SYNTAX;
4201 x.bv_val += STRLENOF("issuer ");
4202 x.bv_len -= STRLENOF("issuer ");
4204 /* eat leading spaces */
4205 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4209 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4213 /* eat leading spaces */
4214 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4218 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4219 return LDAP_INVALID_SYNTAX;
4221 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4222 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4224 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4228 is->bv_val = x.bv_val;
4231 for ( ; is->bv_len < x.bv_len; ) {
4232 if ( is->bv_val[is->bv_len] != '"' ) {
4236 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4243 x.bv_val += is->bv_len + 1;
4244 x.bv_len -= is->bv_len + 1;
4246 /* eat leading spaces */
4247 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4251 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4255 have2 |= HAVE_ISSUER;
4257 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4258 if ( have2 & HAVE_SN ) {
4259 return LDAP_INVALID_SYNTAX;
4262 x.bv_val += STRLENOF("serial ");
4263 x.bv_len -= STRLENOF("serial ");
4265 /* eat leading spaces */
4266 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4270 if ( checkNum( &x, i_sn ) ) {
4271 return LDAP_INVALID_SYNTAX;
4274 x.bv_val += i_sn->bv_len;
4275 x.bv_len -= i_sn->bv_len;
4280 return LDAP_INVALID_SYNTAX;
4283 /* eat leading spaces */
4284 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4288 if ( have2 == HAVE_ALL ) {
4292 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4297 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4301 /* eat leading spaces */
4302 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4306 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4310 have |= HAVE_ISSUER;
4312 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4313 if ( have & HAVE_SN ) {
4314 return LDAP_INVALID_SYNTAX;
4317 /* parse serialNumber */
4318 x.bv_val += STRLENOF("serialNumber");
4319 x.bv_len -= STRLENOF("serialNumber");
4321 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4325 /* eat leading spaces */
4326 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4330 if ( checkNum( &x, sn ) ) {
4331 return LDAP_INVALID_SYNTAX;
4334 x.bv_val += sn->bv_len;
4335 x.bv_len -= sn->bv_len;
4340 return LDAP_INVALID_SYNTAX;
4344 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4348 if ( have == HAVE_ALL ) {
4352 if ( x.bv_val[0] != ',' ) {
4353 return LDAP_INVALID_SYNTAX;
4359 /* should have no characters left... */
4360 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4362 if ( numdquotes == 0 ) {
4363 ber_dupbv_x( &ni, is, ctx );
4368 ni.bv_len = is->bv_len - numdquotes;
4369 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4370 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4371 if ( is->bv_val[src] == '"' ) {
4374 ni.bv_val[dst] = is->bv_val[src];
4376 ni.bv_val[dst] = '\0';
4381 /* need to handle double dquotes here */
4385 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4387 serialNumberAndIssuerSerialValidate(
4392 struct berval sn, i, i_sn;
4394 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4397 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4402 /* validate DN -- doesn't handle double dquote */
4403 rc = dnValidate( NULL, &i );
4405 rc = LDAP_INVALID_SYNTAX;
4408 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4409 slap_sl_free( i.bv_val, NULL );
4413 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4414 in->bv_val, rc, 0 );
4419 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4421 serialNumberAndIssuerSerialPretty(
4427 struct berval sn, i, i_sn, ni = BER_BVNULL;
4431 assert( in != NULL );
4432 assert( out != NULL );
4434 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4437 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4442 rc = dnPretty( syntax, &i, &ni, ctx );
4444 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4445 slap_sl_free( i.bv_val, ctx );
4449 rc = LDAP_INVALID_SYNTAX;
4453 /* make room from sn + "$" */
4454 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4455 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4456 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4458 if ( out->bv_val == NULL ) {
4465 p = lutil_strcopy( p, "{ serialNumber " );
4466 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
4467 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4468 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4469 p = lutil_strcopy( p, "\" }, serial " );
4470 p = lutil_strncopy( p, i_sn.bv_val, i_sn.bv_len );
4471 p = lutil_strcopy( p, " } } }" );
4473 assert( p == &out->bv_val[out->bv_len] );
4476 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4477 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4479 slap_sl_free( ni.bv_val, ctx );
4484 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4486 * This routine is called by attributeCertificateExactNormalize
4487 * when attributeCertificateExactNormalize receives a search
4488 * string instead of a attribute certificate. This routine
4489 * checks if the search value is valid and then returns the
4493 serialNumberAndIssuerSerialNormalize(
4501 struct berval i, ni = BER_BVNULL,
4502 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4503 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4504 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4505 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4509 assert( in != NULL );
4510 assert( out != NULL );
4512 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4515 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4520 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4522 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4523 slap_sl_free( i.bv_val, ctx );
4527 rc = LDAP_INVALID_SYNTAX;
4531 /* Convert sn to canonical hex */
4533 sn2.bv_len = sn.bv_len;
4534 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4535 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4537 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4538 rc = LDAP_INVALID_SYNTAX;
4542 /* Convert i_sn to canonical hex */
4543 i_sn2.bv_val = i_sbuf2;
4544 i_sn2.bv_len = i_sn.bv_len;
4545 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4546 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4548 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4549 rc = LDAP_INVALID_SYNTAX;
4554 sn3.bv_len = sizeof(sbuf3);
4555 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4556 rc = LDAP_INVALID_SYNTAX;
4560 i_sn3.bv_val = i_sbuf3;
4561 i_sn3.bv_len = sizeof(i_sbuf3);
4562 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4563 rc = LDAP_INVALID_SYNTAX;
4567 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4568 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4569 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4571 if ( out->bv_val == NULL ) {
4579 p = lutil_strcopy( p, "{ serialNumber " );
4580 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
4581 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4582 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4583 p = lutil_strcopy( p, "\" }, serial " );
4584 p = lutil_strncopy( p, i_sn3.bv_val, i_sn3.bv_len );
4585 p = lutil_strcopy( p, " } } }" );
4587 assert( p == &out->bv_val[out->bv_len] );
4590 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4591 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4593 if ( sn2.bv_val != sbuf2 ) {
4594 slap_sl_free( sn2.bv_val, ctx );
4597 if ( i_sn2.bv_val != i_sbuf2 ) {
4598 slap_sl_free( i_sn2.bv_val, ctx );
4601 if ( sn3.bv_val != sbuf3 ) {
4602 slap_sl_free( sn3.bv_val, ctx );
4605 if ( i_sn3.bv_val != i_sbuf3 ) {
4606 slap_sl_free( i_sn3.bv_val, ctx );
4609 slap_sl_free( ni.bv_val, ctx );
4614 /* X.509 PMI attributeCertificateExactNormalize */
4616 attributeCertificateExactNormalize(
4621 struct berval *normalized,
4624 BerElementBuffer berbuf;
4625 BerElement *ber = (BerElement *)&berbuf;
4628 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4629 struct berval sn, i_sn, sn2, i_sn2;
4630 struct berval issuer_dn = BER_BVNULL, bvdn;
4632 int rc = LDAP_INVALID_SYNTAX;
4634 if ( BER_BVISEMPTY( val ) ) {
4638 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4639 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4642 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4644 ber_init2( ber, val, LBER_USE_DER );
4645 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4646 tag = ber_skip_tag( ber, &len ); /* Sequence */
4647 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4648 ber_skip_data( ber, len );
4649 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4650 ber_skip_data( ber, len );
4653 tag = ber_skip_tag( ber, &len ); /* Sequence */
4654 /* issuerName (GeneralNames sequence; optional)? */
4655 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4656 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4657 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4658 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4659 rc = LDAP_INVALID_SYNTAX;
4662 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4663 len = ber_ptrlen( ber );
4664 bvdn.bv_val = val->bv_val + len;
4665 bvdn.bv_len = val->bv_len - len;
4666 rc = dnX509normalize( &bvdn, &issuer_dn );
4667 if ( rc != LDAP_SUCCESS ) goto done;
4669 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4670 ber_skip_data( ber, len );
4671 tag = ber_skip_tag( ber, &len ); /* serial number */
4672 if ( tag != LBER_INTEGER ) {
4673 rc = LDAP_INVALID_SYNTAX;
4676 i_sn.bv_val = (char *)ber->ber_ptr;
4678 i_sn2.bv_val = issuer_serialbuf;
4679 i_sn2.bv_len = sizeof(issuer_serialbuf);
4680 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4681 rc = LDAP_INVALID_SYNTAX;
4684 ber_skip_data( ber, len );
4686 /* issuerUID (bitstring; optional)? */
4687 /* objectDigestInfo (sequence; optional)? */
4689 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4690 ber_skip_data( ber, len );
4691 tag = ber_skip_tag( ber, &len ); /* serial number */
4692 if ( tag != LBER_INTEGER ) {
4693 rc = LDAP_INVALID_SYNTAX;
4696 sn.bv_val = (char *)ber->ber_ptr;
4698 sn2.bv_val = serialbuf;
4699 sn2.bv_len = sizeof(serialbuf);
4700 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4701 rc = LDAP_INVALID_SYNTAX;
4704 ber_skip_data( ber, len );
4706 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4707 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4708 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4710 p = normalized->bv_val;
4712 p = lutil_strcopy( p, "{ serialNumber " );
4713 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
4714 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4715 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4716 p = lutil_strcopy( p, "\" }, serial " );
4717 p = lutil_strncopy( p, i_sn2.bv_val, i_sn2.bv_len );
4718 p = lutil_strcopy( p, " } } }" );
4720 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4721 normalized->bv_val, NULL, NULL );
4726 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4727 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4728 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4741 assert( in != NULL );
4742 assert( !BER_BVISNULL( in ) );
4744 for ( i = 0; i < in->bv_len; i++ ) {
4745 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4746 return LDAP_INVALID_SYNTAX;
4750 return LDAP_SUCCESS;
4753 /* Normalize a SID as used inside a CSN:
4754 * three-digit numeric string */
4761 struct berval *normalized,
4766 assert( val != NULL );
4767 assert( normalized != NULL );
4769 ber_dupbv_x( normalized, val, ctx );
4771 for ( i = 0; i < normalized->bv_len; i++ ) {
4772 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4773 ber_memfree_x( normalized->bv_val, ctx );
4774 BER_BVZERO( normalized );
4775 return LDAP_INVALID_SYNTAX;
4778 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4781 return LDAP_SUCCESS;
4789 assert( in != NULL );
4790 assert( !BER_BVISNULL( in ) );
4792 if ( in->bv_len != 3 ) {
4793 return LDAP_INVALID_SYNTAX;
4796 return hexValidate( NULL, in );
4799 /* Normalize a SID as used inside a CSN:
4800 * three-digit numeric string */
4807 struct berval *normalized,
4810 if ( val->bv_len != 3 ) {
4811 return LDAP_INVALID_SYNTAX;
4814 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4824 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4827 /* Normalize a SID as used inside a CSN, either as-is
4828 * (assertion value) or extracted from the CSN
4829 * (attribute value) */
4836 struct berval *normalized,
4844 if ( BER_BVISEMPTY( val ) ) {
4845 return LDAP_INVALID_SYNTAX;
4848 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4849 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4852 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4854 ptr = ber_bvchr( val, '#' );
4855 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4856 return LDAP_INVALID_SYNTAX;
4859 bv.bv_val = ptr + 1;
4860 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4862 ptr = ber_bvchr( &bv, '#' );
4863 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4864 return LDAP_INVALID_SYNTAX;
4867 bv.bv_val = ptr + 1;
4868 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4870 ptr = ber_bvchr( &bv, '#' );
4871 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4872 return LDAP_INVALID_SYNTAX;
4875 bv.bv_len = ptr - bv.bv_val;
4877 if ( bv.bv_len == 2 ) {
4878 /* OpenLDAP 2.3 SID */
4880 buf[ 1 ] = bv.bv_val[ 0 ];
4881 buf[ 2 ] = bv.bv_val[ 1 ];
4888 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4900 assert( in != NULL );
4901 assert( !BER_BVISNULL( in ) );
4903 if ( BER_BVISEMPTY( in ) ) {
4904 return LDAP_INVALID_SYNTAX;
4909 ptr = ber_bvchr( &bv, '#' );
4910 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4911 return LDAP_INVALID_SYNTAX;
4914 bv.bv_len = ptr - bv.bv_val;
4915 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4916 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4918 return LDAP_INVALID_SYNTAX;
4921 rc = generalizedTimeValidate( NULL, &bv );
4922 if ( rc != LDAP_SUCCESS ) {
4926 bv.bv_val = ptr + 1;
4927 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4929 ptr = ber_bvchr( &bv, '#' );
4930 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4931 return LDAP_INVALID_SYNTAX;
4934 bv.bv_len = ptr - bv.bv_val;
4935 if ( bv.bv_len != 6 ) {
4936 return LDAP_INVALID_SYNTAX;
4939 rc = hexValidate( NULL, &bv );
4940 if ( rc != LDAP_SUCCESS ) {
4944 bv.bv_val = ptr + 1;
4945 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4947 ptr = ber_bvchr( &bv, '#' );
4948 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4949 return LDAP_INVALID_SYNTAX;
4952 bv.bv_len = ptr - bv.bv_val;
4953 if ( bv.bv_len == 2 ) {
4954 /* tolerate old 2-digit replica-id */
4955 rc = hexValidate( NULL, &bv );
4958 rc = sidValidate( NULL, &bv );
4960 if ( rc != LDAP_SUCCESS ) {
4964 bv.bv_val = ptr + 1;
4965 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4967 if ( bv.bv_len != 6 ) {
4968 return LDAP_INVALID_SYNTAX;
4971 return hexValidate( NULL, &bv );
4974 /* Normalize a CSN in OpenLDAP 2.1 format */
4981 struct berval *normalized,
4984 struct berval gt, cnt, sid, mod;
4986 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4990 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4991 assert( !BER_BVISEMPTY( val ) );
4995 ptr = ber_bvchr( >, '#' );
4996 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
4997 return LDAP_INVALID_SYNTAX;
5000 gt.bv_len = ptr - gt.bv_val;
5001 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5002 return LDAP_INVALID_SYNTAX;
5005 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5006 return LDAP_INVALID_SYNTAX;
5009 cnt.bv_val = ptr + 1;
5010 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5012 ptr = ber_bvchr( &cnt, '#' );
5013 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5014 return LDAP_INVALID_SYNTAX;
5017 cnt.bv_len = ptr - cnt.bv_val;
5018 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5019 return LDAP_INVALID_SYNTAX;
5022 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5023 return LDAP_INVALID_SYNTAX;
5026 cnt.bv_val += STRLENOF( "0x" );
5027 cnt.bv_len -= STRLENOF( "0x" );
5029 sid.bv_val = ptr + 1;
5030 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5032 ptr = ber_bvchr( &sid, '#' );
5033 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5034 return LDAP_INVALID_SYNTAX;
5037 sid.bv_len = ptr - sid.bv_val;
5038 if ( sid.bv_len != STRLENOF( "0" ) ) {
5039 return LDAP_INVALID_SYNTAX;
5042 mod.bv_val = ptr + 1;
5043 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5044 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5045 return LDAP_INVALID_SYNTAX;
5048 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5052 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5053 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5055 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5057 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5058 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5062 *ptr++ = sid.bv_val[ 0 ];
5066 for ( i = 0; i < mod.bv_len; i++ ) {
5067 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5071 assert( ptr == &bv.bv_val[bv.bv_len] );
5073 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5074 return LDAP_INVALID_SYNTAX;
5077 ber_dupbv_x( normalized, &bv, ctx );
5079 return LDAP_SUCCESS;
5082 /* Normalize a CSN in OpenLDAP 2.3 format */
5089 struct berval *normalized,
5092 struct berval gt, cnt, sid, mod;
5094 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5098 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5099 assert( !BER_BVISEMPTY( val ) );
5103 ptr = ber_bvchr( >, '#' );
5104 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5105 return LDAP_INVALID_SYNTAX;
5108 gt.bv_len = ptr - gt.bv_val;
5109 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5110 return LDAP_INVALID_SYNTAX;
5113 cnt.bv_val = ptr + 1;
5114 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5116 ptr = ber_bvchr( &cnt, '#' );
5117 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5118 return LDAP_INVALID_SYNTAX;
5121 cnt.bv_len = ptr - cnt.bv_val;
5122 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5123 return LDAP_INVALID_SYNTAX;
5126 sid.bv_val = ptr + 1;
5127 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5129 ptr = ber_bvchr( &sid, '#' );
5130 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5131 return LDAP_INVALID_SYNTAX;
5134 sid.bv_len = ptr - sid.bv_val;
5135 if ( sid.bv_len != STRLENOF( "00" ) ) {
5136 return LDAP_INVALID_SYNTAX;
5139 mod.bv_val = ptr + 1;
5140 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5141 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5142 return LDAP_INVALID_SYNTAX;
5145 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5149 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5150 ptr = lutil_strcopy( ptr, ".000000Z#" );
5151 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5154 for ( i = 0; i < sid.bv_len; i++ ) {
5155 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5158 for ( i = 0; i < mod.bv_len; i++ ) {
5159 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5163 assert( ptr == &bv.bv_val[bv.bv_len] );
5164 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5165 return LDAP_INVALID_SYNTAX;
5168 ber_dupbv_x( normalized, &bv, ctx );
5170 return LDAP_SUCCESS;
5173 /* Normalize a CSN */
5180 struct berval *normalized,
5183 struct berval cnt, sid, mod;
5187 assert( val != NULL );
5188 assert( normalized != NULL );
5190 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5192 if ( BER_BVISEMPTY( val ) ) {
5193 return LDAP_INVALID_SYNTAX;
5196 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5197 /* Openldap <= 2.3 */
5199 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5202 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5205 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5208 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5209 return LDAP_INVALID_SYNTAX;
5212 ptr = ber_bvchr( val, '#' );
5213 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5214 return LDAP_INVALID_SYNTAX;
5217 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5218 return LDAP_INVALID_SYNTAX;
5221 cnt.bv_val = ptr + 1;
5222 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5224 ptr = ber_bvchr( &cnt, '#' );
5225 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5226 return LDAP_INVALID_SYNTAX;
5229 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5230 return LDAP_INVALID_SYNTAX;
5233 sid.bv_val = ptr + 1;
5234 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5236 ptr = ber_bvchr( &sid, '#' );
5237 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5238 return LDAP_INVALID_SYNTAX;
5241 sid.bv_len = ptr - sid.bv_val;
5242 if ( sid.bv_len != STRLENOF( "000" ) ) {
5243 return LDAP_INVALID_SYNTAX;
5246 mod.bv_val = ptr + 1;
5247 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5249 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5250 return LDAP_INVALID_SYNTAX;
5253 ber_dupbv_x( normalized, val, ctx );
5255 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5256 i < normalized->bv_len; i++ )
5258 /* assume it's already validated that's all hex digits */
5259 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5262 return LDAP_SUCCESS;
5272 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5275 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5276 /* slight optimization - does not need the start parameter */
5277 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5282 check_time_syntax (struct berval *val,
5285 struct berval *fraction)
5288 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5289 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5290 * GeneralizedTime supports leap seconds, UTCTime does not.
5292 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5293 static const int mdays[2][12] = {
5294 /* non-leap years */
5295 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5297 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5300 int part, c, c1, c2, tzoffset, leapyear = 0;
5303 e = p + val->bv_len;
5305 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5306 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5308 for (part = start; part < 7 && p < e; part++) {
5310 if (!ASCII_DIGIT(c1)) {
5315 return LDAP_INVALID_SYNTAX;
5318 if (!ASCII_DIGIT(c)) {
5319 return LDAP_INVALID_SYNTAX;
5321 c += c1 * 10 - '0' * 11;
5322 if ((part | 1) == 3) {
5325 return LDAP_INVALID_SYNTAX;
5328 if (c >= ceiling[part]) {
5329 if (! (c == 60 && part == 6 && start == 0))
5330 return LDAP_INVALID_SYNTAX;
5334 if (part < 5 + start) {
5335 return LDAP_INVALID_SYNTAX;
5337 for (; part < 9; part++) {
5341 /* leapyear check for the Gregorian calendar (year>1581) */
5342 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5346 if (parts[3] >= mdays[leapyear][parts[2]]) {
5347 return LDAP_INVALID_SYNTAX;
5351 fraction->bv_val = p;
5352 fraction->bv_len = 0;
5353 if (p < e && (*p == '.' || *p == ',')) {
5355 while (++p < e && ASCII_DIGIT(*p)) {
5358 if (p - fraction->bv_val == 1) {
5359 return LDAP_INVALID_SYNTAX;
5361 for (end_num = p; end_num[-1] == '0'; --end_num) {
5364 c = end_num - fraction->bv_val;
5365 if (c != 1) fraction->bv_len = c;
5371 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5377 return LDAP_INVALID_SYNTAX;
5383 for (part = 7; part < 9 && p < e; part++) {
5385 if (!ASCII_DIGIT(c1)) {
5390 return LDAP_INVALID_SYNTAX;
5393 if (!ASCII_DIGIT(c2)) {
5394 return LDAP_INVALID_SYNTAX;
5396 parts[part] = c1 * 10 + c2 - '0' * 11;
5397 if (parts[part] >= ceiling[part]) {
5398 return LDAP_INVALID_SYNTAX;
5401 if (part < 8 + start) {
5402 return LDAP_INVALID_SYNTAX;
5405 if (tzoffset == '-') {
5406 /* negative offset to UTC, ie west of Greenwich */
5407 parts[4] += parts[7];
5408 parts[5] += parts[8];
5409 /* offset is just hhmm, no seconds */
5410 for (part = 6; --part >= 0; ) {
5414 c = mdays[leapyear][parts[2]];
5416 if (parts[part] >= c) {
5418 return LDAP_INVALID_SYNTAX;
5423 } else if (part != 5) {
5428 /* positive offset to UTC, ie east of Greenwich */
5429 parts[4] -= parts[7];
5430 parts[5] -= parts[8];
5431 for (part = 6; --part >= 0; ) {
5432 if (parts[part] < 0) {
5434 return LDAP_INVALID_SYNTAX;
5439 /* make first arg to % non-negative */
5440 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5445 } else if (part != 5) {
5452 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5455 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5462 struct berval *normalized )
5466 rc = check_time_syntax(val, 1, parts, NULL);
5467 if (rc != LDAP_SUCCESS) {
5471 normalized->bv_val = ch_malloc( 14 );
5472 if ( normalized->bv_val == NULL ) {
5473 return LBER_ERROR_MEMORY;
5476 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5477 parts[1], parts[2] + 1, parts[3] + 1,
5478 parts[4], parts[5], parts[6] );
5479 normalized->bv_len = 13;
5481 return LDAP_SUCCESS;
5491 return check_time_syntax(in, 1, parts, NULL);
5494 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5497 generalizedTimeValidate(
5502 struct berval fraction;
5503 return check_time_syntax(in, 0, parts, &fraction);
5507 generalizedTimeNormalize(
5512 struct berval *normalized,
5517 struct berval fraction;
5519 rc = check_time_syntax(val, 0, parts, &fraction);
5520 if (rc != LDAP_SUCCESS) {
5524 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5525 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5526 if ( BER_BVISNULL( normalized ) ) {
5527 return LBER_ERROR_MEMORY;
5530 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5531 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5532 parts[4], parts[5], parts[6] );
5533 if ( !BER_BVISEMPTY( &fraction ) ) {
5534 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5535 fraction.bv_val, fraction.bv_len );
5536 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5538 strcpy( normalized->bv_val + len-1, "Z" );
5539 normalized->bv_len = len;
5541 return LDAP_SUCCESS;
5545 generalizedTimeOrderingMatch(
5550 struct berval *value,
5551 void *assertedValue )
5553 struct berval *asserted = (struct berval *) assertedValue;
5554 ber_len_t v_len = value->bv_len;
5555 ber_len_t av_len = asserted->bv_len;
5557 /* ignore trailing 'Z' when comparing */
5558 int match = memcmp( value->bv_val, asserted->bv_val,
5559 (v_len < av_len ? v_len : av_len) - 1 );
5560 if ( match == 0 ) match = v_len - av_len;
5563 return LDAP_SUCCESS;
5566 /* Index generation function */
5567 int generalizedTimeIndexer(
5572 struct berval *prefix,
5580 BerValue bvtmp; /* 40 bit index */
5582 struct lutil_timet tt;
5584 bvtmp.bv_len = sizeof(tmp);
5586 for( i=0; values[i].bv_val != NULL; i++ ) {
5587 /* just count them */
5590 /* we should have at least one value at this point */
5593 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5595 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5596 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5597 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5598 /* Use 40 bits of time for key */
5599 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5600 lutil_tm2time( &tm, &tt );
5601 tmp[0] = tt.tt_gsec & 0xff;
5602 tmp[4] = tt.tt_sec & 0xff;
5604 tmp[3] = tt.tt_sec & 0xff;
5606 tmp[2] = tt.tt_sec & 0xff;
5608 tmp[1] = tt.tt_sec & 0xff;
5610 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5614 keys[j].bv_val = NULL;
5619 return LDAP_SUCCESS;
5622 /* Index generation function */
5623 int generalizedTimeFilter(
5628 struct berval *prefix,
5629 void * assertedValue,
5635 BerValue bvtmp; /* 40 bit index */
5636 BerValue *value = (BerValue *) assertedValue;
5638 struct lutil_timet tt;
5640 bvtmp.bv_len = sizeof(tmp);
5642 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5643 /* Use 40 bits of time for key */
5644 if ( value->bv_val && value->bv_len >= 10 &&
5645 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5647 lutil_tm2time( &tm, &tt );
5648 tmp[0] = tt.tt_gsec & 0xff;
5649 tmp[4] = tt.tt_sec & 0xff;
5651 tmp[3] = tt.tt_sec & 0xff;
5653 tmp[2] = tt.tt_sec & 0xff;
5655 tmp[1] = tt.tt_sec & 0xff;
5657 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5658 ber_dupbv_x(keys, &bvtmp, ctx );
5659 keys[1].bv_val = NULL;
5667 return LDAP_SUCCESS;
5671 deliveryMethodValidate(
5673 struct berval *val )
5676 #define LENOF(s) (sizeof(s)-1)
5677 struct berval tmp = *val;
5679 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5680 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5681 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5684 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5686 switch( tmp.bv_val[0] ) {
5689 if(( tmp.bv_len >= LENOF("any") ) &&
5690 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5692 tmp.bv_len -= LENOF("any");
5693 tmp.bv_val += LENOF("any");
5696 return LDAP_INVALID_SYNTAX;
5700 if(( tmp.bv_len >= LENOF("mhs") ) &&
5701 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5703 tmp.bv_len -= LENOF("mhs");
5704 tmp.bv_val += LENOF("mhs");
5707 return LDAP_INVALID_SYNTAX;
5711 if(( tmp.bv_len >= LENOF("physical") ) &&
5712 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5714 tmp.bv_len -= LENOF("physical");
5715 tmp.bv_val += LENOF("physical");
5718 return LDAP_INVALID_SYNTAX;
5721 case 'T': /* telex or teletex or telephone */
5722 if(( tmp.bv_len >= LENOF("telex") ) &&
5723 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5725 tmp.bv_len -= LENOF("telex");
5726 tmp.bv_val += LENOF("telex");
5729 if(( tmp.bv_len >= LENOF("teletex") ) &&
5730 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5732 tmp.bv_len -= LENOF("teletex");
5733 tmp.bv_val += LENOF("teletex");
5736 if(( tmp.bv_len >= LENOF("telephone") ) &&
5737 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5739 tmp.bv_len -= LENOF("telephone");
5740 tmp.bv_val += LENOF("telephone");
5743 return LDAP_INVALID_SYNTAX;
5746 case 'G': /* g3fax or g4fax */
5747 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5748 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5749 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5751 tmp.bv_len -= LENOF("g3fax");
5752 tmp.bv_val += LENOF("g3fax");
5755 return LDAP_INVALID_SYNTAX;
5759 if(( tmp.bv_len >= LENOF("ia5") ) &&
5760 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5762 tmp.bv_len -= LENOF("ia5");
5763 tmp.bv_val += LENOF("ia5");
5766 return LDAP_INVALID_SYNTAX;
5770 if(( tmp.bv_len >= LENOF("videotex") ) &&
5771 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5773 tmp.bv_len -= LENOF("videotex");
5774 tmp.bv_val += LENOF("videotex");
5777 return LDAP_INVALID_SYNTAX;
5780 return LDAP_INVALID_SYNTAX;
5783 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5785 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5789 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5793 return LDAP_INVALID_SYNTAX;
5795 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5804 nisNetgroupTripleValidate(
5806 struct berval *val )
5811 if ( BER_BVISEMPTY( val ) ) {
5812 return LDAP_INVALID_SYNTAX;
5815 p = (char *)val->bv_val;
5816 e = p + val->bv_len;
5818 if ( *p != '(' /*')'*/ ) {
5819 return LDAP_INVALID_SYNTAX;
5822 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5826 return LDAP_INVALID_SYNTAX;
5829 } else if ( !AD_CHAR( *p ) ) {
5830 return LDAP_INVALID_SYNTAX;
5834 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5835 return LDAP_INVALID_SYNTAX;
5841 return LDAP_INVALID_SYNTAX;
5844 return LDAP_SUCCESS;
5848 bootParameterValidate(
5850 struct berval *val )
5854 if ( BER_BVISEMPTY( val ) ) {
5855 return LDAP_INVALID_SYNTAX;
5858 p = (char *)val->bv_val;
5859 e = p + val->bv_len;
5862 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5863 if ( !AD_CHAR( *p ) ) {
5864 return LDAP_INVALID_SYNTAX;
5869 return LDAP_INVALID_SYNTAX;
5873 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5874 if ( !AD_CHAR( *p ) ) {
5875 return LDAP_INVALID_SYNTAX;
5880 return LDAP_INVALID_SYNTAX;
5884 for ( p++; p < e; p++ ) {
5885 if ( !SLAP_PRINTABLE( *p ) ) {
5886 return LDAP_INVALID_SYNTAX;
5890 return LDAP_SUCCESS;
5894 firstComponentNormalize(
5899 struct berval *normalized,
5906 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5907 ber_dupbv_x( normalized, val, ctx );
5908 return LDAP_SUCCESS;
5911 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5913 if( ! ( val->bv_val[0] == '(' /*')'*/
5914 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5915 && ! ( val->bv_val[0] == '{' /*'}'*/
5916 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5918 return LDAP_INVALID_SYNTAX;
5921 /* trim leading white space */
5923 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5929 /* grab next word */
5930 comp.bv_val = &val->bv_val[len];
5931 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5932 for( comp.bv_len = 0;
5933 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5939 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5940 rc = numericoidValidate( NULL, &comp );
5941 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5942 rc = integerValidate( NULL, &comp );
5944 rc = LDAP_INVALID_SYNTAX;
5948 if( rc == LDAP_SUCCESS ) {
5949 ber_dupbv_x( normalized, &comp, ctx );
5955 static char *country_gen_syn[] = {
5956 "1.3.6.1.4.1.1466.115.121.1.15",
5957 "1.3.6.1.4.1.1466.115.121.1.26",
5958 "1.3.6.1.4.1.1466.115.121.1.44",
5962 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
5963 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
5965 static slap_syntax_defs_rec syntax_defs[] = {
5966 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
5967 X_BINARY X_NOT_H_R ")",
5968 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
5969 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
5970 0, NULL, NULL, NULL},
5971 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
5972 0, NULL, NULL, NULL},
5973 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
5975 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5976 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
5978 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5979 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
5980 0, NULL, bitStringValidate, NULL },
5981 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
5982 0, NULL, booleanValidate, NULL},
5983 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
5984 X_BINARY X_NOT_H_R ")",
5985 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5986 NULL, certificateValidate, NULL},
5987 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
5988 X_BINARY X_NOT_H_R ")",
5989 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5990 NULL, certificateListValidate, NULL},
5991 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
5992 X_BINARY X_NOT_H_R ")",
5993 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5994 NULL, sequenceValidate, NULL},
5995 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
5996 X_BINARY X_NOT_H_R ")",
5997 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5998 NULL, attributeCertificateValidate, NULL},
5999 #if 0 /* need to go __after__ printableString */
6000 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6001 0, "1.3.6.1.4.1.1466.115.121.1.44",
6002 countryStringValidate, NULL},
6004 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6005 0, NULL, dnValidate, dnPretty},
6006 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6007 0, NULL, rdnValidate, rdnPretty},
6008 #ifdef LDAP_COMP_MATCH
6009 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6010 0, NULL, allComponentsValidate, NULL},
6011 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6012 0, NULL, componentFilterValidate, NULL},
6014 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6015 0, NULL, NULL, NULL},
6016 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6017 0, NULL, deliveryMethodValidate, NULL},
6018 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6019 0, NULL, UTF8StringValidate, NULL},
6020 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6021 0, NULL, NULL, NULL},
6022 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6023 0, NULL, NULL, NULL},
6024 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6025 0, NULL, NULL, NULL},
6026 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6027 0, NULL, NULL, NULL},
6028 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6029 0, NULL, NULL, NULL},
6030 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6031 0, NULL, printablesStringValidate, NULL},
6032 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6033 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6034 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6035 0, NULL, generalizedTimeValidate, NULL},
6036 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6037 0, NULL, NULL, NULL},
6038 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6039 0, NULL, IA5StringValidate, NULL},
6040 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6041 0, NULL, integerValidate, NULL},
6042 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6043 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6044 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6045 0, NULL, NULL, NULL},
6046 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6047 0, NULL, NULL, NULL},
6048 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6049 0, NULL, NULL, NULL},
6050 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6051 0, NULL, NULL, NULL},
6052 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6053 0, NULL, NULL, NULL},
6054 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6055 0, NULL, nameUIDValidate, nameUIDPretty },
6056 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6057 0, NULL, NULL, NULL},
6058 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6059 0, NULL, numericStringValidate, NULL},
6060 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6061 0, NULL, NULL, NULL},
6062 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6063 0, NULL, numericoidValidate, NULL},
6064 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6065 0, NULL, IA5StringValidate, NULL},
6066 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6067 0, NULL, blobValidate, NULL},
6068 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6069 0, NULL, postalAddressValidate, NULL},
6070 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6071 0, NULL, NULL, NULL},
6072 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6073 0, NULL, NULL, NULL},
6074 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6075 0, NULL, printableStringValidate, NULL},
6076 /* moved here because now depends on Directory String, IA5 String
6077 * and Printable String */
6078 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6079 0, country_gen_syn, countryStringValidate, NULL},
6080 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6081 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6082 0, NULL, subtreeSpecificationValidate, NULL},
6083 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6084 X_BINARY X_NOT_H_R ")",
6085 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6086 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6087 0, NULL, printableStringValidate, NULL},
6088 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6089 0, NULL, NULL, NULL},
6090 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6091 0, NULL, printablesStringValidate, NULL},
6092 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6093 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6094 0, NULL, utcTimeValidate, NULL},
6096 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6097 0, NULL, NULL, NULL},
6098 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6099 0, NULL, NULL, NULL},
6100 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6101 0, NULL, NULL, NULL},
6102 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6103 0, NULL, NULL, NULL},
6104 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6105 0, NULL, NULL, NULL},
6107 /* RFC 2307 NIS Syntaxes */
6108 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6109 0, NULL, nisNetgroupTripleValidate, NULL},
6110 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6111 0, NULL, bootParameterValidate, NULL},
6113 /* draft-zeilenga-ldap-x509 */
6114 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6115 SLAP_SYNTAX_HIDE, NULL,
6116 serialNumberAndIssuerValidate,
6117 serialNumberAndIssuerPretty},
6118 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6119 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6120 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6121 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6122 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6123 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6124 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6125 SLAP_SYNTAX_HIDE, NULL,
6126 issuerAndThisUpdateValidate,
6127 issuerAndThisUpdatePretty},
6128 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6129 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6130 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6131 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6132 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6133 SLAP_SYNTAX_HIDE, NULL,
6134 serialNumberAndIssuerSerialValidate,
6135 serialNumberAndIssuerSerialPretty},
6136 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6137 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6139 #ifdef SLAPD_AUTHPASSWD
6140 /* needs updating */
6141 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6142 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6145 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6146 0, NULL, UUIDValidate, UUIDPretty},
6148 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6149 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6151 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6152 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6154 /* OpenLDAP Void Syntax */
6155 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6156 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6158 /* FIXME: OID is unused, but not registered yet */
6159 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6160 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6162 {NULL, 0, NULL, NULL, NULL}
6165 char *csnSIDMatchSyntaxes[] = {
6166 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6169 char *certificateExactMatchSyntaxes[] = {
6170 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6173 char *certificateListExactMatchSyntaxes[] = {
6174 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6177 char *attributeCertificateExactMatchSyntaxes[] = {
6178 attributeCertificateSyntaxOID /* attributeCertificate */,
6182 #ifdef LDAP_COMP_MATCH
6183 char *componentFilterMatchSyntaxes[] = {
6184 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6185 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6186 attributeCertificateSyntaxOID /* attributeCertificate */,
6191 char *directoryStringSyntaxes[] = {
6192 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6195 char *integerFirstComponentMatchSyntaxes[] = {
6196 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6197 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6200 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6201 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6202 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6203 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6204 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6205 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6206 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6207 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6208 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6213 * Other matching rules in X.520 that we do not use (yet):
6215 * 2.5.13.25 uTCTimeMatch
6216 * 2.5.13.26 uTCTimeOrderingMatch
6217 * 2.5.13.31* directoryStringFirstComponentMatch
6218 * 2.5.13.32* wordMatch
6219 * 2.5.13.33* keywordMatch
6220 * 2.5.13.36+ certificatePairExactMatch
6221 * 2.5.13.37+ certificatePairMatch
6222 * 2.5.13.40+ algorithmIdentifierMatch
6223 * 2.5.13.41* storedPrefixMatch
6224 * 2.5.13.42 attributeCertificateMatch
6225 * 2.5.13.43 readerAndKeyIDMatch
6226 * 2.5.13.44 attributeIntegrityMatch
6228 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6229 * (+) described in draft-zeilenga-ldap-x509
6231 static slap_mrule_defs_rec mrule_defs[] = {
6233 * EQUALITY matching rules must be listed after associated APPROX
6234 * matching rules. So, we list all APPROX matching rules first.
6236 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6237 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6238 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6239 NULL, NULL, directoryStringApproxMatch,
6240 directoryStringApproxIndexer, directoryStringApproxFilter,
6243 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6244 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6245 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6246 NULL, NULL, IA5StringApproxMatch,
6247 IA5StringApproxIndexer, IA5StringApproxFilter,
6251 * Other matching rules
6254 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6255 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6256 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6257 NULL, NULL, octetStringMatch,
6258 octetStringIndexer, octetStringFilter,
6261 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6262 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6263 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6264 NULL, dnNormalize, dnMatch,
6265 octetStringIndexer, octetStringFilter,
6268 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6269 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6270 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6271 NULL, dnNormalize, dnRelativeMatch,
6275 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6276 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6277 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6278 NULL, dnNormalize, dnRelativeMatch,
6282 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6283 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6284 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6285 NULL, dnNormalize, dnRelativeMatch,
6289 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6290 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6291 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6292 NULL, dnNormalize, dnRelativeMatch,
6296 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6297 "SYNTAX 1.2.36.79672281.1.5.0 )",
6298 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6299 NULL, rdnNormalize, rdnMatch,
6300 octetStringIndexer, octetStringFilter,
6303 #ifdef LDAP_COMP_MATCH
6304 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6305 "SYNTAX 1.2.36.79672281.1.5.2 )",
6306 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6307 NULL, NULL , componentFilterMatch,
6308 octetStringIndexer, octetStringFilter,
6311 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6312 "SYNTAX 1.2.36.79672281.1.5.3 )",
6313 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6314 NULL, NULL , allComponentsMatch,
6315 octetStringIndexer, octetStringFilter,
6318 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6319 "SYNTAX 1.2.36.79672281.1.5.3 )",
6320 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6321 NULL, NULL , directoryComponentsMatch,
6322 octetStringIndexer, octetStringFilter,
6326 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6327 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6328 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6329 NULL, UTF8StringNormalize, octetStringMatch,
6330 octetStringIndexer, octetStringFilter,
6331 directoryStringApproxMatchOID },
6333 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6334 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6335 SLAP_MR_ORDERING, directoryStringSyntaxes,
6336 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6338 "caseIgnoreMatch" },
6340 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6341 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6342 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6343 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6344 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6345 "caseIgnoreMatch" },
6347 {"( 2.5.13.5 NAME 'caseExactMatch' "
6348 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6349 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6350 NULL, UTF8StringNormalize, octetStringMatch,
6351 octetStringIndexer, octetStringFilter,
6352 directoryStringApproxMatchOID },
6354 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6355 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6356 SLAP_MR_ORDERING, directoryStringSyntaxes,
6357 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6361 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6362 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6363 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6364 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6365 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6368 {"( 2.5.13.8 NAME 'numericStringMatch' "
6369 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6370 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6371 NULL, numericStringNormalize, octetStringMatch,
6372 octetStringIndexer, octetStringFilter,
6375 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6376 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6377 SLAP_MR_ORDERING, NULL,
6378 NULL, numericStringNormalize, octetStringOrderingMatch,
6380 "numericStringMatch" },
6382 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6383 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6384 SLAP_MR_SUBSTR, NULL,
6385 NULL, numericStringNormalize, octetStringSubstringsMatch,
6386 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6387 "numericStringMatch" },
6389 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6390 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6391 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6392 NULL, postalAddressNormalize, octetStringMatch,
6393 octetStringIndexer, octetStringFilter,
6396 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6397 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6398 SLAP_MR_SUBSTR, NULL,
6399 NULL, NULL, NULL, NULL, NULL,
6400 "caseIgnoreListMatch" },
6402 {"( 2.5.13.13 NAME 'booleanMatch' "
6403 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6404 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6405 NULL, NULL, booleanMatch,
6406 octetStringIndexer, octetStringFilter,
6409 {"( 2.5.13.14 NAME 'integerMatch' "
6410 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6411 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6412 NULL, NULL, integerMatch,
6413 integerIndexer, integerFilter,
6416 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6417 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6418 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6419 NULL, NULL, integerMatch,
6423 {"( 2.5.13.16 NAME 'bitStringMatch' "
6424 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6425 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6426 NULL, NULL, octetStringMatch,
6427 octetStringIndexer, octetStringFilter,
6430 {"( 2.5.13.17 NAME 'octetStringMatch' "
6431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6432 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6433 NULL, NULL, octetStringMatch,
6434 octetStringIndexer, octetStringFilter,
6437 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6438 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6439 SLAP_MR_ORDERING, NULL,
6440 NULL, NULL, octetStringOrderingMatch,
6442 "octetStringMatch" },
6444 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6445 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6446 SLAP_MR_SUBSTR, NULL,
6447 NULL, NULL, octetStringSubstringsMatch,
6448 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6449 "octetStringMatch" },
6451 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6453 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6455 telephoneNumberNormalize, octetStringMatch,
6456 octetStringIndexer, octetStringFilter,
6459 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6460 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6461 SLAP_MR_SUBSTR, NULL,
6462 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6463 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6464 "telephoneNumberMatch" },
6466 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6468 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6469 NULL, NULL, NULL, NULL, NULL, NULL },
6471 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6472 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6473 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6474 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6475 uniqueMemberIndexer, uniqueMemberFilter,
6478 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6480 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6481 NULL, NULL, NULL, NULL, NULL, NULL },
6483 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6484 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6485 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6486 NULL, generalizedTimeNormalize, octetStringMatch,
6487 generalizedTimeIndexer, generalizedTimeFilter,
6490 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6492 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6493 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6495 "generalizedTimeMatch" },
6497 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6498 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6499 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6500 integerFirstComponentMatchSyntaxes,
6501 NULL, firstComponentNormalize, integerMatch,
6502 octetStringIndexer, octetStringFilter,
6505 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6507 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6508 objectIdentifierFirstComponentMatchSyntaxes,
6509 NULL, firstComponentNormalize, octetStringMatch,
6510 octetStringIndexer, octetStringFilter,
6513 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6514 "SYNTAX 1.3.6.1.1.15.1 )",
6515 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6516 NULL, certificateExactNormalize, octetStringMatch,
6517 octetStringIndexer, octetStringFilter,
6520 {"( 2.5.13.35 NAME 'certificateMatch' "
6521 "SYNTAX 1.3.6.1.1.15.2 )",
6522 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6523 NULL, NULL, NULL, NULL, NULL,
6526 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6527 "SYNTAX 1.3.6.1.1.15.5 )",
6528 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6529 NULL, certificateListExactNormalize, octetStringMatch,
6530 octetStringIndexer, octetStringFilter,
6533 {"( 2.5.13.39 NAME 'certificateListMatch' "
6534 "SYNTAX 1.3.6.1.1.15.6 )",
6535 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6536 NULL, NULL, NULL, NULL, NULL,
6539 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6540 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6541 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6542 NULL, attributeCertificateExactNormalize, octetStringMatch,
6543 octetStringIndexer, octetStringFilter,
6546 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6547 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6548 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6549 NULL, NULL, NULL, NULL, NULL,
6552 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6553 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6554 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6555 NULL, IA5StringNormalize, octetStringMatch,
6556 octetStringIndexer, octetStringFilter,
6557 IA5StringApproxMatchOID },
6559 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6560 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6561 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6562 NULL, IA5StringNormalize, octetStringMatch,
6563 octetStringIndexer, octetStringFilter,
6564 IA5StringApproxMatchOID },
6566 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6567 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6568 SLAP_MR_SUBSTR, NULL,
6569 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6570 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6571 "caseIgnoreIA5Match" },
6573 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6574 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6575 SLAP_MR_SUBSTR, NULL,
6576 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6577 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6578 "caseExactIA5Match" },
6580 #ifdef SLAPD_AUTHPASSWD
6581 /* needs updating */
6582 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6583 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6584 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6585 NULL, NULL, authPasswordMatch,
6590 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6591 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6593 NULL, NULL, integerBitAndMatch,
6597 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6598 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6600 NULL, NULL, integerBitOrMatch,
6604 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6605 "SYNTAX 1.3.6.1.1.16.1 )",
6606 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6607 NULL, UUIDNormalize, octetStringMatch,
6608 octetStringIndexer, octetStringFilter,
6611 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6612 "SYNTAX 1.3.6.1.1.16.1 )",
6613 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6614 NULL, UUIDNormalize, octetStringOrderingMatch,
6615 octetStringIndexer, octetStringFilter,
6618 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6619 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6620 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6621 NULL, csnNormalize, csnMatch,
6622 csnIndexer, csnFilter,
6625 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6626 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6627 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6628 NULL, NULL, csnOrderingMatch,
6632 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6633 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6634 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6635 NULL, csnSidNormalize, octetStringMatch,
6636 octetStringIndexer, octetStringFilter,
6639 /* FIXME: OID is unused, but not registered yet */
6640 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6641 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6642 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6643 NULL, authzNormalize, authzMatch,
6647 {NULL, SLAP_MR_NONE, NULL,
6648 NULL, NULL, NULL, NULL, NULL,
6653 slap_schema_init( void )
6658 /* we should only be called once (from main) */
6659 assert( schema_init_done == 0 );
6661 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6662 res = register_syntax( &syntax_defs[i] );
6665 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6666 syntax_defs[i].sd_desc );
6671 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6672 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6673 mrule_defs[i].mrd_compat_syntaxes == NULL )
6676 "slap_schema_init: Ignoring unusable matching rule %s\n",
6677 mrule_defs[i].mrd_desc );
6681 res = register_matching_rule( &mrule_defs[i] );
6685 "slap_schema_init: Error registering matching rule %s\n",
6686 mrule_defs[i].mrd_desc );
6691 res = slap_schema_load();
6692 schema_init_done = 1;
6697 schema_destroy( void )
6706 if( schema_init_done ) {
6707 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6708 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );