1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 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>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
29 #include "ldap_utf8.h"
32 #include <openssl/x509.h>
33 #include <openssl/err.h>
34 #include <openssl/rsa.h>
35 #include <openssl/crypto.h>
36 #include <openssl/pem.h>
37 #include <openssl/bio.h>
38 #include <openssl/asn1.h>
39 #include <openssl/x509v3.h>
40 #include <openssl/ssl.h>
43 #include "lutil_hash.h"
44 #define HASH_BYTES LUTIL_HASH_BYTES
45 #define HASH_CONTEXT lutil_HASH_CTX
46 #define HASH_Init(c) lutil_HASHInit(c)
47 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
48 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
50 #define OpenLDAPaciMatch NULL
52 /* approx matching rules */
53 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
54 #define directoryStringApproxMatch approxMatch
55 #define directoryStringApproxIndexer approxIndexer
56 #define directoryStringApproxFilter approxFilter
57 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
58 #define IA5StringApproxMatch approxMatch
59 #define IA5StringApproxIndexer approxIndexer
60 #define IA5StringApproxFilter approxFilter
67 /* no value allowed */
68 return LDAP_INVALID_SYNTAX;
76 /* any value allowed */
80 #define berValidate blobValidate
87 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
88 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
95 static int certificateValidate( Syntax *syntax, struct berval *in )
98 unsigned char *p = (unsigned char *)in->bv_val;
100 xcert = d2i_X509(NULL, &p, in->bv_len);
101 if ( !xcert ) return LDAP_INVALID_SYNTAX;
106 #define certificateValidate sequenceValidate
115 struct berval *value,
116 void *assertedValue )
118 struct berval *asserted = (struct berval *) assertedValue;
119 int match = value->bv_len - asserted->bv_len;
122 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
130 octetStringOrderingMatch(
135 struct berval *value,
136 void *assertedValue )
138 struct berval *asserted = (struct berval *) assertedValue;
139 ber_len_t v_len = value->bv_len;
140 ber_len_t av_len = asserted->bv_len;
142 int match = memcmp( value->bv_val, asserted->bv_val,
143 (v_len < av_len ? v_len : av_len) );
145 if( match == 0 ) match = v_len - av_len;
151 /* Index generation function */
152 int octetStringIndexer(
157 struct berval *prefix,
165 HASH_CONTEXT HASHcontext;
166 unsigned char HASHdigest[HASH_BYTES];
167 struct berval digest;
168 digest.bv_val = (char *)HASHdigest;
169 digest.bv_len = sizeof(HASHdigest);
171 for( i=0; values[i].bv_val != NULL; i++ ) {
172 /* just count them */
175 /* we should have at least one value at this point */
178 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
180 slen = syntax->ssyn_oidlen;
181 mlen = mr->smr_oidlen;
183 for( i=0; values[i].bv_val != NULL; i++ ) {
184 HASH_Init( &HASHcontext );
185 if( prefix != NULL && prefix->bv_len > 0 ) {
186 HASH_Update( &HASHcontext,
187 (unsigned char *)prefix->bv_val,
190 HASH_Update( &HASHcontext,
191 (unsigned char *)syntax->ssyn_oid, slen );
192 HASH_Update( &HASHcontext,
193 (unsigned char *)mr->smr_oid, mlen );
194 HASH_Update( &HASHcontext,
195 (unsigned char *)values[i].bv_val, values[i].bv_len );
196 HASH_Final( HASHdigest, &HASHcontext );
198 ber_dupbv_x( &keys[i], &digest, ctx );
201 keys[i].bv_val = NULL;
209 /* Index generation function */
210 int octetStringFilter(
215 struct berval *prefix,
216 void * assertedValue,
222 HASH_CONTEXT HASHcontext;
223 unsigned char HASHdigest[HASH_BYTES];
224 struct berval *value = (struct berval *) assertedValue;
225 struct berval digest;
226 digest.bv_val = (char *)HASHdigest;
227 digest.bv_len = sizeof(HASHdigest);
229 slen = syntax->ssyn_oidlen;
230 mlen = mr->smr_oidlen;
232 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
234 HASH_Init( &HASHcontext );
235 if( prefix != NULL && prefix->bv_len > 0 ) {
236 HASH_Update( &HASHcontext,
237 (unsigned char *)prefix->bv_val, prefix->bv_len );
239 HASH_Update( &HASHcontext,
240 (unsigned char *)syntax->ssyn_oid, slen );
241 HASH_Update( &HASHcontext,
242 (unsigned char *)mr->smr_oid, mlen );
243 HASH_Update( &HASHcontext,
244 (unsigned char *)value->bv_val, value->bv_len );
245 HASH_Final( HASHdigest, &HASHcontext );
247 ber_dupbv_x( keys, &digest, ctx );
248 keys[1].bv_val = NULL;
257 octetStringSubstringsMatch(
262 struct berval *value,
263 void *assertedValue )
266 SubstringsAssertion *sub = assertedValue;
267 struct berval left = *value;
271 /* Add up asserted input length */
272 if( sub->sa_initial.bv_val ) {
273 inlen += sub->sa_initial.bv_len;
276 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
277 inlen += sub->sa_any[i].bv_len;
280 if( sub->sa_final.bv_val ) {
281 inlen += sub->sa_final.bv_len;
284 if( sub->sa_initial.bv_val ) {
285 if( inlen > left.bv_len ) {
290 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
291 sub->sa_initial.bv_len );
297 left.bv_val += sub->sa_initial.bv_len;
298 left.bv_len -= sub->sa_initial.bv_len;
299 inlen -= sub->sa_initial.bv_len;
302 if( sub->sa_final.bv_val ) {
303 if( inlen > left.bv_len ) {
308 match = memcmp( sub->sa_final.bv_val,
309 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
310 sub->sa_final.bv_len );
316 left.bv_len -= sub->sa_final.bv_len;
317 inlen -= sub->sa_final.bv_len;
321 for(i=0; sub->sa_any[i].bv_val; i++) {
326 if( inlen > left.bv_len ) {
327 /* not enough length */
332 if( sub->sa_any[i].bv_len == 0 ) {
336 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
343 idx = p - left.bv_val;
345 if( idx >= left.bv_len ) {
346 /* this shouldn't happen */
353 if( sub->sa_any[i].bv_len > left.bv_len ) {
354 /* not enough left */
359 match = memcmp( left.bv_val,
360 sub->sa_any[i].bv_val,
361 sub->sa_any[i].bv_len );
369 left.bv_val += sub->sa_any[i].bv_len;
370 left.bv_len -= sub->sa_any[i].bv_len;
371 inlen -= sub->sa_any[i].bv_len;
380 /* Substrings Index generation function */
382 octetStringSubstringsIndexer(
387 struct berval *prefix,
392 ber_len_t i, j, nkeys;
396 HASH_CONTEXT HASHcontext;
397 unsigned char HASHdigest[HASH_BYTES];
398 struct berval digest;
399 digest.bv_val = (char *)HASHdigest;
400 digest.bv_len = sizeof(HASHdigest);
404 for( i=0; values[i].bv_val != NULL; i++ ) {
405 /* count number of indices to generate */
406 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
407 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MAXLEN ) {
408 nkeys += SLAP_INDEX_SUBSTR_IF_MAXLEN -
409 (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
410 } else if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN ) {
411 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
415 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
416 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) {
417 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_ANY_LEN - 1);
421 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
422 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MAXLEN ) {
423 nkeys += SLAP_INDEX_SUBSTR_IF_MAXLEN -
424 ( SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
425 } else if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN ) {
426 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
432 /* no keys to generate */
437 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
439 slen = syntax->ssyn_oidlen;
440 mlen = mr->smr_oidlen;
443 for( i=0; values[i].bv_val != NULL; i++ ) {
446 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
447 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) )
449 char pre = SLAP_INDEX_SUBSTR_PREFIX;
450 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_ANY_LEN - 1);
452 for( j=0; j<max; j++ ) {
453 HASH_Init( &HASHcontext );
454 if( prefix != NULL && prefix->bv_len > 0 ) {
455 HASH_Update( &HASHcontext,
456 (unsigned char *)prefix->bv_val, prefix->bv_len );
459 HASH_Update( &HASHcontext,
460 (unsigned char *)&pre, sizeof( pre ) );
461 HASH_Update( &HASHcontext,
462 (unsigned char *)syntax->ssyn_oid, slen );
463 HASH_Update( &HASHcontext,
464 (unsigned char *)mr->smr_oid, mlen );
465 HASH_Update( &HASHcontext,
466 (unsigned char *)&values[i].bv_val[j],
467 SLAP_INDEX_SUBSTR_ANY_LEN );
468 HASH_Final( HASHdigest, &HASHcontext );
470 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
474 /* skip if too short */
475 if( values[i].bv_len < SLAP_INDEX_SUBSTR_IF_MINLEN ) continue;
477 max = SLAP_INDEX_SUBSTR_IF_MAXLEN < values[i].bv_len
478 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : values[i].bv_len;
480 for( j=SLAP_INDEX_SUBSTR_IF_MINLEN; j<=max; j++ ) {
483 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
484 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
485 HASH_Init( &HASHcontext );
486 if( prefix != NULL && prefix->bv_len > 0 ) {
487 HASH_Update( &HASHcontext,
488 (unsigned char *)prefix->bv_val, prefix->bv_len );
490 HASH_Update( &HASHcontext,
491 (unsigned char *)&pre, sizeof( pre ) );
492 HASH_Update( &HASHcontext,
493 (unsigned char *)syntax->ssyn_oid, slen );
494 HASH_Update( &HASHcontext,
495 (unsigned char *)mr->smr_oid, mlen );
496 HASH_Update( &HASHcontext,
497 (unsigned char *)values[i].bv_val, j );
498 HASH_Final( HASHdigest, &HASHcontext );
500 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
503 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
504 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
505 HASH_Init( &HASHcontext );
506 if( prefix != NULL && prefix->bv_len > 0 ) {
507 HASH_Update( &HASHcontext,
508 (unsigned char *)prefix->bv_val, prefix->bv_len );
510 HASH_Update( &HASHcontext,
511 (unsigned char *)&pre, sizeof( pre ) );
512 HASH_Update( &HASHcontext,
513 (unsigned char *)syntax->ssyn_oid, slen );
514 HASH_Update( &HASHcontext,
515 (unsigned char *)mr->smr_oid, mlen );
516 HASH_Update( &HASHcontext,
517 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
518 HASH_Final( HASHdigest, &HASHcontext );
520 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
527 keys[nkeys].bv_val = NULL;
538 octetStringSubstringsFilter (
543 struct berval *prefix,
544 void * assertedValue,
548 SubstringsAssertion *sa;
551 size_t slen, mlen, klen;
553 HASH_CONTEXT HASHcontext;
554 unsigned char HASHdigest[HASH_BYTES];
555 struct berval *value;
556 struct berval digest;
558 sa = (SubstringsAssertion *) assertedValue;
560 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
561 sa->sa_initial.bv_val != NULL &&
562 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
567 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
569 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
570 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) {
571 /* don't bother accounting with stepping */
572 nkeys += sa->sa_any[i].bv_len -
573 ( SLAP_INDEX_SUBSTR_ANY_LEN - 1 );
578 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
579 sa->sa_final.bv_val != NULL &&
580 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
590 digest.bv_val = (char *)HASHdigest;
591 digest.bv_len = sizeof(HASHdigest);
593 slen = syntax->ssyn_oidlen;
594 mlen = mr->smr_oidlen;
596 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
599 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
600 sa->sa_initial.bv_val != NULL &&
601 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
603 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
604 value = &sa->sa_initial;
606 klen = SLAP_INDEX_SUBSTR_IF_MAXLEN < value->bv_len
607 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : value->bv_len;
609 HASH_Init( &HASHcontext );
610 if( prefix != NULL && prefix->bv_len > 0 ) {
611 HASH_Update( &HASHcontext,
612 (unsigned char *)prefix->bv_val, prefix->bv_len );
614 HASH_Update( &HASHcontext,
615 (unsigned char *)&pre, sizeof( pre ) );
616 HASH_Update( &HASHcontext,
617 (unsigned char *)syntax->ssyn_oid, slen );
618 HASH_Update( &HASHcontext,
619 (unsigned char *)mr->smr_oid, mlen );
620 HASH_Update( &HASHcontext,
621 (unsigned char *)value->bv_val, klen );
622 HASH_Final( HASHdigest, &HASHcontext );
624 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
627 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
629 pre = SLAP_INDEX_SUBSTR_PREFIX;
630 klen = SLAP_INDEX_SUBSTR_ANY_LEN;
632 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
633 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_ANY_LEN ) {
637 value = &sa->sa_any[i];
640 j <= value->bv_len - SLAP_INDEX_SUBSTR_ANY_LEN;
641 j += SLAP_INDEX_SUBSTR_ANY_STEP )
643 HASH_Init( &HASHcontext );
644 if( prefix != NULL && prefix->bv_len > 0 ) {
645 HASH_Update( &HASHcontext,
646 (unsigned char *)prefix->bv_val, prefix->bv_len );
648 HASH_Update( &HASHcontext,
649 (unsigned char *)&pre, sizeof( pre ) );
650 HASH_Update( &HASHcontext,
651 (unsigned char *)syntax->ssyn_oid, slen );
652 HASH_Update( &HASHcontext,
653 (unsigned char *)mr->smr_oid, mlen );
654 HASH_Update( &HASHcontext,
655 (unsigned char *)&value->bv_val[j], klen );
656 HASH_Final( HASHdigest, &HASHcontext );
658 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
663 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
664 sa->sa_final.bv_val != NULL &&
665 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
667 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
668 value = &sa->sa_final;
670 klen = SLAP_INDEX_SUBSTR_IF_MAXLEN < value->bv_len
671 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : value->bv_len;
673 HASH_Init( &HASHcontext );
674 if( prefix != NULL && prefix->bv_len > 0 ) {
675 HASH_Update( &HASHcontext,
676 (unsigned char *)prefix->bv_val, prefix->bv_len );
678 HASH_Update( &HASHcontext,
679 (unsigned char *)&pre, sizeof( pre ) );
680 HASH_Update( &HASHcontext,
681 (unsigned char *)syntax->ssyn_oid, slen );
682 HASH_Update( &HASHcontext,
683 (unsigned char *)mr->smr_oid, mlen );
684 HASH_Update( &HASHcontext,
685 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
686 HASH_Final( HASHdigest, &HASHcontext );
688 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
692 keys[nkeys].bv_val = NULL;
709 /* very unforgiving validation, requires no normalization
710 * before simplistic matching
712 if( in->bv_len < 3 ) {
713 return LDAP_INVALID_SYNTAX;
717 * RFC 2252 section 6.3 Bit String
718 * bitstring = "'" *binary-digit "'B"
719 * binary-digit = "0" / "1"
720 * example: '0101111101'B
723 if( in->bv_val[0] != '\'' ||
724 in->bv_val[in->bv_len-2] != '\'' ||
725 in->bv_val[in->bv_len-1] != 'B' )
727 return LDAP_INVALID_SYNTAX;
730 for( i=in->bv_len-3; i>0; i-- ) {
731 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
732 return LDAP_INVALID_SYNTAX;
740 * Syntax is [RFC2252]:
745 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
747 Values in this syntax are encoded according to the following BNF:
749 bitstring = "'" *binary-digit "'B"
751 binary-digit = "0" / "1"
755 6.21. Name And Optional UID
757 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
759 Values in this syntax are encoded according to the following BNF:
761 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
763 Although the '#' character may occur in a string representation of a
764 distinguished name, no additional special quoting is done. This
765 syntax has been added subsequent to RFC 1778.
769 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
772 * draft-ietf-ldapbis-syntaxes-xx.txt says:
777 A value of the Bit String syntax is a sequence of binary digits. The
778 LDAP-specific encoding of a value of this syntax is defined by the
781 BitString = SQUOTE *binary-digit SQUOTE "B"
783 binary-digit = "0" / "1"
785 The <SQUOTE> rule is defined in [MODELS].
790 The LDAP definition for the Bit String syntax is:
792 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
794 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
798 3.3.21. Name and Optional UID
800 A value of the Name and Optional UID syntax is the distinguished name
801 [MODELS] of an entity optionally accompanied by a unique identifier
802 that serves to differentiate the entity from others with an identical
805 The LDAP-specific encoding of a value of this syntax is defined by
808 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
810 The <BitString> rule is defined in Section 3.3.2. The
811 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
814 Note that although the '#' character may occur in the string
815 representation of a distinguished name, no additional escaping of
816 this character is performed when a <distinguishedName> is encoded in
817 a <NameAndOptionalUID>.
820 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
822 The LDAP definition for the Name and Optional UID syntax is:
824 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
826 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
830 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
833 1.4. Common ABNF Productions
836 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
838 SQUOTE = %x27 ; single quote ("'")
842 * Note: normalization strips any leading "0"s, unless the
843 * bit string is exactly "'0'B", so the normalized example,
844 * in slapd, would result in
846 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
848 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
849 * i.e. "#", doesn't have to be escaped except when at the
850 * beginning of a value, the definition of Name and Optional
851 * UID appears to be flawed, because there is no clear means
852 * to determine whether the UID part is present or not.
856 * cn=Someone,dc=example,dc=com#'1'B
858 * could be either a NameAndOptionalUID with trailing UID, i.e.
860 * DN = "cn=Someone,dc=example,dc=com"
863 * or a NameAndOptionalUID with no trailing UID, and the AVA
864 * in the last RDN made of
867 * attributeValue = com#'1'B
869 * in fact "com#'1'B" is a valid IA5 string.
871 * As a consequence, current slapd code assumes that the
872 * presence of portions of a BitString at the end of the string
873 * representation of a NameAndOptionalUID means a BitString
874 * is expected, and cause an error otherwise. This is quite
875 * arbitrary, and might change in the future.
885 struct berval dn, uid;
887 if( in->bv_len == 0 ) return LDAP_SUCCESS;
889 ber_dupbv( &dn, in );
890 if( !dn.bv_val ) return LDAP_OTHER;
892 /* if there's a "#", try bitStringValidate()... */
893 uid.bv_val = strrchr( dn.bv_val, '#' );
896 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
898 rc = bitStringValidate( NULL, &uid );
899 if ( rc == LDAP_SUCCESS ) {
900 /* in case of success, trim the UID,
901 * otherwise treat it as part of the DN */
902 dn.bv_len -= uid.bv_len + 1;
903 uid.bv_val[-1] = '\0';
907 rc = dnValidate( NULL, &dn );
909 ber_memfree( dn.bv_val );
924 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
926 if( val->bv_len == 0 ) {
927 ber_dupbv_x( out, val, ctx );
929 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
930 return LDAP_INVALID_SYNTAX;
934 struct berval dnval = *val;
935 struct berval uidval = BER_BVNULL;
937 uidval.bv_val = strrchr( val->bv_val, '#' );
938 if ( uidval.bv_val ) {
940 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
942 rc = bitStringValidate( NULL, &uidval );
944 if ( rc == LDAP_SUCCESS ) {
945 ber_dupbv_x( &dnval, val, ctx );
946 dnval.bv_len -= uidval.bv_len + 1;
947 dnval.bv_val[dnval.bv_len] = '\0';
950 uidval.bv_val = NULL;
954 rc = dnPretty( syntax, &dnval, out, ctx );
955 if ( dnval.bv_val != val->bv_val ) {
956 slap_sl_free( dnval.bv_val, ctx );
958 if( rc != LDAP_SUCCESS ) {
962 if( uidval.bv_val ) {
966 tmp = slap_sl_realloc( out->bv_val, out->bv_len
967 + STRLENOF( "#" ) + uidval.bv_len + 1,
970 ber_memfree_x( out->bv_val, ctx );
974 out->bv_val[out->bv_len++] = '#';
975 out->bv_val[out->bv_len++] = '\'';
977 got1 = uidval.bv_len < sizeof("'0'B");
978 for( i = 1; i < uidval.bv_len - 2; i++ ) {
979 c = uidval.bv_val[i];
982 if( got1 ) out->bv_val[out->bv_len++] = c;
986 out->bv_val[out->bv_len++] = c;
991 out->bv_val[out->bv_len++] = '\'';
992 out->bv_val[out->bv_len++] = 'B';
993 out->bv_val[out->bv_len] = '\0';
997 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1003 uniqueMemberNormalize(
1008 struct berval *normalized,
1014 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1016 ber_dupbv_x( &out, val, ctx );
1017 if ( BER_BVISEMPTY( &out ) ) {
1021 struct berval uid = BER_BVNULL;
1023 uid.bv_val = strrchr( out.bv_val, '#' );
1026 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1028 rc = bitStringValidate( NULL, &uid );
1029 if ( rc == LDAP_SUCCESS ) {
1030 uid.bv_val[-1] = '\0';
1031 out.bv_len -= uid.bv_len + 1;
1037 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1039 if( rc != LDAP_SUCCESS ) {
1040 slap_sl_free( out.bv_val, ctx );
1041 return LDAP_INVALID_SYNTAX;
1047 tmp = ch_realloc( normalized->bv_val,
1048 normalized->bv_len + uid.bv_len
1049 + STRLENOF("#") + 1 );
1050 if ( tmp == NULL ) {
1051 ber_memfree_x( normalized->bv_val, ctx );
1055 normalized->bv_val = tmp;
1057 /* insert the separator */
1058 normalized->bv_val[normalized->bv_len++] = '#';
1060 /* append the UID */
1061 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1062 uid.bv_val, uid.bv_len );
1063 normalized->bv_len += uid.bv_len;
1066 normalized->bv_val[normalized->bv_len] = '\0';
1069 slap_sl_free( out.bv_val, ctx );
1072 return LDAP_SUCCESS;
1081 struct berval *value,
1082 void *assertedValue )
1085 struct berval *asserted = (struct berval *) assertedValue;
1086 struct berval assertedDN = *asserted;
1087 struct berval assertedUID = BER_BVNULL;
1088 struct berval valueDN = BER_BVNULL;
1089 struct berval valueUID = BER_BVNULL;
1091 if ( !BER_BVISEMPTY( asserted ) ) {
1092 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1093 if ( !BER_BVISNULL( &assertedUID ) ) {
1094 assertedUID.bv_val++;
1095 assertedUID.bv_len = assertedDN.bv_len
1096 - ( assertedUID.bv_val - assertedDN.bv_val );
1098 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1099 assertedDN.bv_len -= assertedUID.bv_len + 1;
1102 BER_BVZERO( &assertedUID );
1107 if ( !BER_BVISEMPTY( value ) ) {
1110 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1111 if ( !BER_BVISNULL( &valueUID ) ) {
1113 valueUID.bv_len = valueDN.bv_len
1114 - ( valueUID.bv_val - valueDN.bv_val );
1116 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1117 valueDN.bv_len -= valueUID.bv_len + 1;
1120 BER_BVZERO( &valueUID );
1125 if( valueUID.bv_len && assertedUID.bv_len ) {
1126 match = valueUID.bv_len - assertedUID.bv_len;
1129 return LDAP_SUCCESS;
1132 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1135 return LDAP_SUCCESS;
1139 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1143 * Handling boolean syntax and matching is quite rigid.
1144 * A more flexible approach would be to allow a variety
1145 * of strings to be normalized and prettied into TRUE
1153 /* very unforgiving validation, requires no normalization
1154 * before simplistic matching
1157 if( in->bv_len == 4 ) {
1158 if( bvmatch( in, &slap_true_bv ) ) {
1159 return LDAP_SUCCESS;
1161 } else if( in->bv_len == 5 ) {
1162 if( bvmatch( in, &slap_false_bv ) ) {
1163 return LDAP_SUCCESS;
1167 return LDAP_INVALID_SYNTAX;
1176 struct berval *value,
1177 void *assertedValue )
1179 /* simplistic matching allowed by rigid validation */
1180 struct berval *asserted = (struct berval *) assertedValue;
1181 *matchp = value->bv_len != asserted->bv_len;
1182 return LDAP_SUCCESS;
1185 /*-------------------------------------------------------------------
1186 LDAP/X.500 string syntax / matching rules have a few oddities. This
1187 comment attempts to detail how slapd(8) treats them.
1190 StringSyntax X.500 LDAP Matching/Comments
1191 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1192 PrintableString subset subset i/e + ignore insignificant spaces
1193 PrintableString subset subset i/e + ignore insignificant spaces
1194 NumericString subset subset ignore all spaces
1195 IA5String ASCII ASCII i/e + ignore insignificant spaces
1196 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1198 TelephoneNumber subset subset i + ignore all spaces and "-"
1200 See draft-ietf-ldapbis-strpro for details (once published).
1204 In X.500(93), a directory string can be either a PrintableString,
1205 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1206 In later versions, more CHOICEs were added. In all cases the string
1209 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1210 A directory string cannot be zero length.
1212 For matching, there are both case ignore and exact rules. Both
1213 also require that "insignificant" spaces be ignored.
1214 spaces before the first non-space are ignored;
1215 spaces after the last non-space are ignored;
1216 spaces after a space are ignored.
1217 Note: by these rules (and as clarified in X.520), a string of only
1218 spaces is to be treated as if held one space, not empty (which
1219 would be a syntax error).
1222 In ASN.1, numeric string is just a string of digits and spaces
1223 and could be empty. However, in X.500, all attribute values of
1224 numeric string carry a non-empty constraint. For example:
1226 internationalISDNNumber ATTRIBUTE ::= {
1227 WITH SYNTAX InternationalISDNNumber
1228 EQUALITY MATCHING RULE numericStringMatch
1229 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1230 ID id-at-internationalISDNNumber }
1231 InternationalISDNNumber ::=
1232 NumericString (SIZE(1..ub-international-isdn-number))
1234 Unforunately, some assertion values are don't carry the same
1235 constraint (but its unclear how such an assertion could ever
1236 be true). In LDAP, there is one syntax (numericString) not two
1237 (numericString with constraint, numericString without constraint).
1238 This should be treated as numericString with non-empty constraint.
1239 Note that while someone may have no ISDN number, there are no ISDN
1240 numbers which are zero length.
1242 In matching, spaces are ignored.
1245 In ASN.1, Printable string is just a string of printable characters
1246 and can be empty. In X.500, semantics much like NumericString (see
1247 serialNumber for a like example) excepting uses insignificant space
1248 handling instead of ignore all spaces.
1251 Basically same as PrintableString. There are no examples in X.500,
1252 but same logic applies. So we require them to be non-empty as
1255 -------------------------------------------------------------------*/
1264 unsigned char *u = (unsigned char *)in->bv_val;
1266 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1267 /* directory strings cannot be empty */
1268 return LDAP_INVALID_SYNTAX;
1271 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1272 /* get the length indicated by the first byte */
1273 len = LDAP_UTF8_CHARLEN2( u, len );
1275 /* very basic checks */
1278 if( (u[5] & 0xC0) != 0x80 ) {
1279 return LDAP_INVALID_SYNTAX;
1282 if( (u[4] & 0xC0) != 0x80 ) {
1283 return LDAP_INVALID_SYNTAX;
1286 if( (u[3] & 0xC0) != 0x80 ) {
1287 return LDAP_INVALID_SYNTAX;
1290 if( (u[2] & 0xC0 )!= 0x80 ) {
1291 return LDAP_INVALID_SYNTAX;
1294 if( (u[1] & 0xC0) != 0x80 ) {
1295 return LDAP_INVALID_SYNTAX;
1298 /* CHARLEN already validated it */
1301 return LDAP_INVALID_SYNTAX;
1304 /* make sure len corresponds with the offset
1305 to the next character */
1306 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1310 return LDAP_INVALID_SYNTAX;
1313 return LDAP_SUCCESS;
1317 UTF8StringNormalize(
1322 struct berval *normalized,
1325 struct berval tmp, nvalue;
1329 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1331 if( val->bv_val == NULL ) {
1332 /* assume we're dealing with a syntax (e.g., UTF8String)
1333 * which allows empty strings
1335 normalized->bv_len = 0;
1336 normalized->bv_val = NULL;
1337 return LDAP_SUCCESS;
1340 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1341 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1342 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1343 ? LDAP_UTF8_APPROX : 0;
1345 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1350 /* collapse spaces (in place) */
1352 nvalue.bv_val = tmp.bv_val;
1354 wasspace=1; /* trim leading spaces */
1355 for( i=0; i<tmp.bv_len; i++) {
1356 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1357 if( wasspace++ == 0 ) {
1358 /* trim repeated spaces */
1359 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1363 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1367 if( nvalue.bv_len ) {
1369 /* last character was a space, trim it */
1372 nvalue.bv_val[nvalue.bv_len] = '\0';
1375 /* string of all spaces is treated as one space */
1376 nvalue.bv_val[0] = ' ';
1377 nvalue.bv_val[1] = '\0';
1381 *normalized = nvalue;
1382 return LDAP_SUCCESS;
1385 #if defined(SLAPD_APPROX_INITIALS)
1386 # define SLAPD_APPROX_DELIMITER "._ "
1387 # define SLAPD_APPROX_WORDLEN 2
1389 # define SLAPD_APPROX_DELIMITER " "
1390 # define SLAPD_APPROX_WORDLEN 1
1399 struct berval *value,
1400 void *assertedValue )
1402 struct berval *nval, *assertv;
1403 char *val, **values, **words, *c;
1404 int i, count, len, nextchunk=0, nextavail=0;
1406 /* Yes, this is necessary */
1407 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1408 if( nval == NULL ) {
1410 return LDAP_SUCCESS;
1413 /* Yes, this is necessary */
1414 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1415 NULL, LDAP_UTF8_APPROX, NULL );
1416 if( assertv == NULL ) {
1419 return LDAP_SUCCESS;
1422 /* Isolate how many words there are */
1423 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1424 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1425 if ( c == NULL ) break;
1430 /* Get a phonetic copy of each word */
1431 words = (char **)ch_malloc( count * sizeof(char *) );
1432 values = (char **)ch_malloc( count * sizeof(char *) );
1433 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1435 values[i] = phonetic(c);
1438 /* Work through the asserted value's words, to see if at least some
1439 of the words are there, in the same order. */
1441 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1442 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1447 #if defined(SLAPD_APPROX_INITIALS)
1448 else if( len == 1 ) {
1449 /* Single letter words need to at least match one word's initial */
1450 for( i=nextavail; i<count; i++ )
1451 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1458 /* Isolate the next word in the asserted value and phonetic it */
1459 assertv->bv_val[nextchunk+len] = '\0';
1460 val = phonetic( assertv->bv_val + nextchunk );
1462 /* See if this phonetic chunk is in the remaining words of *value */
1463 for( i=nextavail; i<count; i++ ){
1464 if( !strcmp( val, values[i] ) ){
1472 /* This chunk in the asserted value was NOT within the *value. */
1478 /* Go on to the next word in the asserted value */
1482 /* If some of the words were seen, call it a match */
1483 if( nextavail > 0 ) {
1490 /* Cleanup allocs */
1491 ber_bvfree( assertv );
1492 for( i=0; i<count; i++ ) {
1493 ch_free( values[i] );
1499 return LDAP_SUCCESS;
1508 struct berval *prefix,
1514 int i,j, len, wordcount, keycount=0;
1515 struct berval *newkeys;
1516 BerVarray keys=NULL;
1518 for( j=0; values[j].bv_val != NULL; j++ ) {
1519 struct berval val = BER_BVNULL;
1520 /* Yes, this is necessary */
1521 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1522 assert( val.bv_val != NULL );
1524 /* Isolate how many words there are. There will be a key for each */
1525 for( wordcount = 0, c = val.bv_val; *c; c++) {
1526 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1527 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1529 if (*c == '\0') break;
1533 /* Allocate/increase storage to account for new keys */
1534 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1535 * sizeof(struct berval) );
1536 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1537 if( keys ) ch_free( keys );
1540 /* Get a phonetic copy of each word */
1541 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1543 if( len < SLAPD_APPROX_WORDLEN ) continue;
1544 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1549 ber_memfree( val.bv_val );
1551 keys[keycount].bv_val = NULL;
1554 return LDAP_SUCCESS;
1563 struct berval *prefix,
1564 void * assertedValue,
1573 /* Yes, this is necessary */
1574 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1575 NULL, LDAP_UTF8_APPROX, NULL );
1576 if( val == NULL || val->bv_val == NULL ) {
1577 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1578 keys[0].bv_val = NULL;
1581 return LDAP_SUCCESS;
1584 /* Isolate how many words there are. There will be a key for each */
1585 for( count = 0,c = val->bv_val; *c; c++) {
1586 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1587 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1589 if (*c == '\0') break;
1593 /* Allocate storage for new keys */
1594 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1596 /* Get a phonetic copy of each word */
1597 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1599 if( len < SLAPD_APPROX_WORDLEN ) continue;
1600 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1606 keys[count].bv_val = NULL;
1609 return LDAP_SUCCESS;
1612 /* Remove all spaces and '-' characters */
1614 telephoneNumberNormalize(
1619 struct berval *normalized,
1624 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1626 /* validator should have refused an empty string */
1627 assert( val->bv_len );
1629 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1631 for( p = val->bv_val; *p; p++ ) {
1632 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1638 normalized->bv_len = q - normalized->bv_val;
1640 if( normalized->bv_len == 0 ) {
1641 slap_sl_free( normalized->bv_val, ctx );
1642 normalized->bv_val = NULL;
1643 return LDAP_INVALID_SYNTAX;
1646 return LDAP_SUCCESS;
1654 struct berval val = *in;
1656 if( val.bv_len == 0 ) {
1657 /* disallow empty strings */
1658 return LDAP_INVALID_SYNTAX;
1661 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1662 if ( val.bv_len == 1 ) {
1663 return LDAP_SUCCESS;
1666 if ( val.bv_val[0] == '0' ) {
1673 while ( OID_LEADCHAR( val.bv_val[0] )) {
1677 if ( val.bv_len == 0 ) {
1678 return LDAP_SUCCESS;
1682 if( !OID_SEPARATOR( val.bv_val[0] )) {
1690 return LDAP_INVALID_SYNTAX;
1699 struct berval val = *in;
1701 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1703 if ( val.bv_val[0] == '-' ) {
1707 if( val.bv_len == 0 ) { /* bare "-" */
1708 return LDAP_INVALID_SYNTAX;
1711 if( val.bv_val[0] == '0' ) { /* "-0" */
1712 return LDAP_INVALID_SYNTAX;
1715 } else if ( val.bv_val[0] == '0' ) {
1716 if( val.bv_len > 1 ) { /* "0<more>" */
1717 return LDAP_INVALID_SYNTAX;
1720 return LDAP_SUCCESS;
1723 for( i=0; i < val.bv_len; i++ ) {
1724 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1725 return LDAP_INVALID_SYNTAX;
1729 return LDAP_SUCCESS;
1738 struct berval *value,
1739 void *assertedValue )
1741 struct berval *asserted = (struct berval *) assertedValue;
1742 int vsign = 1, asign = 1; /* default sign = '+' */
1747 if( v.bv_val[0] == '-' ) {
1753 if( v.bv_len == 0 ) vsign = 0;
1756 if( a.bv_val[0] == '-' ) {
1762 if( a.bv_len == 0 ) vsign = 0;
1764 match = vsign - asign;
1766 match = ( v.bv_len != a.bv_len
1767 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1768 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1769 if( vsign < 0 ) match = -match;
1773 return LDAP_SUCCESS;
1777 countryStringValidate(
1779 struct berval *val )
1781 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1783 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1784 return LDAP_INVALID_SYNTAX;
1786 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1787 return LDAP_INVALID_SYNTAX;
1790 return LDAP_SUCCESS;
1794 printableStringValidate(
1796 struct berval *val )
1800 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1802 for(i=0; i < val->bv_len; i++) {
1803 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1804 return LDAP_INVALID_SYNTAX;
1808 return LDAP_SUCCESS;
1812 printablesStringValidate(
1814 struct berval *val )
1818 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1820 for(i=0,len=0; i < val->bv_len; i++) {
1821 int c = val->bv_val[i];
1825 return LDAP_INVALID_SYNTAX;
1829 } else if ( SLAP_PRINTABLE(c) ) {
1832 return LDAP_INVALID_SYNTAX;
1837 return LDAP_INVALID_SYNTAX;
1840 return LDAP_SUCCESS;
1846 struct berval *val )
1850 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1852 for(i=0; i < val->bv_len; i++) {
1853 if( !LDAP_ASCII(val->bv_val[i]) ) {
1854 return LDAP_INVALID_SYNTAX;
1858 return LDAP_SUCCESS;
1867 struct berval *normalized,
1871 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1873 assert( val->bv_len );
1875 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1879 /* Ignore initial whitespace */
1880 while ( ASCII_SPACE( *p ) ) p++;
1882 normalized->bv_val = ber_strdup_x( p, ctx );
1883 p = q = normalized->bv_val;
1886 if ( ASCII_SPACE( *p ) ) {
1889 /* Ignore the extra whitespace */
1890 while ( ASCII_SPACE( *p ) ) {
1894 } else if ( casefold ) {
1895 /* Most IA5 rules require casefolding */
1896 *q++ = TOLOWER(*p); p++;
1903 assert( normalized->bv_val <= p );
1907 * If the string ended in space, backup the pointer one
1908 * position. One is enough because the above loop collapsed
1909 * all whitespace to a single space.
1911 if ( ASCII_SPACE( q[-1] ) ) --q;
1913 /* null terminate */
1916 normalized->bv_len = q - normalized->bv_val;
1917 if( normalized->bv_len == 0 ) {
1918 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1919 normalized->bv_val[0] = ' ';
1920 normalized->bv_val[1] = '\0';
1921 normalized->bv_len = 1;
1924 return LDAP_SUCCESS;
1933 if( in->bv_len != 36 ) {
1934 return LDAP_INVALID_SYNTAX;
1937 for( i=0; i<36; i++ ) {
1943 if( in->bv_val[i] != '-' ) {
1944 return LDAP_INVALID_SYNTAX;
1948 if( !ASCII_HEX( in->bv_val[i]) ) {
1949 return LDAP_INVALID_SYNTAX;
1954 return LDAP_SUCCESS;
1963 struct berval *normalized,
1966 unsigned char octet = '\0';
1969 normalized->bv_len = 16;
1970 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1972 for( i=0, j=0; i<36; i++ ) {
1973 unsigned char nibble;
1974 if( val->bv_val[i] == '-' ) {
1977 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1978 nibble = val->bv_val[i] - '0';
1980 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1981 nibble = val->bv_val[i] - ('a'-10);
1983 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1984 nibble = val->bv_val[i] - ('A'-10);
1987 slap_sl_free( normalized->bv_val, ctx );
1988 return LDAP_INVALID_SYNTAX;
1993 normalized->bv_val[j>>1] = octet;
1995 octet = nibble << 4;
2000 normalized->bv_val[normalized->bv_len] = 0;
2001 return LDAP_SUCCESS;
2007 numericStringValidate(
2013 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2015 for(i=0; i < in->bv_len; i++) {
2016 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2017 return LDAP_INVALID_SYNTAX;
2021 return LDAP_SUCCESS;
2025 numericStringNormalize(
2030 struct berval *normalized,
2033 /* removal all spaces */
2036 assert( val->bv_len );
2038 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2041 q = normalized->bv_val;
2044 if ( ASCII_SPACE( *p ) ) {
2045 /* Ignore whitespace */
2052 /* we should have copied no more then is in val */
2053 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2055 /* null terminate */
2058 normalized->bv_len = q - normalized->bv_val;
2060 if( normalized->bv_len == 0 ) {
2061 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2062 normalized->bv_val[0] = ' ';
2063 normalized->bv_val[1] = '\0';
2064 normalized->bv_len = 1;
2067 return LDAP_SUCCESS;
2071 * Integer conversion macros that will use the largest available
2074 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2075 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2076 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2077 # define SLAP_LONG_MAX LLONG_MAX
2078 # define SLAP_LONG_MIN LLONG_MIN
2079 # define SLAP_LONG long long
2081 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2082 # define SLAP_LONG_MAX LONG_MAX
2083 # define SLAP_LONG_MIN LONG_MIN
2084 # define SLAP_LONG long
2085 #endif /* HAVE_STRTOLL ... */
2093 struct berval *value,
2094 void *assertedValue )
2096 SLAP_LONG lValue, lAssertedValue;
2098 /* safe to assume integers are NUL terminated? */
2099 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2100 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2103 return LDAP_CONSTRAINT_VIOLATION;
2106 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2108 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2111 return LDAP_CONSTRAINT_VIOLATION;
2114 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2115 return LDAP_SUCCESS;
2124 struct berval *value,
2125 void *assertedValue )
2127 SLAP_LONG lValue, lAssertedValue;
2129 /* safe to assume integers are NUL terminated? */
2130 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2131 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2134 return LDAP_CONSTRAINT_VIOLATION;
2137 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2139 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2142 return LDAP_CONSTRAINT_VIOLATION;
2145 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2146 return LDAP_SUCCESS;
2150 serialNumberAndIssuerValidate(
2157 struct berval sn, i;
2158 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2160 i.bv_val = strchr( in->bv_val, '$' );
2161 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2163 sn.bv_val = in->bv_val;
2164 sn.bv_len = i.bv_val - in->bv_val;
2167 i.bv_len = in->bv_len - (sn.bv_len + 1);
2169 /* validate serial number (strict for now) */
2170 for( n=0; n < sn.bv_len; n++ ) {
2171 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2175 rc = dnValidate( NULL, &i );
2176 if( rc ) return LDAP_INVALID_SYNTAX;
2178 return LDAP_SUCCESS;
2182 serialNumberAndIssuerPretty(
2191 struct berval sn, i, newi;
2196 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2197 val->bv_val, 0, 0 );
2199 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2201 i.bv_val = strchr( val->bv_val, '$' );
2202 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2204 sn.bv_val = val->bv_val;
2205 sn.bv_len = i.bv_val - val->bv_val;
2208 i.bv_len = val->bv_len - (sn.bv_len + 1);
2210 /* eat leading zeros */
2211 for( n=0; n < (sn.bv_len-1); n++ ) {
2212 if( sn.bv_val[n] != '0' ) break;
2217 for( n=0; n < sn.bv_len; n++ ) {
2218 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2222 rc = dnPretty( syntax, &i, &newi, ctx );
2223 if( rc ) return LDAP_INVALID_SYNTAX;
2225 /* make room from sn + "$" */
2226 out->bv_len = sn.bv_len + newi.bv_len + 1;
2227 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2229 if( out->bv_val == NULL ) {
2230 slap_sl_free( newi.bv_val, ctx );
2234 /* push issuer over */
2235 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2236 /* insert sn and "$" */
2237 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2238 out->bv_val[sn.bv_len] = '$';
2240 out->bv_val[out->bv_len] = '\0';
2242 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2243 out->bv_val, 0, 0 );
2245 return LDAP_SUCCESS;
2249 * This routine is called by certificateExactNormalize when
2250 * certificateExactNormalize receives a search string instead of
2251 * a certificate. This routine checks if the search value is valid
2252 * and then returns the normalized value
2255 serialNumberAndIssuerNormalize(
2266 struct berval sn, i, newi;
2271 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2272 val->bv_val, 0, 0 );
2274 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2276 i.bv_val = strchr( val->bv_val, '$' );
2277 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2279 sn.bv_val = val->bv_val;
2280 sn.bv_len = i.bv_val - val->bv_val;
2283 i.bv_len = val->bv_len - (sn.bv_len + 1);
2285 /* eat leading zeros */
2286 for( n=0; n < (sn.bv_len-1); n++ ) {
2287 if( sn.bv_val[n] != '0' ) break;
2292 for( n=0; n < sn.bv_len; n++ ) {
2293 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2294 return LDAP_INVALID_SYNTAX;
2299 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2300 if( rc ) return LDAP_INVALID_SYNTAX;
2302 /* make room from sn + "$" */
2303 out->bv_len = sn.bv_len + newi.bv_len + 1;
2304 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2306 if( out->bv_val == NULL ) {
2307 slap_sl_free( newi.bv_val, ctx );
2311 /* push issuer over */
2312 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2313 /* insert sn and "$" */
2314 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2315 out->bv_val[sn.bv_len] = '$';
2317 out->bv_val[out->bv_len] = '\0';
2319 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2320 out->bv_val, 0, 0 );
2327 certificateExactNormalize(
2332 struct berval *normalized,
2335 int rc = LDAP_INVALID_SYNTAX;
2337 char *serial = NULL;
2338 ber_len_t seriallen;
2339 struct berval issuer_dn = BER_BVNULL;
2340 X509_NAME *name = NULL;
2341 ASN1_INTEGER *sn = NULL;
2344 if( val->bv_len == 0 ) goto done;
2346 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2347 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2350 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2352 p = (unsigned char *)val->bv_val;
2353 xcert = d2i_X509( NULL, &p, val->bv_len);
2354 if( xcert == NULL ) goto done;
2356 sn=X509_get_serialNumber(xcert);
2357 if ( sn == NULL ) goto done;
2358 serial=i2s_ASN1_INTEGER(0, sn );
2359 if( serial == NULL ) goto done;
2360 seriallen=strlen(serial);
2362 name=X509_get_issuer_name(xcert);
2363 if( name == NULL ) goto done;
2364 rc = dnX509normalize( name, &issuer_dn );
2365 if( rc != LDAP_SUCCESS ) goto done;
2367 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2368 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2369 p = (unsigned char *)normalized->bv_val;
2370 AC_MEMCPY(p, serial, seriallen);
2373 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2374 p += issuer_dn.bv_len;
2377 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2378 normalized->bv_val, NULL, NULL );
2381 if (xcert) X509_free(xcert);
2382 if (serial) ch_free(serial);
2383 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2387 #endif /* HAVE_TLS */
2390 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2391 /* slight optimization - does not need the start parameter */
2392 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2397 check_time_syntax (struct berval *val,
2400 struct berval *fraction)
2403 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2404 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2405 * GeneralizedTime supports leap seconds, UTCTime does not.
2407 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2408 static const int mdays[2][12] = {
2409 /* non-leap years */
2410 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2412 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2415 int part, c, c1, c2, tzoffset, leapyear = 0;
2418 e = p + val->bv_len;
2420 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2421 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2423 for (part = start; part < 7 && p < e; part++) {
2425 if (!ASCII_DIGIT(c1)) {
2430 return LDAP_INVALID_SYNTAX;
2433 if (!ASCII_DIGIT(c)) {
2434 return LDAP_INVALID_SYNTAX;
2436 c += c1 * 10 - '0' * 11;
2437 if ((part | 1) == 3) {
2440 return LDAP_INVALID_SYNTAX;
2443 if (c >= ceiling[part]) {
2444 if (! (c == 60 && part == 6 && start == 0))
2445 return LDAP_INVALID_SYNTAX;
2449 if (part < 5 + start) {
2450 return LDAP_INVALID_SYNTAX;
2452 for (; part < 9; part++) {
2456 /* leapyear check for the Gregorian calendar (year>1581) */
2457 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2461 if (parts[3] >= mdays[leapyear][parts[2]]) {
2462 return LDAP_INVALID_SYNTAX;
2466 fraction->bv_val = p;
2467 fraction->bv_len = 0;
2468 if (p < e && (*p == '.' || *p == ',')) {
2470 while (++p < e && ASCII_DIGIT(*p)) {
2473 if (p - fraction->bv_val == 1) {
2474 return LDAP_INVALID_SYNTAX;
2476 for (end_num = p; end_num[-1] == '0'; --end_num) {
2479 c = end_num - fraction->bv_val;
2480 if (c != 1) fraction->bv_len = c;
2486 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2492 return LDAP_INVALID_SYNTAX;
2498 for (part = 7; part < 9 && p < e; part++) {
2500 if (!ASCII_DIGIT(c1)) {
2505 return LDAP_INVALID_SYNTAX;
2508 if (!ASCII_DIGIT(c2)) {
2509 return LDAP_INVALID_SYNTAX;
2511 parts[part] = c1 * 10 + c2 - '0' * 11;
2512 if (parts[part] >= ceiling[part]) {
2513 return LDAP_INVALID_SYNTAX;
2516 if (part < 8 + start) {
2517 return LDAP_INVALID_SYNTAX;
2520 if (tzoffset == '-') {
2521 /* negative offset to UTC, ie west of Greenwich */
2522 parts[4] += parts[7];
2523 parts[5] += parts[8];
2524 /* offset is just hhmm, no seconds */
2525 for (part = 6; --part >= 0; ) {
2529 c = mdays[leapyear][parts[2]];
2531 if (parts[part] >= c) {
2533 return LDAP_INVALID_SYNTAX;
2538 } else if (part != 5) {
2543 /* positive offset to UTC, ie east of Greenwich */
2544 parts[4] -= parts[7];
2545 parts[5] -= parts[8];
2546 for (part = 6; --part >= 0; ) {
2547 if (parts[part] < 0) {
2549 return LDAP_INVALID_SYNTAX;
2554 /* make first arg to % non-negative */
2555 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2560 } else if (part != 5) {
2567 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2570 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2577 struct berval *normalized )
2581 rc = check_time_syntax(val, 1, parts, NULL);
2582 if (rc != LDAP_SUCCESS) {
2586 normalized->bv_val = ch_malloc( 14 );
2587 if ( normalized->bv_val == NULL ) {
2588 return LBER_ERROR_MEMORY;
2591 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2592 parts[1], parts[2] + 1, parts[3] + 1,
2593 parts[4], parts[5], parts[6] );
2594 normalized->bv_len = 13;
2596 return LDAP_SUCCESS;
2606 return check_time_syntax(in, 1, parts, NULL);
2609 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2612 generalizedTimeValidate(
2617 struct berval fraction;
2618 return check_time_syntax(in, 0, parts, &fraction);
2622 generalizedTimeNormalize(
2627 struct berval *normalized,
2632 struct berval fraction;
2634 rc = check_time_syntax(val, 0, parts, &fraction);
2635 if (rc != LDAP_SUCCESS) {
2639 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2640 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2641 if ( normalized->bv_val == NULL ) {
2642 return LBER_ERROR_MEMORY;
2645 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2646 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2647 parts[4], parts[5], parts[6] );
2648 if ( fraction.bv_len ) {
2649 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2650 fraction.bv_val, fraction.bv_len );
2651 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2653 strcpy( normalized->bv_val + len-1, "Z" );
2654 normalized->bv_len = len;
2656 return LDAP_SUCCESS;
2660 generalizedTimeOrderingMatch(
2665 struct berval *value,
2666 void *assertedValue )
2668 struct berval *asserted = (struct berval *) assertedValue;
2669 ber_len_t v_len = value->bv_len;
2670 ber_len_t av_len = asserted->bv_len;
2672 /* ignore trailing 'Z' when comparing */
2673 int match = memcmp( value->bv_val, asserted->bv_val,
2674 (v_len < av_len ? v_len : av_len) - 1 );
2675 if ( match == 0 ) match = v_len - av_len;
2678 return LDAP_SUCCESS;
2682 deliveryMethodValidate(
2684 struct berval *val )
2687 #define LENOF(s) (sizeof(s)-1)
2688 struct berval tmp = *val;
2690 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2691 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2692 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2695 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2697 switch( tmp.bv_val[0] ) {
2700 if(( tmp.bv_len >= LENOF("any") ) &&
2701 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2703 tmp.bv_len -= LENOF("any");
2704 tmp.bv_val += LENOF("any");
2707 return LDAP_INVALID_SYNTAX;
2711 if(( tmp.bv_len >= LENOF("mhs") ) &&
2712 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2714 tmp.bv_len -= LENOF("mhs");
2715 tmp.bv_val += LENOF("mhs");
2718 return LDAP_INVALID_SYNTAX;
2722 if(( tmp.bv_len >= LENOF("physical") ) &&
2723 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2725 tmp.bv_len -= LENOF("physical");
2726 tmp.bv_val += LENOF("physical");
2729 return LDAP_INVALID_SYNTAX;
2732 case 'T': /* telex or teletex or telephone */
2733 if(( tmp.bv_len >= LENOF("telex") ) &&
2734 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2736 tmp.bv_len -= LENOF("telex");
2737 tmp.bv_val += LENOF("telex");
2740 if(( tmp.bv_len >= LENOF("teletex") ) &&
2741 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2743 tmp.bv_len -= LENOF("teletex");
2744 tmp.bv_val += LENOF("teletex");
2747 if(( tmp.bv_len >= LENOF("telephone") ) &&
2748 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2750 tmp.bv_len -= LENOF("telephone");
2751 tmp.bv_val += LENOF("telephone");
2754 return LDAP_INVALID_SYNTAX;
2757 case 'G': /* g3fax or g4fax */
2758 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2759 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2760 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2762 tmp.bv_len -= LENOF("g3fax");
2763 tmp.bv_val += LENOF("g3fax");
2766 return LDAP_INVALID_SYNTAX;
2770 if(( tmp.bv_len >= LENOF("ia5") ) &&
2771 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2773 tmp.bv_len -= LENOF("ia5");
2774 tmp.bv_val += LENOF("ia5");
2777 return LDAP_INVALID_SYNTAX;
2781 if(( tmp.bv_len >= LENOF("videotex") ) &&
2782 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2784 tmp.bv_len -= LENOF("videotex");
2785 tmp.bv_val += LENOF("videotex");
2788 return LDAP_INVALID_SYNTAX;
2791 return LDAP_INVALID_SYNTAX;
2794 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2796 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2800 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2804 return LDAP_INVALID_SYNTAX;
2806 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2815 nisNetgroupTripleValidate(
2817 struct berval *val )
2822 if ( val->bv_len == 0 ) {
2823 return LDAP_INVALID_SYNTAX;
2826 p = (char *)val->bv_val;
2827 e = p + val->bv_len;
2829 if ( *p != '(' /*')'*/ ) {
2830 return LDAP_INVALID_SYNTAX;
2833 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2837 return LDAP_INVALID_SYNTAX;
2840 } else if ( !AD_CHAR( *p ) ) {
2841 return LDAP_INVALID_SYNTAX;
2845 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2846 return LDAP_INVALID_SYNTAX;
2852 return LDAP_INVALID_SYNTAX;
2855 return LDAP_SUCCESS;
2859 bootParameterValidate(
2861 struct berval *val )
2865 if ( val->bv_len == 0 ) {
2866 return LDAP_INVALID_SYNTAX;
2869 p = (char *)val->bv_val;
2870 e = p + val->bv_len;
2873 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2874 if ( !AD_CHAR( *p ) ) {
2875 return LDAP_INVALID_SYNTAX;
2880 return LDAP_INVALID_SYNTAX;
2884 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2885 if ( !AD_CHAR( *p ) ) {
2886 return LDAP_INVALID_SYNTAX;
2891 return LDAP_INVALID_SYNTAX;
2895 for ( p++; p < e; p++ ) {
2896 if ( !SLAP_PRINTABLE( *p ) ) {
2897 return LDAP_INVALID_SYNTAX;
2901 return LDAP_SUCCESS;
2905 firstComponentNormalize(
2910 struct berval *normalized,
2917 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2918 ber_dupbv_x( normalized, val, ctx );
2919 return LDAP_SUCCESS;
2922 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2924 if( val->bv_val[0] != '(' /*')'*/ &&
2925 val->bv_val[0] != '{' /*'}'*/ )
2927 return LDAP_INVALID_SYNTAX;
2930 /* trim leading white space */
2932 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2938 /* grab next word */
2939 comp.bv_val = &val->bv_val[len];
2940 len = val->bv_len - len;
2942 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2948 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2949 rc = numericoidValidate( NULL, &comp );
2950 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2951 rc = integerValidate( NULL, &comp );
2953 rc = LDAP_INVALID_SYNTAX;
2957 if( rc == LDAP_SUCCESS ) {
2958 ber_dupbv_x( normalized, &comp, ctx );
2965 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2966 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2968 static slap_syntax_defs_rec syntax_defs[] = {
2969 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2970 X_BINARY X_NOT_H_R ")",
2971 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2972 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2974 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2976 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2978 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2979 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2981 SLAP_SYNTAX_BER, berValidate, NULL},
2982 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2983 0, bitStringValidate, NULL },
2984 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2985 0, booleanValidate, NULL},
2986 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2987 X_BINARY X_NOT_H_R ")",
2988 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2989 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2990 X_BINARY X_NOT_H_R ")",
2991 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2992 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2993 X_BINARY X_NOT_H_R ")",
2994 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2995 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2996 0, countryStringValidate, NULL},
2997 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2998 0, dnValidate, dnPretty},
2999 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3000 0, rdnValidate, rdnPretty},
3001 #ifdef LDAP_COMP_MATCH
3002 {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
3003 0, componentFilterValidate, NULL},
3005 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3007 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3008 0, deliveryMethodValidate, NULL},
3009 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3010 0, UTF8StringValidate, NULL},
3011 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3013 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3015 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3017 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3019 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3021 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3022 0, printablesStringValidate, NULL},
3023 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3024 SLAP_SYNTAX_BLOB, NULL, NULL},
3025 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3026 0, generalizedTimeValidate, NULL},
3027 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3029 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3030 0, IA5StringValidate, NULL},
3031 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3032 0, integerValidate, NULL},
3033 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3034 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3035 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3037 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3039 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3041 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3043 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3045 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3046 0, nameUIDValidate, nameUIDPretty },
3047 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3049 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3050 0, numericStringValidate, NULL},
3051 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3053 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3054 0, numericoidValidate, NULL},
3055 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3056 0, IA5StringValidate, NULL},
3057 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3058 0, blobValidate, NULL},
3059 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3060 0, UTF8StringValidate, NULL},
3061 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3063 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3065 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3066 0, printableStringValidate, NULL},
3067 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3068 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3069 0, subtreeSpecificationValidate, NULL},
3070 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3071 X_BINARY X_NOT_H_R ")",
3072 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3073 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3074 0, printableStringValidate, NULL},
3075 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3077 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3078 0, printablesStringValidate, NULL},
3079 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3080 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3081 0, utcTimeValidate, NULL},
3083 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3085 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3087 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3089 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3091 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3094 /* RFC 2307 NIS Syntaxes */
3095 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3096 0, nisNetgroupTripleValidate, NULL},
3097 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3098 0, bootParameterValidate, NULL},
3100 /* From PKIX *//* This OID is not published yet. */
3101 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3103 serialNumberAndIssuerValidate,
3104 serialNumberAndIssuerPretty},
3106 #ifdef SLAPD_ACI_ENABLED
3107 /* OpenLDAP Experimental Syntaxes */
3108 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3110 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3114 #ifdef SLAPD_AUTHPASSWD
3115 /* needs updating */
3116 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3117 SLAP_SYNTAX_HIDE, NULL, NULL},
3120 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3121 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3123 /* OpenLDAP Void Syntax */
3124 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3125 SLAP_SYNTAX_HIDE, inValidate, NULL},
3126 {NULL, 0, NULL, NULL}
3129 char *certificateExactMatchSyntaxes[] = {
3130 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3133 char *directoryStringSyntaxes[] = {
3134 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3137 char *integerFirstComponentMatchSyntaxes[] = {
3138 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3139 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3142 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3143 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3144 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3145 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3146 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3147 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3148 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3149 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3150 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3155 * Other matching rules in X.520 that we do not use (yet):
3157 * 2.5.13.25 uTCTimeMatch
3158 * 2.5.13.26 uTCTimeOrderingMatch
3159 * 2.5.13.31* directoryStringFirstComponentMatch
3160 * 2.5.13.32* wordMatch
3161 * 2.5.13.33* keywordMatch
3162 * 2.5.13.36 certificatePairExactMatch
3163 * 2.5.13.37 certificatePairMatch
3164 * 2.5.13.38 certificateListExactMatch
3165 * 2.5.13.39 certificateListMatch
3166 * 2.5.13.40 algorithmIdentifierMatch
3167 * 2.5.13.41* storedPrefixMatch
3168 * 2.5.13.42 attributeCertificateMatch
3169 * 2.5.13.43 readerAndKeyIDMatch
3170 * 2.5.13.44 attributeIntegrityMatch
3172 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3174 static slap_mrule_defs_rec mrule_defs[] = {
3176 * EQUALITY matching rules must be listed after associated APPROX
3177 * matching rules. So, we list all APPROX matching rules first.
3179 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3180 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3181 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3182 NULL, NULL, directoryStringApproxMatch,
3183 directoryStringApproxIndexer, directoryStringApproxFilter,
3186 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3187 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3188 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3189 NULL, NULL, IA5StringApproxMatch,
3190 IA5StringApproxIndexer, IA5StringApproxFilter,
3194 * Other matching rules
3197 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3198 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3199 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3200 NULL, NULL, octetStringMatch,
3201 octetStringIndexer, octetStringFilter,
3204 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3205 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3206 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3207 NULL, dnNormalize, dnMatch,
3208 octetStringIndexer, octetStringFilter,
3211 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3212 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3213 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3214 NULL, dnNormalize, dnRelativeMatch,
3218 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3219 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3220 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3221 NULL, dnNormalize, dnRelativeMatch,
3225 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3226 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3227 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3228 NULL, dnNormalize, dnRelativeMatch,
3232 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3233 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3234 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3235 NULL, dnNormalize, dnRelativeMatch,
3239 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3240 "SYNTAX 1.2.36.79672281.1.5.0 )",
3241 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3242 NULL, rdnNormalize, rdnMatch,
3243 octetStringIndexer, octetStringFilter,
3246 #ifdef LDAP_COMP_MATCH
3247 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3248 "SYNTAX 1.2.36.79672281.1.5.2 )",
3249 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3250 NULL, NULL , componentFilterMatch,
3251 octetStringIndexer, octetStringFilter,
3255 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3256 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3257 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3258 NULL, UTF8StringNormalize, octetStringMatch,
3259 octetStringIndexer, octetStringFilter,
3260 directoryStringApproxMatchOID },
3262 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3263 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3264 SLAP_MR_ORDERING, directoryStringSyntaxes,
3265 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3267 "caseIgnoreMatch" },
3269 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3270 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3271 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3272 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3273 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3274 "caseIgnoreMatch" },
3276 {"( 2.5.13.5 NAME 'caseExactMatch' "
3277 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3278 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3279 NULL, UTF8StringNormalize, octetStringMatch,
3280 octetStringIndexer, octetStringFilter,
3281 directoryStringApproxMatchOID },
3283 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3284 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3285 SLAP_MR_ORDERING, directoryStringSyntaxes,
3286 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3290 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3291 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3292 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3293 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3294 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3297 {"( 2.5.13.8 NAME 'numericStringMatch' "
3298 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3299 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3300 NULL, numericStringNormalize, octetStringMatch,
3301 octetStringIndexer, octetStringFilter,
3304 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3305 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3306 SLAP_MR_ORDERING, NULL,
3307 NULL, numericStringNormalize, octetStringOrderingMatch,
3309 "numericStringMatch" },
3311 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3312 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3313 SLAP_MR_SUBSTR, NULL,
3314 NULL, numericStringNormalize, octetStringSubstringsMatch,
3315 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3316 "numericStringMatch" },
3318 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3319 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3320 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3321 NULL, NULL, NULL, NULL, NULL, NULL },
3323 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3324 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3325 SLAP_MR_SUBSTR, NULL,
3326 NULL, NULL, NULL, NULL, NULL,
3327 "caseIgnoreListMatch" },
3329 {"( 2.5.13.13 NAME 'booleanMatch' "
3330 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3331 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3332 NULL, NULL, booleanMatch,
3333 octetStringIndexer, octetStringFilter,
3336 {"( 2.5.13.14 NAME 'integerMatch' "
3337 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3338 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3339 NULL, NULL, integerMatch,
3340 octetStringIndexer, octetStringFilter,
3343 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3344 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3345 SLAP_MR_ORDERING, NULL,
3346 NULL, NULL, integerMatch,
3350 {"( 2.5.13.16 NAME 'bitStringMatch' "
3351 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3352 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3353 NULL, NULL, octetStringMatch,
3354 octetStringIndexer, octetStringFilter,
3357 {"( 2.5.13.17 NAME 'octetStringMatch' "
3358 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3359 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3360 NULL, NULL, octetStringMatch,
3361 octetStringIndexer, octetStringFilter,
3364 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3365 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3366 SLAP_MR_ORDERING, NULL,
3367 NULL, NULL, octetStringOrderingMatch,
3369 "octetStringMatch" },
3371 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3373 SLAP_MR_SUBSTR, NULL,
3374 NULL, NULL, octetStringSubstringsMatch,
3375 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3376 "octetStringMatch" },
3378 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3379 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3380 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3382 telephoneNumberNormalize, octetStringMatch,
3383 octetStringIndexer, octetStringFilter,
3386 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3387 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3388 SLAP_MR_SUBSTR, NULL,
3389 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3390 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3391 "telephoneNumberMatch" },
3393 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3394 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3395 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3396 NULL, NULL, NULL, NULL, NULL, NULL },
3398 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3400 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3401 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3405 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3406 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3407 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3408 NULL, NULL, NULL, NULL, NULL, NULL },
3410 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3411 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3412 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3413 NULL, generalizedTimeNormalize, octetStringMatch,
3417 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3418 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3419 SLAP_MR_ORDERING, NULL,
3420 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3422 "generalizedTimeMatch" },
3424 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3425 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3426 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3427 integerFirstComponentMatchSyntaxes,
3428 NULL, firstComponentNormalize, integerMatch,
3429 octetStringIndexer, octetStringFilter,
3432 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3433 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3434 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3435 objectIdentifierFirstComponentMatchSyntaxes,
3436 NULL, firstComponentNormalize, octetStringMatch,
3437 octetStringIndexer, octetStringFilter,
3440 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3441 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3442 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3444 NULL, certificateExactNormalize, octetStringMatch,
3445 octetStringIndexer, octetStringFilter,
3447 NULL, NULL, NULL, NULL, NULL,
3451 {"( 2.5.13.35 NAME 'certificateMatch' "
3452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3453 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3455 NULL, NULL, octetStringMatch,
3456 octetStringIndexer, octetStringFilter,
3458 NULL, NULL, NULL, NULL, NULL,
3462 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3463 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3464 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3465 NULL, IA5StringNormalize, octetStringMatch,
3466 octetStringIndexer, octetStringFilter,
3467 IA5StringApproxMatchOID },
3469 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3470 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3471 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3472 NULL, IA5StringNormalize, octetStringMatch,
3473 octetStringIndexer, octetStringFilter,
3474 IA5StringApproxMatchOID },
3476 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3477 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3478 SLAP_MR_SUBSTR, NULL,
3479 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3480 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3481 "caseIgnoreIA5Match" },
3483 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3484 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3485 SLAP_MR_SUBSTR, NULL,
3486 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3487 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3488 "caseExactIA5Match" },
3490 #ifdef SLAPD_AUTHPASSWD
3491 /* needs updating */
3492 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3493 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3494 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3495 NULL, NULL, authPasswordMatch,
3500 #ifdef SLAPD_ACI_ENABLED
3501 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3502 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3503 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3504 NULL, NULL, OpenLDAPaciMatch,
3509 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3510 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3512 NULL, NULL, integerBitAndMatch,
3516 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3517 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3519 NULL, NULL, integerBitOrMatch,
3523 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3524 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3525 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3526 NULL, UUIDNormalize, octetStringMatch,
3527 octetStringIndexer, octetStringFilter,
3530 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3531 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3532 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3533 NULL, UUIDNormalize, octetStringOrderingMatch,
3534 octetStringIndexer, octetStringFilter,
3537 {NULL, SLAP_MR_NONE, NULL,
3538 NULL, NULL, NULL, NULL, NULL,
3543 slap_schema_init( void )
3548 /* we should only be called once (from main) */
3549 assert( schema_init_done == 0 );
3551 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3552 res = register_syntax( &syntax_defs[i] );
3555 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3556 syntax_defs[i].sd_desc );
3561 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3562 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3563 mrule_defs[i].mrd_compat_syntaxes == NULL )
3566 "slap_schema_init: Ignoring unusable matching rule %s\n",
3567 mrule_defs[i].mrd_desc );
3571 res = register_matching_rule( &mrule_defs[i] );
3575 "slap_schema_init: Error registering matching rule %s\n",
3576 mrule_defs[i].mrd_desc );
3581 res = slap_schema_load();
3582 schema_init_done = 1;
3587 schema_destroy( void )