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 wasspace = 1; /* trim leading spaces */
1327 for( i = 0; i < tmp.bv_len; i++) {
1328 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1329 if( wasspace++ == 0 ) {
1330 /* trim repeated spaces */
1331 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1335 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1339 if( !BER_BVISEMPTY( &nvalue ) ) {
1341 /* last character was a space, trim it */
1344 nvalue.bv_val[nvalue.bv_len] = '\0';
1347 /* string of all spaces is treated as one space */
1348 nvalue.bv_val[0] = ' ';
1349 nvalue.bv_val[1] = '\0';
1353 *normalized = nvalue;
1354 return LDAP_SUCCESS;
1357 #if defined(SLAPD_APPROX_INITIALS)
1358 # define SLAPD_APPROX_DELIMITER "._ "
1359 # define SLAPD_APPROX_WORDLEN 2
1361 # define SLAPD_APPROX_DELIMITER " "
1362 # define SLAPD_APPROX_WORDLEN 1
1371 struct berval *value,
1372 void *assertedValue )
1374 struct berval *nval, *assertv;
1375 char *val, **values, **words, *c;
1376 int i, count, len, nextchunk=0, nextavail=0;
1378 /* Yes, this is necessary */
1379 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1380 if( nval == NULL ) {
1382 return LDAP_SUCCESS;
1385 /* Yes, this is necessary */
1386 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1387 NULL, LDAP_UTF8_APPROX, NULL );
1388 if( assertv == NULL ) {
1391 return LDAP_SUCCESS;
1394 /* Isolate how many words there are */
1395 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1396 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1397 if ( c == NULL ) break;
1402 /* Get a phonetic copy of each word */
1403 words = (char **)ch_malloc( count * sizeof(char *) );
1404 values = (char **)ch_malloc( count * sizeof(char *) );
1405 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1407 values[i] = phonetic(c);
1410 /* Work through the asserted value's words, to see if at least some
1411 of the words are there, in the same order. */
1413 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1414 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1419 #if defined(SLAPD_APPROX_INITIALS)
1420 else if( len == 1 ) {
1421 /* Single letter words need to at least match one word's initial */
1422 for( i=nextavail; i<count; i++ )
1423 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1430 /* Isolate the next word in the asserted value and phonetic it */
1431 assertv->bv_val[nextchunk+len] = '\0';
1432 val = phonetic( assertv->bv_val + nextchunk );
1434 /* See if this phonetic chunk is in the remaining words of *value */
1435 for( i=nextavail; i<count; i++ ){
1436 if( !strcmp( val, values[i] ) ){
1444 /* This chunk in the asserted value was NOT within the *value. */
1450 /* Go on to the next word in the asserted value */
1454 /* If some of the words were seen, call it a match */
1455 if( nextavail > 0 ) {
1462 /* Cleanup allocs */
1463 ber_bvfree( assertv );
1464 for( i=0; i<count; i++ ) {
1465 ch_free( values[i] );
1471 return LDAP_SUCCESS;
1480 struct berval *prefix,
1486 int i,j, len, wordcount, keycount=0;
1487 struct berval *newkeys;
1488 BerVarray keys=NULL;
1490 for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
1491 struct berval val = BER_BVNULL;
1492 /* Yes, this is necessary */
1493 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1494 assert( !BER_BVISNULL( &val ) );
1496 /* Isolate how many words there are. There will be a key for each */
1497 for( wordcount = 0, c = val.bv_val; *c; c++) {
1498 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1499 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1501 if (*c == '\0') break;
1505 /* Allocate/increase storage to account for new keys */
1506 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1507 * sizeof(struct berval) );
1508 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1509 if( keys ) ch_free( keys );
1512 /* Get a phonetic copy of each word */
1513 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1515 if( len < SLAPD_APPROX_WORDLEN ) continue;
1516 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1521 ber_memfree( val.bv_val );
1523 BER_BVZERO( &keys[keycount] );
1526 return LDAP_SUCCESS;
1535 struct berval *prefix,
1536 void * assertedValue,
1545 /* Yes, this is necessary */
1546 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1547 NULL, LDAP_UTF8_APPROX, NULL );
1548 if( val == NULL || BER_BVISNULL( val ) ) {
1549 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1550 BER_BVZERO( &keys[0] );
1553 return LDAP_SUCCESS;
1556 /* Isolate how many words there are. There will be a key for each */
1557 for( count = 0,c = val->bv_val; *c; c++) {
1558 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1559 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1561 if (*c == '\0') break;
1565 /* Allocate storage for new keys */
1566 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1568 /* Get a phonetic copy of each word */
1569 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1571 if( len < SLAPD_APPROX_WORDLEN ) continue;
1572 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1578 BER_BVZERO( &keys[count] );
1581 return LDAP_SUCCESS;
1584 /* Remove all spaces and '-' characters */
1586 telephoneNumberNormalize(
1591 struct berval *normalized,
1596 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1598 /* validator should have refused an empty string */
1599 assert( !BER_BVISEMPTY( val ) );
1601 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1603 for( p = val->bv_val; *p; p++ ) {
1604 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1610 normalized->bv_len = q - normalized->bv_val;
1612 if( BER_BVISEMPTY( normalized ) ) {
1613 slap_sl_free( normalized->bv_val, ctx );
1614 BER_BVZERO( normalized );
1615 return LDAP_INVALID_SYNTAX;
1618 return LDAP_SUCCESS;
1626 struct berval val = *in;
1628 if( BER_BVISEMPTY( &val ) ) {
1629 /* disallow empty strings */
1630 return LDAP_INVALID_SYNTAX;
1633 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1634 if ( val.bv_len == 1 ) {
1635 return LDAP_SUCCESS;
1638 if ( val.bv_val[0] == '0' ) {
1645 while ( OID_LEADCHAR( val.bv_val[0] )) {
1649 if ( val.bv_len == 0 ) {
1650 return LDAP_SUCCESS;
1654 if( !OID_SEPARATOR( val.bv_val[0] )) {
1662 return LDAP_INVALID_SYNTAX;
1671 struct berval val = *in;
1673 if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
1675 if ( val.bv_val[0] == '-' ) {
1679 if( BER_BVISEMPTY( &val ) ) { /* bare "-" */
1680 return LDAP_INVALID_SYNTAX;
1683 if( val.bv_val[0] == '0' ) { /* "-0" */
1684 return LDAP_INVALID_SYNTAX;
1687 } else if ( val.bv_val[0] == '0' ) {
1688 if( val.bv_len > 1 ) { /* "0<more>" */
1689 return LDAP_INVALID_SYNTAX;
1692 return LDAP_SUCCESS;
1695 for( i=0; i < val.bv_len; i++ ) {
1696 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1697 return LDAP_INVALID_SYNTAX;
1701 return LDAP_SUCCESS;
1710 struct berval *value,
1711 void *assertedValue )
1713 struct berval *asserted = (struct berval *) assertedValue;
1714 int vsign = 1, asign = 1; /* default sign = '+' */
1719 if( v.bv_val[0] == '-' ) {
1725 if( BER_BVISEMPTY( &v ) ) vsign = 0;
1728 if( a.bv_val[0] == '-' ) {
1734 if( BER_BVISEMPTY( &a ) ) vsign = 0;
1736 match = vsign - asign;
1738 match = ( v.bv_len != a.bv_len
1739 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1740 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1741 if( vsign < 0 ) match = -match;
1745 return LDAP_SUCCESS;
1749 countryStringValidate(
1751 struct berval *val )
1753 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1755 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1756 return LDAP_INVALID_SYNTAX;
1758 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1759 return LDAP_INVALID_SYNTAX;
1762 return LDAP_SUCCESS;
1766 printableStringValidate(
1768 struct berval *val )
1772 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
1774 for(i=0; i < val->bv_len; i++) {
1775 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1776 return LDAP_INVALID_SYNTAX;
1780 return LDAP_SUCCESS;
1784 printablesStringValidate(
1786 struct berval *val )
1790 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
1792 for(i=0,len=0; i < val->bv_len; i++) {
1793 int c = val->bv_val[i];
1797 return LDAP_INVALID_SYNTAX;
1801 } else if ( SLAP_PRINTABLE(c) ) {
1804 return LDAP_INVALID_SYNTAX;
1809 return LDAP_INVALID_SYNTAX;
1812 return LDAP_SUCCESS;
1818 struct berval *val )
1822 if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
1824 for(i=0; i < val->bv_len; i++) {
1825 if( !LDAP_ASCII(val->bv_val[i]) ) {
1826 return LDAP_INVALID_SYNTAX;
1830 return LDAP_SUCCESS;
1839 struct berval *normalized,
1843 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1845 assert( !BER_BVISEMPTY( val ) );
1847 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1851 /* Ignore initial whitespace */
1852 while ( ASCII_SPACE( *p ) ) p++;
1854 normalized->bv_val = ber_strdup_x( p, ctx );
1855 p = q = normalized->bv_val;
1858 if ( ASCII_SPACE( *p ) ) {
1861 /* Ignore the extra whitespace */
1862 while ( ASCII_SPACE( *p ) ) {
1866 } else if ( casefold ) {
1867 /* Most IA5 rules require casefolding */
1868 *q++ = TOLOWER(*p); p++;
1875 assert( normalized->bv_val <= p );
1879 * If the string ended in space, backup the pointer one
1880 * position. One is enough because the above loop collapsed
1881 * all whitespace to a single space.
1883 if ( ASCII_SPACE( q[-1] ) ) --q;
1885 /* null terminate */
1888 normalized->bv_len = q - normalized->bv_val;
1889 if( BER_BVISEMPTY( normalized ) ) {
1890 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1891 normalized->bv_val[0] = ' ';
1892 normalized->bv_val[1] = '\0';
1893 normalized->bv_len = 1;
1896 return LDAP_SUCCESS;
1905 if( in->bv_len != 36 ) {
1906 return LDAP_INVALID_SYNTAX;
1909 for( i=0; i<36; i++ ) {
1915 if( in->bv_val[i] != '-' ) {
1916 return LDAP_INVALID_SYNTAX;
1920 if( !ASCII_HEX( in->bv_val[i]) ) {
1921 return LDAP_INVALID_SYNTAX;
1926 return LDAP_SUCCESS;
1935 struct berval *normalized,
1938 unsigned char octet = '\0';
1941 normalized->bv_len = 16;
1942 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1944 for( i=0, j=0; i<36; i++ ) {
1945 unsigned char nibble;
1946 if( val->bv_val[i] == '-' ) {
1949 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1950 nibble = val->bv_val[i] - '0';
1952 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1953 nibble = val->bv_val[i] - ('a'-10);
1955 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1956 nibble = val->bv_val[i] - ('A'-10);
1959 slap_sl_free( normalized->bv_val, ctx );
1960 return LDAP_INVALID_SYNTAX;
1965 normalized->bv_val[j>>1] = octet;
1967 octet = nibble << 4;
1972 normalized->bv_val[normalized->bv_len] = 0;
1973 return LDAP_SUCCESS;
1979 numericStringValidate(
1985 if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
1987 for(i=0; i < in->bv_len; i++) {
1988 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1989 return LDAP_INVALID_SYNTAX;
1993 return LDAP_SUCCESS;
1997 numericStringNormalize(
2002 struct berval *normalized,
2005 /* removal all spaces */
2008 assert( !BER_BVISEMPTY( val ) );
2010 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2013 q = normalized->bv_val;
2016 if ( ASCII_SPACE( *p ) ) {
2017 /* Ignore whitespace */
2024 /* we should have copied no more then is in val */
2025 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2027 /* null terminate */
2030 normalized->bv_len = q - normalized->bv_val;
2032 if( BER_BVISEMPTY( normalized ) ) {
2033 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2034 normalized->bv_val[0] = ' ';
2035 normalized->bv_val[1] = '\0';
2036 normalized->bv_len = 1;
2039 return LDAP_SUCCESS;
2043 * Integer conversion macros that will use the largest available
2046 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2047 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2048 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2049 # define SLAP_LONG_MAX LLONG_MAX
2050 # define SLAP_LONG_MIN LLONG_MIN
2051 # define SLAP_LONG long long
2053 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2054 # define SLAP_LONG_MAX LONG_MAX
2055 # define SLAP_LONG_MIN LONG_MIN
2056 # define SLAP_LONG long
2057 #endif /* HAVE_STRTOLL ... */
2065 struct berval *value,
2066 void *assertedValue )
2068 SLAP_LONG lValue, lAssertedValue;
2070 /* safe to assume integers are NUL terminated? */
2071 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2072 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2075 return LDAP_CONSTRAINT_VIOLATION;
2078 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2080 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2083 return LDAP_CONSTRAINT_VIOLATION;
2086 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2087 return LDAP_SUCCESS;
2096 struct berval *value,
2097 void *assertedValue )
2099 SLAP_LONG lValue, lAssertedValue;
2101 /* safe to assume integers are NUL terminated? */
2102 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2103 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2106 return LDAP_CONSTRAINT_VIOLATION;
2109 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2111 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2114 return LDAP_CONSTRAINT_VIOLATION;
2117 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2118 return LDAP_SUCCESS;
2122 serialNumberAndIssuerValidate(
2129 struct berval sn, i;
2130 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2132 i.bv_val = strchr( in->bv_val, '$' );
2133 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2135 sn.bv_val = in->bv_val;
2136 sn.bv_len = i.bv_val - in->bv_val;
2139 i.bv_len = in->bv_len - (sn.bv_len + 1);
2141 /* validate serial number (strict for now) */
2142 for( n=0; n < sn.bv_len; n++ ) {
2143 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2147 rc = dnValidate( NULL, &i );
2148 if( rc ) return LDAP_INVALID_SYNTAX;
2150 return LDAP_SUCCESS;
2154 serialNumberAndIssuerPretty(
2163 struct berval sn, i, newi;
2168 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2169 val->bv_val, 0, 0 );
2171 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2173 i.bv_val = strchr( val->bv_val, '$' );
2174 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2176 sn.bv_val = val->bv_val;
2177 sn.bv_len = i.bv_val - val->bv_val;
2180 i.bv_len = val->bv_len - (sn.bv_len + 1);
2182 /* eat leading zeros */
2183 for( n=0; n < (sn.bv_len-1); n++ ) {
2184 if( sn.bv_val[n] != '0' ) break;
2189 for( n=0; n < sn.bv_len; n++ ) {
2190 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2194 rc = dnPretty( syntax, &i, &newi, ctx );
2195 if( rc ) return LDAP_INVALID_SYNTAX;
2197 /* make room from sn + "$" */
2198 out->bv_len = sn.bv_len + newi.bv_len + 1;
2199 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2201 if( BER_BVISNULL( out ) ) {
2202 slap_sl_free( newi.bv_val, ctx );
2206 /* push issuer over */
2207 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2208 /* insert sn and "$" */
2209 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2210 out->bv_val[sn.bv_len] = '$';
2212 out->bv_val[out->bv_len] = '\0';
2214 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2215 out->bv_val, 0, 0 );
2217 return LDAP_SUCCESS;
2221 * This routine is called by certificateExactNormalize when
2222 * certificateExactNormalize receives a search string instead of
2223 * a certificate. This routine checks if the search value is valid
2224 * and then returns the normalized value
2227 serialNumberAndIssuerNormalize(
2238 struct berval sn, i, newi;
2243 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2244 val->bv_val, 0, 0 );
2246 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2248 i.bv_val = strchr( val->bv_val, '$' );
2249 if( BER_BVISNULL( &i ) ) return LDAP_INVALID_SYNTAX;
2251 sn.bv_val = val->bv_val;
2252 sn.bv_len = i.bv_val - val->bv_val;
2255 i.bv_len = val->bv_len - (sn.bv_len + 1);
2257 /* eat leading zeros */
2258 for( n=0; n < (sn.bv_len-1); n++ ) {
2259 if( sn.bv_val[n] != '0' ) break;
2264 for( n=0; n < sn.bv_len; n++ ) {
2265 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2266 return LDAP_INVALID_SYNTAX;
2271 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2272 if( rc ) return LDAP_INVALID_SYNTAX;
2274 /* make room from sn + "$" */
2275 out->bv_len = sn.bv_len + newi.bv_len + 1;
2276 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2278 if( BER_BVISNULL( out ) ) {
2279 slap_sl_free( newi.bv_val, ctx );
2283 /* push issuer over */
2284 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2285 /* insert sn and "$" */
2286 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2287 out->bv_val[sn.bv_len] = '$';
2289 out->bv_val[out->bv_len] = '\0';
2291 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2292 out->bv_val, 0, 0 );
2299 certificateExactNormalize(
2304 struct berval *normalized,
2307 int rc = LDAP_INVALID_SYNTAX;
2309 char *serial = NULL;
2310 ber_len_t seriallen;
2311 struct berval issuer_dn = BER_BVNULL;
2312 X509_NAME *name = NULL;
2313 ASN1_INTEGER *sn = NULL;
2316 if( BER_BVISEMPTY( val ) ) goto done;
2318 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2319 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2322 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2324 p = (unsigned char *)val->bv_val;
2325 xcert = d2i_X509( NULL, &p, val->bv_len);
2326 if( xcert == NULL ) goto done;
2328 sn=X509_get_serialNumber(xcert);
2329 if ( sn == NULL ) goto done;
2330 serial=i2s_ASN1_INTEGER(0, sn );
2331 if( serial == NULL ) goto done;
2332 seriallen=strlen(serial);
2334 name=X509_get_issuer_name(xcert);
2335 if( name == NULL ) goto done;
2336 rc = dnX509normalize( name, &issuer_dn );
2337 if( rc != LDAP_SUCCESS ) goto done;
2339 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2340 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2341 p = (unsigned char *)normalized->bv_val;
2342 AC_MEMCPY(p, serial, seriallen);
2345 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2346 p += issuer_dn.bv_len;
2349 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2350 normalized->bv_val, NULL, NULL );
2353 if (xcert) X509_free(xcert);
2354 if (serial) ch_free(serial);
2355 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2359 #endif /* HAVE_TLS */
2362 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2363 /* slight optimization - does not need the start parameter */
2364 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2369 check_time_syntax (struct berval *val,
2372 struct berval *fraction)
2375 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2376 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2377 * GeneralizedTime supports leap seconds, UTCTime does not.
2379 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2380 static const int mdays[2][12] = {
2381 /* non-leap years */
2382 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2384 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2387 int part, c, c1, c2, tzoffset, leapyear = 0;
2390 e = p + val->bv_len;
2392 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2393 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2395 for (part = start; part < 7 && p < e; part++) {
2397 if (!ASCII_DIGIT(c1)) {
2402 return LDAP_INVALID_SYNTAX;
2405 if (!ASCII_DIGIT(c)) {
2406 return LDAP_INVALID_SYNTAX;
2408 c += c1 * 10 - '0' * 11;
2409 if ((part | 1) == 3) {
2412 return LDAP_INVALID_SYNTAX;
2415 if (c >= ceiling[part]) {
2416 if (! (c == 60 && part == 6 && start == 0))
2417 return LDAP_INVALID_SYNTAX;
2421 if (part < 5 + start) {
2422 return LDAP_INVALID_SYNTAX;
2424 for (; part < 9; part++) {
2428 /* leapyear check for the Gregorian calendar (year>1581) */
2429 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2433 if (parts[3] >= mdays[leapyear][parts[2]]) {
2434 return LDAP_INVALID_SYNTAX;
2438 fraction->bv_val = p;
2439 fraction->bv_len = 0;
2440 if (p < e && (*p == '.' || *p == ',')) {
2442 while (++p < e && ASCII_DIGIT(*p)) {
2445 if (p - fraction->bv_val == 1) {
2446 return LDAP_INVALID_SYNTAX;
2448 for (end_num = p; end_num[-1] == '0'; --end_num) {
2451 c = end_num - fraction->bv_val;
2452 if (c != 1) fraction->bv_len = c;
2458 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2464 return LDAP_INVALID_SYNTAX;
2470 for (part = 7; part < 9 && p < e; part++) {
2472 if (!ASCII_DIGIT(c1)) {
2477 return LDAP_INVALID_SYNTAX;
2480 if (!ASCII_DIGIT(c2)) {
2481 return LDAP_INVALID_SYNTAX;
2483 parts[part] = c1 * 10 + c2 - '0' * 11;
2484 if (parts[part] >= ceiling[part]) {
2485 return LDAP_INVALID_SYNTAX;
2488 if (part < 8 + start) {
2489 return LDAP_INVALID_SYNTAX;
2492 if (tzoffset == '-') {
2493 /* negative offset to UTC, ie west of Greenwich */
2494 parts[4] += parts[7];
2495 parts[5] += parts[8];
2496 /* offset is just hhmm, no seconds */
2497 for (part = 6; --part >= 0; ) {
2501 c = mdays[leapyear][parts[2]];
2503 if (parts[part] >= c) {
2505 return LDAP_INVALID_SYNTAX;
2510 } else if (part != 5) {
2515 /* positive offset to UTC, ie east of Greenwich */
2516 parts[4] -= parts[7];
2517 parts[5] -= parts[8];
2518 for (part = 6; --part >= 0; ) {
2519 if (parts[part] < 0) {
2521 return LDAP_INVALID_SYNTAX;
2526 /* make first arg to % non-negative */
2527 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2532 } else if (part != 5) {
2539 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2542 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2549 struct berval *normalized )
2553 rc = check_time_syntax(val, 1, parts, NULL);
2554 if (rc != LDAP_SUCCESS) {
2558 normalized->bv_val = ch_malloc( 14 );
2559 if ( normalized->bv_val == NULL ) {
2560 return LBER_ERROR_MEMORY;
2563 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2564 parts[1], parts[2] + 1, parts[3] + 1,
2565 parts[4], parts[5], parts[6] );
2566 normalized->bv_len = 13;
2568 return LDAP_SUCCESS;
2578 return check_time_syntax(in, 1, parts, NULL);
2581 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2584 generalizedTimeValidate(
2589 struct berval fraction;
2590 return check_time_syntax(in, 0, parts, &fraction);
2594 generalizedTimeNormalize(
2599 struct berval *normalized,
2604 struct berval fraction;
2606 rc = check_time_syntax(val, 0, parts, &fraction);
2607 if (rc != LDAP_SUCCESS) {
2611 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2612 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2613 if ( BER_BVISNULL( normalized ) ) {
2614 return LBER_ERROR_MEMORY;
2617 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2618 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2619 parts[4], parts[5], parts[6] );
2620 if ( !BER_BVISEMPTY( &fraction ) ) {
2621 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2622 fraction.bv_val, fraction.bv_len );
2623 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2625 strcpy( normalized->bv_val + len-1, "Z" );
2626 normalized->bv_len = len;
2628 return LDAP_SUCCESS;
2632 generalizedTimeOrderingMatch(
2637 struct berval *value,
2638 void *assertedValue )
2640 struct berval *asserted = (struct berval *) assertedValue;
2641 ber_len_t v_len = value->bv_len;
2642 ber_len_t av_len = asserted->bv_len;
2644 /* ignore trailing 'Z' when comparing */
2645 int match = memcmp( value->bv_val, asserted->bv_val,
2646 (v_len < av_len ? v_len : av_len) - 1 );
2647 if ( match == 0 ) match = v_len - av_len;
2650 return LDAP_SUCCESS;
2653 /* Index generation function */
2654 int generalizedTimeIndexer(
2659 struct berval *prefix,
2668 BerValue bvtmp; /* 40 bit index */
2670 struct lutil_timet tt;
2672 bvtmp.bv_len = sizeof(tmp);
2674 for( i=0; values[i].bv_val != NULL; i++ ) {
2675 /* just count them */
2678 /* we should have at least one value at this point */
2681 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2683 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2684 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2685 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2686 /* Use 40 bits of time for key */
2687 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2688 lutil_tm2time( &tm, &tt );
2689 tmp[0] = tt.tt_gsec & 0xff;
2690 tmp[4] = tt.tt_sec & 0xff;
2692 tmp[3] = tt.tt_sec & 0xff;
2694 tmp[2] = tt.tt_sec & 0xff;
2696 tmp[1] = tt.tt_sec & 0xff;
2698 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2702 keys[j].bv_val = NULL;
2707 return LDAP_SUCCESS;
2710 /* Index generation function */
2711 int generalizedTimeFilter(
2716 struct berval *prefix,
2717 void * assertedValue,
2723 BerValue bvtmp; /* 40 bit index */
2724 BerValue *value = (BerValue *) assertedValue;
2726 struct lutil_timet tt;
2728 bvtmp.bv_len = sizeof(tmp);
2730 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2731 /* Use 40 bits of time for key */
2732 if ( value->bv_val && value->bv_len >= 10 &&
2733 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2735 lutil_tm2time( &tm, &tt );
2736 tmp[0] = tt.tt_gsec & 0xff;
2737 tmp[4] = tt.tt_sec & 0xff;
2739 tmp[3] = tt.tt_sec & 0xff;
2741 tmp[2] = tt.tt_sec & 0xff;
2743 tmp[1] = tt.tt_sec & 0xff;
2745 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2746 ber_dupbv_x(keys, &bvtmp, ctx );
2747 keys[1].bv_val = NULL;
2755 return LDAP_SUCCESS;
2759 deliveryMethodValidate(
2761 struct berval *val )
2764 #define LENOF(s) (sizeof(s)-1)
2765 struct berval tmp = *val;
2767 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2768 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2769 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2772 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2774 switch( tmp.bv_val[0] ) {
2777 if(( tmp.bv_len >= LENOF("any") ) &&
2778 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2780 tmp.bv_len -= LENOF("any");
2781 tmp.bv_val += LENOF("any");
2784 return LDAP_INVALID_SYNTAX;
2788 if(( tmp.bv_len >= LENOF("mhs") ) &&
2789 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2791 tmp.bv_len -= LENOF("mhs");
2792 tmp.bv_val += LENOF("mhs");
2795 return LDAP_INVALID_SYNTAX;
2799 if(( tmp.bv_len >= LENOF("physical") ) &&
2800 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2802 tmp.bv_len -= LENOF("physical");
2803 tmp.bv_val += LENOF("physical");
2806 return LDAP_INVALID_SYNTAX;
2809 case 'T': /* telex or teletex or telephone */
2810 if(( tmp.bv_len >= LENOF("telex") ) &&
2811 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2813 tmp.bv_len -= LENOF("telex");
2814 tmp.bv_val += LENOF("telex");
2817 if(( tmp.bv_len >= LENOF("teletex") ) &&
2818 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2820 tmp.bv_len -= LENOF("teletex");
2821 tmp.bv_val += LENOF("teletex");
2824 if(( tmp.bv_len >= LENOF("telephone") ) &&
2825 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2827 tmp.bv_len -= LENOF("telephone");
2828 tmp.bv_val += LENOF("telephone");
2831 return LDAP_INVALID_SYNTAX;
2834 case 'G': /* g3fax or g4fax */
2835 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2836 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2837 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2839 tmp.bv_len -= LENOF("g3fax");
2840 tmp.bv_val += LENOF("g3fax");
2843 return LDAP_INVALID_SYNTAX;
2847 if(( tmp.bv_len >= LENOF("ia5") ) &&
2848 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2850 tmp.bv_len -= LENOF("ia5");
2851 tmp.bv_val += LENOF("ia5");
2854 return LDAP_INVALID_SYNTAX;
2858 if(( tmp.bv_len >= LENOF("videotex") ) &&
2859 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2861 tmp.bv_len -= LENOF("videotex");
2862 tmp.bv_val += LENOF("videotex");
2865 return LDAP_INVALID_SYNTAX;
2868 return LDAP_INVALID_SYNTAX;
2871 if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
2873 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
2877 if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
2881 return LDAP_INVALID_SYNTAX;
2883 while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
2892 nisNetgroupTripleValidate(
2894 struct berval *val )
2899 if ( BER_BVISEMPTY( val ) ) {
2900 return LDAP_INVALID_SYNTAX;
2903 p = (char *)val->bv_val;
2904 e = p + val->bv_len;
2906 if ( *p != '(' /*')'*/ ) {
2907 return LDAP_INVALID_SYNTAX;
2910 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2914 return LDAP_INVALID_SYNTAX;
2917 } else if ( !AD_CHAR( *p ) ) {
2918 return LDAP_INVALID_SYNTAX;
2922 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2923 return LDAP_INVALID_SYNTAX;
2929 return LDAP_INVALID_SYNTAX;
2932 return LDAP_SUCCESS;
2936 bootParameterValidate(
2938 struct berval *val )
2942 if ( BER_BVISEMPTY( val ) ) {
2943 return LDAP_INVALID_SYNTAX;
2946 p = (char *)val->bv_val;
2947 e = p + val->bv_len;
2950 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2951 if ( !AD_CHAR( *p ) ) {
2952 return LDAP_INVALID_SYNTAX;
2957 return LDAP_INVALID_SYNTAX;
2961 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2962 if ( !AD_CHAR( *p ) ) {
2963 return LDAP_INVALID_SYNTAX;
2968 return LDAP_INVALID_SYNTAX;
2972 for ( p++; p < e; p++ ) {
2973 if ( !SLAP_PRINTABLE( *p ) ) {
2974 return LDAP_INVALID_SYNTAX;
2978 return LDAP_SUCCESS;
2982 firstComponentNormalize(
2987 struct berval *normalized,
2994 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2995 ber_dupbv_x( normalized, val, ctx );
2996 return LDAP_SUCCESS;
2999 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3001 if( val->bv_val[0] != '(' /*')'*/ &&
3002 val->bv_val[0] != '{' /*'}'*/ )
3004 return LDAP_INVALID_SYNTAX;
3007 /* trim leading white space */
3009 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3015 /* grab next word */
3016 comp.bv_val = &val->bv_val[len];
3017 len = val->bv_len - len;
3018 for( comp.bv_len = 0;
3019 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3025 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3026 rc = numericoidValidate( NULL, &comp );
3027 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3028 rc = integerValidate( NULL, &comp );
3030 rc = LDAP_INVALID_SYNTAX;
3034 if( rc == LDAP_SUCCESS ) {
3035 ber_dupbv_x( normalized, &comp, ctx );
3042 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3043 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3045 static slap_syntax_defs_rec syntax_defs[] = {
3046 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3047 X_BINARY X_NOT_H_R ")",
3048 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3049 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3051 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3053 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3055 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3056 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3058 SLAP_SYNTAX_BER, berValidate, NULL},
3059 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3060 0, bitStringValidate, NULL },
3061 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3062 0, booleanValidate, NULL},
3063 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3064 X_BINARY X_NOT_H_R ")",
3065 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3066 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3067 X_BINARY X_NOT_H_R ")",
3068 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3069 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3070 X_BINARY X_NOT_H_R ")",
3071 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3072 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3073 0, countryStringValidate, NULL},
3074 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3075 0, dnValidate, dnPretty},
3076 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3077 0, rdnValidate, rdnPretty},
3078 #ifdef LDAP_COMP_MATCH
3079 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3080 0, allComponentsValidate, NULL},
3081 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3082 0, componentFilterValidate, NULL},
3084 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3086 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3087 0, deliveryMethodValidate, NULL},
3088 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3089 0, UTF8StringValidate, NULL},
3090 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3092 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3094 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3096 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3098 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3100 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3101 0, printablesStringValidate, NULL},
3102 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3103 SLAP_SYNTAX_BLOB, NULL, NULL},
3104 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3105 0, generalizedTimeValidate, NULL},
3106 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3108 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3109 0, IA5StringValidate, NULL},
3110 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3111 0, integerValidate, NULL},
3112 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3113 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3114 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3116 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3118 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3120 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3122 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3124 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3125 0, nameUIDValidate, nameUIDPretty },
3126 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3128 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3129 0, numericStringValidate, NULL},
3130 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3132 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3133 0, numericoidValidate, NULL},
3134 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3135 0, IA5StringValidate, NULL},
3136 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3137 0, blobValidate, NULL},
3138 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3139 0, UTF8StringValidate, NULL},
3140 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3142 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3144 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3145 0, printableStringValidate, NULL},
3146 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3147 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3148 0, subtreeSpecificationValidate, NULL},
3149 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3150 X_BINARY X_NOT_H_R ")",
3151 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3152 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3153 0, printableStringValidate, NULL},
3154 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3156 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3157 0, printablesStringValidate, NULL},
3158 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3159 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3160 0, utcTimeValidate, NULL},
3162 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3164 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3166 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3168 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3170 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3173 /* RFC 2307 NIS Syntaxes */
3174 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3175 0, nisNetgroupTripleValidate, NULL},
3176 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3177 0, bootParameterValidate, NULL},
3179 /* From PKIX *//* This OID is not published yet. */
3180 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3182 serialNumberAndIssuerValidate,
3183 serialNumberAndIssuerPretty},
3185 #ifdef SLAPD_ACI_ENABLED
3186 /* OpenLDAP Experimental Syntaxes */
3187 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3189 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3193 #ifdef SLAPD_AUTHPASSWD
3194 /* needs updating */
3195 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3196 SLAP_SYNTAX_HIDE, NULL, NULL},
3199 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3200 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3202 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3203 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3205 /* OpenLDAP Void Syntax */
3206 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3207 SLAP_SYNTAX_HIDE, inValidate, NULL},
3208 {NULL, 0, NULL, NULL}
3211 char *certificateExactMatchSyntaxes[] = {
3212 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3215 #ifdef LDAP_COMP_MATCH
3216 char *componentFilterMatchSyntaxes[] = {
3217 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3221 char *directoryStringSyntaxes[] = {
3222 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3225 char *integerFirstComponentMatchSyntaxes[] = {
3226 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3227 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3230 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3231 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3232 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3233 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3234 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3235 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3236 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3237 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3238 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3243 * Other matching rules in X.520 that we do not use (yet):
3245 * 2.5.13.25 uTCTimeMatch
3246 * 2.5.13.26 uTCTimeOrderingMatch
3247 * 2.5.13.31* directoryStringFirstComponentMatch
3248 * 2.5.13.32* wordMatch
3249 * 2.5.13.33* keywordMatch
3250 * 2.5.13.36 certificatePairExactMatch
3251 * 2.5.13.37 certificatePairMatch
3252 * 2.5.13.38 certificateListExactMatch
3253 * 2.5.13.39 certificateListMatch
3254 * 2.5.13.40 algorithmIdentifierMatch
3255 * 2.5.13.41* storedPrefixMatch
3256 * 2.5.13.42 attributeCertificateMatch
3257 * 2.5.13.43 readerAndKeyIDMatch
3258 * 2.5.13.44 attributeIntegrityMatch
3260 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3262 static slap_mrule_defs_rec mrule_defs[] = {
3264 * EQUALITY matching rules must be listed after associated APPROX
3265 * matching rules. So, we list all APPROX matching rules first.
3267 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3268 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3269 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3270 NULL, NULL, directoryStringApproxMatch,
3271 directoryStringApproxIndexer, directoryStringApproxFilter,
3274 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3275 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3276 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3277 NULL, NULL, IA5StringApproxMatch,
3278 IA5StringApproxIndexer, IA5StringApproxFilter,
3282 * Other matching rules
3285 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3286 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3287 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3288 NULL, NULL, octetStringMatch,
3289 octetStringIndexer, octetStringFilter,
3292 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3294 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3295 NULL, dnNormalize, dnMatch,
3296 octetStringIndexer, octetStringFilter,
3299 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3300 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3301 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3302 NULL, dnNormalize, dnRelativeMatch,
3306 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3307 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3308 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3309 NULL, dnNormalize, dnRelativeMatch,
3313 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3314 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3315 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3316 NULL, dnNormalize, dnRelativeMatch,
3320 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3321 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3322 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3323 NULL, dnNormalize, dnRelativeMatch,
3327 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3328 "SYNTAX 1.2.36.79672281.1.5.0 )",
3329 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3330 NULL, rdnNormalize, rdnMatch,
3331 octetStringIndexer, octetStringFilter,
3334 #ifdef LDAP_COMP_MATCH
3335 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3336 "SYNTAX 1.2.36.79672281.1.5.2 )",
3337 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3338 NULL, NULL , componentFilterMatch,
3339 octetStringIndexer, octetStringFilter,
3342 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3343 "SYNTAX 1.2.36.79672281.1.5.3 )",
3344 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3345 NULL, NULL , allComponentsMatch,
3346 octetStringIndexer, octetStringFilter,
3349 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3350 "SYNTAX 1.2.36.79672281.1.5.3 )",
3351 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3352 NULL, NULL , directoryComponentsMatch,
3353 octetStringIndexer, octetStringFilter,
3357 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3358 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3359 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3360 NULL, UTF8StringNormalize, octetStringMatch,
3361 octetStringIndexer, octetStringFilter,
3362 directoryStringApproxMatchOID },
3364 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3365 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3366 SLAP_MR_ORDERING, directoryStringSyntaxes,
3367 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3369 "caseIgnoreMatch" },
3371 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3373 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3374 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3375 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3376 "caseIgnoreMatch" },
3378 {"( 2.5.13.5 NAME 'caseExactMatch' "
3379 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3380 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3381 NULL, UTF8StringNormalize, octetStringMatch,
3382 octetStringIndexer, octetStringFilter,
3383 directoryStringApproxMatchOID },
3385 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3386 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3387 SLAP_MR_ORDERING, directoryStringSyntaxes,
3388 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3392 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3393 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3394 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3395 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3396 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3399 {"( 2.5.13.8 NAME 'numericStringMatch' "
3400 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3401 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3402 NULL, numericStringNormalize, octetStringMatch,
3403 octetStringIndexer, octetStringFilter,
3406 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3407 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3408 SLAP_MR_ORDERING, NULL,
3409 NULL, numericStringNormalize, octetStringOrderingMatch,
3411 "numericStringMatch" },
3413 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3414 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3415 SLAP_MR_SUBSTR, NULL,
3416 NULL, numericStringNormalize, octetStringSubstringsMatch,
3417 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3418 "numericStringMatch" },
3420 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3421 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3422 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3423 NULL, NULL, NULL, NULL, NULL, NULL },
3425 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3426 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3427 SLAP_MR_SUBSTR, NULL,
3428 NULL, NULL, NULL, NULL, NULL,
3429 "caseIgnoreListMatch" },
3431 {"( 2.5.13.13 NAME 'booleanMatch' "
3432 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3433 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3434 NULL, NULL, booleanMatch,
3435 octetStringIndexer, octetStringFilter,
3438 {"( 2.5.13.14 NAME 'integerMatch' "
3439 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3440 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3441 NULL, NULL, integerMatch,
3442 octetStringIndexer, octetStringFilter,
3445 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3446 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3447 SLAP_MR_ORDERING, NULL,
3448 NULL, NULL, integerMatch,
3452 {"( 2.5.13.16 NAME 'bitStringMatch' "
3453 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3454 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3455 NULL, NULL, octetStringMatch,
3456 octetStringIndexer, octetStringFilter,
3459 {"( 2.5.13.17 NAME 'octetStringMatch' "
3460 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3461 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3462 NULL, NULL, octetStringMatch,
3463 octetStringIndexer, octetStringFilter,
3466 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3468 SLAP_MR_ORDERING, NULL,
3469 NULL, NULL, octetStringOrderingMatch,
3471 "octetStringMatch" },
3473 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3474 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3475 SLAP_MR_SUBSTR, NULL,
3476 NULL, NULL, octetStringSubstringsMatch,
3477 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3478 "octetStringMatch" },
3480 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3481 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3482 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3484 telephoneNumberNormalize, octetStringMatch,
3485 octetStringIndexer, octetStringFilter,
3488 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3489 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3490 SLAP_MR_SUBSTR, NULL,
3491 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3492 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3493 "telephoneNumberMatch" },
3495 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3496 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3497 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3498 NULL, NULL, NULL, NULL, NULL, NULL },
3500 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3501 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3502 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3503 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3507 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3508 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3509 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3510 NULL, NULL, NULL, NULL, NULL, NULL },
3512 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3514 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3515 NULL, generalizedTimeNormalize, octetStringMatch,
3516 generalizedTimeIndexer, generalizedTimeFilter,
3519 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3520 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3521 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3522 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3524 "generalizedTimeMatch" },
3526 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3527 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3528 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3529 integerFirstComponentMatchSyntaxes,
3530 NULL, firstComponentNormalize, integerMatch,
3531 octetStringIndexer, octetStringFilter,
3534 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3535 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3536 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3537 objectIdentifierFirstComponentMatchSyntaxes,
3538 NULL, firstComponentNormalize, octetStringMatch,
3539 octetStringIndexer, octetStringFilter,
3542 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3543 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3544 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3546 NULL, certificateExactNormalize, octetStringMatch,
3547 octetStringIndexer, octetStringFilter,
3549 NULL, NULL, NULL, NULL, NULL,
3553 {"( 2.5.13.35 NAME 'certificateMatch' "
3554 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3555 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3557 NULL, NULL, octetStringMatch,
3558 octetStringIndexer, octetStringFilter,
3560 NULL, NULL, NULL, NULL, NULL,
3564 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3566 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3567 NULL, IA5StringNormalize, octetStringMatch,
3568 octetStringIndexer, octetStringFilter,
3569 IA5StringApproxMatchOID },
3571 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3572 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3573 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3574 NULL, IA5StringNormalize, octetStringMatch,
3575 octetStringIndexer, octetStringFilter,
3576 IA5StringApproxMatchOID },
3578 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3579 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3580 SLAP_MR_SUBSTR, NULL,
3581 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3582 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3583 "caseIgnoreIA5Match" },
3585 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3586 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3587 SLAP_MR_SUBSTR, NULL,
3588 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3589 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3590 "caseExactIA5Match" },
3592 #ifdef SLAPD_AUTHPASSWD
3593 /* needs updating */
3594 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3595 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3596 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3597 NULL, NULL, authPasswordMatch,
3602 #ifdef SLAPD_ACI_ENABLED
3603 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3604 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3605 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3606 NULL, NULL, OpenLDAPaciMatch,
3611 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3612 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3614 NULL, NULL, integerBitAndMatch,
3618 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3619 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3621 NULL, NULL, integerBitOrMatch,
3625 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3626 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3627 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3628 NULL, UUIDNormalize, octetStringMatch,
3629 octetStringIndexer, octetStringFilter,
3632 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3633 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3634 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3635 NULL, UUIDNormalize, octetStringOrderingMatch,
3636 octetStringIndexer, octetStringFilter,
3639 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3640 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3641 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3642 NULL, NULL, csnMatch,
3643 csnIndexer, csnFilter,
3646 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3647 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3648 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3649 NULL, NULL, csnOrderingMatch,
3653 {NULL, SLAP_MR_NONE, NULL,
3654 NULL, NULL, NULL, NULL, NULL,
3659 slap_schema_init( void )
3664 /* we should only be called once (from main) */
3665 assert( schema_init_done == 0 );
3667 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3668 res = register_syntax( &syntax_defs[i] );
3671 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3672 syntax_defs[i].sd_desc );
3677 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3678 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3679 mrule_defs[i].mrd_compat_syntaxes == NULL )
3682 "slap_schema_init: Ignoring unusable matching rule %s\n",
3683 mrule_defs[i].mrd_desc );
3687 res = register_matching_rule( &mrule_defs[i] );
3691 "slap_schema_init: Error registering matching rule %s\n",
3692 mrule_defs[i].mrd_desc );
3697 res = slap_schema_load();
3698 schema_init_done = 1;
3703 schema_destroy( void )