1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
29 #include "ldap_utf8.h"
32 #include <openssl/x509.h>
33 #include <openssl/err.h>
34 #include <openssl/rsa.h>
35 #include <openssl/crypto.h>
36 #include <openssl/pem.h>
37 #include <openssl/bio.h>
38 #include <openssl/asn1.h>
39 #include <openssl/x509v3.h>
40 #include <openssl/ssl.h>
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 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
64 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
65 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
66 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
73 /* no value allowed */
74 return LDAP_INVALID_SYNTAX;
82 /* any value allowed */
86 #define berValidate blobValidate
93 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
94 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
101 static int certificateValidate( Syntax *syntax, struct berval *in )
104 unsigned char *p = (unsigned char *)in->bv_val;
106 xcert = d2i_X509(NULL, &p, in->bv_len);
107 if ( !xcert ) return LDAP_INVALID_SYNTAX;
112 #define certificateValidate sequenceValidate
121 struct berval *value,
122 void *assertedValue )
124 struct berval *asserted = (struct berval *) assertedValue;
125 int match = value->bv_len - asserted->bv_len;
128 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
136 octetStringOrderingMatch(
141 struct berval *value,
142 void *assertedValue )
144 struct berval *asserted = (struct berval *) assertedValue;
145 ber_len_t v_len = value->bv_len;
146 ber_len_t av_len = asserted->bv_len;
148 int match = memcmp( value->bv_val, asserted->bv_val,
149 (v_len < av_len ? v_len : av_len) );
151 if( match == 0 ) match = v_len - av_len;
158 HASH_CONTEXT *HASHcontext,
159 unsigned char *HASHdigest,
160 struct berval *prefix,
164 unsigned char *value,
167 HASH_Init(HASHcontext);
168 if(prefix && prefix->bv_len > 0) {
169 HASH_Update(HASHcontext,
170 (unsigned char *)prefix->bv_val, prefix->bv_len);
172 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
173 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
174 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
175 HASH_Update(HASHcontext, value, value_len);
176 HASH_Final(HASHdigest, HASHcontext);
180 /* Index generation function */
181 int octetStringIndexer(
186 struct berval *prefix,
194 HASH_CONTEXT HASHcontext;
195 unsigned char HASHdigest[HASH_BYTES];
196 struct berval digest;
197 digest.bv_val = (char *)HASHdigest;
198 digest.bv_len = sizeof(HASHdigest);
200 for( i=0; values[i].bv_val != NULL; i++ ) {
201 /* just count them */
204 /* we should have at least one value at this point */
207 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
209 slen = syntax->ssyn_oidlen;
210 mlen = mr->smr_oidlen;
212 for( i=0; values[i].bv_val != NULL; i++ ) {
213 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
214 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
215 ber_dupbv_x( &keys[i], &digest, ctx );
218 keys[i].bv_val = NULL;
226 /* Index generation function */
227 int octetStringFilter(
232 struct berval *prefix,
233 void * assertedValue,
239 HASH_CONTEXT HASHcontext;
240 unsigned char HASHdigest[HASH_BYTES];
241 struct berval *value = (struct berval *) assertedValue;
242 struct berval digest;
243 digest.bv_val = (char *)HASHdigest;
244 digest.bv_len = sizeof(HASHdigest);
246 slen = syntax->ssyn_oidlen;
247 mlen = mr->smr_oidlen;
249 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
251 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
252 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
254 ber_dupbv_x( keys, &digest, ctx );
255 keys[1].bv_val = NULL;
264 octetStringSubstringsMatch(
269 struct berval *value,
270 void *assertedValue )
273 SubstringsAssertion *sub = assertedValue;
274 struct berval left = *value;
278 /* Add up asserted input length */
279 if( sub->sa_initial.bv_val ) {
280 inlen += sub->sa_initial.bv_len;
283 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
284 inlen += sub->sa_any[i].bv_len;
287 if( sub->sa_final.bv_val ) {
288 inlen += sub->sa_final.bv_len;
291 if( sub->sa_initial.bv_val ) {
292 if( inlen > left.bv_len ) {
297 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
298 sub->sa_initial.bv_len );
304 left.bv_val += sub->sa_initial.bv_len;
305 left.bv_len -= sub->sa_initial.bv_len;
306 inlen -= sub->sa_initial.bv_len;
309 if( sub->sa_final.bv_val ) {
310 if( inlen > left.bv_len ) {
315 match = memcmp( sub->sa_final.bv_val,
316 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
317 sub->sa_final.bv_len );
323 left.bv_len -= sub->sa_final.bv_len;
324 inlen -= sub->sa_final.bv_len;
328 for(i=0; sub->sa_any[i].bv_val; i++) {
333 if( inlen > left.bv_len ) {
334 /* not enough length */
339 if( sub->sa_any[i].bv_len == 0 ) {
343 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
350 idx = p - left.bv_val;
352 if( idx >= left.bv_len ) {
353 /* this shouldn't happen */
360 if( sub->sa_any[i].bv_len > left.bv_len ) {
361 /* not enough left */
366 match = memcmp( left.bv_val,
367 sub->sa_any[i].bv_val,
368 sub->sa_any[i].bv_len );
376 left.bv_val += sub->sa_any[i].bv_len;
377 left.bv_len -= sub->sa_any[i].bv_len;
378 inlen -= sub->sa_any[i].bv_len;
387 /* Substrings Index generation function */
389 octetStringSubstringsIndexer(
394 struct berval *prefix,
399 ber_len_t i, j, len, nkeys;
403 HASH_CONTEXT HASHcontext;
404 unsigned char HASHdigest[HASH_BYTES];
405 struct berval digest;
406 digest.bv_val = (char *)HASHdigest;
407 digest.bv_len = sizeof(HASHdigest);
411 for( i=0; values[i].bv_val != NULL; i++ ) {
412 /* count number of indices to generate */
413 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
414 if( values[i].bv_len >= index_substr_if_maxlen ) {
415 nkeys += index_substr_if_maxlen -
416 (index_substr_if_minlen - 1);
417 } else if( values[i].bv_len >= index_substr_if_minlen ) {
418 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
422 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
423 if( values[i].bv_len >= index_substr_any_len ) {
424 nkeys += values[i].bv_len - (index_substr_any_len - 1);
428 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
429 if( values[i].bv_len >= index_substr_if_maxlen ) {
430 nkeys += index_substr_if_maxlen -
431 (index_substr_if_minlen - 1);
432 } else if( values[i].bv_len >= index_substr_if_minlen ) {
433 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
439 /* no keys to generate */
444 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
446 slen = syntax->ssyn_oidlen;
447 mlen = mr->smr_oidlen;
450 for( i=0; values[i].bv_val != NULL; i++ ) {
453 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
454 ( values[i].bv_len >= index_substr_any_len ) )
456 char pre = SLAP_INDEX_SUBSTR_PREFIX;
457 max = values[i].bv_len - (index_substr_any_len - 1);
459 for( j=0; j<max; j++ ) {
460 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
461 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
462 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
466 /* skip if too short */
467 if( values[i].bv_len < index_substr_if_minlen ) continue;
469 max = index_substr_if_maxlen < values[i].bv_len
470 ? index_substr_if_maxlen : values[i].bv_len;
472 for( j=index_substr_if_minlen; j<=max; j++ ) {
475 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
476 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
477 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
478 syntax, mr, (unsigned char *)values[i].bv_val, j );
479 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
482 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
483 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
484 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
485 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
486 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
493 keys[nkeys].bv_val = NULL;
504 octetStringSubstringsFilter (
509 struct berval *prefix,
510 void * assertedValue,
514 SubstringsAssertion *sa;
516 ber_len_t len, max, nkeys = 0;
517 size_t slen, mlen, klen;
519 HASH_CONTEXT HASHcontext;
520 unsigned char HASHdigest[HASH_BYTES];
521 struct berval *value;
522 struct berval digest;
524 sa = (SubstringsAssertion *) assertedValue;
526 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
527 sa->sa_initial.bv_val != NULL &&
528 sa->sa_initial.bv_len >= index_substr_if_minlen )
531 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
532 ( flags & SLAP_INDEX_SUBSTR_ANY ))
534 nkeys += (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
538 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
540 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
541 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
542 /* don't bother accounting with stepping */
543 nkeys += sa->sa_any[i].bv_len -
544 ( index_substr_any_len - 1 );
549 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
550 sa->sa_final.bv_val != NULL &&
551 sa->sa_final.bv_len >= index_substr_if_minlen )
554 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
555 ( flags & SLAP_INDEX_SUBSTR_ANY ))
557 nkeys += (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
566 digest.bv_val = (char *)HASHdigest;
567 digest.bv_len = sizeof(HASHdigest);
569 slen = syntax->ssyn_oidlen;
570 mlen = mr->smr_oidlen;
572 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
575 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
576 sa->sa_initial.bv_val != NULL &&
577 sa->sa_initial.bv_len >= index_substr_if_minlen )
579 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
580 value = &sa->sa_initial;
582 klen = index_substr_if_maxlen < value->bv_len
583 ? index_substr_if_maxlen : value->bv_len;
585 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
586 syntax, mr, (unsigned char *)value->bv_val, klen );
587 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
589 /* If initial is too long and we have subany indexed, use it
590 * to match the excess...
592 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
595 pre = SLAP_INDEX_SUBSTR_PREFIX;
596 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
598 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
599 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
600 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
605 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
607 pre = SLAP_INDEX_SUBSTR_PREFIX;
608 klen = index_substr_any_len;
610 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
611 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
615 value = &sa->sa_any[i];
618 j <= value->bv_len - index_substr_any_len;
619 j += index_substr_any_step )
621 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
622 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
623 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
628 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
629 sa->sa_final.bv_val != NULL &&
630 sa->sa_final.bv_len >= index_substr_if_minlen )
632 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
633 value = &sa->sa_final;
635 klen = index_substr_if_maxlen < value->bv_len
636 ? index_substr_if_maxlen : value->bv_len;
638 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
639 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
640 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
642 /* If final is too long and we have subany indexed, use it
643 * to match the excess...
645 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
648 pre = SLAP_INDEX_SUBSTR_PREFIX;
649 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
651 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
652 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
653 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
659 keys[nkeys].bv_val = NULL;
676 /* very unforgiving validation, requires no normalization
677 * before simplistic matching
679 if( in->bv_len < 3 ) {
680 return LDAP_INVALID_SYNTAX;
684 * RFC 2252 section 6.3 Bit String
685 * bitstring = "'" *binary-digit "'B"
686 * binary-digit = "0" / "1"
687 * example: '0101111101'B
690 if( in->bv_val[0] != '\'' ||
691 in->bv_val[in->bv_len-2] != '\'' ||
692 in->bv_val[in->bv_len-1] != 'B' )
694 return LDAP_INVALID_SYNTAX;
697 for( i=in->bv_len-3; i>0; i-- ) {
698 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
699 return LDAP_INVALID_SYNTAX;
707 * Syntax is [RFC2252]:
712 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
714 Values in this syntax are encoded according to the following BNF:
716 bitstring = "'" *binary-digit "'B"
718 binary-digit = "0" / "1"
722 6.21. Name And Optional UID
724 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
726 Values in this syntax are encoded according to the following BNF:
728 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
730 Although the '#' character may occur in a string representation of a
731 distinguished name, no additional special quoting is done. This
732 syntax has been added subsequent to RFC 1778.
736 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
739 * draft-ietf-ldapbis-syntaxes-xx.txt says:
744 A value of the Bit String syntax is a sequence of binary digits. The
745 LDAP-specific encoding of a value of this syntax is defined by the
748 BitString = SQUOTE *binary-digit SQUOTE "B"
750 binary-digit = "0" / "1"
752 The <SQUOTE> rule is defined in [MODELS].
757 The LDAP definition for the Bit String syntax is:
759 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
761 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
765 3.3.21. Name and Optional UID
767 A value of the Name and Optional UID syntax is the distinguished name
768 [MODELS] of an entity optionally accompanied by a unique identifier
769 that serves to differentiate the entity from others with an identical
772 The LDAP-specific encoding of a value of this syntax is defined by
775 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
777 The <BitString> rule is defined in Section 3.3.2. The
778 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
781 Note that although the '#' character may occur in the string
782 representation of a distinguished name, no additional escaping of
783 this character is performed when a <distinguishedName> is encoded in
784 a <NameAndOptionalUID>.
787 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
789 The LDAP definition for the Name and Optional UID syntax is:
791 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
793 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
797 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
800 1.4. Common ABNF Productions
803 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
805 SQUOTE = %x27 ; single quote ("'")
809 * Note: normalization strips any leading "0"s, unless the
810 * bit string is exactly "'0'B", so the normalized example,
811 * in slapd, would result in
813 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
815 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
816 * i.e. "#", doesn't have to be escaped except when at the
817 * beginning of a value, the definition of Name and Optional
818 * UID appears to be flawed, because there is no clear means
819 * to determine whether the UID part is present or not.
823 * cn=Someone,dc=example,dc=com#'1'B
825 * could be either a NameAndOptionalUID with trailing UID, i.e.
827 * DN = "cn=Someone,dc=example,dc=com"
830 * or a NameAndOptionalUID with no trailing UID, and the AVA
831 * in the last RDN made of
834 * attributeValue = com#'1'B
836 * in fact "com#'1'B" is a valid IA5 string.
838 * As a consequence, current slapd code assumes that the
839 * presence of portions of a BitString at the end of the string
840 * representation of a NameAndOptionalUID means a BitString
841 * is expected, and cause an error otherwise. This is quite
842 * arbitrary, and might change in the future.
852 struct berval dn, uid;
854 if( in->bv_len == 0 ) return LDAP_SUCCESS;
856 ber_dupbv( &dn, in );
857 if( !dn.bv_val ) return LDAP_OTHER;
859 /* if there's a "#", try bitStringValidate()... */
860 uid.bv_val = strrchr( dn.bv_val, '#' );
863 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
865 rc = bitStringValidate( NULL, &uid );
866 if ( rc == LDAP_SUCCESS ) {
867 /* in case of success, trim the UID,
868 * otherwise treat it as part of the DN */
869 dn.bv_len -= uid.bv_len + 1;
870 uid.bv_val[-1] = '\0';
874 rc = dnValidate( NULL, &dn );
876 ber_memfree( dn.bv_val );
891 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
893 if( val->bv_len == 0 ) {
894 ber_dupbv_x( out, val, ctx );
896 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
897 return LDAP_INVALID_SYNTAX;
901 struct berval dnval = *val;
902 struct berval uidval = BER_BVNULL;
904 uidval.bv_val = strrchr( val->bv_val, '#' );
905 if ( uidval.bv_val ) {
907 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
909 rc = bitStringValidate( NULL, &uidval );
911 if ( rc == LDAP_SUCCESS ) {
912 ber_dupbv_x( &dnval, val, ctx );
913 dnval.bv_len -= uidval.bv_len + 1;
914 dnval.bv_val[dnval.bv_len] = '\0';
917 uidval.bv_val = NULL;
921 rc = dnPretty( syntax, &dnval, out, ctx );
922 if ( dnval.bv_val != val->bv_val ) {
923 slap_sl_free( dnval.bv_val, ctx );
925 if( rc != LDAP_SUCCESS ) {
929 if( uidval.bv_val ) {
933 tmp = slap_sl_realloc( out->bv_val, out->bv_len
934 + STRLENOF( "#" ) + uidval.bv_len + 1,
937 ber_memfree_x( out->bv_val, ctx );
941 out->bv_val[out->bv_len++] = '#';
942 out->bv_val[out->bv_len++] = '\'';
944 got1 = uidval.bv_len < sizeof("'0'B");
945 for( i = 1; i < uidval.bv_len - 2; i++ ) {
946 c = uidval.bv_val[i];
949 if( got1 ) out->bv_val[out->bv_len++] = c;
953 out->bv_val[out->bv_len++] = c;
958 out->bv_val[out->bv_len++] = '\'';
959 out->bv_val[out->bv_len++] = 'B';
960 out->bv_val[out->bv_len] = '\0';
964 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
970 uniqueMemberNormalize(
975 struct berval *normalized,
981 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
983 ber_dupbv_x( &out, val, ctx );
984 if ( BER_BVISEMPTY( &out ) ) {
988 struct berval uid = BER_BVNULL;
990 uid.bv_val = strrchr( out.bv_val, '#' );
993 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
995 rc = bitStringValidate( NULL, &uid );
996 if ( rc == LDAP_SUCCESS ) {
997 uid.bv_val[-1] = '\0';
998 out.bv_len -= uid.bv_len + 1;
1004 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1006 if( rc != LDAP_SUCCESS ) {
1007 slap_sl_free( out.bv_val, ctx );
1008 return LDAP_INVALID_SYNTAX;
1014 tmp = ch_realloc( normalized->bv_val,
1015 normalized->bv_len + uid.bv_len
1016 + STRLENOF("#") + 1 );
1017 if ( tmp == NULL ) {
1018 ber_memfree_x( normalized->bv_val, ctx );
1022 normalized->bv_val = tmp;
1024 /* insert the separator */
1025 normalized->bv_val[normalized->bv_len++] = '#';
1027 /* append the UID */
1028 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1029 uid.bv_val, uid.bv_len );
1030 normalized->bv_len += uid.bv_len;
1033 normalized->bv_val[normalized->bv_len] = '\0';
1036 slap_sl_free( out.bv_val, ctx );
1039 return LDAP_SUCCESS;
1048 struct berval *value,
1049 void *assertedValue )
1052 struct berval *asserted = (struct berval *) assertedValue;
1053 struct berval assertedDN = *asserted;
1054 struct berval assertedUID = BER_BVNULL;
1055 struct berval valueDN = BER_BVNULL;
1056 struct berval valueUID = BER_BVNULL;
1058 if ( !BER_BVISEMPTY( asserted ) ) {
1059 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1060 if ( !BER_BVISNULL( &assertedUID ) ) {
1061 assertedUID.bv_val++;
1062 assertedUID.bv_len = assertedDN.bv_len
1063 - ( assertedUID.bv_val - assertedDN.bv_val );
1065 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1066 assertedDN.bv_len -= assertedUID.bv_len + 1;
1069 BER_BVZERO( &assertedUID );
1074 if ( !BER_BVISEMPTY( value ) ) {
1077 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1078 if ( !BER_BVISNULL( &valueUID ) ) {
1080 valueUID.bv_len = valueDN.bv_len
1081 - ( valueUID.bv_val - valueDN.bv_val );
1083 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1084 valueDN.bv_len -= valueUID.bv_len + 1;
1087 BER_BVZERO( &valueUID );
1092 if( valueUID.bv_len && assertedUID.bv_len ) {
1093 match = valueUID.bv_len - assertedUID.bv_len;
1096 return LDAP_SUCCESS;
1099 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1102 return LDAP_SUCCESS;
1106 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1110 * Handling boolean syntax and matching is quite rigid.
1111 * A more flexible approach would be to allow a variety
1112 * of strings to be normalized and prettied into TRUE
1120 /* very unforgiving validation, requires no normalization
1121 * before simplistic matching
1124 if( in->bv_len == 4 ) {
1125 if( bvmatch( in, &slap_true_bv ) ) {
1126 return LDAP_SUCCESS;
1128 } else if( in->bv_len == 5 ) {
1129 if( bvmatch( in, &slap_false_bv ) ) {
1130 return LDAP_SUCCESS;
1134 return LDAP_INVALID_SYNTAX;
1143 struct berval *value,
1144 void *assertedValue )
1146 /* simplistic matching allowed by rigid validation */
1147 struct berval *asserted = (struct berval *) assertedValue;
1148 *matchp = value->bv_len != asserted->bv_len;
1149 return LDAP_SUCCESS;
1152 /*-------------------------------------------------------------------
1153 LDAP/X.500 string syntax / matching rules have a few oddities. This
1154 comment attempts to detail how slapd(8) treats them.
1157 StringSyntax X.500 LDAP Matching/Comments
1158 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1159 PrintableString subset subset i/e + ignore insignificant spaces
1160 PrintableString subset subset i/e + ignore insignificant spaces
1161 NumericString subset subset ignore all spaces
1162 IA5String ASCII ASCII i/e + ignore insignificant spaces
1163 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1165 TelephoneNumber subset subset i + ignore all spaces and "-"
1167 See draft-ietf-ldapbis-strpro for details (once published).
1171 In X.500(93), a directory string can be either a PrintableString,
1172 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1173 In later versions, more CHOICEs were added. In all cases the string
1176 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1177 A directory string cannot be zero length.
1179 For matching, there are both case ignore and exact rules. Both
1180 also require that "insignificant" spaces be ignored.
1181 spaces before the first non-space are ignored;
1182 spaces after the last non-space are ignored;
1183 spaces after a space are ignored.
1184 Note: by these rules (and as clarified in X.520), a string of only
1185 spaces is to be treated as if held one space, not empty (which
1186 would be a syntax error).
1189 In ASN.1, numeric string is just a string of digits and spaces
1190 and could be empty. However, in X.500, all attribute values of
1191 numeric string carry a non-empty constraint. For example:
1193 internationalISDNNumber ATTRIBUTE ::= {
1194 WITH SYNTAX InternationalISDNNumber
1195 EQUALITY MATCHING RULE numericStringMatch
1196 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1197 ID id-at-internationalISDNNumber }
1198 InternationalISDNNumber ::=
1199 NumericString (SIZE(1..ub-international-isdn-number))
1201 Unforunately, some assertion values are don't carry the same
1202 constraint (but its unclear how such an assertion could ever
1203 be true). In LDAP, there is one syntax (numericString) not two
1204 (numericString with constraint, numericString without constraint).
1205 This should be treated as numericString with non-empty constraint.
1206 Note that while someone may have no ISDN number, there are no ISDN
1207 numbers which are zero length.
1209 In matching, spaces are ignored.
1212 In ASN.1, Printable string is just a string of printable characters
1213 and can be empty. In X.500, semantics much like NumericString (see
1214 serialNumber for a like example) excepting uses insignificant space
1215 handling instead of ignore all spaces.
1218 Basically same as PrintableString. There are no examples in X.500,
1219 but same logic applies. So we require them to be non-empty as
1222 -------------------------------------------------------------------*/
1231 unsigned char *u = (unsigned char *)in->bv_val;
1233 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1234 /* directory strings cannot be empty */
1235 return LDAP_INVALID_SYNTAX;
1238 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1239 /* get the length indicated by the first byte */
1240 len = LDAP_UTF8_CHARLEN2( u, len );
1242 /* very basic checks */
1245 if( (u[5] & 0xC0) != 0x80 ) {
1246 return LDAP_INVALID_SYNTAX;
1249 if( (u[4] & 0xC0) != 0x80 ) {
1250 return LDAP_INVALID_SYNTAX;
1253 if( (u[3] & 0xC0) != 0x80 ) {
1254 return LDAP_INVALID_SYNTAX;
1257 if( (u[2] & 0xC0 )!= 0x80 ) {
1258 return LDAP_INVALID_SYNTAX;
1261 if( (u[1] & 0xC0) != 0x80 ) {
1262 return LDAP_INVALID_SYNTAX;
1265 /* CHARLEN already validated it */
1268 return LDAP_INVALID_SYNTAX;
1271 /* make sure len corresponds with the offset
1272 to the next character */
1273 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1277 return LDAP_INVALID_SYNTAX;
1280 return LDAP_SUCCESS;
1284 UTF8StringNormalize(
1289 struct berval *normalized,
1292 struct berval tmp, nvalue;
1296 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1298 if( val->bv_val == NULL ) {
1299 /* assume we're dealing with a syntax (e.g., UTF8String)
1300 * which allows empty strings
1302 normalized->bv_len = 0;
1303 normalized->bv_val = NULL;
1304 return LDAP_SUCCESS;
1307 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1308 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1309 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1310 ? LDAP_UTF8_APPROX : 0;
1312 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1317 /* collapse spaces (in place) */
1319 nvalue.bv_val = tmp.bv_val;
1321 wasspace=1; /* trim leading spaces */
1322 for( i=0; i<tmp.bv_len; i++) {
1323 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1324 if( wasspace++ == 0 ) {
1325 /* trim repeated spaces */
1326 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1330 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1334 if( nvalue.bv_len ) {
1336 /* last character was a space, trim it */
1339 nvalue.bv_val[nvalue.bv_len] = '\0';
1342 /* string of all spaces is treated as one space */
1343 nvalue.bv_val[0] = ' ';
1344 nvalue.bv_val[1] = '\0';
1348 *normalized = nvalue;
1349 return LDAP_SUCCESS;
1352 #if defined(SLAPD_APPROX_INITIALS)
1353 # define SLAPD_APPROX_DELIMITER "._ "
1354 # define SLAPD_APPROX_WORDLEN 2
1356 # define SLAPD_APPROX_DELIMITER " "
1357 # define SLAPD_APPROX_WORDLEN 1
1366 struct berval *value,
1367 void *assertedValue )
1369 struct berval *nval, *assertv;
1370 char *val, **values, **words, *c;
1371 int i, count, len, nextchunk=0, nextavail=0;
1373 /* Yes, this is necessary */
1374 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1375 if( nval == NULL ) {
1377 return LDAP_SUCCESS;
1380 /* Yes, this is necessary */
1381 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1382 NULL, LDAP_UTF8_APPROX, NULL );
1383 if( assertv == NULL ) {
1386 return LDAP_SUCCESS;
1389 /* Isolate how many words there are */
1390 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1391 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1392 if ( c == NULL ) break;
1397 /* Get a phonetic copy of each word */
1398 words = (char **)ch_malloc( count * sizeof(char *) );
1399 values = (char **)ch_malloc( count * sizeof(char *) );
1400 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1402 values[i] = phonetic(c);
1405 /* Work through the asserted value's words, to see if at least some
1406 of the words are there, in the same order. */
1408 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1409 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1414 #if defined(SLAPD_APPROX_INITIALS)
1415 else if( len == 1 ) {
1416 /* Single letter words need to at least match one word's initial */
1417 for( i=nextavail; i<count; i++ )
1418 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1425 /* Isolate the next word in the asserted value and phonetic it */
1426 assertv->bv_val[nextchunk+len] = '\0';
1427 val = phonetic( assertv->bv_val + nextchunk );
1429 /* See if this phonetic chunk is in the remaining words of *value */
1430 for( i=nextavail; i<count; i++ ){
1431 if( !strcmp( val, values[i] ) ){
1439 /* This chunk in the asserted value was NOT within the *value. */
1445 /* Go on to the next word in the asserted value */
1449 /* If some of the words were seen, call it a match */
1450 if( nextavail > 0 ) {
1457 /* Cleanup allocs */
1458 ber_bvfree( assertv );
1459 for( i=0; i<count; i++ ) {
1460 ch_free( values[i] );
1466 return LDAP_SUCCESS;
1475 struct berval *prefix,
1481 int i,j, len, wordcount, keycount=0;
1482 struct berval *newkeys;
1483 BerVarray keys=NULL;
1485 for( j=0; values[j].bv_val != NULL; j++ ) {
1486 struct berval val = BER_BVNULL;
1487 /* Yes, this is necessary */
1488 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1489 assert( val.bv_val != NULL );
1491 /* Isolate how many words there are. There will be a key for each */
1492 for( wordcount = 0, c = val.bv_val; *c; c++) {
1493 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1494 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1496 if (*c == '\0') break;
1500 /* Allocate/increase storage to account for new keys */
1501 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1502 * sizeof(struct berval) );
1503 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1504 if( keys ) ch_free( keys );
1507 /* Get a phonetic copy of each word */
1508 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1510 if( len < SLAPD_APPROX_WORDLEN ) continue;
1511 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1516 ber_memfree( val.bv_val );
1518 keys[keycount].bv_val = NULL;
1521 return LDAP_SUCCESS;
1530 struct berval *prefix,
1531 void * assertedValue,
1540 /* Yes, this is necessary */
1541 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1542 NULL, LDAP_UTF8_APPROX, NULL );
1543 if( val == NULL || val->bv_val == NULL ) {
1544 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1545 keys[0].bv_val = NULL;
1548 return LDAP_SUCCESS;
1551 /* Isolate how many words there are. There will be a key for each */
1552 for( count = 0,c = val->bv_val; *c; c++) {
1553 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1554 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1556 if (*c == '\0') break;
1560 /* Allocate storage for new keys */
1561 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1563 /* Get a phonetic copy of each word */
1564 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1566 if( len < SLAPD_APPROX_WORDLEN ) continue;
1567 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1573 keys[count].bv_val = NULL;
1576 return LDAP_SUCCESS;
1579 /* Remove all spaces and '-' characters */
1581 telephoneNumberNormalize(
1586 struct berval *normalized,
1591 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1593 /* validator should have refused an empty string */
1594 assert( val->bv_len );
1596 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1598 for( p = val->bv_val; *p; p++ ) {
1599 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1605 normalized->bv_len = q - normalized->bv_val;
1607 if( normalized->bv_len == 0 ) {
1608 slap_sl_free( normalized->bv_val, ctx );
1609 normalized->bv_val = NULL;
1610 return LDAP_INVALID_SYNTAX;
1613 return LDAP_SUCCESS;
1621 struct berval val = *in;
1623 if( val.bv_len == 0 ) {
1624 /* disallow empty strings */
1625 return LDAP_INVALID_SYNTAX;
1628 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1629 if ( val.bv_len == 1 ) {
1630 return LDAP_SUCCESS;
1633 if ( val.bv_val[0] == '0' ) {
1640 while ( OID_LEADCHAR( val.bv_val[0] )) {
1644 if ( val.bv_len == 0 ) {
1645 return LDAP_SUCCESS;
1649 if( !OID_SEPARATOR( val.bv_val[0] )) {
1657 return LDAP_INVALID_SYNTAX;
1666 struct berval val = *in;
1668 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1670 if ( val.bv_val[0] == '-' ) {
1674 if( val.bv_len == 0 ) { /* bare "-" */
1675 return LDAP_INVALID_SYNTAX;
1678 if( val.bv_val[0] == '0' ) { /* "-0" */
1679 return LDAP_INVALID_SYNTAX;
1682 } else if ( val.bv_val[0] == '0' ) {
1683 if( val.bv_len > 1 ) { /* "0<more>" */
1684 return LDAP_INVALID_SYNTAX;
1687 return LDAP_SUCCESS;
1690 for( i=0; i < val.bv_len; i++ ) {
1691 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1692 return LDAP_INVALID_SYNTAX;
1696 return LDAP_SUCCESS;
1705 struct berval *value,
1706 void *assertedValue )
1708 struct berval *asserted = (struct berval *) assertedValue;
1709 int vsign = 1, asign = 1; /* default sign = '+' */
1714 if( v.bv_val[0] == '-' ) {
1720 if( v.bv_len == 0 ) vsign = 0;
1723 if( a.bv_val[0] == '-' ) {
1729 if( a.bv_len == 0 ) vsign = 0;
1731 match = vsign - asign;
1733 match = ( v.bv_len != a.bv_len
1734 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1735 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1736 if( vsign < 0 ) match = -match;
1740 return LDAP_SUCCESS;
1744 countryStringValidate(
1746 struct berval *val )
1748 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1750 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1751 return LDAP_INVALID_SYNTAX;
1753 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1754 return LDAP_INVALID_SYNTAX;
1757 return LDAP_SUCCESS;
1761 printableStringValidate(
1763 struct berval *val )
1767 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1769 for(i=0; i < val->bv_len; i++) {
1770 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1771 return LDAP_INVALID_SYNTAX;
1775 return LDAP_SUCCESS;
1779 printablesStringValidate(
1781 struct berval *val )
1785 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1787 for(i=0,len=0; i < val->bv_len; i++) {
1788 int c = val->bv_val[i];
1792 return LDAP_INVALID_SYNTAX;
1796 } else if ( SLAP_PRINTABLE(c) ) {
1799 return LDAP_INVALID_SYNTAX;
1804 return LDAP_INVALID_SYNTAX;
1807 return LDAP_SUCCESS;
1813 struct berval *val )
1817 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1819 for(i=0; i < val->bv_len; i++) {
1820 if( !LDAP_ASCII(val->bv_val[i]) ) {
1821 return LDAP_INVALID_SYNTAX;
1825 return LDAP_SUCCESS;
1834 struct berval *normalized,
1838 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1840 assert( val->bv_len );
1842 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1846 /* Ignore initial whitespace */
1847 while ( ASCII_SPACE( *p ) ) p++;
1849 normalized->bv_val = ber_strdup_x( p, ctx );
1850 p = q = normalized->bv_val;
1853 if ( ASCII_SPACE( *p ) ) {
1856 /* Ignore the extra whitespace */
1857 while ( ASCII_SPACE( *p ) ) {
1861 } else if ( casefold ) {
1862 /* Most IA5 rules require casefolding */
1863 *q++ = TOLOWER(*p); p++;
1870 assert( normalized->bv_val <= p );
1874 * If the string ended in space, backup the pointer one
1875 * position. One is enough because the above loop collapsed
1876 * all whitespace to a single space.
1878 if ( ASCII_SPACE( q[-1] ) ) --q;
1880 /* null terminate */
1883 normalized->bv_len = q - normalized->bv_val;
1884 if( normalized->bv_len == 0 ) {
1885 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1886 normalized->bv_val[0] = ' ';
1887 normalized->bv_val[1] = '\0';
1888 normalized->bv_len = 1;
1891 return LDAP_SUCCESS;
1900 if( in->bv_len != 36 ) {
1901 return LDAP_INVALID_SYNTAX;
1904 for( i=0; i<36; i++ ) {
1910 if( in->bv_val[i] != '-' ) {
1911 return LDAP_INVALID_SYNTAX;
1915 if( !ASCII_HEX( in->bv_val[i]) ) {
1916 return LDAP_INVALID_SYNTAX;
1921 return LDAP_SUCCESS;
1930 struct berval *normalized,
1933 unsigned char octet = '\0';
1936 normalized->bv_len = 16;
1937 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1939 for( i=0, j=0; i<36; i++ ) {
1940 unsigned char nibble;
1941 if( val->bv_val[i] == '-' ) {
1944 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1945 nibble = val->bv_val[i] - '0';
1947 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1948 nibble = val->bv_val[i] - ('a'-10);
1950 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1951 nibble = val->bv_val[i] - ('A'-10);
1954 slap_sl_free( normalized->bv_val, ctx );
1955 return LDAP_INVALID_SYNTAX;
1960 normalized->bv_val[j>>1] = octet;
1962 octet = nibble << 4;
1967 normalized->bv_val[normalized->bv_len] = 0;
1968 return LDAP_SUCCESS;
1974 numericStringValidate(
1980 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1982 for(i=0; i < in->bv_len; i++) {
1983 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1984 return LDAP_INVALID_SYNTAX;
1988 return LDAP_SUCCESS;
1992 numericStringNormalize(
1997 struct berval *normalized,
2000 /* removal all spaces */
2003 assert( val->bv_len );
2005 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2008 q = normalized->bv_val;
2011 if ( ASCII_SPACE( *p ) ) {
2012 /* Ignore whitespace */
2019 /* we should have copied no more then is in val */
2020 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2022 /* null terminate */
2025 normalized->bv_len = q - normalized->bv_val;
2027 if( normalized->bv_len == 0 ) {
2028 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2029 normalized->bv_val[0] = ' ';
2030 normalized->bv_val[1] = '\0';
2031 normalized->bv_len = 1;
2034 return LDAP_SUCCESS;
2038 * Integer conversion macros that will use the largest available
2041 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2042 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2043 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2044 # define SLAP_LONG_MAX LLONG_MAX
2045 # define SLAP_LONG_MIN LLONG_MIN
2046 # define SLAP_LONG long long
2048 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2049 # define SLAP_LONG_MAX LONG_MAX
2050 # define SLAP_LONG_MIN LONG_MIN
2051 # define SLAP_LONG long
2052 #endif /* HAVE_STRTOLL ... */
2060 struct berval *value,
2061 void *assertedValue )
2063 SLAP_LONG lValue, lAssertedValue;
2065 /* safe to assume integers are NUL terminated? */
2066 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2067 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2070 return LDAP_CONSTRAINT_VIOLATION;
2073 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2075 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2078 return LDAP_CONSTRAINT_VIOLATION;
2081 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2082 return LDAP_SUCCESS;
2091 struct berval *value,
2092 void *assertedValue )
2094 SLAP_LONG lValue, lAssertedValue;
2096 /* safe to assume integers are NUL terminated? */
2097 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2098 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2101 return LDAP_CONSTRAINT_VIOLATION;
2104 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2106 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2109 return LDAP_CONSTRAINT_VIOLATION;
2112 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2113 return LDAP_SUCCESS;
2117 serialNumberAndIssuerValidate(
2124 struct berval sn, i;
2125 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2127 i.bv_val = strchr( in->bv_val, '$' );
2128 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2130 sn.bv_val = in->bv_val;
2131 sn.bv_len = i.bv_val - in->bv_val;
2134 i.bv_len = in->bv_len - (sn.bv_len + 1);
2136 /* validate serial number (strict for now) */
2137 for( n=0; n < sn.bv_len; n++ ) {
2138 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2142 rc = dnValidate( NULL, &i );
2143 if( rc ) return LDAP_INVALID_SYNTAX;
2145 return LDAP_SUCCESS;
2149 serialNumberAndIssuerPretty(
2158 struct berval sn, i, newi;
2163 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2164 val->bv_val, 0, 0 );
2166 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2168 i.bv_val = strchr( val->bv_val, '$' );
2169 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2171 sn.bv_val = val->bv_val;
2172 sn.bv_len = i.bv_val - val->bv_val;
2175 i.bv_len = val->bv_len - (sn.bv_len + 1);
2177 /* eat leading zeros */
2178 for( n=0; n < (sn.bv_len-1); n++ ) {
2179 if( sn.bv_val[n] != '0' ) break;
2184 for( n=0; n < sn.bv_len; n++ ) {
2185 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2189 rc = dnPretty( syntax, &i, &newi, ctx );
2190 if( rc ) return LDAP_INVALID_SYNTAX;
2192 /* make room from sn + "$" */
2193 out->bv_len = sn.bv_len + newi.bv_len + 1;
2194 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2196 if( out->bv_val == NULL ) {
2197 slap_sl_free( newi.bv_val, ctx );
2201 /* push issuer over */
2202 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2203 /* insert sn and "$" */
2204 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2205 out->bv_val[sn.bv_len] = '$';
2207 out->bv_val[out->bv_len] = '\0';
2209 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2210 out->bv_val, 0, 0 );
2212 return LDAP_SUCCESS;
2216 * This routine is called by certificateExactNormalize when
2217 * certificateExactNormalize receives a search string instead of
2218 * a certificate. This routine checks if the search value is valid
2219 * and then returns the normalized value
2222 serialNumberAndIssuerNormalize(
2233 struct berval sn, i, newi;
2238 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2239 val->bv_val, 0, 0 );
2241 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2243 i.bv_val = strchr( val->bv_val, '$' );
2244 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2246 sn.bv_val = val->bv_val;
2247 sn.bv_len = i.bv_val - val->bv_val;
2250 i.bv_len = val->bv_len - (sn.bv_len + 1);
2252 /* eat leading zeros */
2253 for( n=0; n < (sn.bv_len-1); n++ ) {
2254 if( sn.bv_val[n] != '0' ) break;
2259 for( n=0; n < sn.bv_len; n++ ) {
2260 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2261 return LDAP_INVALID_SYNTAX;
2266 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2267 if( rc ) return LDAP_INVALID_SYNTAX;
2269 /* make room from sn + "$" */
2270 out->bv_len = sn.bv_len + newi.bv_len + 1;
2271 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2273 if( out->bv_val == NULL ) {
2274 slap_sl_free( newi.bv_val, ctx );
2278 /* push issuer over */
2279 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2280 /* insert sn and "$" */
2281 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2282 out->bv_val[sn.bv_len] = '$';
2284 out->bv_val[out->bv_len] = '\0';
2286 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2287 out->bv_val, 0, 0 );
2294 certificateExactNormalize(
2299 struct berval *normalized,
2302 int rc = LDAP_INVALID_SYNTAX;
2304 char *serial = NULL;
2305 ber_len_t seriallen;
2306 struct berval issuer_dn = BER_BVNULL;
2307 X509_NAME *name = NULL;
2308 ASN1_INTEGER *sn = NULL;
2311 if( val->bv_len == 0 ) goto done;
2313 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2314 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2317 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2319 p = (unsigned char *)val->bv_val;
2320 xcert = d2i_X509( NULL, &p, val->bv_len);
2321 if( xcert == NULL ) goto done;
2323 sn=X509_get_serialNumber(xcert);
2324 if ( sn == NULL ) goto done;
2325 serial=i2s_ASN1_INTEGER(0, sn );
2326 if( serial == NULL ) goto done;
2327 seriallen=strlen(serial);
2329 name=X509_get_issuer_name(xcert);
2330 if( name == NULL ) goto done;
2331 rc = dnX509normalize( name, &issuer_dn );
2332 if( rc != LDAP_SUCCESS ) goto done;
2334 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2335 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2336 p = (unsigned char *)normalized->bv_val;
2337 AC_MEMCPY(p, serial, seriallen);
2340 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2341 p += issuer_dn.bv_len;
2344 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2345 normalized->bv_val, NULL, NULL );
2348 if (xcert) X509_free(xcert);
2349 if (serial) ch_free(serial);
2350 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2354 #endif /* HAVE_TLS */
2357 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2358 /* slight optimization - does not need the start parameter */
2359 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2364 check_time_syntax (struct berval *val,
2367 struct berval *fraction)
2370 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2371 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2372 * GeneralizedTime supports leap seconds, UTCTime does not.
2374 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2375 static const int mdays[2][12] = {
2376 /* non-leap years */
2377 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2379 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2382 int part, c, c1, c2, tzoffset, leapyear = 0;
2385 e = p + val->bv_len;
2387 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2388 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2390 for (part = start; part < 7 && p < e; part++) {
2392 if (!ASCII_DIGIT(c1)) {
2397 return LDAP_INVALID_SYNTAX;
2400 if (!ASCII_DIGIT(c)) {
2401 return LDAP_INVALID_SYNTAX;
2403 c += c1 * 10 - '0' * 11;
2404 if ((part | 1) == 3) {
2407 return LDAP_INVALID_SYNTAX;
2410 if (c >= ceiling[part]) {
2411 if (! (c == 60 && part == 6 && start == 0))
2412 return LDAP_INVALID_SYNTAX;
2416 if (part < 5 + start) {
2417 return LDAP_INVALID_SYNTAX;
2419 for (; part < 9; part++) {
2423 /* leapyear check for the Gregorian calendar (year>1581) */
2424 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2428 if (parts[3] >= mdays[leapyear][parts[2]]) {
2429 return LDAP_INVALID_SYNTAX;
2433 fraction->bv_val = p;
2434 fraction->bv_len = 0;
2435 if (p < e && (*p == '.' || *p == ',')) {
2437 while (++p < e && ASCII_DIGIT(*p)) {
2440 if (p - fraction->bv_val == 1) {
2441 return LDAP_INVALID_SYNTAX;
2443 for (end_num = p; end_num[-1] == '0'; --end_num) {
2446 c = end_num - fraction->bv_val;
2447 if (c != 1) fraction->bv_len = c;
2453 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2459 return LDAP_INVALID_SYNTAX;
2465 for (part = 7; part < 9 && p < e; part++) {
2467 if (!ASCII_DIGIT(c1)) {
2472 return LDAP_INVALID_SYNTAX;
2475 if (!ASCII_DIGIT(c2)) {
2476 return LDAP_INVALID_SYNTAX;
2478 parts[part] = c1 * 10 + c2 - '0' * 11;
2479 if (parts[part] >= ceiling[part]) {
2480 return LDAP_INVALID_SYNTAX;
2483 if (part < 8 + start) {
2484 return LDAP_INVALID_SYNTAX;
2487 if (tzoffset == '-') {
2488 /* negative offset to UTC, ie west of Greenwich */
2489 parts[4] += parts[7];
2490 parts[5] += parts[8];
2491 /* offset is just hhmm, no seconds */
2492 for (part = 6; --part >= 0; ) {
2496 c = mdays[leapyear][parts[2]];
2498 if (parts[part] >= c) {
2500 return LDAP_INVALID_SYNTAX;
2505 } else if (part != 5) {
2510 /* positive offset to UTC, ie east of Greenwich */
2511 parts[4] -= parts[7];
2512 parts[5] -= parts[8];
2513 for (part = 6; --part >= 0; ) {
2514 if (parts[part] < 0) {
2516 return LDAP_INVALID_SYNTAX;
2521 /* make first arg to % non-negative */
2522 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2527 } else if (part != 5) {
2534 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2537 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2544 struct berval *normalized )
2548 rc = check_time_syntax(val, 1, parts, NULL);
2549 if (rc != LDAP_SUCCESS) {
2553 normalized->bv_val = ch_malloc( 14 );
2554 if ( normalized->bv_val == NULL ) {
2555 return LBER_ERROR_MEMORY;
2558 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2559 parts[1], parts[2] + 1, parts[3] + 1,
2560 parts[4], parts[5], parts[6] );
2561 normalized->bv_len = 13;
2563 return LDAP_SUCCESS;
2573 return check_time_syntax(in, 1, parts, NULL);
2576 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2579 generalizedTimeValidate(
2584 struct berval fraction;
2585 return check_time_syntax(in, 0, parts, &fraction);
2589 generalizedTimeNormalize(
2594 struct berval *normalized,
2599 struct berval fraction;
2601 rc = check_time_syntax(val, 0, parts, &fraction);
2602 if (rc != LDAP_SUCCESS) {
2606 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2607 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2608 if ( normalized->bv_val == NULL ) {
2609 return LBER_ERROR_MEMORY;
2612 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2613 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2614 parts[4], parts[5], parts[6] );
2615 if ( fraction.bv_len ) {
2616 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2617 fraction.bv_val, fraction.bv_len );
2618 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2620 strcpy( normalized->bv_val + len-1, "Z" );
2621 normalized->bv_len = len;
2623 return LDAP_SUCCESS;
2627 generalizedTimeOrderingMatch(
2632 struct berval *value,
2633 void *assertedValue )
2635 struct berval *asserted = (struct berval *) assertedValue;
2636 ber_len_t v_len = value->bv_len;
2637 ber_len_t av_len = asserted->bv_len;
2639 /* ignore trailing 'Z' when comparing */
2640 int match = memcmp( value->bv_val, asserted->bv_val,
2641 (v_len < av_len ? v_len : av_len) - 1 );
2642 if ( match == 0 ) match = v_len - av_len;
2645 return LDAP_SUCCESS;
2648 /* Index generation function */
2649 int generalizedTimeIndexer(
2654 struct berval *prefix,
2663 BerValue bvtmp; /* 40 bit index */
2665 struct lutil_timet tt;
2667 bvtmp.bv_len = sizeof(tmp);
2669 for( i=0; values[i].bv_val != NULL; i++ ) {
2670 /* just count them */
2673 /* we should have at least one value at this point */
2676 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2678 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2679 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2680 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2681 /* Use 40 bits of time for key */
2682 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2683 lutil_tm2time( &tm, &tt );
2684 tmp[0] = tt.tt_gsec & 0xff;
2685 tmp[4] = tt.tt_sec & 0xff;
2687 tmp[3] = tt.tt_sec & 0xff;
2689 tmp[2] = tt.tt_sec & 0xff;
2691 tmp[1] = tt.tt_sec & 0xff;
2693 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2697 keys[j].bv_val = NULL;
2702 return LDAP_SUCCESS;
2705 /* Index generation function */
2706 int generalizedTimeFilter(
2711 struct berval *prefix,
2712 void * assertedValue,
2718 BerValue bvtmp; /* 40 bit index */
2719 BerValue *value = (BerValue *) assertedValue;
2721 struct lutil_timet tt;
2723 bvtmp.bv_len = sizeof(tmp);
2725 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2727 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2728 assert(value->bv_val != NULL && value->bv_len >= 10);
2729 /* Use 40 bits of time for key */
2730 if ( lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2731 lutil_tm2time( &tm, &tt );
2732 tmp[0] = tt.tt_gsec & 0xff;
2733 tmp[4] = tt.tt_sec & 0xff;
2735 tmp[3] = tt.tt_sec & 0xff;
2737 tmp[2] = tt.tt_sec & 0xff;
2739 tmp[1] = tt.tt_sec & 0xff;
2741 ber_dupbv_x(keys, &bvtmp, ctx );
2743 keys[0].bv_val = NULL;
2747 keys[1].bv_val = NULL;
2752 return LDAP_SUCCESS;
2756 deliveryMethodValidate(
2758 struct berval *val )
2761 #define LENOF(s) (sizeof(s)-1)
2762 struct berval tmp = *val;
2764 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2765 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2766 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2769 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2771 switch( tmp.bv_val[0] ) {
2774 if(( tmp.bv_len >= LENOF("any") ) &&
2775 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2777 tmp.bv_len -= LENOF("any");
2778 tmp.bv_val += LENOF("any");
2781 return LDAP_INVALID_SYNTAX;
2785 if(( tmp.bv_len >= LENOF("mhs") ) &&
2786 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2788 tmp.bv_len -= LENOF("mhs");
2789 tmp.bv_val += LENOF("mhs");
2792 return LDAP_INVALID_SYNTAX;
2796 if(( tmp.bv_len >= LENOF("physical") ) &&
2797 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2799 tmp.bv_len -= LENOF("physical");
2800 tmp.bv_val += LENOF("physical");
2803 return LDAP_INVALID_SYNTAX;
2806 case 'T': /* telex or teletex or telephone */
2807 if(( tmp.bv_len >= LENOF("telex") ) &&
2808 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2810 tmp.bv_len -= LENOF("telex");
2811 tmp.bv_val += LENOF("telex");
2814 if(( tmp.bv_len >= LENOF("teletex") ) &&
2815 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2817 tmp.bv_len -= LENOF("teletex");
2818 tmp.bv_val += LENOF("teletex");
2821 if(( tmp.bv_len >= LENOF("telephone") ) &&
2822 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2824 tmp.bv_len -= LENOF("telephone");
2825 tmp.bv_val += LENOF("telephone");
2828 return LDAP_INVALID_SYNTAX;
2831 case 'G': /* g3fax or g4fax */
2832 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2833 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2834 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2836 tmp.bv_len -= LENOF("g3fax");
2837 tmp.bv_val += LENOF("g3fax");
2840 return LDAP_INVALID_SYNTAX;
2844 if(( tmp.bv_len >= LENOF("ia5") ) &&
2845 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2847 tmp.bv_len -= LENOF("ia5");
2848 tmp.bv_val += LENOF("ia5");
2851 return LDAP_INVALID_SYNTAX;
2855 if(( tmp.bv_len >= LENOF("videotex") ) &&
2856 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2858 tmp.bv_len -= LENOF("videotex");
2859 tmp.bv_val += LENOF("videotex");
2862 return LDAP_INVALID_SYNTAX;
2865 return LDAP_INVALID_SYNTAX;
2868 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2870 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2874 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2878 return LDAP_INVALID_SYNTAX;
2880 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2889 nisNetgroupTripleValidate(
2891 struct berval *val )
2896 if ( val->bv_len == 0 ) {
2897 return LDAP_INVALID_SYNTAX;
2900 p = (char *)val->bv_val;
2901 e = p + val->bv_len;
2903 if ( *p != '(' /*')'*/ ) {
2904 return LDAP_INVALID_SYNTAX;
2907 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2911 return LDAP_INVALID_SYNTAX;
2914 } else if ( !AD_CHAR( *p ) ) {
2915 return LDAP_INVALID_SYNTAX;
2919 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2920 return LDAP_INVALID_SYNTAX;
2926 return LDAP_INVALID_SYNTAX;
2929 return LDAP_SUCCESS;
2933 bootParameterValidate(
2935 struct berval *val )
2939 if ( val->bv_len == 0 ) {
2940 return LDAP_INVALID_SYNTAX;
2943 p = (char *)val->bv_val;
2944 e = p + val->bv_len;
2947 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2948 if ( !AD_CHAR( *p ) ) {
2949 return LDAP_INVALID_SYNTAX;
2954 return LDAP_INVALID_SYNTAX;
2958 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2959 if ( !AD_CHAR( *p ) ) {
2960 return LDAP_INVALID_SYNTAX;
2965 return LDAP_INVALID_SYNTAX;
2969 for ( p++; p < e; p++ ) {
2970 if ( !SLAP_PRINTABLE( *p ) ) {
2971 return LDAP_INVALID_SYNTAX;
2975 return LDAP_SUCCESS;
2979 firstComponentNormalize(
2984 struct berval *normalized,
2991 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2992 ber_dupbv_x( normalized, val, ctx );
2993 return LDAP_SUCCESS;
2996 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2998 if( val->bv_val[0] != '(' /*')'*/ &&
2999 val->bv_val[0] != '{' /*'}'*/ )
3001 return LDAP_INVALID_SYNTAX;
3004 /* trim leading white space */
3006 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3012 /* grab next word */
3013 comp.bv_val = &val->bv_val[len];
3014 len = val->bv_len - len;
3016 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3022 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3023 rc = numericoidValidate( NULL, &comp );
3024 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3025 rc = integerValidate( NULL, &comp );
3027 rc = LDAP_INVALID_SYNTAX;
3031 if( rc == LDAP_SUCCESS ) {
3032 ber_dupbv_x( normalized, &comp, ctx );
3039 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3040 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3042 static slap_syntax_defs_rec syntax_defs[] = {
3043 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3044 X_BINARY X_NOT_H_R ")",
3045 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3046 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3048 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3050 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3052 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3053 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3055 SLAP_SYNTAX_BER, berValidate, NULL},
3056 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3057 0, bitStringValidate, NULL },
3058 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3059 0, booleanValidate, NULL},
3060 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3061 X_BINARY X_NOT_H_R ")",
3062 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3063 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3064 X_BINARY X_NOT_H_R ")",
3065 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3066 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
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.11 DESC 'Country String' )",
3070 0, countryStringValidate, NULL},
3071 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3072 0, dnValidate, dnPretty},
3073 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3074 0, rdnValidate, rdnPretty},
3075 #ifdef LDAP_COMP_MATCH
3076 {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
3077 0, componentFilterValidate, NULL},
3079 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3081 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3082 0, deliveryMethodValidate, NULL},
3083 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3084 0, UTF8StringValidate, NULL},
3085 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3087 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3089 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3091 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3093 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3095 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3096 0, printablesStringValidate, NULL},
3097 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3098 SLAP_SYNTAX_BLOB, NULL, NULL},
3099 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3100 0, generalizedTimeValidate, NULL},
3101 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3103 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3104 0, IA5StringValidate, NULL},
3105 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3106 0, integerValidate, NULL},
3107 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3108 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3109 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3111 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3113 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3115 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3117 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3119 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3120 0, nameUIDValidate, nameUIDPretty },
3121 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3123 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3124 0, numericStringValidate, NULL},
3125 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3127 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3128 0, numericoidValidate, NULL},
3129 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3130 0, IA5StringValidate, NULL},
3131 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3132 0, blobValidate, NULL},
3133 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3134 0, UTF8StringValidate, NULL},
3135 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3137 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3139 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3140 0, printableStringValidate, NULL},
3141 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3142 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3143 0, subtreeSpecificationValidate, NULL},
3144 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3145 X_BINARY X_NOT_H_R ")",
3146 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3147 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3148 0, printableStringValidate, NULL},
3149 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3151 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3152 0, printablesStringValidate, NULL},
3153 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3154 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3155 0, utcTimeValidate, NULL},
3157 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3159 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3161 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3163 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3165 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3168 /* RFC 2307 NIS Syntaxes */
3169 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3170 0, nisNetgroupTripleValidate, NULL},
3171 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3172 0, bootParameterValidate, NULL},
3174 /* From PKIX *//* This OID is not published yet. */
3175 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3177 serialNumberAndIssuerValidate,
3178 serialNumberAndIssuerPretty},
3180 #ifdef SLAPD_ACI_ENABLED
3181 /* OpenLDAP Experimental Syntaxes */
3182 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3184 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3188 #ifdef SLAPD_AUTHPASSWD
3189 /* needs updating */
3190 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3191 SLAP_SYNTAX_HIDE, NULL, NULL},
3194 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3195 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3197 /* OpenLDAP Void Syntax */
3198 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3199 SLAP_SYNTAX_HIDE, inValidate, NULL},
3200 {NULL, 0, NULL, NULL}
3203 char *certificateExactMatchSyntaxes[] = {
3204 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3207 char *directoryStringSyntaxes[] = {
3208 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3211 char *integerFirstComponentMatchSyntaxes[] = {
3212 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3213 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3216 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3217 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3218 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3219 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3220 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3221 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3222 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3223 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3224 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3229 * Other matching rules in X.520 that we do not use (yet):
3231 * 2.5.13.25 uTCTimeMatch
3232 * 2.5.13.26 uTCTimeOrderingMatch
3233 * 2.5.13.31* directoryStringFirstComponentMatch
3234 * 2.5.13.32* wordMatch
3235 * 2.5.13.33* keywordMatch
3236 * 2.5.13.36 certificatePairExactMatch
3237 * 2.5.13.37 certificatePairMatch
3238 * 2.5.13.38 certificateListExactMatch
3239 * 2.5.13.39 certificateListMatch
3240 * 2.5.13.40 algorithmIdentifierMatch
3241 * 2.5.13.41* storedPrefixMatch
3242 * 2.5.13.42 attributeCertificateMatch
3243 * 2.5.13.43 readerAndKeyIDMatch
3244 * 2.5.13.44 attributeIntegrityMatch
3246 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3248 static slap_mrule_defs_rec mrule_defs[] = {
3250 * EQUALITY matching rules must be listed after associated APPROX
3251 * matching rules. So, we list all APPROX matching rules first.
3253 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3254 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3255 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3256 NULL, NULL, directoryStringApproxMatch,
3257 directoryStringApproxIndexer, directoryStringApproxFilter,
3260 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3261 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3262 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3263 NULL, NULL, IA5StringApproxMatch,
3264 IA5StringApproxIndexer, IA5StringApproxFilter,
3268 * Other matching rules
3271 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3272 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3273 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3274 NULL, NULL, octetStringMatch,
3275 octetStringIndexer, octetStringFilter,
3278 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3279 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3280 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3281 NULL, dnNormalize, dnMatch,
3282 octetStringIndexer, octetStringFilter,
3285 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3286 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3287 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3288 NULL, dnNormalize, dnRelativeMatch,
3292 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3294 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3295 NULL, dnNormalize, dnRelativeMatch,
3299 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
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.11 NAME 'dnSuperiorMatch' "
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.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3314 "SYNTAX 1.2.36.79672281.1.5.0 )",
3315 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3316 NULL, rdnNormalize, rdnMatch,
3317 octetStringIndexer, octetStringFilter,
3320 #ifdef LDAP_COMP_MATCH
3321 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3322 "SYNTAX 1.2.36.79672281.1.5.2 )",
3323 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3324 NULL, NULL , componentFilterMatch,
3325 octetStringIndexer, octetStringFilter,
3329 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3330 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3331 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3332 NULL, UTF8StringNormalize, octetStringMatch,
3333 octetStringIndexer, octetStringFilter,
3334 directoryStringApproxMatchOID },
3336 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3337 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3338 SLAP_MR_ORDERING, directoryStringSyntaxes,
3339 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3341 "caseIgnoreMatch" },
3343 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3344 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3345 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3346 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3347 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3348 "caseIgnoreMatch" },
3350 {"( 2.5.13.5 NAME 'caseExactMatch' "
3351 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3352 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3353 NULL, UTF8StringNormalize, octetStringMatch,
3354 octetStringIndexer, octetStringFilter,
3355 directoryStringApproxMatchOID },
3357 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3358 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3359 SLAP_MR_ORDERING, directoryStringSyntaxes,
3360 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3364 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3365 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3366 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3367 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3368 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3371 {"( 2.5.13.8 NAME 'numericStringMatch' "
3372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3373 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3374 NULL, numericStringNormalize, octetStringMatch,
3375 octetStringIndexer, octetStringFilter,
3378 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3379 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3380 SLAP_MR_ORDERING, NULL,
3381 NULL, numericStringNormalize, octetStringOrderingMatch,
3383 "numericStringMatch" },
3385 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3386 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3387 SLAP_MR_SUBSTR, NULL,
3388 NULL, numericStringNormalize, octetStringSubstringsMatch,
3389 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3390 "numericStringMatch" },
3392 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3393 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3394 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3395 NULL, NULL, NULL, NULL, NULL, NULL },
3397 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3398 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3399 SLAP_MR_SUBSTR, NULL,
3400 NULL, NULL, NULL, NULL, NULL,
3401 "caseIgnoreListMatch" },
3403 {"( 2.5.13.13 NAME 'booleanMatch' "
3404 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3405 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3406 NULL, NULL, booleanMatch,
3407 octetStringIndexer, octetStringFilter,
3410 {"( 2.5.13.14 NAME 'integerMatch' "
3411 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3412 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3413 NULL, NULL, integerMatch,
3414 octetStringIndexer, octetStringFilter,
3417 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3418 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3419 SLAP_MR_ORDERING, NULL,
3420 NULL, NULL, integerMatch,
3424 {"( 2.5.13.16 NAME 'bitStringMatch' "
3425 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3426 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3427 NULL, NULL, octetStringMatch,
3428 octetStringIndexer, octetStringFilter,
3431 {"( 2.5.13.17 NAME 'octetStringMatch' "
3432 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3433 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3434 NULL, NULL, octetStringMatch,
3435 octetStringIndexer, octetStringFilter,
3438 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3439 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3440 SLAP_MR_ORDERING, NULL,
3441 NULL, NULL, octetStringOrderingMatch,
3443 "octetStringMatch" },
3445 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3446 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3447 SLAP_MR_SUBSTR, NULL,
3448 NULL, NULL, octetStringSubstringsMatch,
3449 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3450 "octetStringMatch" },
3452 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3453 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3454 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3456 telephoneNumberNormalize, octetStringMatch,
3457 octetStringIndexer, octetStringFilter,
3460 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3461 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3462 SLAP_MR_SUBSTR, NULL,
3463 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3464 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3465 "telephoneNumberMatch" },
3467 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3468 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3469 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3470 NULL, NULL, NULL, NULL, NULL, NULL },
3472 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3473 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3474 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3475 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3479 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3480 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3481 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3482 NULL, NULL, NULL, NULL, NULL, NULL },
3484 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3485 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3486 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3487 NULL, generalizedTimeNormalize, octetStringMatch,
3488 generalizedTimeIndexer, generalizedTimeFilter,
3491 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3492 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3493 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3494 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3496 "generalizedTimeMatch" },
3498 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3499 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3500 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3501 integerFirstComponentMatchSyntaxes,
3502 NULL, firstComponentNormalize, integerMatch,
3503 octetStringIndexer, octetStringFilter,
3506 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3507 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3508 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3509 objectIdentifierFirstComponentMatchSyntaxes,
3510 NULL, firstComponentNormalize, octetStringMatch,
3511 octetStringIndexer, octetStringFilter,
3514 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3515 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3516 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3518 NULL, certificateExactNormalize, octetStringMatch,
3519 octetStringIndexer, octetStringFilter,
3521 NULL, NULL, NULL, NULL, NULL,
3525 {"( 2.5.13.35 NAME 'certificateMatch' "
3526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3527 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3529 NULL, NULL, octetStringMatch,
3530 octetStringIndexer, octetStringFilter,
3532 NULL, NULL, NULL, NULL, NULL,
3536 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3538 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3539 NULL, IA5StringNormalize, octetStringMatch,
3540 octetStringIndexer, octetStringFilter,
3541 IA5StringApproxMatchOID },
3543 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3545 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3546 NULL, IA5StringNormalize, octetStringMatch,
3547 octetStringIndexer, octetStringFilter,
3548 IA5StringApproxMatchOID },
3550 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3552 SLAP_MR_SUBSTR, NULL,
3553 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3554 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3555 "caseIgnoreIA5Match" },
3557 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3559 SLAP_MR_SUBSTR, NULL,
3560 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3561 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3562 "caseExactIA5Match" },
3564 #ifdef SLAPD_AUTHPASSWD
3565 /* needs updating */
3566 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3567 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3568 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3569 NULL, NULL, authPasswordMatch,
3574 #ifdef SLAPD_ACI_ENABLED
3575 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3576 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3577 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3578 NULL, NULL, OpenLDAPaciMatch,
3583 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3584 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3586 NULL, NULL, integerBitAndMatch,
3590 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3591 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3593 NULL, NULL, integerBitOrMatch,
3597 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3598 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3599 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3600 NULL, UUIDNormalize, octetStringMatch,
3601 octetStringIndexer, octetStringFilter,
3604 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3605 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3606 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3607 NULL, UUIDNormalize, octetStringOrderingMatch,
3608 octetStringIndexer, octetStringFilter,
3611 {NULL, SLAP_MR_NONE, NULL,
3612 NULL, NULL, NULL, NULL, NULL,
3617 slap_schema_init( void )
3622 /* we should only be called once (from main) */
3623 assert( schema_init_done == 0 );
3625 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3626 res = register_syntax( &syntax_defs[i] );
3629 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3630 syntax_defs[i].sd_desc );
3635 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3636 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3637 mrule_defs[i].mrd_compat_syntaxes == NULL )
3640 "slap_schema_init: Ignoring unusable matching rule %s\n",
3641 mrule_defs[i].mrd_desc );
3645 res = register_matching_rule( &mrule_defs[i] );
3649 "slap_schema_init: Error registering matching rule %s\n",
3650 mrule_defs[i].mrd_desc );
3655 res = slap_schema_load();
3656 schema_init_done = 1;
3661 schema_destroy( void )