1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2009 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
26 #include <ac/string.h>
27 #include <ac/socket.h>
30 #include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */
32 #include "ldap_utf8.h"
35 #include "lutil_hash.h"
36 #define HASH_BYTES LUTIL_HASH_BYTES
37 #define HASH_CONTEXT lutil_HASH_CTX
38 #define HASH_Init(c) lutil_HASHInit(c)
39 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
40 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
42 /* approx matching rules */
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
52 /* Change Sequence Number (CSN) - much of this will change */
53 #define csnMatch octetStringMatch
54 #define csnOrderingMatch octetStringOrderingMatch
55 #define csnIndexer generalizedTimeIndexer
56 #define csnFilter generalizedTimeFilter
58 #define authzMatch octetStringMatch
60 /* X.509 PMI ldapSyntaxes */
61 /* FIXME: need to create temporary OIDs under OpenLDAP's arc;
62 * these are currently hijacked
64 * 1.3.6.1.4.1.4203.666 OpenLDAP
65 * 1.3.6.1.4.1.4203.666.11 self-contained works
66 * 1.3.6.1.4.1.4203.666.11.10 X.509 PMI
67 * 1.3.6.1.4.1.4203.666.11.10.2 X.509 PMI ldapSyntaxes
68 * 1.3.6.1.4.1.4203.666.11.10.2.1 AttributeCertificate (supported)
69 * 1.3.6.1.4.1.4203.666.11.10.2.2 AttributeCertificateExactAssertion (supported)
70 * 1.3.6.1.4.1.4203.666.11.10.2.3 AttributeCertificateAssertion (not supported)
71 * 1.3.6.1.4.1.4203.666.11.10.2.4 AttCertPath (X-SUBST'ed right now in pmi.schema)
72 * 1.3.6.1.4.1.4203.666.11.10.2.5 PolicySyntax (X-SUBST'ed right now in pmi.schema)
73 * 1.3.6.1.4.1.4203.666.11.10.2.6 RoleSyntax (X-SUBST'ed right now in pmi.schema)
75 #if 0 /* from <draft-ietf-pkix-ldap-schema-02.txt> (expired) */
76 #define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5"
77 #define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6"
78 #define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7"
79 #else /* from OpenLDAP's experimental oid arc */
80 #define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2"
81 #define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1"
82 #define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2"
83 #define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3"
86 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
87 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
88 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
89 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
91 unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
92 unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
93 SLAP_INDEX_INTLEN_DEFAULT );
95 ldap_pvt_thread_mutex_t ad_undef_mutex;
96 ldap_pvt_thread_mutex_t oc_undef_mutex;
99 generalizedTimeValidate(
103 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
108 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
115 /* no value allowed */
116 return LDAP_INVALID_SYNTAX;
124 /* any value allowed */
128 #define berValidate blobValidate
135 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
136 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
141 /* X.509 related stuff */
150 SLAP_TAG_UTCTIME = 0x17U,
151 SLAP_TAG_GENERALIZEDTIME = 0x18U
155 #define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
158 SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
159 SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1,
160 SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2,
161 SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
165 SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
169 GeneralName ::= CHOICE {
170 otherName [0] INSTANCE OF OTHER-NAME,
171 rfc822Name [1] IA5String,
172 dNSName [2] IA5String,
173 x400Address [3] ORAddress,
174 directoryName [4] Name,
175 ediPartyName [5] EDIPartyName,
176 uniformResourceIdentifier [6] IA5String,
177 iPAddress [7] OCTET STRING,
178 registeredID [8] OBJECT IDENTIFIER }
181 SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0,
182 SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1,
183 SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2,
184 SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3,
185 SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4,
186 SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5,
187 SLAP_X509_GN_URI = SLAP_X509_OPTION + 6,
188 SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7,
189 SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8
192 /* X.509 PMI related stuff */
199 SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0
202 /* X.509 certificate validation */
204 certificateValidate( Syntax *syntax, struct berval *in )
206 BerElementBuffer berbuf;
207 BerElement *ber = (BerElement *)&berbuf;
210 ber_int_t version = SLAP_X509_V1;
212 ber_init2( ber, in, LBER_USE_DER );
213 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
214 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
215 tag = ber_skip_tag( ber, &len ); /* Sequence */
216 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
217 tag = ber_peek_tag( ber, &len );
218 /* Optional version */
219 if ( tag == SLAP_X509_OPT_C_VERSION ) {
220 tag = ber_skip_tag( ber, &len );
221 tag = ber_get_int( ber, &version );
222 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
224 /* NOTE: don't try to parse Serial, because it might be longer
225 * than sizeof(ber_int_t); deferred to certificateExactNormalize() */
226 tag = ber_skip_tag( ber, &len ); /* Serial */
227 if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
228 ber_skip_data( ber, len );
229 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
230 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
231 ber_skip_data( ber, len );
232 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
233 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
234 ber_skip_data( ber, len );
235 tag = ber_skip_tag( ber, &len ); /* Validity */
236 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
237 ber_skip_data( ber, len );
238 tag = ber_skip_tag( ber, &len ); /* Subject DN */
239 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
240 ber_skip_data( ber, len );
241 tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */
242 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
243 ber_skip_data( ber, len );
244 tag = ber_skip_tag( ber, &len );
245 if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) { /* issuerUniqueID */
246 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
247 ber_skip_data( ber, len );
248 tag = ber_skip_tag( ber, &len );
250 if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) { /* subjectUniqueID */
251 if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
252 ber_skip_data( ber, len );
253 tag = ber_skip_tag( ber, &len );
255 if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) { /* Extensions */
256 if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
257 tag = ber_skip_tag( ber, &len );
258 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
259 ber_skip_data( ber, len );
260 tag = ber_skip_tag( ber, &len );
262 /* signatureAlgorithm */
263 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
264 ber_skip_data( ber, len );
265 tag = ber_skip_tag( ber, &len );
267 if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
268 ber_skip_data( ber, len );
269 tag = ber_skip_tag( ber, &len );
270 /* Must be at end now */
271 if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
275 /* X.509 certificate list validation */
277 certificateListValidate( Syntax *syntax, struct berval *in )
279 BerElementBuffer berbuf;
280 BerElement *ber = (BerElement *)&berbuf;
283 ber_int_t version = SLAP_X509_V1;
285 ber_init2( ber, in, LBER_USE_DER );
286 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
287 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
288 tag = ber_skip_tag( ber, &len ); /* Sequence */
289 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
290 tag = ber_peek_tag( ber, &len );
291 /* Optional version */
292 if ( tag == LBER_INTEGER ) {
293 tag = ber_get_int( ber, &version );
294 assert( tag == LBER_INTEGER );
295 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
297 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
298 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
299 ber_skip_data( ber, len );
300 tag = ber_skip_tag( ber, &len ); /* Issuer DN */
301 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
302 ber_skip_data( ber, len );
303 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
304 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
305 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
306 ber_skip_data( ber, len );
307 /* Optional nextUpdate */
308 tag = ber_skip_tag( ber, &len );
309 if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
310 ber_skip_data( ber, len );
311 tag = ber_skip_tag( ber, &len );
313 /* revokedCertificates - Sequence of Sequence, Optional */
314 if ( tag == LBER_SEQUENCE ) {
316 if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
317 /* Should NOT be empty */
318 ber_skip_data( ber, len );
319 tag = ber_skip_tag( ber, &len );
322 /* Optional Extensions */
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 BER_BVZERO( normalized );
2818 return LDAP_INVALID_SYNTAX;
2823 normalized->bv_val[j>>1] = octet;
2825 octet = nibble << 4;
2830 normalized->bv_val[normalized->bv_len] = 0;
2831 return LDAP_SUCCESS;
2837 numericStringValidate(
2843 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2845 for(i=0; i < in->bv_len; i++) {
2846 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2847 return LDAP_INVALID_SYNTAX;
2851 return LDAP_SUCCESS;
2855 numericStringNormalize(
2860 struct berval *normalized,
2863 /* removal all spaces */
2866 assert( !BER_BVISEMPTY( val ) );
2868 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2871 q = normalized->bv_val;
2874 if ( ASCII_SPACE( *p ) ) {
2875 /* Ignore whitespace */
2882 /* we should have copied no more than is in val */
2883 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2885 /* null terminate */
2888 normalized->bv_len = q - normalized->bv_val;
2890 if( BER_BVISEMPTY( normalized ) ) {
2891 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2892 normalized->bv_val[0] = ' ';
2893 normalized->bv_val[1] = '\0';
2894 normalized->bv_len = 1;
2897 return LDAP_SUCCESS;
2901 * Integer conversion macros that will use the largest available
2904 #if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
2905 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2906 # define SLAP_LONG long long
2908 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2909 # define SLAP_LONG long
2910 #endif /* HAVE_STRTOLL ... */
2918 struct berval *value,
2919 void *assertedValue )
2921 SLAP_LONG lValue, lAssertedValue;
2924 /* safe to assume integers are NUL terminated? */
2925 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2926 if( errno == ERANGE )
2928 return LDAP_CONSTRAINT_VIOLATION;
2931 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2933 if( errno == ERANGE )
2935 return LDAP_CONSTRAINT_VIOLATION;
2938 *matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
2939 return LDAP_SUCCESS;
2948 struct berval *value,
2949 void *assertedValue )
2951 SLAP_LONG lValue, lAssertedValue;
2954 /* safe to assume integers are NUL terminated? */
2955 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2956 if( errno == ERANGE )
2958 return LDAP_CONSTRAINT_VIOLATION;
2961 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2963 if( errno == ERANGE )
2965 return LDAP_CONSTRAINT_VIOLATION;
2968 *matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
2969 return LDAP_SUCCESS;
2973 checkNum( struct berval *in, struct berval *out )
2975 /* parse serialNumber */
2976 ber_len_t neg = 0, extra = 0;
2979 out->bv_val = in->bv_val;
2982 if ( out->bv_val[0] == '-' ) {
2987 if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
2988 first = out->bv_val[2];
2991 out->bv_len += STRLENOF("0x");
2992 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
2993 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
2996 } else if ( out->bv_val[0] == '\'' ) {
2997 first = out->bv_val[1];
3000 out->bv_len += STRLENOF("'");
3002 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3003 if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
3005 if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
3008 out->bv_len += STRLENOF("'H");
3011 first = out->bv_val[0];
3012 for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
3013 if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
3017 if ( !( out->bv_len > neg ) ) {
3021 if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
3029 serialNumberAndIssuerCheck(
3037 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3039 if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3040 /* Parse old format */
3041 is->bv_val = ber_bvchr( in, '$' );
3042 if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
3044 sn->bv_val = in->bv_val;
3045 sn->bv_len = is->bv_val - in->bv_val;
3048 is->bv_len = in->bv_len - (sn->bv_len + 1);
3050 /* eat leading zeros */
3051 for( n=0; n < (sn->bv_len-1); n++ ) {
3052 if( sn->bv_val[n] != '0' ) break;
3057 for( n=0; n < sn->bv_len; n++ ) {
3058 if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
3062 /* Parse GSER format */
3067 HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
3071 struct berval x = *in;
3077 /* eat leading spaces */
3078 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3082 /* should be at issuer or serialNumber NamedValue */
3083 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3084 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3087 x.bv_val += STRLENOF("issuer");
3088 x.bv_len -= STRLENOF("issuer");
3090 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3094 /* eat leading spaces */
3095 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3099 /* For backward compatibility, this part is optional */
3100 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
3101 x.bv_val += STRLENOF("rdnSequence:");
3102 x.bv_len -= STRLENOF("rdnSequence:");
3105 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3109 is->bv_val = x.bv_val;
3112 for ( ; is->bv_len < x.bv_len; ) {
3113 if ( is->bv_val[is->bv_len] != '"' ) {
3117 if ( is->bv_val[is->bv_len+1] == '"' ) {
3124 x.bv_val += is->bv_len + 1;
3125 x.bv_len -= is->bv_len + 1;
3127 have |= HAVE_ISSUER;
3129 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
3131 if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
3133 /* parse serialNumber */
3134 x.bv_val += STRLENOF("serialNumber");
3135 x.bv_len -= STRLENOF("serialNumber");
3137 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3141 /* eat leading spaces */
3142 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3146 if ( checkNum( &x, sn ) ) {
3147 return LDAP_INVALID_SYNTAX;
3150 x.bv_val += sn->bv_len;
3151 x.bv_len -= sn->bv_len;
3156 return LDAP_INVALID_SYNTAX;
3159 /* eat leading spaces */
3160 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3164 if ( have == HAVE_ALL ) {
3168 if ( x.bv_val[0] != ',' ) {
3169 return LDAP_INVALID_SYNTAX;
3176 /* should have no characters left... */
3177 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3179 if ( numdquotes == 0 ) {
3180 ber_dupbv_x( &ni, is, ctx );
3185 ni.bv_len = is->bv_len - numdquotes;
3186 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3187 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3188 if ( is->bv_val[src] == '"' ) {
3191 ni.bv_val[dst] = is->bv_val[src];
3193 ni.bv_val[dst] = '\0';
3203 serialNumberAndIssuerValidate(
3208 struct berval sn, i;
3210 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
3213 rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
3218 /* validate DN -- doesn't handle double dquote */
3219 rc = dnValidate( NULL, &i );
3221 rc = LDAP_INVALID_SYNTAX;
3224 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3225 slap_sl_free( i.bv_val, NULL );
3228 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
3229 in->bv_val, rc, 0 );
3236 serialNumberAndIssuerPretty(
3243 struct berval sn, i, ni = BER_BVNULL;
3246 assert( in != NULL );
3247 assert( out != NULL );
3251 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
3254 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3259 rc = dnPretty( syntax, &i, &ni, ctx );
3261 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3262 slap_sl_free( i.bv_val, ctx );
3266 rc = LDAP_INVALID_SYNTAX;
3270 /* make room from sn + "$" */
3271 out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
3272 + sn.bv_len + ni.bv_len;
3273 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3275 if ( out->bv_val == NULL ) {
3282 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3283 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
3284 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3285 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3286 p = lutil_strcopy( p, /*{*/ "\" }" );
3288 assert( p == &out->bv_val[out->bv_len] );
3291 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
3292 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3294 slap_sl_free( ni.bv_val, ctx );
3296 return LDAP_SUCCESS;
3306 /* Use hex format. '123456789abcdef'H */
3307 unsigned char *ptr, zero = '\0';
3310 ber_len_t i, len, nlen;
3312 assert( in != NULL );
3313 assert( !BER_BVISNULL( in ) );
3314 assert( out != NULL );
3315 assert( !BER_BVISNULL( out ) );
3317 ptr = (unsigned char *)in->bv_val;
3320 /* Check for minimal encodings */
3322 if ( ptr[0] & 0x80 ) {
3323 if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
3327 } else if ( ptr[0] == 0 ) {
3328 if ( !( ptr[1] & 0x80 ) ) {
3335 } else if ( len == 0 ) {
3336 /* FIXME: this should not be possible,
3337 * since a value of zero would have length 1 */
3342 first = !( ptr[0] & 0xf0U );
3343 nlen = len * 2 - first + STRLENOF("''H"); /* quotes, H */
3344 if ( nlen >= out->bv_len ) {
3345 out->bv_val = slap_sl_malloc( nlen + 1, ctx );
3351 sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
3355 for ( ; i < len; i++ ) {
3356 sprintf( sptr, "%02X", ptr[i] );
3363 assert( sptr == &out->bv_val[nlen] );
3370 #define SLAP_SN_BUFLEN (64)
3373 * This routine is called by certificateExactNormalize when
3374 * certificateExactNormalize receives a search string instead of
3375 * a certificate. This routine checks if the search value is valid
3376 * and then returns the normalized value
3379 serialNumberAndIssuerNormalize(
3387 struct berval sn, sn2, sn3, i, ni;
3388 char sbuf2[SLAP_SN_BUFLEN];
3389 char sbuf3[SLAP_SN_BUFLEN];
3393 assert( in != NULL );
3394 assert( out != NULL );
3396 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
3399 rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
3404 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3406 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3407 slap_sl_free( i.bv_val, ctx );
3411 return LDAP_INVALID_SYNTAX;
3414 /* Convert sn to canonical hex */
3416 if ( sn.bv_len > sizeof( sbuf2 ) ) {
3417 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
3419 sn2.bv_len = sn.bv_len;
3420 if ( lutil_str2bin( &sn, &sn2, ctx )) {
3421 rc = LDAP_INVALID_SYNTAX;
3426 sn3.bv_len = sizeof(sbuf3);
3427 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
3428 rc = LDAP_INVALID_SYNTAX;
3432 out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3433 + sn3.bv_len + ni.bv_len;
3434 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3436 if ( out->bv_val == NULL ) {
3444 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3445 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
3446 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3447 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3448 p = lutil_strcopy( p, /*{*/ "\" }" );
3450 assert( p == &out->bv_val[out->bv_len] );
3453 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
3454 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3456 if ( sn2.bv_val != sbuf2 ) {
3457 slap_sl_free( sn2.bv_val, ctx );
3460 if ( sn3.bv_val != sbuf3 ) {
3461 slap_sl_free( sn3.bv_val, ctx );
3464 slap_sl_free( ni.bv_val, ctx );
3470 certificateExactNormalize(
3475 struct berval *normalized,
3478 BerElementBuffer berbuf;
3479 BerElement *ber = (BerElement *)&berbuf;
3483 char serialbuf2[SLAP_SN_BUFLEN];
3484 struct berval sn, sn2 = BER_BVNULL;
3485 struct berval issuer_dn = BER_BVNULL, bvdn;
3487 int rc = LDAP_INVALID_SYNTAX;
3489 assert( val != NULL );
3491 Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
3492 val->bv_val, val->bv_len, 0 );
3494 if ( BER_BVISEMPTY( val ) ) goto done;
3496 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3497 return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
3500 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3502 ber_init2( ber, val, LBER_USE_DER );
3503 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
3504 tag = ber_skip_tag( ber, &len ); /* Sequence */
3505 tag = ber_peek_tag( ber, &len ); /* Optional version? */
3506 if ( tag == SLAP_X509_OPT_C_VERSION ) {
3507 tag = ber_skip_tag( ber, &len );
3508 tag = ber_get_int( ber, &i ); /* version */
3511 /* NOTE: move the test here from certificateValidate,
3512 * so that we can validate certs with serial longer
3513 * than sizeof(ber_int_t) */
3514 tag = ber_skip_tag( ber, &len ); /* serial */
3516 sn.bv_val = (char *)ber->ber_ptr;
3517 sn2.bv_val = serialbuf2;
3518 sn2.bv_len = sizeof(serialbuf2);
3519 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
3520 rc = LDAP_INVALID_SYNTAX;
3523 ber_skip_data( ber, len );
3525 tag = ber_skip_tag( ber, &len ); /* SignatureAlg */
3526 ber_skip_data( ber, len );
3527 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
3528 len = ber_ptrlen( ber );
3529 bvdn.bv_val = val->bv_val + len;
3530 bvdn.bv_len = val->bv_len - len;
3532 rc = dnX509normalize( &bvdn, &issuer_dn );
3533 if ( rc != LDAP_SUCCESS ) goto done;
3535 normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
3536 + sn2.bv_len + issuer_dn.bv_len;
3537 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
3539 p = normalized->bv_val;
3541 p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
3542 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
3543 p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
3544 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
3545 p = lutil_strcopy( p, /*{*/ "\" }" );
3550 Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
3551 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
3553 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
3554 if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
3559 /* X.509 PKI certificateList stuff */
3561 checkTime( struct berval *in, struct berval *out )
3565 char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3568 assert( in != NULL );
3569 assert( !BER_BVISNULL( in ) );
3570 assert( !BER_BVISEMPTY( in ) );
3572 if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
3576 if ( out != NULL ) {
3577 assert( !BER_BVISNULL( out ) );
3578 assert( out->bv_len >= sizeof( buf ) );
3579 bv.bv_val = out->bv_val;
3585 for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
3586 if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
3589 if ( in->bv_val[i] != 'Z' ) {
3594 if ( i != in->bv_len ) {
3598 if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
3599 lutil_strncopy( bv.bv_val, in->bv_val, i );
3602 } else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
3603 char *p = bv.bv_val;
3604 if ( in->bv_val[0] < '7' ) {
3605 p = lutil_strcopy( p, "20" );
3608 p = lutil_strcopy( p, "19" );
3610 lutil_strncopy( p, in->bv_val, i );
3617 rc = generalizedTimeValidate( NULL, &bv );
3618 if ( rc == LDAP_SUCCESS && out != NULL ) {
3619 out->bv_len = bv.bv_len;
3622 return rc != LDAP_SUCCESS;
3626 issuerAndThisUpdateCheck(
3633 struct berval x = *in;
3634 struct berval ni = BER_BVNULL;
3635 /* Parse GSER format */
3639 HAVE_THISUPDATE = 0x2,
3640 HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
3644 if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
3646 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
3647 return LDAP_INVALID_SYNTAX;
3651 x.bv_len -= STRLENOF("{}");
3654 /* eat leading spaces */
3655 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3659 /* should be at issuer or thisUpdate */
3660 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
3661 if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
3664 x.bv_val += STRLENOF("issuer");
3665 x.bv_len -= STRLENOF("issuer");
3667 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3671 /* eat leading spaces */
3672 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3676 /* For backward compatibility, this part is optional */
3677 if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
3678 return LDAP_INVALID_SYNTAX;
3680 x.bv_val += STRLENOF("rdnSequence:");
3681 x.bv_len -= STRLENOF("rdnSequence:");
3683 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3687 is->bv_val = x.bv_val;
3690 for ( ; is->bv_len < x.bv_len; ) {
3691 if ( is->bv_val[is->bv_len] != '"' ) {
3695 if ( is->bv_val[is->bv_len+1] == '"' ) {
3702 x.bv_val += is->bv_len + 1;
3703 x.bv_len -= is->bv_len + 1;
3705 have |= HAVE_ISSUER;
3707 } else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
3709 if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
3711 /* parse thisUpdate */
3712 x.bv_val += STRLENOF("thisUpdate");
3713 x.bv_len -= STRLENOF("thisUpdate");
3715 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
3719 /* eat leading spaces */
3720 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3724 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
3728 tu->bv_val = x.bv_val;
3731 for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
3732 if ( tu->bv_val[tu->bv_len] == '"' ) {
3736 x.bv_val += tu->bv_len + 1;
3737 x.bv_len -= tu->bv_len + 1;
3739 have |= HAVE_THISUPDATE;
3742 return LDAP_INVALID_SYNTAX;
3745 /* eat leading spaces */
3746 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
3750 if ( have == HAVE_ALL ) {
3754 if ( x.bv_val[0] != ',' ) {
3755 return LDAP_INVALID_SYNTAX;
3762 /* should have no characters left... */
3763 if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
3765 if ( numdquotes == 0 ) {
3766 ber_dupbv_x( &ni, is, ctx );
3771 ni.bv_len = is->bv_len - numdquotes;
3772 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
3773 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
3774 if ( is->bv_val[src] == '"' ) {
3777 ni.bv_val[dst] = is->bv_val[src];
3779 ni.bv_val[dst] = '\0';
3788 issuerAndThisUpdateValidate(
3793 struct berval i, tu;
3795 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
3798 rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
3803 /* validate DN -- doesn't handle double dquote */
3804 rc = dnValidate( NULL, &i );
3806 rc = LDAP_INVALID_SYNTAX;
3808 } else if ( checkTime( &tu, NULL ) ) {
3809 rc = LDAP_INVALID_SYNTAX;
3812 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3813 slap_sl_free( i.bv_val, NULL );
3816 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
3817 in->bv_val, rc, 0 );
3824 issuerAndThisUpdatePretty(
3831 struct berval i, tu, ni = BER_BVNULL;
3834 assert( in != NULL );
3835 assert( out != NULL );
3839 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
3842 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3847 rc = dnPretty( syntax, &i, &ni, ctx );
3849 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3850 slap_sl_free( i.bv_val, ctx );
3853 if ( rc || checkTime( &tu, NULL ) ) {
3854 rc = LDAP_INVALID_SYNTAX;
3859 out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
3860 + ni.bv_len + tu.bv_len;
3861 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3863 if ( out->bv_val == NULL ) {
3870 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3871 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3872 p = lutil_strcopy( p, "\", thisUpdate \"" );
3873 p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
3874 p = lutil_strcopy( p, /*{*/ "\" }" );
3876 assert( p == &out->bv_val[out->bv_len] );
3879 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
3880 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3882 slap_sl_free( ni.bv_val, ctx );
3888 issuerAndThisUpdateNormalize(
3896 struct berval i, ni, tu, tu2;
3897 char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3901 assert( in != NULL );
3902 assert( out != NULL );
3904 Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
3907 rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
3912 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
3914 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
3915 slap_sl_free( i.bv_val, ctx );
3919 tu2.bv_len = sizeof( sbuf );
3920 if ( rc || checkTime( &tu, &tu2 ) ) {
3921 return LDAP_INVALID_SYNTAX;
3924 out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
3925 + ni.bv_len + tu2.bv_len;
3926 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
3928 if ( out->bv_val == NULL ) {
3936 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
3937 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
3938 p = lutil_strcopy( p, "\", thisUpdate \"" );
3939 p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
3940 p = lutil_strcopy( p, /*{*/ "\" }" );
3942 assert( p == &out->bv_val[out->bv_len] );
3945 Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
3946 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
3948 slap_sl_free( ni.bv_val, ctx );
3954 certificateListExactNormalize(
3959 struct berval *normalized,
3962 BerElementBuffer berbuf;
3963 BerElement *ber = (BerElement *)&berbuf;
3967 struct berval issuer_dn = BER_BVNULL, bvdn,
3969 char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
3970 int rc = LDAP_INVALID_SYNTAX;
3972 assert( val != NULL );
3974 Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
3975 val->bv_val, val->bv_len, 0 );
3977 if ( BER_BVISEMPTY( val ) ) goto done;
3979 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
3980 return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
3983 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
3985 ber_init2( ber, val, LBER_USE_DER );
3986 tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
3987 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3988 tag = ber_skip_tag( ber, &len ); /* Sequence */
3989 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3990 tag = ber_peek_tag( ber, &len );
3991 /* Optional version */
3992 if ( tag == LBER_INTEGER ) {
3993 tag = ber_get_int( ber, &version );
3994 assert( tag == LBER_INTEGER );
3995 if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
3997 tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
3998 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
3999 ber_skip_data( ber, len );
4001 tag = ber_peek_tag( ber, &len ); /* IssuerDN */
4002 if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
4003 len = ber_ptrlen( ber );
4004 bvdn.bv_val = val->bv_val + len;
4005 bvdn.bv_len = val->bv_len - len;
4006 tag = ber_skip_tag( ber, &len );
4007 ber_skip_data( ber, len );
4009 tag = ber_skip_tag( ber, &len ); /* thisUpdate */
4010 /* Time is a CHOICE { UTCTime, GeneralizedTime } */
4011 if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
4012 bvtu.bv_val = (char *)ber->ber_ptr;
4015 rc = dnX509normalize( &bvdn, &issuer_dn );
4016 if ( rc != LDAP_SUCCESS ) goto done;
4018 thisUpdate.bv_val = tubuf;
4019 thisUpdate.bv_len = sizeof(tubuf);
4020 if ( checkTime( &bvtu, &thisUpdate ) ) {
4021 rc = LDAP_INVALID_SYNTAX;
4025 normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
4026 + issuer_dn.bv_len + thisUpdate.bv_len;
4027 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4029 p = normalized->bv_val;
4031 p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
4032 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4033 p = lutil_strcopy( p, "\", thisUpdate \"" );
4034 p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
4035 p = lutil_strcopy( p, /*{*/ "\" }" );
4040 Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
4041 val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
4043 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4048 /* X.509 PMI serialNumberAndIssuerSerialCheck
4050 AttributeCertificateExactAssertion ::= SEQUENCE {
4051 serialNumber CertificateSerialNumber,
4052 issuer AttCertIssuer }
4054 CertificateSerialNumber ::= INTEGER
4056 AttCertIssuer ::= [0] SEQUENCE {
4057 issuerName GeneralNames OPTIONAL,
4058 baseCertificateID [0] IssuerSerial OPTIONAL,
4059 objectDigestInfo [1] ObjectDigestInfo OPTIONAL }
4060 -- At least one component shall be present
4062 GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
4064 GeneralName ::= CHOICE {
4065 otherName [0] INSTANCE OF OTHER-NAME,
4066 rfc822Name [1] IA5String,
4067 dNSName [2] IA5String,
4068 x400Address [3] ORAddress,
4069 directoryName [4] Name,
4070 ediPartyName [5] EDIPartyName,
4071 uniformResourceIdentifier [6] IA5String,
4072 iPAddress [7] OCTET STRING,
4073 registeredID [8] OBJECT IDENTIFIER }
4075 IssuerSerial ::= SEQUENCE {
4076 issuer GeneralNames,
4077 serial CertificateSerialNumber,
4078 issuerUID UniqueIdentifier OPTIONAL }
4080 ObjectDigestInfo ::= SEQUENCE {
4081 digestedObjectType ENUMERATED {
4084 otherObjectTypes (2) },
4085 otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
4086 digestAlgorithm AlgorithmIdentifier,
4087 objectDigest BIT STRING }
4089 * The way I interpret it, an assertion should look like
4091 { serialNumber 'dd'H,
4092 issuer { issuerName { directoryName:rdnSequence:"cn=yyy" }, -- optional
4093 baseCertificateID { serial '1d'H,
4094 issuer { directoryName:rdnSequence:"cn=zzz" },
4095 issuerUID <value> -- optional
4097 objectDigestInfo { ... } -- optional
4101 * with issuerName, baseCertificateID and objectDigestInfo optional,
4102 * at least one present; the way it's currently implemented, it is
4104 { serialNumber 'dd'H,
4105 issuer { baseCertificateID { serial '1d'H,
4106 issuer { directoryName:rdnSequence:"cn=zzz" }
4111 * with all the above parts mandatory.
4114 serialNumberAndIssuerSerialCheck(
4118 struct berval *i_sn, /* contain serial of baseCertificateID */
4121 /* Parse GSER format */
4126 HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
4127 } have = HAVE_NONE, have2 = HAVE_NONE;
4129 struct berval x = *in;
4132 if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
4135 if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
4142 /* eat leading spaces */
4143 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4147 /* should be at issuer or serialNumber NamedValue */
4148 if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
4149 if ( have & HAVE_ISSUER ) {
4150 return LDAP_INVALID_SYNTAX;
4153 /* parse IssuerSerial */
4154 x.bv_val += STRLENOF("issuer");
4155 x.bv_len -= STRLENOF("issuer");
4157 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4161 /* eat leading spaces */
4162 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4166 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4170 /* eat leading spaces */
4171 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4175 if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
4176 return LDAP_INVALID_SYNTAX;
4178 x.bv_val += STRLENOF("baseCertificateID ");
4179 x.bv_len -= STRLENOF("baseCertificateID ");
4181 /* eat leading spaces */
4182 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4186 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4191 /* eat leading spaces */
4192 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4196 /* parse issuer of baseCertificateID */
4197 if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
4198 if ( have2 & HAVE_ISSUER ) {
4199 return LDAP_INVALID_SYNTAX;
4202 x.bv_val += STRLENOF("issuer ");
4203 x.bv_len -= STRLENOF("issuer ");
4205 /* eat leading spaces */
4206 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4210 if ( x.bv_val[0] != '{' /*}*/ ) return LDAP_INVALID_SYNTAX;
4214 /* eat leading spaces */
4215 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4219 if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
4220 return LDAP_INVALID_SYNTAX;
4222 x.bv_val += STRLENOF("directoryName:rdnSequence:");
4223 x.bv_len -= STRLENOF("directoryName:rdnSequence:");
4225 if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
4229 is->bv_val = x.bv_val;
4232 for ( ; is->bv_len < x.bv_len; ) {
4233 if ( is->bv_val[is->bv_len] != '"' ) {
4237 if ( is->bv_val[is->bv_len + 1] == '"' ) {
4244 x.bv_val += is->bv_len + 1;
4245 x.bv_len -= is->bv_len + 1;
4247 /* eat leading spaces */
4248 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4252 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4256 have2 |= HAVE_ISSUER;
4258 } else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
4259 if ( have2 & HAVE_SN ) {
4260 return LDAP_INVALID_SYNTAX;
4263 x.bv_val += STRLENOF("serial ");
4264 x.bv_len -= STRLENOF("serial ");
4266 /* eat leading spaces */
4267 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
4271 if ( checkNum( &x, i_sn ) ) {
4272 return LDAP_INVALID_SYNTAX;
4275 x.bv_val += i_sn->bv_len;
4276 x.bv_len -= i_sn->bv_len;
4281 return LDAP_INVALID_SYNTAX;
4284 /* eat leading spaces */
4285 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4289 if ( have2 == HAVE_ALL ) {
4293 if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
4298 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4302 /* eat leading spaces */
4303 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4307 if ( x.bv_val[0] != /*{*/ '}' ) return LDAP_INVALID_SYNTAX;
4311 have |= HAVE_ISSUER;
4313 } else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
4314 if ( have & HAVE_SN ) {
4315 return LDAP_INVALID_SYNTAX;
4318 /* parse serialNumber */
4319 x.bv_val += STRLENOF("serialNumber");
4320 x.bv_len -= STRLENOF("serialNumber");
4322 if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
4326 /* eat leading spaces */
4327 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4331 if ( checkNum( &x, sn ) ) {
4332 return LDAP_INVALID_SYNTAX;
4335 x.bv_val += sn->bv_len;
4336 x.bv_len -= sn->bv_len;
4341 return LDAP_INVALID_SYNTAX;
4345 for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
4349 if ( have == HAVE_ALL ) {
4353 if ( x.bv_val[0] != ',' ) {
4354 return LDAP_INVALID_SYNTAX;
4360 /* should have no characters left... */
4361 if( x.bv_len ) return LDAP_INVALID_SYNTAX;
4363 if ( numdquotes == 0 ) {
4364 ber_dupbv_x( &ni, is, ctx );
4369 ni.bv_len = is->bv_len - numdquotes;
4370 ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
4371 for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
4372 if ( is->bv_val[src] == '"' ) {
4375 ni.bv_val[dst] = is->bv_val[src];
4377 ni.bv_val[dst] = '\0';
4382 /* need to handle double dquotes here */
4386 /* X.509 PMI serialNumberAndIssuerSerialValidate */
4388 serialNumberAndIssuerSerialValidate(
4393 struct berval sn, i, i_sn;
4395 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
4398 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
4403 /* validate DN -- doesn't handle double dquote */
4404 rc = dnValidate( NULL, &i );
4406 rc = LDAP_INVALID_SYNTAX;
4409 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4410 slap_sl_free( i.bv_val, NULL );
4414 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
4415 in->bv_val, rc, 0 );
4420 /* X.509 PMI serialNumberAndIssuerSerialPretty */
4422 serialNumberAndIssuerSerialPretty(
4428 struct berval sn, i, i_sn, ni = BER_BVNULL;
4432 assert( in != NULL );
4433 assert( out != NULL );
4435 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
4438 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4443 rc = dnPretty( syntax, &i, &ni, ctx );
4445 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4446 slap_sl_free( i.bv_val, ctx );
4450 rc = LDAP_INVALID_SYNTAX;
4454 /* make room from sn + "$" */
4455 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4456 + sn.bv_len + ni.bv_len + i_sn.bv_len;
4457 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4459 if ( out->bv_val == NULL ) {
4466 p = lutil_strcopy( p, "{ serialNumber " );
4467 p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
4468 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4469 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4470 p = lutil_strcopy( p, "\" }, serial " );
4471 p = lutil_strncopy( p, i_sn.bv_val, i_sn.bv_len );
4472 p = lutil_strcopy( p, " } } }" );
4474 assert( p == &out->bv_val[out->bv_len] );
4477 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
4478 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4480 slap_sl_free( ni.bv_val, ctx );
4485 /* X.509 PMI serialNumberAndIssuerSerialNormalize */
4487 * This routine is called by attributeCertificateExactNormalize
4488 * when attributeCertificateExactNormalize receives a search
4489 * string instead of a attribute certificate. This routine
4490 * checks if the search value is valid and then returns the
4494 serialNumberAndIssuerSerialNormalize(
4502 struct berval i, ni = BER_BVNULL,
4503 sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
4504 i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
4505 char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
4506 sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
4510 assert( in != NULL );
4511 assert( out != NULL );
4513 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
4516 rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
4521 rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
4523 if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
4524 slap_sl_free( i.bv_val, ctx );
4528 rc = LDAP_INVALID_SYNTAX;
4532 /* Convert sn to canonical hex */
4534 sn2.bv_len = sn.bv_len;
4535 if ( sn.bv_len > sizeof( sbuf2 ) ) {
4536 sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
4538 if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
4539 rc = LDAP_INVALID_SYNTAX;
4543 /* Convert i_sn to canonical hex */
4544 i_sn2.bv_val = i_sbuf2;
4545 i_sn2.bv_len = i_sn.bv_len;
4546 if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
4547 i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
4549 if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
4550 rc = LDAP_INVALID_SYNTAX;
4555 sn3.bv_len = sizeof(sbuf3);
4556 if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
4557 rc = LDAP_INVALID_SYNTAX;
4561 i_sn3.bv_val = i_sbuf3;
4562 i_sn3.bv_len = sizeof(i_sbuf3);
4563 if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
4564 rc = LDAP_INVALID_SYNTAX;
4568 out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
4569 + sn3.bv_len + ni.bv_len + i_sn3.bv_len;
4570 out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
4572 if ( out->bv_val == NULL ) {
4580 p = lutil_strcopy( p, "{ serialNumber " );
4581 p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
4582 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4583 p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
4584 p = lutil_strcopy( p, "\" }, serial " );
4585 p = lutil_strncopy( p, i_sn3.bv_val, i_sn3.bv_len );
4586 p = lutil_strcopy( p, " } } }" );
4588 assert( p == &out->bv_val[out->bv_len] );
4591 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
4592 in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
4594 if ( sn2.bv_val != sbuf2 ) {
4595 slap_sl_free( sn2.bv_val, ctx );
4598 if ( i_sn2.bv_val != i_sbuf2 ) {
4599 slap_sl_free( i_sn2.bv_val, ctx );
4602 if ( sn3.bv_val != sbuf3 ) {
4603 slap_sl_free( sn3.bv_val, ctx );
4606 if ( i_sn3.bv_val != i_sbuf3 ) {
4607 slap_sl_free( i_sn3.bv_val, ctx );
4610 slap_sl_free( ni.bv_val, ctx );
4615 /* X.509 PMI attributeCertificateExactNormalize */
4617 attributeCertificateExactNormalize(
4622 struct berval *normalized,
4625 BerElementBuffer berbuf;
4626 BerElement *ber = (BerElement *)&berbuf;
4629 char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
4630 struct berval sn, i_sn, sn2, i_sn2;
4631 struct berval issuer_dn = BER_BVNULL, bvdn;
4633 int rc = LDAP_INVALID_SYNTAX;
4635 if ( BER_BVISEMPTY( val ) ) {
4639 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4640 return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
4643 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4645 ber_init2( ber, val, LBER_USE_DER );
4646 tag = ber_skip_tag( ber, &len ); /* Signed Sequence */
4647 tag = ber_skip_tag( ber, &len ); /* Sequence */
4648 tag = ber_skip_tag( ber, &len ); /* (Mandatory) version; must be v2(1) */
4649 ber_skip_data( ber, len );
4650 tag = ber_skip_tag( ber, &len ); /* Holder Sequence */
4651 ber_skip_data( ber, len );
4654 tag = ber_skip_tag( ber, &len ); /* Sequence */
4655 /* issuerName (GeneralNames sequence; optional)? */
4656 tag = ber_skip_tag( ber, &len ); /* baseCertificateID (sequence; optional)? */
4657 tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
4658 tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
4659 if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
4660 rc = LDAP_INVALID_SYNTAX;
4663 tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
4664 len = ber_ptrlen( ber );
4665 bvdn.bv_val = val->bv_val + len;
4666 bvdn.bv_len = val->bv_len - len;
4667 rc = dnX509normalize( &bvdn, &issuer_dn );
4668 if ( rc != LDAP_SUCCESS ) goto done;
4670 tag = ber_skip_tag( ber, &len ); /* sequence of RDN */
4671 ber_skip_data( ber, len );
4672 tag = ber_skip_tag( ber, &len ); /* serial number */
4673 if ( tag != LBER_INTEGER ) {
4674 rc = LDAP_INVALID_SYNTAX;
4677 i_sn.bv_val = (char *)ber->ber_ptr;
4679 i_sn2.bv_val = issuer_serialbuf;
4680 i_sn2.bv_len = sizeof(issuer_serialbuf);
4681 if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
4682 rc = LDAP_INVALID_SYNTAX;
4685 ber_skip_data( ber, len );
4687 /* issuerUID (bitstring; optional)? */
4688 /* objectDigestInfo (sequence; optional)? */
4690 tag = ber_skip_tag( ber, &len ); /* Signature (sequence) */
4691 ber_skip_data( ber, len );
4692 tag = ber_skip_tag( ber, &len ); /* serial number */
4693 if ( tag != LBER_INTEGER ) {
4694 rc = LDAP_INVALID_SYNTAX;
4697 sn.bv_val = (char *)ber->ber_ptr;
4699 sn2.bv_val = serialbuf;
4700 sn2.bv_len = sizeof(serialbuf);
4701 if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
4702 rc = LDAP_INVALID_SYNTAX;
4705 ber_skip_data( ber, len );
4707 normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
4708 + sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
4709 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
4711 p = normalized->bv_val;
4713 p = lutil_strcopy( p, "{ serialNumber " );
4714 p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
4715 p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
4716 p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
4717 p = lutil_strcopy( p, "\" }, serial " );
4718 p = lutil_strncopy( p, i_sn2.bv_val, i_sn2.bv_len );
4719 p = lutil_strcopy( p, " } } }" );
4721 Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
4722 normalized->bv_val, NULL, NULL );
4727 if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
4728 if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
4729 if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
4742 assert( in != NULL );
4743 assert( !BER_BVISNULL( in ) );
4745 for ( i = 0; i < in->bv_len; i++ ) {
4746 if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
4747 return LDAP_INVALID_SYNTAX;
4751 return LDAP_SUCCESS;
4754 /* Normalize a SID as used inside a CSN:
4755 * three-digit numeric string */
4762 struct berval *normalized,
4767 assert( val != NULL );
4768 assert( normalized != NULL );
4770 ber_dupbv_x( normalized, val, ctx );
4772 for ( i = 0; i < normalized->bv_len; i++ ) {
4773 if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
4774 ber_memfree_x( normalized->bv_val, ctx );
4775 BER_BVZERO( normalized );
4776 return LDAP_INVALID_SYNTAX;
4779 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
4782 return LDAP_SUCCESS;
4790 assert( in != NULL );
4791 assert( !BER_BVISNULL( in ) );
4793 if ( in->bv_len != 3 ) {
4794 return LDAP_INVALID_SYNTAX;
4797 return hexValidate( NULL, in );
4800 /* Normalize a SID as used inside a CSN:
4801 * three-digit numeric string */
4808 struct berval *normalized,
4811 if ( val->bv_len != 3 ) {
4812 return LDAP_INVALID_SYNTAX;
4815 return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
4825 return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
4828 /* Normalize a SID as used inside a CSN, either as-is
4829 * (assertion value) or extracted from the CSN
4830 * (attribute value) */
4837 struct berval *normalized,
4845 if ( BER_BVISEMPTY( val ) ) {
4846 return LDAP_INVALID_SYNTAX;
4849 if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
4850 return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
4853 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
4855 ptr = ber_bvchr( val, '#' );
4856 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4857 return LDAP_INVALID_SYNTAX;
4860 bv.bv_val = ptr + 1;
4861 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4863 ptr = ber_bvchr( &bv, '#' );
4864 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4865 return LDAP_INVALID_SYNTAX;
4868 bv.bv_val = ptr + 1;
4869 bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
4871 ptr = ber_bvchr( &bv, '#' );
4872 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
4873 return LDAP_INVALID_SYNTAX;
4876 bv.bv_len = ptr - bv.bv_val;
4878 if ( bv.bv_len == 2 ) {
4879 /* OpenLDAP 2.3 SID */
4881 buf[ 1 ] = bv.bv_val[ 0 ];
4882 buf[ 2 ] = bv.bv_val[ 1 ];
4889 return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
4901 assert( in != NULL );
4902 assert( !BER_BVISNULL( in ) );
4904 if ( BER_BVISEMPTY( in ) ) {
4905 return LDAP_INVALID_SYNTAX;
4910 ptr = ber_bvchr( &bv, '#' );
4911 if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
4912 return LDAP_INVALID_SYNTAX;
4915 bv.bv_len = ptr - bv.bv_val;
4916 if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
4917 bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
4919 return LDAP_INVALID_SYNTAX;
4922 rc = generalizedTimeValidate( NULL, &bv );
4923 if ( rc != LDAP_SUCCESS ) {
4927 bv.bv_val = ptr + 1;
4928 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4930 ptr = ber_bvchr( &bv, '#' );
4931 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4932 return LDAP_INVALID_SYNTAX;
4935 bv.bv_len = ptr - bv.bv_val;
4936 if ( bv.bv_len != 6 ) {
4937 return LDAP_INVALID_SYNTAX;
4940 rc = hexValidate( NULL, &bv );
4941 if ( rc != LDAP_SUCCESS ) {
4945 bv.bv_val = ptr + 1;
4946 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4948 ptr = ber_bvchr( &bv, '#' );
4949 if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
4950 return LDAP_INVALID_SYNTAX;
4953 bv.bv_len = ptr - bv.bv_val;
4954 if ( bv.bv_len == 2 ) {
4955 /* tolerate old 2-digit replica-id */
4956 rc = hexValidate( NULL, &bv );
4959 rc = sidValidate( NULL, &bv );
4961 if ( rc != LDAP_SUCCESS ) {
4965 bv.bv_val = ptr + 1;
4966 bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
4968 if ( bv.bv_len != 6 ) {
4969 return LDAP_INVALID_SYNTAX;
4972 return hexValidate( NULL, &bv );
4975 /* Normalize a CSN in OpenLDAP 2.1 format */
4982 struct berval *normalized,
4985 struct berval gt, cnt, sid, mod;
4987 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
4991 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
4992 assert( !BER_BVISEMPTY( val ) );
4996 ptr = ber_bvchr( >, '#' );
4997 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
4998 return LDAP_INVALID_SYNTAX;
5001 gt.bv_len = ptr - gt.bv_val;
5002 if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
5003 return LDAP_INVALID_SYNTAX;
5006 if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
5007 return LDAP_INVALID_SYNTAX;
5010 cnt.bv_val = ptr + 1;
5011 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5013 ptr = ber_bvchr( &cnt, '#' );
5014 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5015 return LDAP_INVALID_SYNTAX;
5018 cnt.bv_len = ptr - cnt.bv_val;
5019 if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
5020 return LDAP_INVALID_SYNTAX;
5023 if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
5024 return LDAP_INVALID_SYNTAX;
5027 cnt.bv_val += STRLENOF( "0x" );
5028 cnt.bv_len -= STRLENOF( "0x" );
5030 sid.bv_val = ptr + 1;
5031 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5033 ptr = ber_bvchr( &sid, '#' );
5034 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5035 return LDAP_INVALID_SYNTAX;
5038 sid.bv_len = ptr - sid.bv_val;
5039 if ( sid.bv_len != STRLENOF( "0" ) ) {
5040 return LDAP_INVALID_SYNTAX;
5043 mod.bv_val = ptr + 1;
5044 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5045 if ( mod.bv_len != STRLENOF( "0000" ) ) {
5046 return LDAP_INVALID_SYNTAX;
5049 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5053 ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
5054 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
5056 ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
5058 ptr = lutil_strcopy( ptr, ".000000Z#00" );
5059 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5063 *ptr++ = sid.bv_val[ 0 ];
5067 for ( i = 0; i < mod.bv_len; i++ ) {
5068 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5072 assert( ptr == &bv.bv_val[bv.bv_len] );
5074 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5075 return LDAP_INVALID_SYNTAX;
5078 ber_dupbv_x( normalized, &bv, ctx );
5080 return LDAP_SUCCESS;
5083 /* Normalize a CSN in OpenLDAP 2.3 format */
5090 struct berval *normalized,
5093 struct berval gt, cnt, sid, mod;
5095 char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
5099 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5100 assert( !BER_BVISEMPTY( val ) );
5104 ptr = ber_bvchr( >, '#' );
5105 if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
5106 return LDAP_INVALID_SYNTAX;
5109 gt.bv_len = ptr - gt.bv_val;
5110 if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
5111 return LDAP_INVALID_SYNTAX;
5114 cnt.bv_val = ptr + 1;
5115 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5117 ptr = ber_bvchr( &cnt, '#' );
5118 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5119 return LDAP_INVALID_SYNTAX;
5122 cnt.bv_len = ptr - cnt.bv_val;
5123 if ( cnt.bv_len != STRLENOF( "000000" ) ) {
5124 return LDAP_INVALID_SYNTAX;
5127 sid.bv_val = ptr + 1;
5128 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5130 ptr = ber_bvchr( &sid, '#' );
5131 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5132 return LDAP_INVALID_SYNTAX;
5135 sid.bv_len = ptr - sid.bv_val;
5136 if ( sid.bv_len != STRLENOF( "00" ) ) {
5137 return LDAP_INVALID_SYNTAX;
5140 mod.bv_val = ptr + 1;
5141 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5142 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5143 return LDAP_INVALID_SYNTAX;
5146 bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
5150 ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
5151 ptr = lutil_strcopy( ptr, ".000000Z#" );
5152 ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
5155 for ( i = 0; i < sid.bv_len; i++ ) {
5156 *ptr++ = TOLOWER( sid.bv_val[ i ] );
5159 for ( i = 0; i < mod.bv_len; i++ ) {
5160 *ptr++ = TOLOWER( mod.bv_val[ i ] );
5164 assert( ptr == &bv.bv_val[bv.bv_len] );
5165 if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
5166 return LDAP_INVALID_SYNTAX;
5169 ber_dupbv_x( normalized, &bv, ctx );
5171 return LDAP_SUCCESS;
5174 /* Normalize a CSN */
5181 struct berval *normalized,
5184 struct berval cnt, sid, mod;
5188 assert( val != NULL );
5189 assert( normalized != NULL );
5191 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
5193 if ( BER_BVISEMPTY( val ) ) {
5194 return LDAP_INVALID_SYNTAX;
5197 if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
5198 /* Openldap <= 2.3 */
5200 return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
5203 if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
5206 return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
5209 if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
5210 return LDAP_INVALID_SYNTAX;
5213 ptr = ber_bvchr( val, '#' );
5214 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5215 return LDAP_INVALID_SYNTAX;
5218 if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
5219 return LDAP_INVALID_SYNTAX;
5222 cnt.bv_val = ptr + 1;
5223 cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
5225 ptr = ber_bvchr( &cnt, '#' );
5226 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5227 return LDAP_INVALID_SYNTAX;
5230 if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
5231 return LDAP_INVALID_SYNTAX;
5234 sid.bv_val = ptr + 1;
5235 sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
5237 ptr = ber_bvchr( &sid, '#' );
5238 if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
5239 return LDAP_INVALID_SYNTAX;
5242 sid.bv_len = ptr - sid.bv_val;
5243 if ( sid.bv_len != STRLENOF( "000" ) ) {
5244 return LDAP_INVALID_SYNTAX;
5247 mod.bv_val = ptr + 1;
5248 mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
5250 if ( mod.bv_len != STRLENOF( "000000" ) ) {
5251 return LDAP_INVALID_SYNTAX;
5254 ber_dupbv_x( normalized, val, ctx );
5256 for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
5257 i < normalized->bv_len; i++ )
5259 /* assume it's already validated that's all hex digits */
5260 normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
5263 return LDAP_SUCCESS;
5273 return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
5276 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
5277 /* slight optimization - does not need the start parameter */
5278 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
5283 check_time_syntax (struct berval *val,
5286 struct berval *fraction)
5289 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
5290 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
5291 * GeneralizedTime supports leap seconds, UTCTime does not.
5293 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
5294 static const int mdays[2][12] = {
5295 /* non-leap years */
5296 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
5298 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
5301 int part, c, c1, c2, tzoffset, leapyear = 0;
5304 e = p + val->bv_len;
5306 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5307 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
5309 for (part = start; part < 7 && p < e; part++) {
5311 if (!ASCII_DIGIT(c1)) {
5316 return LDAP_INVALID_SYNTAX;
5319 if (!ASCII_DIGIT(c)) {
5320 return LDAP_INVALID_SYNTAX;
5322 c += c1 * 10 - '0' * 11;
5323 if ((part | 1) == 3) {
5326 return LDAP_INVALID_SYNTAX;
5329 if (c >= ceiling[part]) {
5330 if (! (c == 60 && part == 6 && start == 0))
5331 return LDAP_INVALID_SYNTAX;
5335 if (part < 5 + start) {
5336 return LDAP_INVALID_SYNTAX;
5338 for (; part < 9; part++) {
5342 /* leapyear check for the Gregorian calendar (year>1581) */
5343 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
5347 if (parts[3] >= mdays[leapyear][parts[2]]) {
5348 return LDAP_INVALID_SYNTAX;
5352 fraction->bv_val = p;
5353 fraction->bv_len = 0;
5354 if (p < e && (*p == '.' || *p == ',')) {
5356 while (++p < e && ASCII_DIGIT(*p)) {
5359 if (p - fraction->bv_val == 1) {
5360 return LDAP_INVALID_SYNTAX;
5362 for (end_num = p; end_num[-1] == '0'; --end_num) {
5365 c = end_num - fraction->bv_val;
5366 if (c != 1) fraction->bv_len = c;
5372 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5378 return LDAP_INVALID_SYNTAX;
5384 for (part = 7; part < 9 && p < e; part++) {
5386 if (!ASCII_DIGIT(c1)) {
5391 return LDAP_INVALID_SYNTAX;
5394 if (!ASCII_DIGIT(c2)) {
5395 return LDAP_INVALID_SYNTAX;
5397 parts[part] = c1 * 10 + c2 - '0' * 11;
5398 if (parts[part] >= ceiling[part]) {
5399 return LDAP_INVALID_SYNTAX;
5402 if (part < 8 + start) {
5403 return LDAP_INVALID_SYNTAX;
5406 if (tzoffset == '-') {
5407 /* negative offset to UTC, ie west of Greenwich */
5408 parts[4] += parts[7];
5409 parts[5] += parts[8];
5410 /* offset is just hhmm, no seconds */
5411 for (part = 6; --part >= 0; ) {
5415 c = mdays[leapyear][parts[2]];
5417 if (parts[part] >= c) {
5419 return LDAP_INVALID_SYNTAX;
5424 } else if (part != 5) {
5429 /* positive offset to UTC, ie east of Greenwich */
5430 parts[4] -= parts[7];
5431 parts[5] -= parts[8];
5432 for (part = 6; --part >= 0; ) {
5433 if (parts[part] < 0) {
5435 return LDAP_INVALID_SYNTAX;
5440 /* make first arg to % non-negative */
5441 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
5446 } else if (part != 5) {
5453 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
5456 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
5463 struct berval *normalized )
5467 rc = check_time_syntax(val, 1, parts, NULL);
5468 if (rc != LDAP_SUCCESS) {
5472 normalized->bv_val = ch_malloc( 14 );
5473 if ( normalized->bv_val == NULL ) {
5474 return LBER_ERROR_MEMORY;
5477 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
5478 parts[1], parts[2] + 1, parts[3] + 1,
5479 parts[4], parts[5], parts[6] );
5480 normalized->bv_len = 13;
5482 return LDAP_SUCCESS;
5492 return check_time_syntax(in, 1, parts, NULL);
5495 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
5498 generalizedTimeValidate(
5503 struct berval fraction;
5504 return check_time_syntax(in, 0, parts, &fraction);
5508 generalizedTimeNormalize(
5513 struct berval *normalized,
5518 struct berval fraction;
5520 rc = check_time_syntax(val, 0, parts, &fraction);
5521 if (rc != LDAP_SUCCESS) {
5525 len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
5526 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
5527 if ( BER_BVISNULL( normalized ) ) {
5528 return LBER_ERROR_MEMORY;
5531 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
5532 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
5533 parts[4], parts[5], parts[6] );
5534 if ( !BER_BVISEMPTY( &fraction ) ) {
5535 memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
5536 fraction.bv_val, fraction.bv_len );
5537 normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
5539 strcpy( normalized->bv_val + len-1, "Z" );
5540 normalized->bv_len = len;
5542 return LDAP_SUCCESS;
5546 generalizedTimeOrderingMatch(
5551 struct berval *value,
5552 void *assertedValue )
5554 struct berval *asserted = (struct berval *) assertedValue;
5555 ber_len_t v_len = value->bv_len;
5556 ber_len_t av_len = asserted->bv_len;
5558 /* ignore trailing 'Z' when comparing */
5559 int match = memcmp( value->bv_val, asserted->bv_val,
5560 (v_len < av_len ? v_len : av_len) - 1 );
5561 if ( match == 0 ) match = v_len - av_len;
5564 return LDAP_SUCCESS;
5567 /* Index generation function */
5568 int generalizedTimeIndexer(
5573 struct berval *prefix,
5581 BerValue bvtmp; /* 40 bit index */
5583 struct lutil_timet tt;
5585 bvtmp.bv_len = sizeof(tmp);
5587 for( i=0; values[i].bv_val != NULL; i++ ) {
5588 /* just count them */
5591 /* we should have at least one value at this point */
5594 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
5596 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5597 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
5598 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
5599 /* Use 40 bits of time for key */
5600 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
5601 lutil_tm2time( &tm, &tt );
5602 tmp[0] = tt.tt_gsec & 0xff;
5603 tmp[4] = tt.tt_sec & 0xff;
5605 tmp[3] = tt.tt_sec & 0xff;
5607 tmp[2] = tt.tt_sec & 0xff;
5609 tmp[1] = tt.tt_sec & 0xff;
5611 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
5615 keys[j].bv_val = NULL;
5620 return LDAP_SUCCESS;
5623 /* Index generation function */
5624 int generalizedTimeFilter(
5629 struct berval *prefix,
5630 void * assertedValue,
5636 BerValue bvtmp; /* 40 bit index */
5637 BerValue *value = (BerValue *) assertedValue;
5639 struct lutil_timet tt;
5641 bvtmp.bv_len = sizeof(tmp);
5643 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
5644 /* Use 40 bits of time for key */
5645 if ( value->bv_val && value->bv_len >= 10 &&
5646 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
5648 lutil_tm2time( &tm, &tt );
5649 tmp[0] = tt.tt_gsec & 0xff;
5650 tmp[4] = tt.tt_sec & 0xff;
5652 tmp[3] = tt.tt_sec & 0xff;
5654 tmp[2] = tt.tt_sec & 0xff;
5656 tmp[1] = tt.tt_sec & 0xff;
5658 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
5659 ber_dupbv_x(keys, &bvtmp, ctx );
5660 keys[1].bv_val = NULL;
5668 return LDAP_SUCCESS;
5672 deliveryMethodValidate(
5674 struct berval *val )
5677 #define LENOF(s) (sizeof(s)-1)
5678 struct berval tmp = *val;
5680 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
5681 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
5682 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
5685 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5687 switch( tmp.bv_val[0] ) {
5690 if(( tmp.bv_len >= LENOF("any") ) &&
5691 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
5693 tmp.bv_len -= LENOF("any");
5694 tmp.bv_val += LENOF("any");
5697 return LDAP_INVALID_SYNTAX;
5701 if(( tmp.bv_len >= LENOF("mhs") ) &&
5702 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
5704 tmp.bv_len -= LENOF("mhs");
5705 tmp.bv_val += LENOF("mhs");
5708 return LDAP_INVALID_SYNTAX;
5712 if(( tmp.bv_len >= LENOF("physical") ) &&
5713 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
5715 tmp.bv_len -= LENOF("physical");
5716 tmp.bv_val += LENOF("physical");
5719 return LDAP_INVALID_SYNTAX;
5722 case 'T': /* telex or teletex or telephone */
5723 if(( tmp.bv_len >= LENOF("telex") ) &&
5724 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
5726 tmp.bv_len -= LENOF("telex");
5727 tmp.bv_val += LENOF("telex");
5730 if(( tmp.bv_len >= LENOF("teletex") ) &&
5731 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
5733 tmp.bv_len -= LENOF("teletex");
5734 tmp.bv_val += LENOF("teletex");
5737 if(( tmp.bv_len >= LENOF("telephone") ) &&
5738 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
5740 tmp.bv_len -= LENOF("telephone");
5741 tmp.bv_val += LENOF("telephone");
5744 return LDAP_INVALID_SYNTAX;
5747 case 'G': /* g3fax or g4fax */
5748 if(( tmp.bv_len >= LENOF("g3fax") ) && (
5749 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
5750 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
5752 tmp.bv_len -= LENOF("g3fax");
5753 tmp.bv_val += LENOF("g3fax");
5756 return LDAP_INVALID_SYNTAX;
5760 if(( tmp.bv_len >= LENOF("ia5") ) &&
5761 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
5763 tmp.bv_len -= LENOF("ia5");
5764 tmp.bv_val += LENOF("ia5");
5767 return LDAP_INVALID_SYNTAX;
5771 if(( tmp.bv_len >= LENOF("videotex") ) &&
5772 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
5774 tmp.bv_len -= LENOF("videotex");
5775 tmp.bv_val += LENOF("videotex");
5778 return LDAP_INVALID_SYNTAX;
5781 return LDAP_INVALID_SYNTAX;
5784 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
5786 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5790 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
5794 return LDAP_INVALID_SYNTAX;
5796 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
5805 nisNetgroupTripleValidate(
5807 struct berval *val )
5812 if ( BER_BVISEMPTY( val ) ) {
5813 return LDAP_INVALID_SYNTAX;
5816 p = (char *)val->bv_val;
5817 e = p + val->bv_len;
5819 if ( *p != '(' /*')'*/ ) {
5820 return LDAP_INVALID_SYNTAX;
5823 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
5827 return LDAP_INVALID_SYNTAX;
5830 } else if ( !AD_CHAR( *p ) ) {
5831 return LDAP_INVALID_SYNTAX;
5835 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
5836 return LDAP_INVALID_SYNTAX;
5842 return LDAP_INVALID_SYNTAX;
5845 return LDAP_SUCCESS;
5849 bootParameterValidate(
5851 struct berval *val )
5855 if ( BER_BVISEMPTY( val ) ) {
5856 return LDAP_INVALID_SYNTAX;
5859 p = (char *)val->bv_val;
5860 e = p + val->bv_len;
5863 for (; ( p < e ) && ( *p != '=' ); p++ ) {
5864 if ( !AD_CHAR( *p ) ) {
5865 return LDAP_INVALID_SYNTAX;
5870 return LDAP_INVALID_SYNTAX;
5874 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
5875 if ( !AD_CHAR( *p ) ) {
5876 return LDAP_INVALID_SYNTAX;
5881 return LDAP_INVALID_SYNTAX;
5885 for ( p++; p < e; p++ ) {
5886 if ( !SLAP_PRINTABLE( *p ) ) {
5887 return LDAP_INVALID_SYNTAX;
5891 return LDAP_SUCCESS;
5895 firstComponentNormalize(
5900 struct berval *normalized,
5907 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
5908 ber_dupbv_x( normalized, val, ctx );
5909 return LDAP_SUCCESS;
5912 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
5914 if( ! ( val->bv_val[0] == '(' /*')'*/
5915 && val->bv_val[val->bv_len - 1] == /*'('*/ ')' )
5916 && ! ( val->bv_val[0] == '{' /*'}'*/
5917 && val->bv_val[val->bv_len - 1] == /*'('*/ '}' ) )
5919 return LDAP_INVALID_SYNTAX;
5922 /* trim leading white space */
5924 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
5930 /* grab next word */
5931 comp.bv_val = &val->bv_val[len];
5932 len = val->bv_len - len - STRLENOF(/*"{"*/ "}");
5933 for( comp.bv_len = 0;
5934 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
5940 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
5941 rc = numericoidValidate( NULL, &comp );
5942 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
5943 rc = integerValidate( NULL, &comp );
5945 rc = LDAP_INVALID_SYNTAX;
5949 if( rc == LDAP_SUCCESS ) {
5950 ber_dupbv_x( normalized, &comp, ctx );
5956 static char *country_gen_syn[] = {
5957 "1.3.6.1.4.1.1466.115.121.1.15",
5958 "1.3.6.1.4.1.1466.115.121.1.26",
5959 "1.3.6.1.4.1.1466.115.121.1.44",
5963 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
5964 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
5966 static slap_syntax_defs_rec syntax_defs[] = {
5967 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
5968 X_BINARY X_NOT_H_R ")",
5969 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
5970 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
5971 0, NULL, NULL, NULL},
5972 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
5973 0, NULL, NULL, NULL},
5974 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
5976 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
5977 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
5979 SLAP_SYNTAX_BER, NULL, berValidate, NULL},
5980 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
5981 0, NULL, bitStringValidate, NULL },
5982 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
5983 0, NULL, booleanValidate, NULL},
5984 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
5985 X_BINARY X_NOT_H_R ")",
5986 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5987 NULL, certificateValidate, NULL},
5988 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
5989 X_BINARY X_NOT_H_R ")",
5990 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5991 NULL, certificateListValidate, NULL},
5992 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
5993 X_BINARY X_NOT_H_R ")",
5994 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5995 NULL, sequenceValidate, NULL},
5996 {"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
5997 X_BINARY X_NOT_H_R ")",
5998 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
5999 NULL, attributeCertificateValidate, NULL},
6000 #if 0 /* need to go __after__ printableString */
6001 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6002 0, "1.3.6.1.4.1.1466.115.121.1.44",
6003 countryStringValidate, NULL},
6005 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
6006 0, NULL, dnValidate, dnPretty},
6007 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
6008 0, NULL, rdnValidate, rdnPretty},
6009 #ifdef LDAP_COMP_MATCH
6010 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
6011 0, NULL, allComponentsValidate, NULL},
6012 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
6013 0, NULL, componentFilterValidate, NULL},
6015 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
6016 0, NULL, NULL, NULL},
6017 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
6018 0, NULL, deliveryMethodValidate, NULL},
6019 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
6020 0, NULL, UTF8StringValidate, NULL},
6021 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
6022 0, NULL, NULL, NULL},
6023 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
6024 0, NULL, NULL, NULL},
6025 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
6026 0, NULL, NULL, NULL},
6027 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
6028 0, NULL, NULL, NULL},
6029 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
6030 0, NULL, NULL, NULL},
6031 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
6032 0, NULL, printablesStringValidate, NULL},
6033 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
6034 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
6035 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
6036 0, NULL, generalizedTimeValidate, NULL},
6037 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
6038 0, NULL, NULL, NULL},
6039 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
6040 0, NULL, IA5StringValidate, NULL},
6041 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
6042 0, NULL, integerValidate, NULL},
6043 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
6044 SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
6045 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
6046 0, NULL, NULL, NULL},
6047 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
6048 0, NULL, NULL, NULL},
6049 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
6050 0, NULL, NULL, NULL},
6051 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
6052 0, NULL, NULL, NULL},
6053 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
6054 0, NULL, NULL, NULL},
6055 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
6056 0, NULL, nameUIDValidate, nameUIDPretty },
6057 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
6058 0, NULL, NULL, NULL},
6059 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
6060 0, NULL, numericStringValidate, NULL},
6061 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
6062 0, NULL, NULL, NULL},
6063 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
6064 0, NULL, numericoidValidate, NULL},
6065 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
6066 0, NULL, IA5StringValidate, NULL},
6067 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
6068 0, NULL, blobValidate, NULL},
6069 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
6070 0, NULL, postalAddressValidate, NULL},
6071 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
6072 0, NULL, NULL, NULL},
6073 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
6074 0, NULL, NULL, NULL},
6075 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
6076 0, NULL, printableStringValidate, NULL},
6077 /* moved here because now depends on Directory String, IA5 String
6078 * and Printable String */
6079 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
6080 0, country_gen_syn, countryStringValidate, NULL},
6081 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
6082 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
6083 0, NULL, subtreeSpecificationValidate, NULL},
6084 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
6085 X_BINARY X_NOT_H_R ")",
6086 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
6087 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
6088 0, NULL, printableStringValidate, NULL},
6089 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
6090 0, NULL, NULL, NULL},
6091 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
6092 0, NULL, printablesStringValidate, NULL},
6093 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
6094 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
6095 0, NULL, utcTimeValidate, NULL},
6097 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
6098 0, NULL, NULL, NULL},
6099 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
6100 0, NULL, NULL, NULL},
6101 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
6102 0, NULL, NULL, NULL},
6103 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
6104 0, NULL, NULL, NULL},
6105 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
6106 0, NULL, NULL, NULL},
6108 /* RFC 2307 NIS Syntaxes */
6109 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
6110 0, NULL, nisNetgroupTripleValidate, NULL},
6111 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
6112 0, NULL, bootParameterValidate, NULL},
6114 /* draft-zeilenga-ldap-x509 */
6115 {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
6116 SLAP_SYNTAX_HIDE, NULL,
6117 serialNumberAndIssuerValidate,
6118 serialNumberAndIssuerPretty},
6119 {"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
6120 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6121 {"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
6122 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6123 {"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
6124 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6125 {"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
6126 SLAP_SYNTAX_HIDE, NULL,
6127 issuerAndThisUpdateValidate,
6128 issuerAndThisUpdatePretty},
6129 {"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
6130 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6131 {"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
6132 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6133 {"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
6134 SLAP_SYNTAX_HIDE, NULL,
6135 serialNumberAndIssuerSerialValidate,
6136 serialNumberAndIssuerSerialPretty},
6137 {"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
6138 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6140 #ifdef SLAPD_AUTHPASSWD
6141 /* needs updating */
6142 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
6143 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
6146 {"( 1.3.6.1.1.16.1 DESC 'UUID' )",
6147 0, NULL, UUIDValidate, UUIDPretty},
6149 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
6150 SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
6152 {"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
6153 SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
6155 /* OpenLDAP Void Syntax */
6156 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
6157 SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
6159 /* FIXME: OID is unused, but not registered yet */
6160 {"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
6161 SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
6163 {NULL, 0, NULL, NULL, NULL}
6166 char *csnSIDMatchSyntaxes[] = {
6167 "1.3.6.1.4.1.4203.666.11.2.1" /* csn */,
6170 char *certificateExactMatchSyntaxes[] = {
6171 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6174 char *certificateListExactMatchSyntaxes[] = {
6175 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6178 char *attributeCertificateExactMatchSyntaxes[] = {
6179 attributeCertificateSyntaxOID /* attributeCertificate */,
6183 #ifdef LDAP_COMP_MATCH
6184 char *componentFilterMatchSyntaxes[] = {
6185 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
6186 "1.3.6.1.4.1.1466.115.121.1.9" /* certificateList */,
6187 attributeCertificateSyntaxOID /* attributeCertificate */,
6192 char *directoryStringSyntaxes[] = {
6193 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
6196 char *integerFirstComponentMatchSyntaxes[] = {
6197 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
6198 "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */,
6201 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
6202 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
6203 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
6204 "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */,
6205 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
6206 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
6207 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
6208 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
6209 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
6214 * Other matching rules in X.520 that we do not use (yet):
6216 * 2.5.13.25 uTCTimeMatch
6217 * 2.5.13.26 uTCTimeOrderingMatch
6218 * 2.5.13.31* directoryStringFirstComponentMatch
6219 * 2.5.13.32* wordMatch
6220 * 2.5.13.33* keywordMatch
6221 * 2.5.13.36+ certificatePairExactMatch
6222 * 2.5.13.37+ certificatePairMatch
6223 * 2.5.13.40+ algorithmIdentifierMatch
6224 * 2.5.13.41* storedPrefixMatch
6225 * 2.5.13.42 attributeCertificateMatch
6226 * 2.5.13.43 readerAndKeyIDMatch
6227 * 2.5.13.44 attributeIntegrityMatch
6229 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
6230 * (+) described in draft-zeilenga-ldap-x509
6232 static slap_mrule_defs_rec mrule_defs[] = {
6234 * EQUALITY matching rules must be listed after associated APPROX
6235 * matching rules. So, we list all APPROX matching rules first.
6237 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
6238 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6239 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6240 NULL, NULL, directoryStringApproxMatch,
6241 directoryStringApproxIndexer, directoryStringApproxFilter,
6244 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
6245 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6246 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
6247 NULL, NULL, IA5StringApproxMatch,
6248 IA5StringApproxIndexer, IA5StringApproxFilter,
6252 * Other matching rules
6255 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
6256 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6257 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6258 NULL, NULL, octetStringMatch,
6259 octetStringIndexer, octetStringFilter,
6262 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
6263 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6264 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6265 NULL, dnNormalize, dnMatch,
6266 octetStringIndexer, octetStringFilter,
6269 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
6270 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6271 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6272 NULL, dnNormalize, dnRelativeMatch,
6276 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
6277 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6278 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6279 NULL, dnNormalize, dnRelativeMatch,
6283 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
6284 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6285 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6286 NULL, dnNormalize, dnRelativeMatch,
6290 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
6291 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
6292 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
6293 NULL, dnNormalize, dnRelativeMatch,
6297 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
6298 "SYNTAX 1.2.36.79672281.1.5.0 )",
6299 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6300 NULL, rdnNormalize, rdnMatch,
6301 octetStringIndexer, octetStringFilter,
6304 #ifdef LDAP_COMP_MATCH
6305 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
6306 "SYNTAX 1.2.36.79672281.1.5.2 )",
6307 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
6308 NULL, NULL , componentFilterMatch,
6309 octetStringIndexer, octetStringFilter,
6312 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
6313 "SYNTAX 1.2.36.79672281.1.5.3 )",
6314 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6315 NULL, NULL , allComponentsMatch,
6316 octetStringIndexer, octetStringFilter,
6319 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
6320 "SYNTAX 1.2.36.79672281.1.5.3 )",
6321 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
6322 NULL, NULL , directoryComponentsMatch,
6323 octetStringIndexer, octetStringFilter,
6327 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
6328 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6329 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6330 NULL, UTF8StringNormalize, octetStringMatch,
6331 octetStringIndexer, octetStringFilter,
6332 directoryStringApproxMatchOID },
6334 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
6335 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6336 SLAP_MR_ORDERING, directoryStringSyntaxes,
6337 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6339 "caseIgnoreMatch" },
6341 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
6342 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6343 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6344 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6345 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6346 "caseIgnoreMatch" },
6348 {"( 2.5.13.5 NAME 'caseExactMatch' "
6349 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6350 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
6351 NULL, UTF8StringNormalize, octetStringMatch,
6352 octetStringIndexer, octetStringFilter,
6353 directoryStringApproxMatchOID },
6355 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
6356 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
6357 SLAP_MR_ORDERING, directoryStringSyntaxes,
6358 NULL, UTF8StringNormalize, octetStringOrderingMatch,
6362 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
6363 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6364 SLAP_MR_SUBSTR, directoryStringSyntaxes,
6365 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
6366 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6369 {"( 2.5.13.8 NAME 'numericStringMatch' "
6370 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6371 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6372 NULL, numericStringNormalize, octetStringMatch,
6373 octetStringIndexer, octetStringFilter,
6376 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
6377 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
6378 SLAP_MR_ORDERING, NULL,
6379 NULL, numericStringNormalize, octetStringOrderingMatch,
6381 "numericStringMatch" },
6383 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
6384 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6385 SLAP_MR_SUBSTR, NULL,
6386 NULL, numericStringNormalize, octetStringSubstringsMatch,
6387 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6388 "numericStringMatch" },
6390 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
6391 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
6392 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6393 NULL, postalAddressNormalize, octetStringMatch,
6394 octetStringIndexer, octetStringFilter,
6397 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
6398 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6399 SLAP_MR_SUBSTR, NULL,
6400 NULL, NULL, NULL, NULL, NULL,
6401 "caseIgnoreListMatch" },
6403 {"( 2.5.13.13 NAME 'booleanMatch' "
6404 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
6405 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6406 NULL, NULL, booleanMatch,
6407 octetStringIndexer, octetStringFilter,
6410 {"( 2.5.13.14 NAME 'integerMatch' "
6411 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6412 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6413 NULL, NULL, integerMatch,
6414 integerIndexer, integerFilter,
6417 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
6418 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6419 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6420 NULL, NULL, integerMatch,
6424 {"( 2.5.13.16 NAME 'bitStringMatch' "
6425 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
6426 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6427 NULL, NULL, octetStringMatch,
6428 octetStringIndexer, octetStringFilter,
6431 {"( 2.5.13.17 NAME 'octetStringMatch' "
6432 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6433 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6434 NULL, NULL, octetStringMatch,
6435 octetStringIndexer, octetStringFilter,
6438 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
6439 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6440 SLAP_MR_ORDERING, NULL,
6441 NULL, NULL, octetStringOrderingMatch,
6443 "octetStringMatch" },
6445 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
6446 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6447 SLAP_MR_SUBSTR, NULL,
6448 NULL, NULL, octetStringSubstringsMatch,
6449 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6450 "octetStringMatch" },
6452 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
6453 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
6454 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6456 telephoneNumberNormalize, octetStringMatch,
6457 octetStringIndexer, octetStringFilter,
6460 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
6461 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
6462 SLAP_MR_SUBSTR, NULL,
6463 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
6464 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6465 "telephoneNumberMatch" },
6467 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
6468 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
6469 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6470 NULL, NULL, NULL, NULL, NULL, NULL },
6472 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
6473 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
6474 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6475 NULL, uniqueMemberNormalize, uniqueMemberMatch,
6476 uniqueMemberIndexer, uniqueMemberFilter,
6479 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
6480 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
6481 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6482 NULL, NULL, NULL, NULL, NULL, NULL },
6484 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
6485 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6486 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
6487 NULL, generalizedTimeNormalize, octetStringMatch,
6488 generalizedTimeIndexer, generalizedTimeFilter,
6491 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
6492 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
6493 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6494 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
6496 "generalizedTimeMatch" },
6498 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
6499 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6500 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6501 integerFirstComponentMatchSyntaxes,
6502 NULL, firstComponentNormalize, integerMatch,
6503 octetStringIndexer, octetStringFilter,
6506 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
6507 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
6508 SLAP_MR_EQUALITY | SLAP_MR_EXT,
6509 objectIdentifierFirstComponentMatchSyntaxes,
6510 NULL, firstComponentNormalize, octetStringMatch,
6511 octetStringIndexer, octetStringFilter,
6514 {"( 2.5.13.34 NAME 'certificateExactMatch' "
6515 "SYNTAX 1.3.6.1.1.15.1 )",
6516 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
6517 NULL, certificateExactNormalize, octetStringMatch,
6518 octetStringIndexer, octetStringFilter,
6521 {"( 2.5.13.35 NAME 'certificateMatch' "
6522 "SYNTAX 1.3.6.1.1.15.2 )",
6523 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6524 NULL, NULL, NULL, NULL, NULL,
6527 {"( 2.5.13.38 NAME 'certificateListExactMatch' "
6528 "SYNTAX 1.3.6.1.1.15.5 )",
6529 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
6530 NULL, certificateListExactNormalize, octetStringMatch,
6531 octetStringIndexer, octetStringFilter,
6534 {"( 2.5.13.39 NAME 'certificateListMatch' "
6535 "SYNTAX 1.3.6.1.1.15.6 )",
6536 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6537 NULL, NULL, NULL, NULL, NULL,
6540 {"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
6541 "SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
6542 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
6543 NULL, attributeCertificateExactNormalize, octetStringMatch,
6544 octetStringIndexer, octetStringFilter,
6547 {"( 2.5.13.46 NAME 'attributeCertificateMatch' "
6548 "SYNTAX " attributeCertificateAssertionSyntaxOID " )",
6549 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
6550 NULL, NULL, NULL, NULL, NULL,
6553 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
6554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6555 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6556 NULL, IA5StringNormalize, octetStringMatch,
6557 octetStringIndexer, octetStringFilter,
6558 IA5StringApproxMatchOID },
6560 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
6561 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6562 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
6563 NULL, IA5StringNormalize, octetStringMatch,
6564 octetStringIndexer, octetStringFilter,
6565 IA5StringApproxMatchOID },
6567 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
6568 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6569 SLAP_MR_SUBSTR, NULL,
6570 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6571 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6572 "caseIgnoreIA5Match" },
6574 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
6575 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
6576 SLAP_MR_SUBSTR, NULL,
6577 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
6578 octetStringSubstringsIndexer, octetStringSubstringsFilter,
6579 "caseExactIA5Match" },
6581 #ifdef SLAPD_AUTHPASSWD
6582 /* needs updating */
6583 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
6584 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
6585 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6586 NULL, NULL, authPasswordMatch,
6591 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
6592 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6594 NULL, NULL, integerBitAndMatch,
6598 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
6599 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
6601 NULL, NULL, integerBitOrMatch,
6605 {"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
6606 "SYNTAX 1.3.6.1.1.16.1 )",
6607 SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
6608 NULL, UUIDNormalize, octetStringMatch,
6609 octetStringIndexer, octetStringFilter,
6612 {"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
6613 "SYNTAX 1.3.6.1.1.16.1 )",
6614 SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
6615 NULL, UUIDNormalize, octetStringOrderingMatch,
6616 octetStringIndexer, octetStringFilter,
6619 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
6620 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6621 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
6622 NULL, csnNormalize, csnMatch,
6623 csnIndexer, csnFilter,
6626 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
6627 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
6628 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
6629 NULL, NULL, csnOrderingMatch,
6633 {"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
6634 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
6635 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
6636 NULL, csnSidNormalize, octetStringMatch,
6637 octetStringIndexer, octetStringFilter,
6640 /* FIXME: OID is unused, but not registered yet */
6641 {"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
6642 "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
6643 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
6644 NULL, authzNormalize, authzMatch,
6648 {NULL, SLAP_MR_NONE, NULL,
6649 NULL, NULL, NULL, NULL, NULL,
6654 slap_schema_init( void )
6659 /* we should only be called once (from main) */
6660 assert( schema_init_done == 0 );
6662 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
6663 res = register_syntax( &syntax_defs[i] );
6666 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
6667 syntax_defs[i].sd_desc );
6672 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
6673 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
6674 mrule_defs[i].mrd_compat_syntaxes == NULL )
6677 "slap_schema_init: Ignoring unusable matching rule %s\n",
6678 mrule_defs[i].mrd_desc );
6682 res = register_matching_rule( &mrule_defs[i] );
6686 "slap_schema_init: Error registering matching rule %s\n",
6687 mrule_defs[i].mrd_desc );
6692 res = slap_schema_load();
6693 schema_init_done = 1;
6698 schema_destroy( void )
6707 if( schema_init_done ) {
6708 ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
6709 ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );