1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 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>
44 #include "lutil_hash.h"
45 #define HASH_BYTES LUTIL_HASH_BYTES
46 #define HASH_CONTEXT lutil_HASH_CTX
47 #define HASH_Init(c) lutil_HASHInit(c)
48 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
49 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
51 #define OpenLDAPaciMatch NULL
53 /* approx matching rules */
54 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
55 #define directoryStringApproxMatch approxMatch
56 #define directoryStringApproxIndexer approxIndexer
57 #define directoryStringApproxFilter approxFilter
58 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
59 #define IA5StringApproxMatch approxMatch
60 #define IA5StringApproxIndexer approxIndexer
61 #define IA5StringApproxFilter approxFilter
63 /* Change Sequence Number (CSN) - much of this will change */
64 #define csnValidate blobValidate
65 #define csnMatch octetStringMatch
66 #define csnOrderingMatch octetStringOrderingMatch
67 #define csnIndexer generalizedTimeIndexer
68 #define csnFilter generalizedTimeFilter
70 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
71 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
72 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
73 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
80 /* no value allowed */
81 return LDAP_INVALID_SYNTAX;
89 /* any value allowed */
93 #define berValidate blobValidate
100 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
101 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
108 static int certificateValidate( Syntax *syntax, struct berval *in )
111 unsigned char *p = (unsigned char *)in->bv_val;
113 xcert = d2i_X509(NULL, &p, in->bv_len);
114 if ( !xcert ) return LDAP_INVALID_SYNTAX;
119 #define certificateValidate sequenceValidate
128 struct berval *value,
129 void *assertedValue )
131 struct berval *asserted = (struct berval *) assertedValue;
132 int match = value->bv_len - asserted->bv_len;
135 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
143 octetStringOrderingMatch(
148 struct berval *value,
149 void *assertedValue )
151 struct berval *asserted = (struct berval *) assertedValue;
152 ber_len_t v_len = value->bv_len;
153 ber_len_t av_len = asserted->bv_len;
155 int match = memcmp( value->bv_val, asserted->bv_val,
156 (v_len < av_len ? v_len : av_len) );
158 if( match == 0 ) match = v_len - av_len;
166 HASH_CONTEXT *HASHcontext,
167 unsigned char *HASHdigest,
168 struct berval *prefix,
172 unsigned char *value,
175 HASH_Init(HASHcontext);
176 if(prefix && prefix->bv_len > 0) {
177 HASH_Update(HASHcontext,
178 (unsigned char *)prefix->bv_val, prefix->bv_len);
180 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
181 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
182 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
183 HASH_Update(HASHcontext, value, value_len);
184 HASH_Final(HASHdigest, HASHcontext);
188 /* Index generation function */
189 int octetStringIndexer(
194 struct berval *prefix,
202 HASH_CONTEXT HASHcontext;
203 unsigned char HASHdigest[HASH_BYTES];
204 struct berval digest;
205 digest.bv_val = (char *)HASHdigest;
206 digest.bv_len = sizeof(HASHdigest);
208 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
209 /* just count them */
212 /* we should have at least one value at this point */
215 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
217 slen = syntax->ssyn_oidlen;
218 mlen = mr->smr_oidlen;
220 for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
221 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
222 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
223 ber_dupbv_x( &keys[i], &digest, ctx );
226 BER_BVZERO( &keys[i] );
233 /* Index generation function */
234 int octetStringFilter(
239 struct berval *prefix,
240 void * assertedValue,
246 HASH_CONTEXT HASHcontext;
247 unsigned char HASHdigest[HASH_BYTES];
248 struct berval *value = (struct berval *) assertedValue;
249 struct berval digest;
250 digest.bv_val = (char *)HASHdigest;
251 digest.bv_len = sizeof(HASHdigest);
253 slen = syntax->ssyn_oidlen;
254 mlen = mr->smr_oidlen;
256 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
258 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
259 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
261 ber_dupbv_x( keys, &digest, ctx );
262 BER_BVZERO( &keys[1] );
270 octetStringSubstringsMatch(
275 struct berval *value,
276 void *assertedValue )
279 SubstringsAssertion *sub = assertedValue;
280 struct berval left = *value;
284 /* Add up asserted input length */
285 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
286 inlen += sub->sa_initial.bv_len;
289 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
290 inlen += sub->sa_any[i].bv_len;
293 if ( !BER_BVISNULL( &sub->sa_final ) ) {
294 inlen += sub->sa_final.bv_len;
297 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
298 if ( inlen > left.bv_len ) {
303 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
304 sub->sa_initial.bv_len );
310 left.bv_val += sub->sa_initial.bv_len;
311 left.bv_len -= sub->sa_initial.bv_len;
312 inlen -= sub->sa_initial.bv_len;
315 if ( !BER_BVISNULL( &sub->sa_final ) ) {
316 if ( inlen > left.bv_len ) {
321 match = memcmp( sub->sa_final.bv_val,
322 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
323 sub->sa_final.bv_len );
329 left.bv_len -= sub->sa_final.bv_len;
330 inlen -= sub->sa_final.bv_len;
334 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
339 if ( inlen > left.bv_len ) {
340 /* not enough length */
345 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
349 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
356 idx = p - left.bv_val;
358 if ( idx >= left.bv_len ) {
359 /* this shouldn't happen */
366 if ( sub->sa_any[i].bv_len > left.bv_len ) {
367 /* not enough left */
372 match = memcmp( left.bv_val,
373 sub->sa_any[i].bv_val,
374 sub->sa_any[i].bv_len );
382 left.bv_val += sub->sa_any[i].bv_len;
383 left.bv_len -= sub->sa_any[i].bv_len;
384 inlen -= sub->sa_any[i].bv_len;
393 /* Substrings Index generation function */
395 octetStringSubstringsIndexer(
400 struct berval *prefix,
405 ber_len_t i, j, len, nkeys;
409 HASH_CONTEXT HASHcontext;
410 unsigned char HASHdigest[HASH_BYTES];
411 struct berval digest;
412 digest.bv_val = (char *)HASHdigest;
413 digest.bv_len = sizeof(HASHdigest);
417 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
418 /* count number of indices to generate */
419 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
420 if( values[i].bv_len >= index_substr_if_maxlen ) {
421 nkeys += index_substr_if_maxlen -
422 (index_substr_if_minlen - 1);
423 } else if( values[i].bv_len >= index_substr_if_minlen ) {
424 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
428 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
429 if( values[i].bv_len >= index_substr_any_len ) {
430 nkeys += values[i].bv_len - (index_substr_any_len - 1);
434 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
435 if( values[i].bv_len >= index_substr_if_maxlen ) {
436 nkeys += index_substr_if_maxlen -
437 (index_substr_if_minlen - 1);
438 } else if( values[i].bv_len >= index_substr_if_minlen ) {
439 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
445 /* no keys to generate */
450 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
452 slen = syntax->ssyn_oidlen;
453 mlen = mr->smr_oidlen;
456 for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
459 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
460 ( values[i].bv_len >= index_substr_any_len ) )
462 char pre = SLAP_INDEX_SUBSTR_PREFIX;
463 max = values[i].bv_len - (index_substr_any_len - 1);
465 for( j=0; j<max; j++ ) {
466 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
467 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
468 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
472 /* skip if too short */
473 if( values[i].bv_len < index_substr_if_minlen ) continue;
475 max = index_substr_if_maxlen < values[i].bv_len
476 ? index_substr_if_maxlen : values[i].bv_len;
478 for( j=index_substr_if_minlen; j<=max; j++ ) {
481 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
482 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
483 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
484 syntax, mr, (unsigned char *)values[i].bv_val, j );
485 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
488 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
489 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
490 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
491 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
492 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
499 BER_BVZERO( &keys[nkeys] );
510 octetStringSubstringsFilter (
515 struct berval *prefix,
516 void * assertedValue,
520 SubstringsAssertion *sa;
522 ber_len_t len, max, nkeys = 0;
523 size_t slen, mlen, klen;
525 HASH_CONTEXT HASHcontext;
526 unsigned char HASHdigest[HASH_BYTES];
527 struct berval *value;
528 struct berval digest;
530 sa = (SubstringsAssertion *) assertedValue;
532 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
533 !BER_BVISNULL( &sa->sa_initial ) &&
534 sa->sa_initial.bv_len >= index_substr_if_minlen )
537 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
538 ( flags & SLAP_INDEX_SUBSTR_ANY ))
540 nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
544 if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
546 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
547 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
548 /* don't bother accounting with stepping */
549 nkeys += sa->sa_any[i].bv_len -
550 ( index_substr_any_len - 1 );
555 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
556 !BER_BVISNULL( &sa->sa_final ) &&
557 sa->sa_final.bv_len >= index_substr_if_minlen )
560 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
561 ( flags & SLAP_INDEX_SUBSTR_ANY ))
563 nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
572 digest.bv_val = (char *)HASHdigest;
573 digest.bv_len = sizeof(HASHdigest);
575 slen = syntax->ssyn_oidlen;
576 mlen = mr->smr_oidlen;
578 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
581 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
582 !BER_BVISNULL( &sa->sa_initial ) &&
583 sa->sa_initial.bv_len >= index_substr_if_minlen )
585 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
586 value = &sa->sa_initial;
588 klen = index_substr_if_maxlen < value->bv_len
589 ? index_substr_if_maxlen : value->bv_len;
591 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
592 syntax, mr, (unsigned char *)value->bv_val, klen );
593 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
595 /* If initial is too long and we have subany indexed, use it
596 * to match the excess...
598 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
601 pre = SLAP_INDEX_SUBSTR_PREFIX;
602 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
604 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
605 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
606 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
611 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
613 pre = SLAP_INDEX_SUBSTR_PREFIX;
614 klen = index_substr_any_len;
616 for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
617 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
621 value = &sa->sa_any[i];
624 j <= value->bv_len - index_substr_any_len;
625 j += index_substr_any_step )
627 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
628 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
629 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
634 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
635 !BER_BVISNULL( &sa->sa_final ) &&
636 sa->sa_final.bv_len >= index_substr_if_minlen )
638 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
639 value = &sa->sa_final;
641 klen = index_substr_if_maxlen < value->bv_len
642 ? index_substr_if_maxlen : value->bv_len;
644 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
645 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
646 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
648 /* If final is too long and we have subany indexed, use it
649 * to match the excess...
651 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
654 pre = SLAP_INDEX_SUBSTR_PREFIX;
655 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
657 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
658 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
659 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
665 BER_BVZERO( &keys[nkeys] );
682 /* very unforgiving validation, requires no normalization
683 * before simplistic matching
685 if( in->bv_len < 3 ) {
686 return LDAP_INVALID_SYNTAX;
690 * RFC 2252 section 6.3 Bit String
691 * bitstring = "'" *binary-digit "'B"
692 * binary-digit = "0" / "1"
693 * example: '0101111101'B
696 if( in->bv_val[0] != '\'' ||
697 in->bv_val[in->bv_len - 2] != '\'' ||
698 in->bv_val[in->bv_len - 1] != 'B' )
700 return LDAP_INVALID_SYNTAX;
703 for( i = in->bv_len - 3; i > 0; i-- ) {
704 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
705 return LDAP_INVALID_SYNTAX;
713 * Syntax is [RFC2252]:
718 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
720 Values in this syntax are encoded according to the following BNF:
722 bitstring = "'" *binary-digit "'B"
724 binary-digit = "0" / "1"
728 6.21. Name And Optional UID
730 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
732 Values in this syntax are encoded according to the following BNF:
734 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
736 Although the '#' character may occur in a string representation of a
737 distinguished name, no additional special quoting is done. This
738 syntax has been added subsequent to RFC 1778.
742 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
745 * draft-ietf-ldapbis-syntaxes-xx.txt says:
750 A value of the Bit String syntax is a sequence of binary digits. The
751 LDAP-specific encoding of a value of this syntax is defined by the
754 BitString = SQUOTE *binary-digit SQUOTE "B"
756 binary-digit = "0" / "1"
758 The <SQUOTE> rule is defined in [MODELS].
763 The LDAP definition for the Bit String syntax is:
765 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
767 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
771 3.3.21. Name and Optional UID
773 A value of the Name and Optional UID syntax is the distinguished name
774 [MODELS] of an entity optionally accompanied by a unique identifier
775 that serves to differentiate the entity from others with an identical
778 The LDAP-specific encoding of a value of this syntax is defined by
781 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
783 The <BitString> rule is defined in Section 3.3.2. The
784 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
787 Note that although the '#' character may occur in the string
788 representation of a distinguished name, no additional escaping of
789 this character is performed when a <distinguishedName> is encoded in
790 a <NameAndOptionalUID>.
793 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
795 The LDAP definition for the Name and Optional UID syntax is:
797 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
799 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
803 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
806 1.4. Common ABNF Productions
809 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
811 SQUOTE = %x27 ; single quote ("'")
815 * Note: normalization strips any leading "0"s, unless the
816 * bit string is exactly "'0'B", so the normalized example,
817 * in slapd, would result in
819 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
821 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
822 * i.e. "#", doesn't have to be escaped except when at the
823 * beginning of a value, the definition of Name and Optional
824 * UID appears to be flawed, because there is no clear means
825 * to determine whether the UID part is present or not.
829 * cn=Someone,dc=example,dc=com#'1'B
831 * could be either a NameAndOptionalUID with trailing UID, i.e.
833 * DN = "cn=Someone,dc=example,dc=com"
836 * or a NameAndOptionalUID with no trailing UID, and the AVA
837 * in the last RDN made of
840 * attributeValue = com#'1'B
842 * in fact "com#'1'B" is a valid IA5 string.
844 * As a consequence, current slapd code assumes that the
845 * presence of portions of a BitString at the end of the string
846 * representation of a NameAndOptionalUID means a BitString
847 * is expected, and cause an error otherwise. This is quite
848 * arbitrary, and might change in the future.
858 struct berval dn, uid;
860 if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
862 ber_dupbv( &dn, in );
863 if( !dn.bv_val ) return LDAP_OTHER;
865 /* if there's a "#", try bitStringValidate()... */
866 uid.bv_val = strrchr( dn.bv_val, '#' );
867 if ( !BER_BVISNULL( &uid ) ) {
869 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
871 rc = bitStringValidate( NULL, &uid );
872 if ( rc == LDAP_SUCCESS ) {
873 /* in case of success, trim the UID,
874 * otherwise treat it as part of the DN */
875 dn.bv_len -= uid.bv_len + 1;
876 uid.bv_val[-1] = '\0';
880 rc = dnValidate( NULL, &dn );
882 ber_memfree( dn.bv_val );
897 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
899 if( BER_BVISEMPTY( val ) ) {
900 ber_dupbv_x( out, val, ctx );
902 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
903 return LDAP_INVALID_SYNTAX;
907 struct berval dnval = *val;
908 struct berval uidval = BER_BVNULL;
910 uidval.bv_val = strrchr( val->bv_val, '#' );
911 if ( !BER_BVISNULL( &uidval ) ) {
913 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
915 rc = bitStringValidate( NULL, &uidval );
917 if ( rc == LDAP_SUCCESS ) {
918 ber_dupbv_x( &dnval, val, ctx );
919 dnval.bv_len -= uidval.bv_len + 1;
920 dnval.bv_val[dnval.bv_len] = '\0';
923 BER_BVZERO( &uidval );
927 rc = dnPretty( syntax, &dnval, out, ctx );
928 if ( dnval.bv_val != val->bv_val ) {
929 slap_sl_free( dnval.bv_val, ctx );
931 if( rc != LDAP_SUCCESS ) {
935 if( !BER_BVISNULL( &uidval ) ) {
939 tmp = slap_sl_realloc( out->bv_val, out->bv_len
940 + STRLENOF( "#" ) + uidval.bv_len + 1,
943 ber_memfree_x( out->bv_val, ctx );
947 out->bv_val[out->bv_len++] = '#';
948 out->bv_val[out->bv_len++] = '\'';
950 got1 = uidval.bv_len < sizeof("'0'B");
951 for( i = 1; i < uidval.bv_len - 2; i++ ) {
952 c = uidval.bv_val[i];
955 if( got1 ) out->bv_val[out->bv_len++] = c;
959 out->bv_val[out->bv_len++] = c;
964 out->bv_val[out->bv_len++] = '\'';
965 out->bv_val[out->bv_len++] = 'B';
966 out->bv_val[out->bv_len] = '\0';
970 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
976 uniqueMemberNormalize(
981 struct berval *normalized,
987 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
989 ber_dupbv_x( &out, val, ctx );
990 if ( BER_BVISEMPTY( &out ) ) {
994 struct berval uid = BER_BVNULL;
996 uid.bv_val = strrchr( out.bv_val, '#' );
997 if ( !BER_BVISNULL( &uid ) ) {
999 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1001 rc = bitStringValidate( NULL, &uid );
1002 if ( rc == LDAP_SUCCESS ) {
1003 uid.bv_val[-1] = '\0';
1004 out.bv_len -= uid.bv_len + 1;
1010 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1012 if( rc != LDAP_SUCCESS ) {
1013 slap_sl_free( out.bv_val, ctx );
1014 return LDAP_INVALID_SYNTAX;
1017 if( !BER_BVISNULL( &uid ) ) {
1020 tmp = ch_realloc( normalized->bv_val,
1021 normalized->bv_len + uid.bv_len
1022 + STRLENOF("#") + 1 );
1023 if ( tmp == NULL ) {
1024 ber_memfree_x( normalized->bv_val, ctx );
1028 normalized->bv_val = tmp;
1030 /* insert the separator */
1031 normalized->bv_val[normalized->bv_len++] = '#';
1033 /* append the UID */
1034 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1035 uid.bv_val, uid.bv_len );
1036 normalized->bv_len += uid.bv_len;
1039 normalized->bv_val[normalized->bv_len] = '\0';
1042 slap_sl_free( out.bv_val, ctx );
1045 return LDAP_SUCCESS;
1054 struct berval *value,
1055 void *assertedValue )
1058 struct berval *asserted = (struct berval *) assertedValue;
1059 struct berval assertedDN = *asserted;
1060 struct berval assertedUID = BER_BVNULL;
1061 struct berval valueDN = BER_BVNULL;
1062 struct berval valueUID = BER_BVNULL;
1064 if ( !BER_BVISEMPTY( asserted ) ) {
1065 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1066 if ( !BER_BVISNULL( &assertedUID ) ) {
1067 assertedUID.bv_val++;
1068 assertedUID.bv_len = assertedDN.bv_len
1069 - ( assertedUID.bv_val - assertedDN.bv_val );
1071 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1072 assertedDN.bv_len -= assertedUID.bv_len + 1;
1075 BER_BVZERO( &assertedUID );
1080 if ( !BER_BVISEMPTY( value ) ) {
1083 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1084 if ( !BER_BVISNULL( &valueUID ) ) {
1086 valueUID.bv_len = valueDN.bv_len
1087 - ( valueUID.bv_val - valueDN.bv_val );
1089 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1090 valueDN.bv_len -= valueUID.bv_len + 1;
1093 BER_BVZERO( &valueUID );
1098 if( valueUID.bv_len && assertedUID.bv_len ) {
1099 match = valueUID.bv_len - assertedUID.bv_len;
1102 return LDAP_SUCCESS;
1105 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1108 return LDAP_SUCCESS;
1112 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1116 * Handling boolean syntax and matching is quite rigid.
1117 * A more flexible approach would be to allow a variety
1118 * of strings to be normalized and prettied into TRUE
1126 /* very unforgiving validation, requires no normalization
1127 * before simplistic matching
1130 if( in->bv_len == 4 ) {
1131 if( bvmatch( in, &slap_true_bv ) ) {
1132 return LDAP_SUCCESS;
1134 } else if( in->bv_len == 5 ) {
1135 if( bvmatch( in, &slap_false_bv ) ) {
1136 return LDAP_SUCCESS;
1140 return LDAP_INVALID_SYNTAX;
1149 struct berval *value,
1150 void *assertedValue )
1152 /* simplistic matching allowed by rigid validation */
1153 struct berval *asserted = (struct berval *) assertedValue;
1154 *matchp = value->bv_len != asserted->bv_len;
1155 return LDAP_SUCCESS;
1158 /*-------------------------------------------------------------------
1159 LDAP/X.500 string syntax / matching rules have a few oddities. This
1160 comment attempts to detail how slapd(8) treats them.
1163 StringSyntax X.500 LDAP Matching/Comments
1164 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1165 PrintableString subset subset i/e + ignore insignificant spaces
1166 PrintableString subset subset i/e + ignore insignificant spaces
1167 NumericString subset subset ignore all spaces
1168 IA5String ASCII ASCII i/e + ignore insignificant spaces
1169 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1171 TelephoneNumber subset subset i + ignore all spaces and "-"
1173 See draft-ietf-ldapbis-strpro for details (once published).
1177 In X.500(93), a directory string can be either a PrintableString,
1178 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1179 In later versions, more CHOICEs were added. In all cases the string
1182 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1183 A directory string cannot be zero length.
1185 For matching, there are both case ignore and exact rules. Both
1186 also require that "insignificant" spaces be ignored.
1187 spaces before the first non-space are ignored;
1188 spaces after the last non-space are ignored;
1189 spaces after a space are ignored.
1190 Note: by these rules (and as clarified in X.520), a string of only
1191 spaces is to be treated as if held one space, not empty (which
1192 would be a syntax error).
1195 In ASN.1, numeric string is just a string of digits and spaces
1196 and could be empty. However, in X.500, all attribute values of
1197 numeric string carry a non-empty constraint. For example:
1199 internationalISDNNumber ATTRIBUTE ::= {
1200 WITH SYNTAX InternationalISDNNumber
1201 EQUALITY MATCHING RULE numericStringMatch
1202 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1203 ID id-at-internationalISDNNumber }
1204 InternationalISDNNumber ::=
1205 NumericString (SIZE(1..ub-international-isdn-number))
1207 Unforunately, some assertion values are don't carry the same
1208 constraint (but its unclear how such an assertion could ever
1209 be true). In LDAP, there is one syntax (numericString) not two
1210 (numericString with constraint, numericString without constraint).
1211 This should be treated as numericString with non-empty constraint.
1212 Note that while someone may have no ISDN number, there are no ISDN
1213 numbers which are zero length.
1215 In matching, spaces are ignored.
1218 In ASN.1, Printable string is just a string of printable characters
1219 and can be empty. In X.500, semantics much like NumericString (see
1220 serialNumber for a like example) excepting uses insignificant space
1221 handling instead of ignore all spaces.
1224 Basically same as PrintableString. There are no examples in X.500,
1225 but same logic applies. So we require them to be non-empty as
1228 -------------------------------------------------------------------*/
1237 unsigned char *u = (unsigned char *)in->bv_val;
1239 if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
1240 /* directory strings cannot be empty */
1241 return LDAP_INVALID_SYNTAX;
1244 for( count = in->bv_len; count > 0; count -= len, u += len ) {
1245 /* get the length indicated by the first byte */
1246 len = LDAP_UTF8_CHARLEN2( u, len );
1248 /* very basic checks */
1251 if( (u[5] & 0xC0) != 0x80 ) {
1252 return LDAP_INVALID_SYNTAX;
1255 if( (u[4] & 0xC0) != 0x80 ) {
1256 return LDAP_INVALID_SYNTAX;
1259 if( (u[3] & 0xC0) != 0x80 ) {
1260 return LDAP_INVALID_SYNTAX;
1263 if( (u[2] & 0xC0 )!= 0x80 ) {
1264 return LDAP_INVALID_SYNTAX;
1267 if( (u[1] & 0xC0) != 0x80 ) {
1268 return LDAP_INVALID_SYNTAX;
1271 /* CHARLEN already validated it */
1274 return LDAP_INVALID_SYNTAX;
1277 /* make sure len corresponds with the offset
1278 to the next character */
1279 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1283 return LDAP_INVALID_SYNTAX;
1286 return LDAP_SUCCESS;
1290 UTF8StringNormalize(
1295 struct berval *normalized,
1298 struct berval tmp, nvalue;
1302 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1304 if( BER_BVISNULL( val ) ) {
1305 /* assume we're dealing with a syntax (e.g., UTF8String)
1306 * which allows empty strings
1308 BER_BVZERO( normalized );
1309 return LDAP_SUCCESS;
1312 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1313 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1314 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1315 ? LDAP_UTF8_APPROX : 0;
1317 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1322 /* collapse spaces (in place) */
1324 nvalue.bv_val = tmp.bv_val;
1326 /* trim leading spaces? */
1327 wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
1328 (( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
1330 for( i = 0; i < tmp.bv_len; i++) {
1331 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1332 if( wasspace++ == 0 ) {
1333 /* trim repeated spaces */
1334 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1338 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1342 if( !BER_BVISEMPTY( &nvalue ) ) {
1343 /* trim trailing space? */
1345 (( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
1346 ( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
1350 nvalue.bv_val[nvalue.bv_len] = '\0';
1353 /* string of all spaces is treated as one space */
1354 nvalue.bv_val[0] = ' ';
1355 nvalue.bv_val[1] = '\0';
1359 *normalized = nvalue;
1360 return LDAP_SUCCESS;
1364 directoryStringSubstringsMatch(
1369 struct berval *value,
1370 void *assertedValue )
1373 SubstringsAssertion *sub = assertedValue;
1374 struct berval left = *value;
1378 if ( !BER_BVISNULL( &sub->sa_initial ) ) {
1379 if ( sub->sa_initial.bv_len > left.bv_len ) {
1380 /* not enough left */
1385 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1386 sub->sa_initial.bv_len );
1392 left.bv_val += sub->sa_initial.bv_len;
1393 left.bv_len -= sub->sa_initial.bv_len;
1395 priorspace = ASCII_SPACE(
1396 sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
1399 if ( sub->sa_any ) {
1400 for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
1404 if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
1405 && ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
1407 /* allow next space to match */
1414 if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
1418 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1419 /* not enough left */
1424 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1431 idx = p - left.bv_val;
1433 if ( idx >= left.bv_len ) {
1434 /* this shouldn't happen */
1441 if ( sub->sa_any[i].bv_len > left.bv_len ) {
1442 /* not enough left */
1447 match = memcmp( left.bv_val,
1448 sub->sa_any[i].bv_val,
1449 sub->sa_any[i].bv_len );
1457 left.bv_val += sub->sa_any[i].bv_len;
1458 left.bv_len -= sub->sa_any[i].bv_len;
1460 priorspace = ASCII_SPACE(
1461 sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
1465 if ( !BER_BVISNULL( &sub->sa_final ) ) {
1466 if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
1467 && ASCII_SPACE( sub->sa_final.bv_val[0] ))
1469 /* allow next space to match */
1474 if ( sub->sa_final.bv_len > left.bv_len ) {
1475 /* not enough left */
1480 match = memcmp( sub->sa_final.bv_val,
1481 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1482 sub->sa_final.bv_len );
1491 return LDAP_SUCCESS;
1494 #if defined(SLAPD_APPROX_INITIALS)
1495 # define SLAPD_APPROX_DELIMITER "._ "
1496 # define SLAPD_APPROX_WORDLEN 2
1498 # define SLAPD_APPROX_DELIMITER " "
1499 # define SLAPD_APPROX_WORDLEN 1
1508 struct berval *value,
1509 void *assertedValue )
1511 struct berval *nval, *assertv;
1512 char *val, **values, **words, *c;
1513 int i, count, len, nextchunk=0, nextavail=0;
1515 /* Yes, this is necessary */
1516 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1517 if( nval == NULL ) {
1519 return LDAP_SUCCESS;
1522 /* Yes, this is necessary */
1523 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1524 NULL, LDAP_UTF8_APPROX, NULL );
1525 if( assertv == NULL ) {
1528 return LDAP_SUCCESS;
1531 /* Isolate how many words there are */
1532 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1533 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1534 if ( c == NULL ) break;
1539 /* Get a phonetic copy of each word */
1540 words = (char **)ch_malloc( count * sizeof(char *) );
1541 values = (char **)ch_malloc( count * sizeof(char *) );
1542 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1544 values[i] = phonetic(c);
1547 /* Work through the asserted value's words, to see if at least some
1548 of the words are there, in the same order. */
1550 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1551 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1556 #if defined(SLAPD_APPROX_INITIALS)
1557 else if( len == 1 ) {
1558 /* Single letter words need to at least match one word's initial */
1559 for( i=nextavail; i<count; i++ )
1560 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1567 /* Isolate the next word in the asserted value and phonetic it */
1568 assertv->bv_val[nextchunk+len] = '\0';
1569 val = phonetic( assertv->bv_val + nextchunk );
1571 /* See if this phonetic chunk is in the remaining words of *value */
1572 for( i=nextavail; i<count; i++ ){
1573 if( !strcmp( val, values[i] ) ){
1581 /* This chunk in the asserted value was NOT within the *value. */
1587 /* Go on to the next word in the asserted value */
1591 /* If some of the words were seen, call it a match */
1592 if( nextavail > 0 ) {
1599 /* Cleanup allocs */
1600 ber_bvfree( assertv );
1601 for( i=0; i<count; i++ ) {
1602 ch_free( values[i] );
1608 return LDAP_SUCCESS;
1617 struct berval *prefix,
1623 int i,j, len, wordcount, keycount=0;
1624 struct berval *newkeys;
1625 BerVarray keys=NULL;
1627 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1628 struct berval val = BER_BVNULL;
1629 /* Yes, this is necessary */
1630 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1631 assert( !BER_BVISNULL( &val ) );
1633 /* Isolate how many words there are. There will be a key for each */
1634 for( wordcount = 0, c = val.bv_val; *c; c++) {
1635 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1636 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1638 if (*c == '\0') break;
1642 /* Allocate/increase storage to account for new keys */
1643 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1644 * sizeof(struct berval) );
1645 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1646 if( keys ) ch_free( keys );
1649 /* Get a phonetic copy of each word */
1650 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1652 if( len < SLAPD_APPROX_WORDLEN ) continue;
1653 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1658 ber_memfree( val.bv_val );
1660 BER_BVZERO( &keys[keycount] );
1663 return LDAP_SUCCESS;
1672 struct berval *prefix,
1673 void * assertedValue,
1682 /* Yes, this is necessary */
1683 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1684 NULL, LDAP_UTF8_APPROX, NULL );
1685 if( val == NULL || BER_BVISNULL( val ) ) {
1686 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1687 BER_BVZERO( &keys[0] );
1690 return LDAP_SUCCESS;
1693 /* Isolate how many words there are. There will be a key for each */
1694 for( count = 0,c = val->bv_val; *c; c++) {
1695 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1696 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1698 if (*c == '\0') break;
1702 /* Allocate storage for new keys */
1703 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1705 /* Get a phonetic copy of each word */
1706 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1708 if( len < SLAPD_APPROX_WORDLEN ) continue;
1709 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1715 BER_BVZERO( &keys[count] );
1718 return LDAP_SUCCESS;
1721 /* Remove all spaces and '-' characters */
1723 telephoneNumberNormalize(
1728 struct berval *normalized,
1733 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1735 /* validator should have refused an empty string */
1736 assert( !BER_BVISEMPTY( val ) );
1738 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1740 for( p = val->bv_val; *p; p++ ) {
1741 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1747 normalized->bv_len = q - normalized->bv_val;
1749 if( BER_BVISEMPTY( normalized ) ) {
1750 slap_sl_free( normalized->bv_val, ctx );
1751 BER_BVZERO( normalized );
1752 return LDAP_INVALID_SYNTAX;
1755 return LDAP_SUCCESS;
1763 struct berval val = *in;
1765 if( BER_BVISEMPTY( &val ) ) {
1766 /* disallow empty strings */
1767 return LDAP_INVALID_SYNTAX;
1770 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1771 if ( val.bv_len == 1 ) {
1772 return LDAP_SUCCESS;
1775 if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
1782 while ( OID_LEADCHAR( val.bv_val[0] )) {
1786 if ( val.bv_len == 0 ) {
1787 return LDAP_SUCCESS;
1791 if( !OID_SEPARATOR( val.bv_val[0] )) {
1799 return LDAP_INVALID_SYNTAX;
1808 struct berval val = *in;
1810 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1812 if ( val.bv_val[0] == '-' ) {
1816 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1817 return LDAP_INVALID_SYNTAX;
1820 if( val.bv_val[0] == '0' ) { /* "-0" */
1821 return LDAP_INVALID_SYNTAX;
1824 } else if ( val.bv_val[0] == '0' ) {
1825 if( val.bv_len > 1 ) { /* "0<more>" */
1826 return LDAP_INVALID_SYNTAX;
1829 return LDAP_SUCCESS;
1832 for( i=0; i < val.bv_len; i++ ) {
1833 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1834 return LDAP_INVALID_SYNTAX;
1838 return LDAP_SUCCESS;
1847 struct berval *value,
1848 void *assertedValue )
1850 struct berval *asserted = (struct berval *) assertedValue;
1851 int vsign = 1, asign = 1; /* default sign = '+' */
1856 if( v.bv_val[0] == '-' ) {
1862 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1865 if( a.bv_val[0] == '-' ) {
1871 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1873 match = vsign - asign;
1875 match = ( v.bv_len != a.bv_len
1876 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1877 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1878 if( vsign < 0 ) match = -match;
1882 return LDAP_SUCCESS;
1886 countryStringValidate(
1888 struct berval *val )
1890 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1892 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1893 return LDAP_INVALID_SYNTAX;
1895 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1896 return LDAP_INVALID_SYNTAX;
1899 return LDAP_SUCCESS;
1903 printableStringValidate(
1905 struct berval *val )
1909 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
1911 for(i=0; i < val->bv_len; i++) {
1912 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1913 return LDAP_INVALID_SYNTAX;
1917 return LDAP_SUCCESS;
1921 printablesStringValidate(
1923 struct berval *val )
1927 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
1929 for(i=0,len=0; i < val->bv_len; i++) {
1930 int c = val->bv_val[i];
1934 return LDAP_INVALID_SYNTAX;
1938 } else if ( SLAP_PRINTABLE(c) ) {
1941 return LDAP_INVALID_SYNTAX;
1946 return LDAP_INVALID_SYNTAX;
1949 return LDAP_SUCCESS;
1955 struct berval *val )
1959 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
1961 for(i=0; i < val->bv_len; i++) {
1962 if( !LDAP_ASCII(val->bv_val[i]) ) {
1963 return LDAP_INVALID_SYNTAX;
1967 return LDAP_SUCCESS;
1976 struct berval *normalized,
1980 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1982 assert( !BER_BVISEMPTY( val ) );
1984 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1988 /* Ignore initial whitespace */
1989 while ( ASCII_SPACE( *p ) ) p++;
1991 normalized->bv_val = ber_strdup_x( p, ctx );
1992 p = q = normalized->bv_val;
1995 if ( ASCII_SPACE( *p ) ) {
1998 /* Ignore the extra whitespace */
1999 while ( ASCII_SPACE( *p ) ) {
2003 } else if ( casefold ) {
2004 /* Most IA5 rules require casefolding */
2005 *q++ = TOLOWER(*p); p++;
2012 assert( normalized->bv_val <= p );
2016 * If the string ended in space, backup the pointer one
2017 * position. One is enough because the above loop collapsed
2018 * all whitespace to a single space.
2020 if ( ASCII_SPACE( q[-1] ) ) --q;
2022 /* null terminate */
2025 normalized->bv_len = q - normalized->bv_val;
2026 if( BER_BVISEMPTY( normalized ) ) {
2027 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2028 normalized->bv_val[0] = ' ';
2029 normalized->bv_val[1] = '\0';
2030 normalized->bv_len = 1;
2033 return LDAP_SUCCESS;
2042 if( in->bv_len != 36 ) {
2043 return LDAP_INVALID_SYNTAX;
2046 for( i=0; i<36; i++ ) {
2052 if( in->bv_val[i] != '-' ) {
2053 return LDAP_INVALID_SYNTAX;
2057 if( !ASCII_HEX( in->bv_val[i]) ) {
2058 return LDAP_INVALID_SYNTAX;
2063 return LDAP_SUCCESS;
2072 struct berval *normalized,
2075 unsigned char octet = '\0';
2078 normalized->bv_len = 16;
2079 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
2081 for( i=0, j=0; i<36; i++ ) {
2082 unsigned char nibble;
2083 if( val->bv_val[i] == '-' ) {
2086 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2087 nibble = val->bv_val[i] - '0';
2089 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2090 nibble = val->bv_val[i] - ('a'-10);
2092 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2093 nibble = val->bv_val[i] - ('A'-10);
2096 slap_sl_free( normalized->bv_val, ctx );
2097 return LDAP_INVALID_SYNTAX;
2102 normalized->bv_val[j>>1] = octet;
2104 octet = nibble << 4;
2109 normalized->bv_val[normalized->bv_len] = 0;
2110 return LDAP_SUCCESS;
2116 numericStringValidate(
2122 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
2124 for(i=0; i < in->bv_len; i++) {
2125 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2126 return LDAP_INVALID_SYNTAX;
2130 return LDAP_SUCCESS;
2134 numericStringNormalize(
2139 struct berval *normalized,
2142 /* removal all spaces */
2145 assert( !BER_BVISEMPTY( val ) );
2147 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2150 q = normalized->bv_val;
2153 if ( ASCII_SPACE( *p ) ) {
2154 /* Ignore whitespace */
2161 /* we should have copied no more then is in val */
2162 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2164 /* null terminate */
2167 normalized->bv_len = q - normalized->bv_val;
2169 if( BER_BVISEMPTY( normalized ) ) {
2170 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2171 normalized->bv_val[0] = ' ';
2172 normalized->bv_val[1] = '\0';
2173 normalized->bv_len = 1;
2176 return LDAP_SUCCESS;
2180 * Integer conversion macros that will use the largest available
2183 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2184 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2185 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2186 # define SLAP_LONG_MAX LLONG_MAX
2187 # define SLAP_LONG_MIN LLONG_MIN
2188 # define SLAP_LONG long long
2190 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2191 # define SLAP_LONG_MAX LONG_MAX
2192 # define SLAP_LONG_MIN LONG_MIN
2193 # define SLAP_LONG long
2194 #endif /* HAVE_STRTOLL ... */
2202 struct berval *value,
2203 void *assertedValue )
2205 SLAP_LONG lValue, lAssertedValue;
2207 /* safe to assume integers are NUL terminated? */
2208 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2209 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2212 return LDAP_CONSTRAINT_VIOLATION;
2215 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2217 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2220 return LDAP_CONSTRAINT_VIOLATION;
2223 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2224 return LDAP_SUCCESS;
2233 struct berval *value,
2234 void *assertedValue )
2236 SLAP_LONG lValue, lAssertedValue;
2238 /* safe to assume integers are NUL terminated? */
2239 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2240 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2243 return LDAP_CONSTRAINT_VIOLATION;
2246 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2248 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2251 return LDAP_CONSTRAINT_VIOLATION;
2254 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2255 return LDAP_SUCCESS;
2259 serialNumberAndIssuerValidate(
2266 struct berval sn, i;
2267 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2269 i.bv_val = strchr( in->bv_val, '$' );
2270 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2272 sn.bv_val = in->bv_val;
2273 sn.bv_len = i.bv_val - in->bv_val;
2276 i.bv_len = in->bv_len - (sn.bv_len + 1);
2278 /* validate serial number (strict for now) */
2279 for( n=0; n < sn.bv_len; n++ ) {
2280 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2284 rc = dnValidate( NULL, &i );
2285 if( rc ) return LDAP_INVALID_SYNTAX;
2287 return LDAP_SUCCESS;
2291 serialNumberAndIssuerPretty(
2300 struct berval sn, i, newi;
2305 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2306 val->bv_val, 0, 0 );
2308 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2310 i.bv_val = strchr( val->bv_val, '$' );
2311 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2313 sn.bv_val = val->bv_val;
2314 sn.bv_len = i.bv_val - val->bv_val;
2317 i.bv_len = val->bv_len - (sn.bv_len + 1);
2319 /* eat leading zeros */
2320 for( n=0; n < (sn.bv_len-1); n++ ) {
2321 if( sn.bv_val[n] != '0' ) break;
2326 for( n=0; n < sn.bv_len; n++ ) {
2327 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2331 rc = dnPretty( syntax, &i, &newi, ctx );
2332 if( rc ) return LDAP_INVALID_SYNTAX;
2334 /* make room from sn + "$" */
2335 out->bv_len = sn.bv_len + newi.bv_len + 1;
2336 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2338 if( BER_BVISNULL( out ) ) {
2339 slap_sl_free( newi.bv_val, ctx );
2343 /* push issuer over */
2344 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2345 /* insert sn and "$" */
2346 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2347 out->bv_val[sn.bv_len] = '$';
2349 out->bv_val[out->bv_len] = '\0';
2351 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2352 out->bv_val, 0, 0 );
2354 return LDAP_SUCCESS;
2358 * This routine is called by certificateExactNormalize when
2359 * certificateExactNormalize receives a search string instead of
2360 * a certificate. This routine checks if the search value is valid
2361 * and then returns the normalized value
2364 serialNumberAndIssuerNormalize(
2375 struct berval sn, i, newi;
2380 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2381 val->bv_val, 0, 0 );
2383 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2385 i.bv_val = strchr( val->bv_val, '$' );
2386 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2388 sn.bv_val = val->bv_val;
2389 sn.bv_len = i.bv_val - val->bv_val;
2392 i.bv_len = val->bv_len - (sn.bv_len + 1);
2394 /* eat leading zeros */
2395 for( n=0; n < (sn.bv_len-1); n++ ) {
2396 if( sn.bv_val[n] != '0' ) break;
2401 for( n=0; n < sn.bv_len; n++ ) {
2402 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2403 return LDAP_INVALID_SYNTAX;
2408 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2409 if( rc ) return LDAP_INVALID_SYNTAX;
2411 /* make room from sn + "$" */
2412 out->bv_len = sn.bv_len + newi.bv_len + 1;
2413 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2415 if( BER_BVISNULL( out ) ) {
2416 slap_sl_free( newi.bv_val, ctx );
2420 /* push issuer over */
2421 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2422 /* insert sn and "$" */
2423 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2424 out->bv_val[sn.bv_len] = '$';
2426 out->bv_val[out->bv_len] = '\0';
2428 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2429 out->bv_val, 0, 0 );
2436 certificateExactNormalize(
2441 struct berval *normalized,
2444 int rc = LDAP_INVALID_SYNTAX;
2446 char *serial = NULL;
2447 ber_len_t seriallen;
2448 struct berval issuer_dn = BER_BVNULL;
2449 X509_NAME *name = NULL;
2450 ASN1_INTEGER *sn = NULL;
2453 if( BER_BVISEMPTY( val ) ) goto done;
2455 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2456 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2459 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2461 p = (unsigned char *)val->bv_val;
2462 xcert = d2i_X509( NULL, &p, val->bv_len);
2463 if( xcert == NULL ) goto done;
2465 sn=X509_get_serialNumber(xcert);
2466 if ( sn == NULL ) goto done;
2467 serial=i2s_ASN1_INTEGER(0, sn );
2468 if( serial == NULL ) goto done;
2469 seriallen=strlen(serial);
2471 name=X509_get_issuer_name(xcert);
2472 if( name == NULL ) goto done;
2473 rc = dnX509normalize( name, &issuer_dn );
2474 if( rc != LDAP_SUCCESS ) goto done;
2476 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2477 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2478 p = (unsigned char *)normalized->bv_val;
2479 AC_MEMCPY(p, serial, seriallen);
2482 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2483 p += issuer_dn.bv_len;
2486 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2487 normalized->bv_val, NULL, NULL );
2490 if (xcert) X509_free(xcert);
2491 if (serial) ch_free(serial);
2492 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2496 #endif /* HAVE_TLS */
2499 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2500 /* slight optimization - does not need the start parameter */
2501 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2506 check_time_syntax (struct berval *val,
2509 struct berval *fraction)
2512 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2513 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2514 * GeneralizedTime supports leap seconds, UTCTime does not.
2516 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2517 static const int mdays[2][12] = {
2518 /* non-leap years */
2519 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2521 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2524 int part, c, c1, c2, tzoffset, leapyear = 0;
2527 e = p + val->bv_len;
2529 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2530 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2532 for (part = start; part < 7 && p < e; part++) {
2534 if (!ASCII_DIGIT(c1)) {
2539 return LDAP_INVALID_SYNTAX;
2542 if (!ASCII_DIGIT(c)) {
2543 return LDAP_INVALID_SYNTAX;
2545 c += c1 * 10 - '0' * 11;
2546 if ((part | 1) == 3) {
2549 return LDAP_INVALID_SYNTAX;
2552 if (c >= ceiling[part]) {
2553 if (! (c == 60 && part == 6 && start == 0))
2554 return LDAP_INVALID_SYNTAX;
2558 if (part < 5 + start) {
2559 return LDAP_INVALID_SYNTAX;
2561 for (; part < 9; part++) {
2565 /* leapyear check for the Gregorian calendar (year>1581) */
2566 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2570 if (parts[3] >= mdays[leapyear][parts[2]]) {
2571 return LDAP_INVALID_SYNTAX;
2575 fraction->bv_val = p;
2576 fraction->bv_len = 0;
2577 if (p < e && (*p == '.' || *p == ',')) {
2579 while (++p < e && ASCII_DIGIT(*p)) {
2582 if (p - fraction->bv_val == 1) {
2583 return LDAP_INVALID_SYNTAX;
2585 for (end_num = p; end_num[-1] == '0'; --end_num) {
2588 c = end_num - fraction->bv_val;
2589 if (c != 1) fraction->bv_len = c;
2595 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2601 return LDAP_INVALID_SYNTAX;
2607 for (part = 7; part < 9 && p < e; part++) {
2609 if (!ASCII_DIGIT(c1)) {
2614 return LDAP_INVALID_SYNTAX;
2617 if (!ASCII_DIGIT(c2)) {
2618 return LDAP_INVALID_SYNTAX;
2620 parts[part] = c1 * 10 + c2 - '0' * 11;
2621 if (parts[part] >= ceiling[part]) {
2622 return LDAP_INVALID_SYNTAX;
2625 if (part < 8 + start) {
2626 return LDAP_INVALID_SYNTAX;
2629 if (tzoffset == '-') {
2630 /* negative offset to UTC, ie west of Greenwich */
2631 parts[4] += parts[7];
2632 parts[5] += parts[8];
2633 /* offset is just hhmm, no seconds */
2634 for (part = 6; --part >= 0; ) {
2638 c = mdays[leapyear][parts[2]];
2640 if (parts[part] >= c) {
2642 return LDAP_INVALID_SYNTAX;
2647 } else if (part != 5) {
2652 /* positive offset to UTC, ie east of Greenwich */
2653 parts[4] -= parts[7];
2654 parts[5] -= parts[8];
2655 for (part = 6; --part >= 0; ) {
2656 if (parts[part] < 0) {
2658 return LDAP_INVALID_SYNTAX;
2663 /* make first arg to % non-negative */
2664 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2669 } else if (part != 5) {
2676 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2679 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2686 struct berval *normalized )
2690 rc = check_time_syntax(val, 1, parts, NULL);
2691 if (rc != LDAP_SUCCESS) {
2695 normalized->bv_val = ch_malloc( 14 );
2696 if ( normalized->bv_val == NULL ) {
2697 return LBER_ERROR_MEMORY;
2700 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2701 parts[1], parts[2] + 1, parts[3] + 1,
2702 parts[4], parts[5], parts[6] );
2703 normalized->bv_len = 13;
2705 return LDAP_SUCCESS;
2715 return check_time_syntax(in, 1, parts, NULL);
2718 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2721 generalizedTimeValidate(
2726 struct berval fraction;
2727 return check_time_syntax(in, 0, parts, &fraction);
2731 generalizedTimeNormalize(
2736 struct berval *normalized,
2741 struct berval fraction;
2743 rc = check_time_syntax(val, 0, parts, &fraction);
2744 if (rc != LDAP_SUCCESS) {
2748 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2749 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2750 if ( BER_BVISNULL( normalized ) ) {
2751 return LBER_ERROR_MEMORY;
2754 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2755 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2756 parts[4], parts[5], parts[6] );
2757 if ( !BER_BVISEMPTY( &fraction ) ) {
2758 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2759 fraction.bv_val, fraction.bv_len );
2760 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2762 strcpy( normalized->bv_val + len-1, "Z" );
2763 normalized->bv_len = len;
2765 return LDAP_SUCCESS;
2769 generalizedTimeOrderingMatch(
2774 struct berval *value,
2775 void *assertedValue )
2777 struct berval *asserted = (struct berval *) assertedValue;
2778 ber_len_t v_len = value->bv_len;
2779 ber_len_t av_len = asserted->bv_len;
2781 /* ignore trailing 'Z' when comparing */
2782 int match = memcmp( value->bv_val, asserted->bv_val,
2783 (v_len < av_len ? v_len : av_len) - 1 );
2784 if ( match == 0 ) match = v_len - av_len;
2787 return LDAP_SUCCESS;
2790 /* Index generation function */
2791 int generalizedTimeIndexer(
2796 struct berval *prefix,
2805 BerValue bvtmp; /* 40 bit index */
2807 struct lutil_timet tt;
2809 bvtmp.bv_len = sizeof(tmp);
2811 for( i=0; values[i].bv_val != NULL; i++ ) {
2812 /* just count them */
2815 /* we should have at least one value at this point */
2818 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2820 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2821 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2822 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2823 /* Use 40 bits of time for key */
2824 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2825 lutil_tm2time( &tm, &tt );
2826 tmp[0] = tt.tt_gsec & 0xff;
2827 tmp[4] = tt.tt_sec & 0xff;
2829 tmp[3] = tt.tt_sec & 0xff;
2831 tmp[2] = tt.tt_sec & 0xff;
2833 tmp[1] = tt.tt_sec & 0xff;
2835 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2839 keys[j].bv_val = NULL;
2844 return LDAP_SUCCESS;
2847 /* Index generation function */
2848 int generalizedTimeFilter(
2853 struct berval *prefix,
2854 void * assertedValue,
2860 BerValue bvtmp; /* 40 bit index */
2861 BerValue *value = (BerValue *) assertedValue;
2863 struct lutil_timet tt;
2865 bvtmp.bv_len = sizeof(tmp);
2867 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2868 /* Use 40 bits of time for key */
2869 if ( value->bv_val && value->bv_len >= 10 &&
2870 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2872 lutil_tm2time( &tm, &tt );
2873 tmp[0] = tt.tt_gsec & 0xff;
2874 tmp[4] = tt.tt_sec & 0xff;
2876 tmp[3] = tt.tt_sec & 0xff;
2878 tmp[2] = tt.tt_sec & 0xff;
2880 tmp[1] = tt.tt_sec & 0xff;
2882 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2883 ber_dupbv_x(keys, &bvtmp, ctx );
2884 keys[1].bv_val = NULL;
2892 return LDAP_SUCCESS;
2896 deliveryMethodValidate(
2898 struct berval *val )
2901 #define LENOF(s) (sizeof(s)-1)
2902 struct berval tmp = *val;
2904 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2905 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2906 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2909 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2911 switch( tmp.bv_val[0] ) {
2914 if(( tmp.bv_len >= LENOF("any") ) &&
2915 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2917 tmp.bv_len -= LENOF("any");
2918 tmp.bv_val += LENOF("any");
2921 return LDAP_INVALID_SYNTAX;
2925 if(( tmp.bv_len >= LENOF("mhs") ) &&
2926 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2928 tmp.bv_len -= LENOF("mhs");
2929 tmp.bv_val += LENOF("mhs");
2932 return LDAP_INVALID_SYNTAX;
2936 if(( tmp.bv_len >= LENOF("physical") ) &&
2937 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2939 tmp.bv_len -= LENOF("physical");
2940 tmp.bv_val += LENOF("physical");
2943 return LDAP_INVALID_SYNTAX;
2946 case 'T': /* telex or teletex or telephone */
2947 if(( tmp.bv_len >= LENOF("telex") ) &&
2948 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2950 tmp.bv_len -= LENOF("telex");
2951 tmp.bv_val += LENOF("telex");
2954 if(( tmp.bv_len >= LENOF("teletex") ) &&
2955 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2957 tmp.bv_len -= LENOF("teletex");
2958 tmp.bv_val += LENOF("teletex");
2961 if(( tmp.bv_len >= LENOF("telephone") ) &&
2962 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2964 tmp.bv_len -= LENOF("telephone");
2965 tmp.bv_val += LENOF("telephone");
2968 return LDAP_INVALID_SYNTAX;
2971 case 'G': /* g3fax or g4fax */
2972 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2973 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2974 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2976 tmp.bv_len -= LENOF("g3fax");
2977 tmp.bv_val += LENOF("g3fax");
2980 return LDAP_INVALID_SYNTAX;
2984 if(( tmp.bv_len >= LENOF("ia5") ) &&
2985 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2987 tmp.bv_len -= LENOF("ia5");
2988 tmp.bv_val += LENOF("ia5");
2991 return LDAP_INVALID_SYNTAX;
2995 if(( tmp.bv_len >= LENOF("videotex") ) &&
2996 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2998 tmp.bv_len -= LENOF("videotex");
2999 tmp.bv_val += LENOF("videotex");
3002 return LDAP_INVALID_SYNTAX;
3005 return LDAP_INVALID_SYNTAX;
3008 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
3010 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3014 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
3018 return LDAP_INVALID_SYNTAX;
3020 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
3029 nisNetgroupTripleValidate(
3031 struct berval *val )
3036 if ( BER_BVISEMPTY( val ) ) {
3037 return LDAP_INVALID_SYNTAX;
3040 p = (char *)val->bv_val;
3041 e = p + val->bv_len;
3043 if ( *p != '(' /*')'*/ ) {
3044 return LDAP_INVALID_SYNTAX;
3047 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
3051 return LDAP_INVALID_SYNTAX;
3054 } else if ( !AD_CHAR( *p ) ) {
3055 return LDAP_INVALID_SYNTAX;
3059 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3060 return LDAP_INVALID_SYNTAX;
3066 return LDAP_INVALID_SYNTAX;
3069 return LDAP_SUCCESS;
3073 bootParameterValidate(
3075 struct berval *val )
3079 if ( BER_BVISEMPTY( val ) ) {
3080 return LDAP_INVALID_SYNTAX;
3083 p = (char *)val->bv_val;
3084 e = p + val->bv_len;
3087 for (; ( p < e ) && ( *p != '=' ); p++ ) {
3088 if ( !AD_CHAR( *p ) ) {
3089 return LDAP_INVALID_SYNTAX;
3094 return LDAP_INVALID_SYNTAX;
3098 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3099 if ( !AD_CHAR( *p ) ) {
3100 return LDAP_INVALID_SYNTAX;
3105 return LDAP_INVALID_SYNTAX;
3109 for ( p++; p < e; p++ ) {
3110 if ( !SLAP_PRINTABLE( *p ) ) {
3111 return LDAP_INVALID_SYNTAX;
3115 return LDAP_SUCCESS;
3119 firstComponentNormalize(
3124 struct berval *normalized,
3131 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
3132 ber_dupbv_x( normalized, val, ctx );
3133 return LDAP_SUCCESS;
3136 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3138 if( val->bv_val[0] != '(' /*')'*/ &&
3139 val->bv_val[0] != '{' /*'}'*/ )
3141 return LDAP_INVALID_SYNTAX;
3144 /* trim leading white space */
3146 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3152 /* grab next word */
3153 comp.bv_val = &val->bv_val[len];
3154 len = val->bv_len - len;
3155 for( comp.bv_len = 0;
3156 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3162 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3163 rc = numericoidValidate( NULL, &comp );
3164 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3165 rc = integerValidate( NULL, &comp );
3167 rc = LDAP_INVALID_SYNTAX;
3171 if( rc == LDAP_SUCCESS ) {
3172 ber_dupbv_x( normalized, &comp, ctx );
3179 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3180 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3182 static slap_syntax_defs_rec syntax_defs[] = {
3183 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3184 X_BINARY X_NOT_H_R ")",
3185 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3186 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3188 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3190 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3192 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3193 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3195 SLAP_SYNTAX_BER, berValidate, NULL},
3196 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3197 0, bitStringValidate, NULL },
3198 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3199 0, booleanValidate, NULL},
3200 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3201 X_BINARY X_NOT_H_R ")",
3202 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3203 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3204 X_BINARY X_NOT_H_R ")",
3205 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3206 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3207 X_BINARY X_NOT_H_R ")",
3208 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3209 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3210 0, countryStringValidate, NULL},
3211 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3212 0, dnValidate, dnPretty},
3213 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3214 0, rdnValidate, rdnPretty},
3215 #ifdef LDAP_COMP_MATCH
3216 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3217 0, allComponentsValidate, NULL},
3218 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3219 0, componentFilterValidate, NULL},
3221 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3223 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3224 0, deliveryMethodValidate, NULL},
3225 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3226 0, UTF8StringValidate, NULL},
3227 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3229 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3231 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3233 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3235 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3237 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3238 0, printablesStringValidate, NULL},
3239 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3240 SLAP_SYNTAX_BLOB, NULL, NULL},
3241 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3242 0, generalizedTimeValidate, NULL},
3243 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3245 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3246 0, IA5StringValidate, NULL},
3247 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3248 0, integerValidate, NULL},
3249 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3250 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3251 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3253 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3255 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3257 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3259 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3261 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3262 0, nameUIDValidate, nameUIDPretty },
3263 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3265 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3266 0, numericStringValidate, NULL},
3267 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3269 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3270 0, numericoidValidate, NULL},
3271 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3272 0, IA5StringValidate, NULL},
3273 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3274 0, blobValidate, NULL},
3275 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3276 0, UTF8StringValidate, NULL},
3277 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3279 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3281 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3282 0, printableStringValidate, NULL},
3283 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3284 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3285 0, subtreeSpecificationValidate, NULL},
3286 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3287 X_BINARY X_NOT_H_R ")",
3288 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3289 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3290 0, printableStringValidate, NULL},
3291 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3293 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3294 0, printablesStringValidate, NULL},
3295 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3296 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3297 0, utcTimeValidate, NULL},
3299 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3301 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3303 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3305 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3307 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3310 /* RFC 2307 NIS Syntaxes */
3311 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3312 0, nisNetgroupTripleValidate, NULL},
3313 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3314 0, bootParameterValidate, NULL},
3316 /* From PKIX *//* This OID is not published yet. */
3317 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3319 serialNumberAndIssuerValidate,
3320 serialNumberAndIssuerPretty},
3322 #ifdef SLAPD_ACI_ENABLED
3323 /* OpenLDAP Experimental Syntaxes */
3324 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3326 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3330 #ifdef SLAPD_AUTHPASSWD
3331 /* needs updating */
3332 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3333 SLAP_SYNTAX_HIDE, NULL, NULL},
3336 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3337 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3339 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3340 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3342 /* OpenLDAP Void Syntax */
3343 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3344 SLAP_SYNTAX_HIDE, inValidate, NULL},
3345 {NULL, 0, NULL, NULL}
3348 char *certificateExactMatchSyntaxes[] = {
3349 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3352 #ifdef LDAP_COMP_MATCH
3353 char *componentFilterMatchSyntaxes[] = {
3354 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3358 char *directoryStringSyntaxes[] = {
3359 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3362 char *integerFirstComponentMatchSyntaxes[] = {
3363 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3364 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3367 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3368 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3369 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3370 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3371 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3372 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3373 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3374 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3375 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3380 * Other matching rules in X.520 that we do not use (yet):
3382 * 2.5.13.25 uTCTimeMatch
3383 * 2.5.13.26 uTCTimeOrderingMatch
3384 * 2.5.13.31* directoryStringFirstComponentMatch
3385 * 2.5.13.32* wordMatch
3386 * 2.5.13.33* keywordMatch
3387 * 2.5.13.36 certificatePairExactMatch
3388 * 2.5.13.37 certificatePairMatch
3389 * 2.5.13.38 certificateListExactMatch
3390 * 2.5.13.39 certificateListMatch
3391 * 2.5.13.40 algorithmIdentifierMatch
3392 * 2.5.13.41* storedPrefixMatch
3393 * 2.5.13.42 attributeCertificateMatch
3394 * 2.5.13.43 readerAndKeyIDMatch
3395 * 2.5.13.44 attributeIntegrityMatch
3397 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3399 static slap_mrule_defs_rec mrule_defs[] = {
3401 * EQUALITY matching rules must be listed after associated APPROX
3402 * matching rules. So, we list all APPROX matching rules first.
3404 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3405 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3406 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3407 NULL, NULL, directoryStringApproxMatch,
3408 directoryStringApproxIndexer, directoryStringApproxFilter,
3411 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3412 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3413 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3414 NULL, NULL, IA5StringApproxMatch,
3415 IA5StringApproxIndexer, IA5StringApproxFilter,
3419 * Other matching rules
3422 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3423 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3424 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3425 NULL, NULL, octetStringMatch,
3426 octetStringIndexer, octetStringFilter,
3429 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3430 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3431 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3432 NULL, dnNormalize, dnMatch,
3433 octetStringIndexer, octetStringFilter,
3436 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3437 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3438 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3439 NULL, dnNormalize, dnRelativeMatch,
3443 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3444 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3445 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3446 NULL, dnNormalize, dnRelativeMatch,
3450 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3451 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3452 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3453 NULL, dnNormalize, dnRelativeMatch,
3457 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3458 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3459 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3460 NULL, dnNormalize, dnRelativeMatch,
3464 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3465 "SYNTAX 1.2.36.79672281.1.5.0 )",
3466 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3467 NULL, rdnNormalize, rdnMatch,
3468 octetStringIndexer, octetStringFilter,
3471 #ifdef LDAP_COMP_MATCH
3472 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3473 "SYNTAX 1.2.36.79672281.1.5.2 )",
3474 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3475 NULL, NULL , componentFilterMatch,
3476 octetStringIndexer, octetStringFilter,
3479 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3480 "SYNTAX 1.2.36.79672281.1.5.3 )",
3481 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3482 NULL, NULL , allComponentsMatch,
3483 octetStringIndexer, octetStringFilter,
3486 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3487 "SYNTAX 1.2.36.79672281.1.5.3 )",
3488 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3489 NULL, NULL , directoryComponentsMatch,
3490 octetStringIndexer, octetStringFilter,
3494 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3495 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3496 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3497 NULL, UTF8StringNormalize, octetStringMatch,
3498 octetStringIndexer, octetStringFilter,
3499 directoryStringApproxMatchOID },
3501 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3503 SLAP_MR_ORDERING, directoryStringSyntaxes,
3504 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3506 "caseIgnoreMatch" },
3508 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3510 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3511 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3512 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3513 "caseIgnoreMatch" },
3515 {"( 2.5.13.5 NAME 'caseExactMatch' "
3516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3517 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3518 NULL, UTF8StringNormalize, octetStringMatch,
3519 octetStringIndexer, octetStringFilter,
3520 directoryStringApproxMatchOID },
3522 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3524 SLAP_MR_ORDERING, directoryStringSyntaxes,
3525 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3529 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3530 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3531 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3532 NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
3533 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3536 {"( 2.5.13.8 NAME 'numericStringMatch' "
3537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3538 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3539 NULL, numericStringNormalize, octetStringMatch,
3540 octetStringIndexer, octetStringFilter,
3543 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3545 SLAP_MR_ORDERING, NULL,
3546 NULL, numericStringNormalize, octetStringOrderingMatch,
3548 "numericStringMatch" },
3550 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3552 SLAP_MR_SUBSTR, NULL,
3553 NULL, numericStringNormalize, octetStringSubstringsMatch,
3554 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3555 "numericStringMatch" },
3557 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3559 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3560 NULL, NULL, NULL, NULL, NULL, NULL },
3562 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3563 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3564 SLAP_MR_SUBSTR, NULL,
3565 NULL, NULL, NULL, NULL, NULL,
3566 "caseIgnoreListMatch" },
3568 {"( 2.5.13.13 NAME 'booleanMatch' "
3569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3570 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3571 NULL, NULL, booleanMatch,
3572 octetStringIndexer, octetStringFilter,
3575 {"( 2.5.13.14 NAME 'integerMatch' "
3576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3577 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3578 NULL, NULL, integerMatch,
3579 octetStringIndexer, octetStringFilter,
3582 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3583 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3584 SLAP_MR_ORDERING, NULL,
3585 NULL, NULL, integerMatch,
3589 {"( 2.5.13.16 NAME 'bitStringMatch' "
3590 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3591 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3592 NULL, NULL, octetStringMatch,
3593 octetStringIndexer, octetStringFilter,
3596 {"( 2.5.13.17 NAME 'octetStringMatch' "
3597 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3598 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3599 NULL, NULL, octetStringMatch,
3600 octetStringIndexer, octetStringFilter,
3603 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3604 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3605 SLAP_MR_ORDERING, NULL,
3606 NULL, NULL, octetStringOrderingMatch,
3608 "octetStringMatch" },
3610 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3611 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3612 SLAP_MR_SUBSTR, NULL,
3613 NULL, NULL, octetStringSubstringsMatch,
3614 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3615 "octetStringMatch" },
3617 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3618 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3619 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3621 telephoneNumberNormalize, octetStringMatch,
3622 octetStringIndexer, octetStringFilter,
3625 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3626 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3627 SLAP_MR_SUBSTR, NULL,
3628 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3629 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3630 "telephoneNumberMatch" },
3632 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3633 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3634 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3635 NULL, NULL, NULL, NULL, NULL, NULL },
3637 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3638 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3639 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3640 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3644 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3645 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3646 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3647 NULL, NULL, NULL, NULL, NULL, NULL },
3649 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3651 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3652 NULL, generalizedTimeNormalize, octetStringMatch,
3653 generalizedTimeIndexer, generalizedTimeFilter,
3656 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3657 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3658 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3659 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3661 "generalizedTimeMatch" },
3663 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3664 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3665 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3666 integerFirstComponentMatchSyntaxes,
3667 NULL, firstComponentNormalize, integerMatch,
3668 octetStringIndexer, octetStringFilter,
3671 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3672 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3673 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3674 objectIdentifierFirstComponentMatchSyntaxes,
3675 NULL, firstComponentNormalize, octetStringMatch,
3676 octetStringIndexer, octetStringFilter,
3679 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3680 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3681 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3683 NULL, certificateExactNormalize, octetStringMatch,
3684 octetStringIndexer, octetStringFilter,
3686 NULL, NULL, NULL, NULL, NULL,
3690 {"( 2.5.13.35 NAME 'certificateMatch' "
3691 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3692 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3694 NULL, NULL, octetStringMatch,
3695 octetStringIndexer, octetStringFilter,
3697 NULL, NULL, NULL, NULL, NULL,
3701 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3702 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3703 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3704 NULL, IA5StringNormalize, octetStringMatch,
3705 octetStringIndexer, octetStringFilter,
3706 IA5StringApproxMatchOID },
3708 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3709 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3710 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3711 NULL, IA5StringNormalize, octetStringMatch,
3712 octetStringIndexer, octetStringFilter,
3713 IA5StringApproxMatchOID },
3715 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3716 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3717 SLAP_MR_SUBSTR, NULL,
3718 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3719 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3720 "caseIgnoreIA5Match" },
3722 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3723 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3724 SLAP_MR_SUBSTR, NULL,
3725 NULL, IA5StringNormalize, directoryStringSubstringsMatch,
3726 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3727 "caseExactIA5Match" },
3729 #ifdef SLAPD_AUTHPASSWD
3730 /* needs updating */
3731 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3732 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3733 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3734 NULL, NULL, authPasswordMatch,
3739 #ifdef SLAPD_ACI_ENABLED
3740 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3741 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3742 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3743 NULL, NULL, OpenLDAPaciMatch,
3748 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3749 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3751 NULL, NULL, integerBitAndMatch,
3755 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3756 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3758 NULL, NULL, integerBitOrMatch,
3762 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3763 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3764 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3765 NULL, UUIDNormalize, octetStringMatch,
3766 octetStringIndexer, octetStringFilter,
3769 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3770 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3771 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3772 NULL, UUIDNormalize, octetStringOrderingMatch,
3773 octetStringIndexer, octetStringFilter,
3776 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3777 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3778 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3779 NULL, NULL, csnMatch,
3780 csnIndexer, csnFilter,
3783 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3784 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3785 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3786 NULL, NULL, csnOrderingMatch,
3790 {NULL, SLAP_MR_NONE, NULL,
3791 NULL, NULL, NULL, NULL, NULL,
3796 slap_schema_init( void )
3801 /* we should only be called once (from main) */
3802 assert( schema_init_done == 0 );
3804 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3805 res = register_syntax( &syntax_defs[i] );
3808 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3809 syntax_defs[i].sd_desc );
3814 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3815 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3816 mrule_defs[i].mrd_compat_syntaxes == NULL )
3819 "slap_schema_init: Ignoring unusable matching rule %s\n",
3820 mrule_defs[i].mrd_desc );
3824 res = register_matching_rule( &mrule_defs[i] );
3828 "slap_schema_init: Error registering matching rule %s\n",
3829 mrule_defs[i].mrd_desc );
3834 res = slap_schema_load();
3835 schema_init_done = 1;
3840 schema_destroy( void )