1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
29 #include "ldap_utf8.h"
32 #include <openssl/x509.h>
33 #include <openssl/err.h>
34 #include <openssl/rsa.h>
35 #include <openssl/crypto.h>
36 #include <openssl/pem.h>
37 #include <openssl/bio.h>
38 #include <openssl/asn1.h>
39 #include <openssl/x509v3.h>
40 #include <openssl/ssl.h>
43 #include "lutil_hash.h"
44 #define HASH_BYTES LUTIL_HASH_BYTES
45 #define HASH_CONTEXT lutil_HASH_CTX
46 #define HASH_Init(c) lutil_HASHInit(c)
47 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
48 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
50 #define OpenLDAPaciMatch NULL
52 /* approx matching rules */
53 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
54 #define directoryStringApproxMatch approxMatch
55 #define directoryStringApproxIndexer approxIndexer
56 #define directoryStringApproxFilter approxFilter
57 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
58 #define IA5StringApproxMatch approxMatch
59 #define IA5StringApproxIndexer approxIndexer
60 #define IA5StringApproxFilter approxFilter
62 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
63 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
64 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
65 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
72 /* no value allowed */
73 return LDAP_INVALID_SYNTAX;
81 /* any value allowed */
85 #define berValidate blobValidate
92 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
93 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
100 static int certificateValidate( Syntax *syntax, struct berval *in )
103 unsigned char *p = (unsigned char *)in->bv_val;
105 xcert = d2i_X509(NULL, &p, in->bv_len);
106 if ( !xcert ) return LDAP_INVALID_SYNTAX;
111 #define certificateValidate sequenceValidate
120 struct berval *value,
121 void *assertedValue )
123 struct berval *asserted = (struct berval *) assertedValue;
124 int match = value->bv_len - asserted->bv_len;
127 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
135 octetStringOrderingMatch(
140 struct berval *value,
141 void *assertedValue )
143 struct berval *asserted = (struct berval *) assertedValue;
144 ber_len_t v_len = value->bv_len;
145 ber_len_t av_len = asserted->bv_len;
147 int match = memcmp( value->bv_val, asserted->bv_val,
148 (v_len < av_len ? v_len : av_len) );
150 if( match == 0 ) match = v_len - av_len;
157 HASH_CONTEXT *HASHcontext,
158 unsigned char *HASHdigest,
159 struct berval *prefix,
163 unsigned char *value,
166 HASH_Init(HASHcontext);
167 if(prefix && prefix->bv_len > 0) {
168 HASH_Update(HASHcontext,
169 (unsigned char *)prefix->bv_val, prefix->bv_len);
171 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
172 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
173 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
174 HASH_Update(HASHcontext, value, value_len);
175 HASH_Final(HASHdigest, HASHcontext);
179 /* Index generation function */
180 int octetStringIndexer(
185 struct berval *prefix,
193 HASH_CONTEXT HASHcontext;
194 unsigned char HASHdigest[HASH_BYTES];
195 struct berval digest;
196 digest.bv_val = (char *)HASHdigest;
197 digest.bv_len = sizeof(HASHdigest);
199 for( i=0; values[i].bv_val != NULL; i++ ) {
200 /* just count them */
203 /* we should have at least one value at this point */
206 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
208 slen = syntax->ssyn_oidlen;
209 mlen = mr->smr_oidlen;
211 /* XXX this invocation does not like hashDigestify() */
212 for( i=0; values[i].bv_val != NULL; i++ ) {
213 HASH_Init( &HASHcontext );
214 if( prefix != NULL && prefix->bv_len > 0 ) {
215 HASH_Update( &HASHcontext,
216 (unsigned char *)prefix->bv_val,
219 HASH_Update( &HASHcontext,
220 (unsigned char *)syntax->ssyn_oid, slen );
221 HASH_Update( &HASHcontext,
222 (unsigned char *)mr->smr_oid, mlen );
223 HASH_Update( &HASHcontext,
224 (unsigned char *)values[i].bv_val, values[i].bv_len );
225 HASH_Final( HASHdigest, &HASHcontext );
227 ber_dupbv_x( &keys[i], &digest, ctx );
230 keys[i].bv_val = NULL;
238 /* Index generation function */
239 int octetStringFilter(
244 struct berval *prefix,
245 void * assertedValue,
251 HASH_CONTEXT HASHcontext;
252 unsigned char HASHdigest[HASH_BYTES];
253 struct berval *value = (struct berval *) assertedValue;
254 struct berval digest;
255 digest.bv_val = (char *)HASHdigest;
256 digest.bv_len = sizeof(HASHdigest);
258 slen = syntax->ssyn_oidlen;
259 mlen = mr->smr_oidlen;
261 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
263 HASH_Init( &HASHcontext );
264 if( prefix != NULL && prefix->bv_len > 0 ) {
265 HASH_Update( &HASHcontext,
266 (unsigned char *)prefix->bv_val, prefix->bv_len );
268 HASH_Update( &HASHcontext,
269 (unsigned char *)syntax->ssyn_oid, slen );
270 HASH_Update( &HASHcontext,
271 (unsigned char *)mr->smr_oid, mlen );
272 HASH_Update( &HASHcontext,
273 (unsigned char *)value->bv_val, value->bv_len );
274 HASH_Final( HASHdigest, &HASHcontext );
276 ber_dupbv_x( keys, &digest, ctx );
277 keys[1].bv_val = NULL;
286 octetStringSubstringsMatch(
291 struct berval *value,
292 void *assertedValue )
295 SubstringsAssertion *sub = assertedValue;
296 struct berval left = *value;
300 /* Add up asserted input length */
301 if( sub->sa_initial.bv_val ) {
302 inlen += sub->sa_initial.bv_len;
305 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
306 inlen += sub->sa_any[i].bv_len;
309 if( sub->sa_final.bv_val ) {
310 inlen += sub->sa_final.bv_len;
313 if( sub->sa_initial.bv_val ) {
314 if( inlen > left.bv_len ) {
319 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
320 sub->sa_initial.bv_len );
326 left.bv_val += sub->sa_initial.bv_len;
327 left.bv_len -= sub->sa_initial.bv_len;
328 inlen -= sub->sa_initial.bv_len;
331 if( sub->sa_final.bv_val ) {
332 if( inlen > left.bv_len ) {
337 match = memcmp( sub->sa_final.bv_val,
338 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
339 sub->sa_final.bv_len );
345 left.bv_len -= sub->sa_final.bv_len;
346 inlen -= sub->sa_final.bv_len;
350 for(i=0; sub->sa_any[i].bv_val; i++) {
355 if( inlen > left.bv_len ) {
356 /* not enough length */
361 if( sub->sa_any[i].bv_len == 0 ) {
365 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
372 idx = p - left.bv_val;
374 if( idx >= left.bv_len ) {
375 /* this shouldn't happen */
382 if( sub->sa_any[i].bv_len > left.bv_len ) {
383 /* not enough left */
388 match = memcmp( left.bv_val,
389 sub->sa_any[i].bv_val,
390 sub->sa_any[i].bv_len );
398 left.bv_val += sub->sa_any[i].bv_len;
399 left.bv_len -= sub->sa_any[i].bv_len;
400 inlen -= sub->sa_any[i].bv_len;
409 /* Substrings Index generation function */
411 octetStringSubstringsIndexer(
416 struct berval *prefix,
421 ber_len_t i, j, len, nkeys;
425 HASH_CONTEXT HASHcontext;
426 unsigned char HASHdigest[HASH_BYTES];
427 struct berval digest;
428 digest.bv_val = (char *)HASHdigest;
429 digest.bv_len = sizeof(HASHdigest);
433 for( i=0; values[i].bv_val != NULL; i++ ) {
434 /* count number of indices to generate */
435 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
436 if( values[i].bv_len >= index_substr_if_maxlen ) {
437 nkeys += index_substr_if_maxlen -
438 (index_substr_if_minlen - 1);
439 } else if( values[i].bv_len >= index_substr_if_minlen ) {
440 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
444 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
445 if( values[i].bv_len >= index_substr_any_len ) {
446 nkeys += values[i].bv_len - (index_substr_any_len - 1);
450 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
451 if( values[i].bv_len >= index_substr_if_maxlen ) {
452 nkeys += index_substr_if_maxlen -
453 (index_substr_if_minlen - 1);
454 } else if( values[i].bv_len >= index_substr_if_minlen ) {
455 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
461 /* no keys to generate */
466 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
468 slen = syntax->ssyn_oidlen;
469 mlen = mr->smr_oidlen;
472 for( i=0; values[i].bv_val != NULL; i++ ) {
475 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
476 ( values[i].bv_len >= index_substr_any_len ) )
478 char pre = SLAP_INDEX_SUBSTR_PREFIX;
479 max = values[i].bv_len - (index_substr_any_len - 1);
481 for( j=0; j<max; j++ ) {
482 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
483 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
484 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
488 /* skip if too short */
489 if( values[i].bv_len < index_substr_if_minlen ) continue;
491 max = index_substr_if_maxlen < values[i].bv_len
492 ? index_substr_if_maxlen : values[i].bv_len;
494 for( j=index_substr_if_minlen; j<=max; j++ ) {
497 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
498 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
499 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
500 syntax, mr, (unsigned char *)values[i].bv_val, j );
501 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
504 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
505 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
506 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
507 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
508 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
515 keys[nkeys].bv_val = NULL;
526 octetStringSubstringsFilter (
531 struct berval *prefix,
532 void * assertedValue,
536 SubstringsAssertion *sa;
538 ber_len_t len, max, nkeys = 0;
539 size_t slen, mlen, klen;
541 HASH_CONTEXT HASHcontext;
542 unsigned char HASHdigest[HASH_BYTES];
543 struct berval *value;
544 struct berval digest;
546 sa = (SubstringsAssertion *) assertedValue;
548 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
549 sa->sa_initial.bv_val != NULL &&
550 sa->sa_initial.bv_len >= index_substr_if_minlen )
553 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
554 ( flags & SLAP_INDEX_SUBSTR_ANY ))
556 nkeys += (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
560 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
562 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
563 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
564 /* don't bother accounting with stepping */
565 nkeys += sa->sa_any[i].bv_len -
566 ( index_substr_any_len - 1 );
571 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
572 sa->sa_final.bv_val != NULL &&
573 sa->sa_final.bv_len >= index_substr_if_minlen )
576 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
577 ( flags & SLAP_INDEX_SUBSTR_ANY ))
579 nkeys += (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
588 digest.bv_val = (char *)HASHdigest;
589 digest.bv_len = sizeof(HASHdigest);
591 slen = syntax->ssyn_oidlen;
592 mlen = mr->smr_oidlen;
594 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
597 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
598 sa->sa_initial.bv_val != NULL &&
599 sa->sa_initial.bv_len >= index_substr_if_minlen )
601 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
602 value = &sa->sa_initial;
604 klen = index_substr_if_maxlen < value->bv_len
605 ? index_substr_if_maxlen : value->bv_len;
607 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
608 syntax, mr, (unsigned char *)value->bv_val, klen );
609 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
611 /* If initial is too long and we have subany indexed, use it
612 * to match the excess...
614 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
617 pre = SLAP_INDEX_SUBSTR_PREFIX;
618 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
620 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
621 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
622 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
627 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
629 pre = SLAP_INDEX_SUBSTR_PREFIX;
630 klen = index_substr_any_len;
632 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
633 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
637 value = &sa->sa_any[i];
640 j <= value->bv_len - index_substr_any_len;
641 j += index_substr_any_step )
643 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
644 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
645 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
650 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
651 sa->sa_final.bv_val != NULL &&
652 sa->sa_final.bv_len >= index_substr_if_minlen )
654 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
655 value = &sa->sa_final;
657 klen = index_substr_if_maxlen < value->bv_len
658 ? index_substr_if_maxlen : value->bv_len;
660 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
661 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
662 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
664 /* If final is too long and we have subany indexed, use it
665 * to match the excess...
667 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
670 pre = SLAP_INDEX_SUBSTR_PREFIX;
671 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
673 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
674 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
675 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
681 keys[nkeys].bv_val = NULL;
698 /* very unforgiving validation, requires no normalization
699 * before simplistic matching
701 if( in->bv_len < 3 ) {
702 return LDAP_INVALID_SYNTAX;
706 * RFC 2252 section 6.3 Bit String
707 * bitstring = "'" *binary-digit "'B"
708 * binary-digit = "0" / "1"
709 * example: '0101111101'B
712 if( in->bv_val[0] != '\'' ||
713 in->bv_val[in->bv_len-2] != '\'' ||
714 in->bv_val[in->bv_len-1] != 'B' )
716 return LDAP_INVALID_SYNTAX;
719 for( i=in->bv_len-3; i>0; i-- ) {
720 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
721 return LDAP_INVALID_SYNTAX;
729 * Syntax is [RFC2252]:
734 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
736 Values in this syntax are encoded according to the following BNF:
738 bitstring = "'" *binary-digit "'B"
740 binary-digit = "0" / "1"
744 6.21. Name And Optional UID
746 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
748 Values in this syntax are encoded according to the following BNF:
750 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
752 Although the '#' character may occur in a string representation of a
753 distinguished name, no additional special quoting is done. This
754 syntax has been added subsequent to RFC 1778.
758 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
761 * draft-ietf-ldapbis-syntaxes-xx.txt says:
766 A value of the Bit String syntax is a sequence of binary digits. The
767 LDAP-specific encoding of a value of this syntax is defined by the
770 BitString = SQUOTE *binary-digit SQUOTE "B"
772 binary-digit = "0" / "1"
774 The <SQUOTE> rule is defined in [MODELS].
779 The LDAP definition for the Bit String syntax is:
781 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
783 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
787 3.3.21. Name and Optional UID
789 A value of the Name and Optional UID syntax is the distinguished name
790 [MODELS] of an entity optionally accompanied by a unique identifier
791 that serves to differentiate the entity from others with an identical
794 The LDAP-specific encoding of a value of this syntax is defined by
797 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
799 The <BitString> rule is defined in Section 3.3.2. The
800 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
803 Note that although the '#' character may occur in the string
804 representation of a distinguished name, no additional escaping of
805 this character is performed when a <distinguishedName> is encoded in
806 a <NameAndOptionalUID>.
809 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
811 The LDAP definition for the Name and Optional UID syntax is:
813 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
815 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
819 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
822 1.4. Common ABNF Productions
825 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
827 SQUOTE = %x27 ; single quote ("'")
831 * Note: normalization strips any leading "0"s, unless the
832 * bit string is exactly "'0'B", so the normalized example,
833 * in slapd, would result in
835 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
837 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
838 * i.e. "#", doesn't have to be escaped except when at the
839 * beginning of a value, the definition of Name and Optional
840 * UID appears to be flawed, because there is no clear means
841 * to determine whether the UID part is present or not.
845 * cn=Someone,dc=example,dc=com#'1'B
847 * could be either a NameAndOptionalUID with trailing UID, i.e.
849 * DN = "cn=Someone,dc=example,dc=com"
852 * or a NameAndOptionalUID with no trailing UID, and the AVA
853 * in the last RDN made of
856 * attributeValue = com#'1'B
858 * in fact "com#'1'B" is a valid IA5 string.
860 * As a consequence, current slapd code assumes that the
861 * presence of portions of a BitString at the end of the string
862 * representation of a NameAndOptionalUID means a BitString
863 * is expected, and cause an error otherwise. This is quite
864 * arbitrary, and might change in the future.
874 struct berval dn, uid;
876 if( in->bv_len == 0 ) return LDAP_SUCCESS;
878 ber_dupbv( &dn, in );
879 if( !dn.bv_val ) return LDAP_OTHER;
881 /* if there's a "#", try bitStringValidate()... */
882 uid.bv_val = strrchr( dn.bv_val, '#' );
885 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
887 rc = bitStringValidate( NULL, &uid );
888 if ( rc == LDAP_SUCCESS ) {
889 /* in case of success, trim the UID,
890 * otherwise treat it as part of the DN */
891 dn.bv_len -= uid.bv_len + 1;
892 uid.bv_val[-1] = '\0';
896 rc = dnValidate( NULL, &dn );
898 ber_memfree( dn.bv_val );
913 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
915 if( val->bv_len == 0 ) {
916 ber_dupbv_x( out, val, ctx );
918 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
919 return LDAP_INVALID_SYNTAX;
923 struct berval dnval = *val;
924 struct berval uidval = BER_BVNULL;
926 uidval.bv_val = strrchr( val->bv_val, '#' );
927 if ( uidval.bv_val ) {
929 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
931 rc = bitStringValidate( NULL, &uidval );
933 if ( rc == LDAP_SUCCESS ) {
934 ber_dupbv_x( &dnval, val, ctx );
935 dnval.bv_len -= uidval.bv_len + 1;
936 dnval.bv_val[dnval.bv_len] = '\0';
939 uidval.bv_val = NULL;
943 rc = dnPretty( syntax, &dnval, out, ctx );
944 if ( dnval.bv_val != val->bv_val ) {
945 slap_sl_free( dnval.bv_val, ctx );
947 if( rc != LDAP_SUCCESS ) {
951 if( uidval.bv_val ) {
955 tmp = slap_sl_realloc( out->bv_val, out->bv_len
956 + STRLENOF( "#" ) + uidval.bv_len + 1,
959 ber_memfree_x( out->bv_val, ctx );
963 out->bv_val[out->bv_len++] = '#';
964 out->bv_val[out->bv_len++] = '\'';
966 got1 = uidval.bv_len < sizeof("'0'B");
967 for( i = 1; i < uidval.bv_len - 2; i++ ) {
968 c = uidval.bv_val[i];
971 if( got1 ) out->bv_val[out->bv_len++] = c;
975 out->bv_val[out->bv_len++] = c;
980 out->bv_val[out->bv_len++] = '\'';
981 out->bv_val[out->bv_len++] = 'B';
982 out->bv_val[out->bv_len] = '\0';
986 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
992 uniqueMemberNormalize(
997 struct berval *normalized,
1003 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1005 ber_dupbv_x( &out, val, ctx );
1006 if ( BER_BVISEMPTY( &out ) ) {
1010 struct berval uid = BER_BVNULL;
1012 uid.bv_val = strrchr( out.bv_val, '#' );
1015 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1017 rc = bitStringValidate( NULL, &uid );
1018 if ( rc == LDAP_SUCCESS ) {
1019 uid.bv_val[-1] = '\0';
1020 out.bv_len -= uid.bv_len + 1;
1026 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1028 if( rc != LDAP_SUCCESS ) {
1029 slap_sl_free( out.bv_val, ctx );
1030 return LDAP_INVALID_SYNTAX;
1036 tmp = ch_realloc( normalized->bv_val,
1037 normalized->bv_len + uid.bv_len
1038 + STRLENOF("#") + 1 );
1039 if ( tmp == NULL ) {
1040 ber_memfree_x( normalized->bv_val, ctx );
1044 normalized->bv_val = tmp;
1046 /* insert the separator */
1047 normalized->bv_val[normalized->bv_len++] = '#';
1049 /* append the UID */
1050 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1051 uid.bv_val, uid.bv_len );
1052 normalized->bv_len += uid.bv_len;
1055 normalized->bv_val[normalized->bv_len] = '\0';
1058 slap_sl_free( out.bv_val, ctx );
1061 return LDAP_SUCCESS;
1070 struct berval *value,
1071 void *assertedValue )
1074 struct berval *asserted = (struct berval *) assertedValue;
1075 struct berval assertedDN = *asserted;
1076 struct berval assertedUID = BER_BVNULL;
1077 struct berval valueDN = BER_BVNULL;
1078 struct berval valueUID = BER_BVNULL;
1080 if ( !BER_BVISEMPTY( asserted ) ) {
1081 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1082 if ( !BER_BVISNULL( &assertedUID ) ) {
1083 assertedUID.bv_val++;
1084 assertedUID.bv_len = assertedDN.bv_len
1085 - ( assertedUID.bv_val - assertedDN.bv_val );
1087 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1088 assertedDN.bv_len -= assertedUID.bv_len + 1;
1091 BER_BVZERO( &assertedUID );
1096 if ( !BER_BVISEMPTY( value ) ) {
1099 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1100 if ( !BER_BVISNULL( &valueUID ) ) {
1102 valueUID.bv_len = valueDN.bv_len
1103 - ( valueUID.bv_val - valueDN.bv_val );
1105 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1106 valueDN.bv_len -= valueUID.bv_len + 1;
1109 BER_BVZERO( &valueUID );
1114 if( valueUID.bv_len && assertedUID.bv_len ) {
1115 match = valueUID.bv_len - assertedUID.bv_len;
1118 return LDAP_SUCCESS;
1121 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1124 return LDAP_SUCCESS;
1128 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1132 * Handling boolean syntax and matching is quite rigid.
1133 * A more flexible approach would be to allow a variety
1134 * of strings to be normalized and prettied into TRUE
1142 /* very unforgiving validation, requires no normalization
1143 * before simplistic matching
1146 if( in->bv_len == 4 ) {
1147 if( bvmatch( in, &slap_true_bv ) ) {
1148 return LDAP_SUCCESS;
1150 } else if( in->bv_len == 5 ) {
1151 if( bvmatch( in, &slap_false_bv ) ) {
1152 return LDAP_SUCCESS;
1156 return LDAP_INVALID_SYNTAX;
1165 struct berval *value,
1166 void *assertedValue )
1168 /* simplistic matching allowed by rigid validation */
1169 struct berval *asserted = (struct berval *) assertedValue;
1170 *matchp = value->bv_len != asserted->bv_len;
1171 return LDAP_SUCCESS;
1174 /*-------------------------------------------------------------------
1175 LDAP/X.500 string syntax / matching rules have a few oddities. This
1176 comment attempts to detail how slapd(8) treats them.
1179 StringSyntax X.500 LDAP Matching/Comments
1180 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1181 PrintableString subset subset i/e + ignore insignificant spaces
1182 PrintableString subset subset i/e + ignore insignificant spaces
1183 NumericString subset subset ignore all spaces
1184 IA5String ASCII ASCII i/e + ignore insignificant spaces
1185 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1187 TelephoneNumber subset subset i + ignore all spaces and "-"
1189 See draft-ietf-ldapbis-strpro for details (once published).
1193 In X.500(93), a directory string can be either a PrintableString,
1194 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1195 In later versions, more CHOICEs were added. In all cases the string
1198 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1199 A directory string cannot be zero length.
1201 For matching, there are both case ignore and exact rules. Both
1202 also require that "insignificant" spaces be ignored.
1203 spaces before the first non-space are ignored;
1204 spaces after the last non-space are ignored;
1205 spaces after a space are ignored.
1206 Note: by these rules (and as clarified in X.520), a string of only
1207 spaces is to be treated as if held one space, not empty (which
1208 would be a syntax error).
1211 In ASN.1, numeric string is just a string of digits and spaces
1212 and could be empty. However, in X.500, all attribute values of
1213 numeric string carry a non-empty constraint. For example:
1215 internationalISDNNumber ATTRIBUTE ::= {
1216 WITH SYNTAX InternationalISDNNumber
1217 EQUALITY MATCHING RULE numericStringMatch
1218 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1219 ID id-at-internationalISDNNumber }
1220 InternationalISDNNumber ::=
1221 NumericString (SIZE(1..ub-international-isdn-number))
1223 Unforunately, some assertion values are don't carry the same
1224 constraint (but its unclear how such an assertion could ever
1225 be true). In LDAP, there is one syntax (numericString) not two
1226 (numericString with constraint, numericString without constraint).
1227 This should be treated as numericString with non-empty constraint.
1228 Note that while someone may have no ISDN number, there are no ISDN
1229 numbers which are zero length.
1231 In matching, spaces are ignored.
1234 In ASN.1, Printable string is just a string of printable characters
1235 and can be empty. In X.500, semantics much like NumericString (see
1236 serialNumber for a like example) excepting uses insignificant space
1237 handling instead of ignore all spaces.
1240 Basically same as PrintableString. There are no examples in X.500,
1241 but same logic applies. So we require them to be non-empty as
1244 -------------------------------------------------------------------*/
1253 unsigned char *u = (unsigned char *)in->bv_val;
1255 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1256 /* directory strings cannot be empty */
1257 return LDAP_INVALID_SYNTAX;
1260 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1261 /* get the length indicated by the first byte */
1262 len = LDAP_UTF8_CHARLEN2( u, len );
1264 /* very basic checks */
1267 if( (u[5] & 0xC0) != 0x80 ) {
1268 return LDAP_INVALID_SYNTAX;
1271 if( (u[4] & 0xC0) != 0x80 ) {
1272 return LDAP_INVALID_SYNTAX;
1275 if( (u[3] & 0xC0) != 0x80 ) {
1276 return LDAP_INVALID_SYNTAX;
1279 if( (u[2] & 0xC0 )!= 0x80 ) {
1280 return LDAP_INVALID_SYNTAX;
1283 if( (u[1] & 0xC0) != 0x80 ) {
1284 return LDAP_INVALID_SYNTAX;
1287 /* CHARLEN already validated it */
1290 return LDAP_INVALID_SYNTAX;
1293 /* make sure len corresponds with the offset
1294 to the next character */
1295 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1299 return LDAP_INVALID_SYNTAX;
1302 return LDAP_SUCCESS;
1306 UTF8StringNormalize(
1311 struct berval *normalized,
1314 struct berval tmp, nvalue;
1318 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1320 if( val->bv_val == NULL ) {
1321 /* assume we're dealing with a syntax (e.g., UTF8String)
1322 * which allows empty strings
1324 normalized->bv_len = 0;
1325 normalized->bv_val = NULL;
1326 return LDAP_SUCCESS;
1329 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1330 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1331 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1332 ? LDAP_UTF8_APPROX : 0;
1334 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1339 /* collapse spaces (in place) */
1341 nvalue.bv_val = tmp.bv_val;
1343 wasspace=1; /* trim leading spaces */
1344 for( i=0; i<tmp.bv_len; i++) {
1345 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1346 if( wasspace++ == 0 ) {
1347 /* trim repeated spaces */
1348 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1352 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1356 if( nvalue.bv_len ) {
1358 /* last character was a space, trim it */
1361 nvalue.bv_val[nvalue.bv_len] = '\0';
1364 /* string of all spaces is treated as one space */
1365 nvalue.bv_val[0] = ' ';
1366 nvalue.bv_val[1] = '\0';
1370 *normalized = nvalue;
1371 return LDAP_SUCCESS;
1374 #if defined(SLAPD_APPROX_INITIALS)
1375 # define SLAPD_APPROX_DELIMITER "._ "
1376 # define SLAPD_APPROX_WORDLEN 2
1378 # define SLAPD_APPROX_DELIMITER " "
1379 # define SLAPD_APPROX_WORDLEN 1
1388 struct berval *value,
1389 void *assertedValue )
1391 struct berval *nval, *assertv;
1392 char *val, **values, **words, *c;
1393 int i, count, len, nextchunk=0, nextavail=0;
1395 /* Yes, this is necessary */
1396 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1397 if( nval == NULL ) {
1399 return LDAP_SUCCESS;
1402 /* Yes, this is necessary */
1403 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1404 NULL, LDAP_UTF8_APPROX, NULL );
1405 if( assertv == NULL ) {
1408 return LDAP_SUCCESS;
1411 /* Isolate how many words there are */
1412 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1413 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1414 if ( c == NULL ) break;
1419 /* Get a phonetic copy of each word */
1420 words = (char **)ch_malloc( count * sizeof(char *) );
1421 values = (char **)ch_malloc( count * sizeof(char *) );
1422 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1424 values[i] = phonetic(c);
1427 /* Work through the asserted value's words, to see if at least some
1428 of the words are there, in the same order. */
1430 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1431 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1436 #if defined(SLAPD_APPROX_INITIALS)
1437 else if( len == 1 ) {
1438 /* Single letter words need to at least match one word's initial */
1439 for( i=nextavail; i<count; i++ )
1440 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1447 /* Isolate the next word in the asserted value and phonetic it */
1448 assertv->bv_val[nextchunk+len] = '\0';
1449 val = phonetic( assertv->bv_val + nextchunk );
1451 /* See if this phonetic chunk is in the remaining words of *value */
1452 for( i=nextavail; i<count; i++ ){
1453 if( !strcmp( val, values[i] ) ){
1461 /* This chunk in the asserted value was NOT within the *value. */
1467 /* Go on to the next word in the asserted value */
1471 /* If some of the words were seen, call it a match */
1472 if( nextavail > 0 ) {
1479 /* Cleanup allocs */
1480 ber_bvfree( assertv );
1481 for( i=0; i<count; i++ ) {
1482 ch_free( values[i] );
1488 return LDAP_SUCCESS;
1497 struct berval *prefix,
1503 int i,j, len, wordcount, keycount=0;
1504 struct berval *newkeys;
1505 BerVarray keys=NULL;
1507 for( j=0; values[j].bv_val != NULL; j++ ) {
1508 struct berval val = BER_BVNULL;
1509 /* Yes, this is necessary */
1510 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1511 assert( val.bv_val != NULL );
1513 /* Isolate how many words there are. There will be a key for each */
1514 for( wordcount = 0, c = val.bv_val; *c; c++) {
1515 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1516 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1518 if (*c == '\0') break;
1522 /* Allocate/increase storage to account for new keys */
1523 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1524 * sizeof(struct berval) );
1525 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1526 if( keys ) ch_free( keys );
1529 /* Get a phonetic copy of each word */
1530 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1532 if( len < SLAPD_APPROX_WORDLEN ) continue;
1533 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1538 ber_memfree( val.bv_val );
1540 keys[keycount].bv_val = NULL;
1543 return LDAP_SUCCESS;
1552 struct berval *prefix,
1553 void * assertedValue,
1562 /* Yes, this is necessary */
1563 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1564 NULL, LDAP_UTF8_APPROX, NULL );
1565 if( val == NULL || val->bv_val == NULL ) {
1566 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1567 keys[0].bv_val = NULL;
1570 return LDAP_SUCCESS;
1573 /* Isolate how many words there are. There will be a key for each */
1574 for( count = 0,c = val->bv_val; *c; c++) {
1575 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1576 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1578 if (*c == '\0') break;
1582 /* Allocate storage for new keys */
1583 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1585 /* Get a phonetic copy of each word */
1586 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1588 if( len < SLAPD_APPROX_WORDLEN ) continue;
1589 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1595 keys[count].bv_val = NULL;
1598 return LDAP_SUCCESS;
1601 /* Remove all spaces and '-' characters */
1603 telephoneNumberNormalize(
1608 struct berval *normalized,
1613 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1615 /* validator should have refused an empty string */
1616 assert( val->bv_len );
1618 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1620 for( p = val->bv_val; *p; p++ ) {
1621 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1627 normalized->bv_len = q - normalized->bv_val;
1629 if( normalized->bv_len == 0 ) {
1630 slap_sl_free( normalized->bv_val, ctx );
1631 normalized->bv_val = NULL;
1632 return LDAP_INVALID_SYNTAX;
1635 return LDAP_SUCCESS;
1643 struct berval val = *in;
1645 if( val.bv_len == 0 ) {
1646 /* disallow empty strings */
1647 return LDAP_INVALID_SYNTAX;
1650 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1651 if ( val.bv_len == 1 ) {
1652 return LDAP_SUCCESS;
1655 if ( val.bv_val[0] == '0' ) {
1662 while ( OID_LEADCHAR( val.bv_val[0] )) {
1666 if ( val.bv_len == 0 ) {
1667 return LDAP_SUCCESS;
1671 if( !OID_SEPARATOR( val.bv_val[0] )) {
1679 return LDAP_INVALID_SYNTAX;
1688 struct berval val = *in;
1690 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1692 if ( val.bv_val[0] == '-' ) {
1696 if( val.bv_len == 0 ) { /* bare "-" */
1697 return LDAP_INVALID_SYNTAX;
1700 if( val.bv_val[0] == '0' ) { /* "-0" */
1701 return LDAP_INVALID_SYNTAX;
1704 } else if ( val.bv_val[0] == '0' ) {
1705 if( val.bv_len > 1 ) { /* "0<more>" */
1706 return LDAP_INVALID_SYNTAX;
1709 return LDAP_SUCCESS;
1712 for( i=0; i < val.bv_len; i++ ) {
1713 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1714 return LDAP_INVALID_SYNTAX;
1718 return LDAP_SUCCESS;
1727 struct berval *value,
1728 void *assertedValue )
1730 struct berval *asserted = (struct berval *) assertedValue;
1731 int vsign = 1, asign = 1; /* default sign = '+' */
1736 if( v.bv_val[0] == '-' ) {
1742 if( v.bv_len == 0 ) vsign = 0;
1745 if( a.bv_val[0] == '-' ) {
1751 if( a.bv_len == 0 ) vsign = 0;
1753 match = vsign - asign;
1755 match = ( v.bv_len != a.bv_len
1756 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1757 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1758 if( vsign < 0 ) match = -match;
1762 return LDAP_SUCCESS;
1766 countryStringValidate(
1768 struct berval *val )
1770 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1772 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1773 return LDAP_INVALID_SYNTAX;
1775 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1776 return LDAP_INVALID_SYNTAX;
1779 return LDAP_SUCCESS;
1783 printableStringValidate(
1785 struct berval *val )
1789 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1791 for(i=0; i < val->bv_len; i++) {
1792 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1793 return LDAP_INVALID_SYNTAX;
1797 return LDAP_SUCCESS;
1801 printablesStringValidate(
1803 struct berval *val )
1807 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1809 for(i=0,len=0; i < val->bv_len; i++) {
1810 int c = val->bv_val[i];
1814 return LDAP_INVALID_SYNTAX;
1818 } else if ( SLAP_PRINTABLE(c) ) {
1821 return LDAP_INVALID_SYNTAX;
1826 return LDAP_INVALID_SYNTAX;
1829 return LDAP_SUCCESS;
1835 struct berval *val )
1839 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1841 for(i=0; i < val->bv_len; i++) {
1842 if( !LDAP_ASCII(val->bv_val[i]) ) {
1843 return LDAP_INVALID_SYNTAX;
1847 return LDAP_SUCCESS;
1856 struct berval *normalized,
1860 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1862 assert( val->bv_len );
1864 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1868 /* Ignore initial whitespace */
1869 while ( ASCII_SPACE( *p ) ) p++;
1871 normalized->bv_val = ber_strdup_x( p, ctx );
1872 p = q = normalized->bv_val;
1875 if ( ASCII_SPACE( *p ) ) {
1878 /* Ignore the extra whitespace */
1879 while ( ASCII_SPACE( *p ) ) {
1883 } else if ( casefold ) {
1884 /* Most IA5 rules require casefolding */
1885 *q++ = TOLOWER(*p); p++;
1892 assert( normalized->bv_val <= p );
1896 * If the string ended in space, backup the pointer one
1897 * position. One is enough because the above loop collapsed
1898 * all whitespace to a single space.
1900 if ( ASCII_SPACE( q[-1] ) ) --q;
1902 /* null terminate */
1905 normalized->bv_len = q - normalized->bv_val;
1906 if( normalized->bv_len == 0 ) {
1907 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1908 normalized->bv_val[0] = ' ';
1909 normalized->bv_val[1] = '\0';
1910 normalized->bv_len = 1;
1913 return LDAP_SUCCESS;
1922 if( in->bv_len != 36 ) {
1923 return LDAP_INVALID_SYNTAX;
1926 for( i=0; i<36; i++ ) {
1932 if( in->bv_val[i] != '-' ) {
1933 return LDAP_INVALID_SYNTAX;
1937 if( !ASCII_HEX( in->bv_val[i]) ) {
1938 return LDAP_INVALID_SYNTAX;
1943 return LDAP_SUCCESS;
1952 struct berval *normalized,
1955 unsigned char octet = '\0';
1958 normalized->bv_len = 16;
1959 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1961 for( i=0, j=0; i<36; i++ ) {
1962 unsigned char nibble;
1963 if( val->bv_val[i] == '-' ) {
1966 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1967 nibble = val->bv_val[i] - '0';
1969 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1970 nibble = val->bv_val[i] - ('a'-10);
1972 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1973 nibble = val->bv_val[i] - ('A'-10);
1976 slap_sl_free( normalized->bv_val, ctx );
1977 return LDAP_INVALID_SYNTAX;
1982 normalized->bv_val[j>>1] = octet;
1984 octet = nibble << 4;
1989 normalized->bv_val[normalized->bv_len] = 0;
1990 return LDAP_SUCCESS;
1996 numericStringValidate(
2002 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2004 for(i=0; i < in->bv_len; i++) {
2005 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2006 return LDAP_INVALID_SYNTAX;
2010 return LDAP_SUCCESS;
2014 numericStringNormalize(
2019 struct berval *normalized,
2022 /* removal all spaces */
2025 assert( val->bv_len );
2027 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2030 q = normalized->bv_val;
2033 if ( ASCII_SPACE( *p ) ) {
2034 /* Ignore whitespace */
2041 /* we should have copied no more then is in val */
2042 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2044 /* null terminate */
2047 normalized->bv_len = q - normalized->bv_val;
2049 if( normalized->bv_len == 0 ) {
2050 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2051 normalized->bv_val[0] = ' ';
2052 normalized->bv_val[1] = '\0';
2053 normalized->bv_len = 1;
2056 return LDAP_SUCCESS;
2060 * Integer conversion macros that will use the largest available
2063 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2064 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2065 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2066 # define SLAP_LONG_MAX LLONG_MAX
2067 # define SLAP_LONG_MIN LLONG_MIN
2068 # define SLAP_LONG long long
2070 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2071 # define SLAP_LONG_MAX LONG_MAX
2072 # define SLAP_LONG_MIN LONG_MIN
2073 # define SLAP_LONG long
2074 #endif /* HAVE_STRTOLL ... */
2082 struct berval *value,
2083 void *assertedValue )
2085 SLAP_LONG lValue, lAssertedValue;
2087 /* safe to assume integers are NUL terminated? */
2088 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2089 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2092 return LDAP_CONSTRAINT_VIOLATION;
2095 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2097 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2100 return LDAP_CONSTRAINT_VIOLATION;
2103 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2104 return LDAP_SUCCESS;
2113 struct berval *value,
2114 void *assertedValue )
2116 SLAP_LONG lValue, lAssertedValue;
2118 /* safe to assume integers are NUL terminated? */
2119 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2120 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2123 return LDAP_CONSTRAINT_VIOLATION;
2126 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2128 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2131 return LDAP_CONSTRAINT_VIOLATION;
2134 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2135 return LDAP_SUCCESS;
2139 serialNumberAndIssuerValidate(
2146 struct berval sn, i;
2147 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2149 i.bv_val = strchr( in->bv_val, '$' );
2150 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2152 sn.bv_val = in->bv_val;
2153 sn.bv_len = i.bv_val - in->bv_val;
2156 i.bv_len = in->bv_len - (sn.bv_len + 1);
2158 /* validate serial number (strict for now) */
2159 for( n=0; n < sn.bv_len; n++ ) {
2160 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2164 rc = dnValidate( NULL, &i );
2165 if( rc ) return LDAP_INVALID_SYNTAX;
2167 return LDAP_SUCCESS;
2171 serialNumberAndIssuerPretty(
2180 struct berval sn, i, newi;
2185 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2186 val->bv_val, 0, 0 );
2188 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2190 i.bv_val = strchr( val->bv_val, '$' );
2191 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2193 sn.bv_val = val->bv_val;
2194 sn.bv_len = i.bv_val - val->bv_val;
2197 i.bv_len = val->bv_len - (sn.bv_len + 1);
2199 /* eat leading zeros */
2200 for( n=0; n < (sn.bv_len-1); n++ ) {
2201 if( sn.bv_val[n] != '0' ) break;
2206 for( n=0; n < sn.bv_len; n++ ) {
2207 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2211 rc = dnPretty( syntax, &i, &newi, ctx );
2212 if( rc ) return LDAP_INVALID_SYNTAX;
2214 /* make room from sn + "$" */
2215 out->bv_len = sn.bv_len + newi.bv_len + 1;
2216 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2218 if( out->bv_val == NULL ) {
2219 slap_sl_free( newi.bv_val, ctx );
2223 /* push issuer over */
2224 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2225 /* insert sn and "$" */
2226 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2227 out->bv_val[sn.bv_len] = '$';
2229 out->bv_val[out->bv_len] = '\0';
2231 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2232 out->bv_val, 0, 0 );
2234 return LDAP_SUCCESS;
2238 * This routine is called by certificateExactNormalize when
2239 * certificateExactNormalize receives a search string instead of
2240 * a certificate. This routine checks if the search value is valid
2241 * and then returns the normalized value
2244 serialNumberAndIssuerNormalize(
2255 struct berval sn, i, newi;
2260 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2261 val->bv_val, 0, 0 );
2263 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2265 i.bv_val = strchr( val->bv_val, '$' );
2266 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2268 sn.bv_val = val->bv_val;
2269 sn.bv_len = i.bv_val - val->bv_val;
2272 i.bv_len = val->bv_len - (sn.bv_len + 1);
2274 /* eat leading zeros */
2275 for( n=0; n < (sn.bv_len-1); n++ ) {
2276 if( sn.bv_val[n] != '0' ) break;
2281 for( n=0; n < sn.bv_len; n++ ) {
2282 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2283 return LDAP_INVALID_SYNTAX;
2288 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2289 if( rc ) return LDAP_INVALID_SYNTAX;
2291 /* make room from sn + "$" */
2292 out->bv_len = sn.bv_len + newi.bv_len + 1;
2293 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2295 if( out->bv_val == NULL ) {
2296 slap_sl_free( newi.bv_val, ctx );
2300 /* push issuer over */
2301 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2302 /* insert sn and "$" */
2303 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2304 out->bv_val[sn.bv_len] = '$';
2306 out->bv_val[out->bv_len] = '\0';
2308 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2309 out->bv_val, 0, 0 );
2316 certificateExactNormalize(
2321 struct berval *normalized,
2324 int rc = LDAP_INVALID_SYNTAX;
2326 char *serial = NULL;
2327 ber_len_t seriallen;
2328 struct berval issuer_dn = BER_BVNULL;
2329 X509_NAME *name = NULL;
2330 ASN1_INTEGER *sn = NULL;
2333 if( val->bv_len == 0 ) goto done;
2335 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2336 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2339 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2341 p = (unsigned char *)val->bv_val;
2342 xcert = d2i_X509( NULL, &p, val->bv_len);
2343 if( xcert == NULL ) goto done;
2345 sn=X509_get_serialNumber(xcert);
2346 if ( sn == NULL ) goto done;
2347 serial=i2s_ASN1_INTEGER(0, sn );
2348 if( serial == NULL ) goto done;
2349 seriallen=strlen(serial);
2351 name=X509_get_issuer_name(xcert);
2352 if( name == NULL ) goto done;
2353 rc = dnX509normalize( name, &issuer_dn );
2354 if( rc != LDAP_SUCCESS ) goto done;
2356 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2357 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2358 p = (unsigned char *)normalized->bv_val;
2359 AC_MEMCPY(p, serial, seriallen);
2362 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2363 p += issuer_dn.bv_len;
2366 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2367 normalized->bv_val, NULL, NULL );
2370 if (xcert) X509_free(xcert);
2371 if (serial) ch_free(serial);
2372 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2376 #endif /* HAVE_TLS */
2379 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2380 /* slight optimization - does not need the start parameter */
2381 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2386 check_time_syntax (struct berval *val,
2389 struct berval *fraction)
2392 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2393 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2394 * GeneralizedTime supports leap seconds, UTCTime does not.
2396 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2397 static const int mdays[2][12] = {
2398 /* non-leap years */
2399 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2401 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2404 int part, c, c1, c2, tzoffset, leapyear = 0;
2407 e = p + val->bv_len;
2409 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2410 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2412 for (part = start; part < 7 && p < e; part++) {
2414 if (!ASCII_DIGIT(c1)) {
2419 return LDAP_INVALID_SYNTAX;
2422 if (!ASCII_DIGIT(c)) {
2423 return LDAP_INVALID_SYNTAX;
2425 c += c1 * 10 - '0' * 11;
2426 if ((part | 1) == 3) {
2429 return LDAP_INVALID_SYNTAX;
2432 if (c >= ceiling[part]) {
2433 if (! (c == 60 && part == 6 && start == 0))
2434 return LDAP_INVALID_SYNTAX;
2438 if (part < 5 + start) {
2439 return LDAP_INVALID_SYNTAX;
2441 for (; part < 9; part++) {
2445 /* leapyear check for the Gregorian calendar (year>1581) */
2446 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2450 if (parts[3] >= mdays[leapyear][parts[2]]) {
2451 return LDAP_INVALID_SYNTAX;
2455 fraction->bv_val = p;
2456 fraction->bv_len = 0;
2457 if (p < e && (*p == '.' || *p == ',')) {
2459 while (++p < e && ASCII_DIGIT(*p)) {
2462 if (p - fraction->bv_val == 1) {
2463 return LDAP_INVALID_SYNTAX;
2465 for (end_num = p; end_num[-1] == '0'; --end_num) {
2468 c = end_num - fraction->bv_val;
2469 if (c != 1) fraction->bv_len = c;
2475 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2481 return LDAP_INVALID_SYNTAX;
2487 for (part = 7; part < 9 && p < e; part++) {
2489 if (!ASCII_DIGIT(c1)) {
2494 return LDAP_INVALID_SYNTAX;
2497 if (!ASCII_DIGIT(c2)) {
2498 return LDAP_INVALID_SYNTAX;
2500 parts[part] = c1 * 10 + c2 - '0' * 11;
2501 if (parts[part] >= ceiling[part]) {
2502 return LDAP_INVALID_SYNTAX;
2505 if (part < 8 + start) {
2506 return LDAP_INVALID_SYNTAX;
2509 if (tzoffset == '-') {
2510 /* negative offset to UTC, ie west of Greenwich */
2511 parts[4] += parts[7];
2512 parts[5] += parts[8];
2513 /* offset is just hhmm, no seconds */
2514 for (part = 6; --part >= 0; ) {
2518 c = mdays[leapyear][parts[2]];
2520 if (parts[part] >= c) {
2522 return LDAP_INVALID_SYNTAX;
2527 } else if (part != 5) {
2532 /* positive offset to UTC, ie east of Greenwich */
2533 parts[4] -= parts[7];
2534 parts[5] -= parts[8];
2535 for (part = 6; --part >= 0; ) {
2536 if (parts[part] < 0) {
2538 return LDAP_INVALID_SYNTAX;
2543 /* make first arg to % non-negative */
2544 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2549 } else if (part != 5) {
2556 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2559 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2566 struct berval *normalized )
2570 rc = check_time_syntax(val, 1, parts, NULL);
2571 if (rc != LDAP_SUCCESS) {
2575 normalized->bv_val = ch_malloc( 14 );
2576 if ( normalized->bv_val == NULL ) {
2577 return LBER_ERROR_MEMORY;
2580 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2581 parts[1], parts[2] + 1, parts[3] + 1,
2582 parts[4], parts[5], parts[6] );
2583 normalized->bv_len = 13;
2585 return LDAP_SUCCESS;
2595 return check_time_syntax(in, 1, parts, NULL);
2598 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2601 generalizedTimeValidate(
2606 struct berval fraction;
2607 return check_time_syntax(in, 0, parts, &fraction);
2611 generalizedTimeNormalize(
2616 struct berval *normalized,
2621 struct berval fraction;
2623 rc = check_time_syntax(val, 0, parts, &fraction);
2624 if (rc != LDAP_SUCCESS) {
2628 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2629 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2630 if ( normalized->bv_val == NULL ) {
2631 return LBER_ERROR_MEMORY;
2634 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2635 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2636 parts[4], parts[5], parts[6] );
2637 if ( fraction.bv_len ) {
2638 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2639 fraction.bv_val, fraction.bv_len );
2640 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2642 strcpy( normalized->bv_val + len-1, "Z" );
2643 normalized->bv_len = len;
2645 return LDAP_SUCCESS;
2649 generalizedTimeOrderingMatch(
2654 struct berval *value,
2655 void *assertedValue )
2657 struct berval *asserted = (struct berval *) assertedValue;
2658 ber_len_t v_len = value->bv_len;
2659 ber_len_t av_len = asserted->bv_len;
2661 /* ignore trailing 'Z' when comparing */
2662 int match = memcmp( value->bv_val, asserted->bv_val,
2663 (v_len < av_len ? v_len : av_len) - 1 );
2664 if ( match == 0 ) match = v_len - av_len;
2667 return LDAP_SUCCESS;
2671 deliveryMethodValidate(
2673 struct berval *val )
2676 #define LENOF(s) (sizeof(s)-1)
2677 struct berval tmp = *val;
2679 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2680 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2681 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2684 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2686 switch( tmp.bv_val[0] ) {
2689 if(( tmp.bv_len >= LENOF("any") ) &&
2690 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2692 tmp.bv_len -= LENOF("any");
2693 tmp.bv_val += LENOF("any");
2696 return LDAP_INVALID_SYNTAX;
2700 if(( tmp.bv_len >= LENOF("mhs") ) &&
2701 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2703 tmp.bv_len -= LENOF("mhs");
2704 tmp.bv_val += LENOF("mhs");
2707 return LDAP_INVALID_SYNTAX;
2711 if(( tmp.bv_len >= LENOF("physical") ) &&
2712 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2714 tmp.bv_len -= LENOF("physical");
2715 tmp.bv_val += LENOF("physical");
2718 return LDAP_INVALID_SYNTAX;
2721 case 'T': /* telex or teletex or telephone */
2722 if(( tmp.bv_len >= LENOF("telex") ) &&
2723 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2725 tmp.bv_len -= LENOF("telex");
2726 tmp.bv_val += LENOF("telex");
2729 if(( tmp.bv_len >= LENOF("teletex") ) &&
2730 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2732 tmp.bv_len -= LENOF("teletex");
2733 tmp.bv_val += LENOF("teletex");
2736 if(( tmp.bv_len >= LENOF("telephone") ) &&
2737 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2739 tmp.bv_len -= LENOF("telephone");
2740 tmp.bv_val += LENOF("telephone");
2743 return LDAP_INVALID_SYNTAX;
2746 case 'G': /* g3fax or g4fax */
2747 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2748 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2749 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2751 tmp.bv_len -= LENOF("g3fax");
2752 tmp.bv_val += LENOF("g3fax");
2755 return LDAP_INVALID_SYNTAX;
2759 if(( tmp.bv_len >= LENOF("ia5") ) &&
2760 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2762 tmp.bv_len -= LENOF("ia5");
2763 tmp.bv_val += LENOF("ia5");
2766 return LDAP_INVALID_SYNTAX;
2770 if(( tmp.bv_len >= LENOF("videotex") ) &&
2771 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2773 tmp.bv_len -= LENOF("videotex");
2774 tmp.bv_val += LENOF("videotex");
2777 return LDAP_INVALID_SYNTAX;
2780 return LDAP_INVALID_SYNTAX;
2783 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2785 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2789 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2793 return LDAP_INVALID_SYNTAX;
2795 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2804 nisNetgroupTripleValidate(
2806 struct berval *val )
2811 if ( val->bv_len == 0 ) {
2812 return LDAP_INVALID_SYNTAX;
2815 p = (char *)val->bv_val;
2816 e = p + val->bv_len;
2818 if ( *p != '(' /*')'*/ ) {
2819 return LDAP_INVALID_SYNTAX;
2822 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2826 return LDAP_INVALID_SYNTAX;
2829 } else if ( !AD_CHAR( *p ) ) {
2830 return LDAP_INVALID_SYNTAX;
2834 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2835 return LDAP_INVALID_SYNTAX;
2841 return LDAP_INVALID_SYNTAX;
2844 return LDAP_SUCCESS;
2848 bootParameterValidate(
2850 struct berval *val )
2854 if ( val->bv_len == 0 ) {
2855 return LDAP_INVALID_SYNTAX;
2858 p = (char *)val->bv_val;
2859 e = p + val->bv_len;
2862 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2863 if ( !AD_CHAR( *p ) ) {
2864 return LDAP_INVALID_SYNTAX;
2869 return LDAP_INVALID_SYNTAX;
2873 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2874 if ( !AD_CHAR( *p ) ) {
2875 return LDAP_INVALID_SYNTAX;
2880 return LDAP_INVALID_SYNTAX;
2884 for ( p++; p < e; p++ ) {
2885 if ( !SLAP_PRINTABLE( *p ) ) {
2886 return LDAP_INVALID_SYNTAX;
2890 return LDAP_SUCCESS;
2894 firstComponentNormalize(
2899 struct berval *normalized,
2906 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2907 ber_dupbv_x( normalized, val, ctx );
2908 return LDAP_SUCCESS;
2911 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2913 if( val->bv_val[0] != '(' /*')'*/ &&
2914 val->bv_val[0] != '{' /*'}'*/ )
2916 return LDAP_INVALID_SYNTAX;
2919 /* trim leading white space */
2921 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2927 /* grab next word */
2928 comp.bv_val = &val->bv_val[len];
2929 len = val->bv_len - len;
2931 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2937 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2938 rc = numericoidValidate( NULL, &comp );
2939 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2940 rc = integerValidate( NULL, &comp );
2942 rc = LDAP_INVALID_SYNTAX;
2946 if( rc == LDAP_SUCCESS ) {
2947 ber_dupbv_x( normalized, &comp, ctx );
2954 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2955 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2957 static slap_syntax_defs_rec syntax_defs[] = {
2958 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2959 X_BINARY X_NOT_H_R ")",
2960 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2961 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2963 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2965 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2967 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2968 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2970 SLAP_SYNTAX_BER, berValidate, NULL},
2971 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2972 0, bitStringValidate, NULL },
2973 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2974 0, booleanValidate, NULL},
2975 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2976 X_BINARY X_NOT_H_R ")",
2977 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2978 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2979 X_BINARY X_NOT_H_R ")",
2980 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2981 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2982 X_BINARY X_NOT_H_R ")",
2983 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2984 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2985 0, countryStringValidate, NULL},
2986 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2987 0, dnValidate, dnPretty},
2988 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
2989 0, rdnValidate, rdnPretty},
2990 #ifdef LDAP_COMP_MATCH
2991 {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
2992 0, componentFilterValidate, NULL},
2994 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2996 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2997 0, deliveryMethodValidate, NULL},
2998 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2999 0, UTF8StringValidate, NULL},
3000 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3002 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3004 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3006 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3008 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3010 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3011 0, printablesStringValidate, NULL},
3012 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3013 SLAP_SYNTAX_BLOB, NULL, NULL},
3014 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3015 0, generalizedTimeValidate, NULL},
3016 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3018 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3019 0, IA5StringValidate, NULL},
3020 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3021 0, integerValidate, NULL},
3022 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3023 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3024 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3026 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3028 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3030 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3032 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3034 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3035 0, nameUIDValidate, nameUIDPretty },
3036 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3038 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3039 0, numericStringValidate, NULL},
3040 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3042 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3043 0, numericoidValidate, NULL},
3044 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3045 0, IA5StringValidate, NULL},
3046 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3047 0, blobValidate, NULL},
3048 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3049 0, UTF8StringValidate, NULL},
3050 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3052 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3054 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3055 0, printableStringValidate, NULL},
3056 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3057 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3058 0, subtreeSpecificationValidate, NULL},
3059 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3060 X_BINARY X_NOT_H_R ")",
3061 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3062 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3063 0, printableStringValidate, NULL},
3064 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3066 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3067 0, printablesStringValidate, NULL},
3068 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3069 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3070 0, utcTimeValidate, NULL},
3072 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3074 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3076 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3078 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3080 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3083 /* RFC 2307 NIS Syntaxes */
3084 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3085 0, nisNetgroupTripleValidate, NULL},
3086 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3087 0, bootParameterValidate, NULL},
3089 /* From PKIX *//* This OID is not published yet. */
3090 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3092 serialNumberAndIssuerValidate,
3093 serialNumberAndIssuerPretty},
3095 #ifdef SLAPD_ACI_ENABLED
3096 /* OpenLDAP Experimental Syntaxes */
3097 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3099 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3103 #ifdef SLAPD_AUTHPASSWD
3104 /* needs updating */
3105 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3106 SLAP_SYNTAX_HIDE, NULL, NULL},
3109 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3110 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3112 /* OpenLDAP Void Syntax */
3113 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3114 SLAP_SYNTAX_HIDE, inValidate, NULL},
3115 {NULL, 0, NULL, NULL}
3118 char *certificateExactMatchSyntaxes[] = {
3119 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3122 char *directoryStringSyntaxes[] = {
3123 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3126 char *integerFirstComponentMatchSyntaxes[] = {
3127 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3128 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3131 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3132 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3133 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3134 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3135 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3136 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3137 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3138 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3139 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3144 * Other matching rules in X.520 that we do not use (yet):
3146 * 2.5.13.25 uTCTimeMatch
3147 * 2.5.13.26 uTCTimeOrderingMatch
3148 * 2.5.13.31* directoryStringFirstComponentMatch
3149 * 2.5.13.32* wordMatch
3150 * 2.5.13.33* keywordMatch
3151 * 2.5.13.36 certificatePairExactMatch
3152 * 2.5.13.37 certificatePairMatch
3153 * 2.5.13.38 certificateListExactMatch
3154 * 2.5.13.39 certificateListMatch
3155 * 2.5.13.40 algorithmIdentifierMatch
3156 * 2.5.13.41* storedPrefixMatch
3157 * 2.5.13.42 attributeCertificateMatch
3158 * 2.5.13.43 readerAndKeyIDMatch
3159 * 2.5.13.44 attributeIntegrityMatch
3161 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3163 static slap_mrule_defs_rec mrule_defs[] = {
3165 * EQUALITY matching rules must be listed after associated APPROX
3166 * matching rules. So, we list all APPROX matching rules first.
3168 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3169 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3170 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3171 NULL, NULL, directoryStringApproxMatch,
3172 directoryStringApproxIndexer, directoryStringApproxFilter,
3175 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3176 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3177 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3178 NULL, NULL, IA5StringApproxMatch,
3179 IA5StringApproxIndexer, IA5StringApproxFilter,
3183 * Other matching rules
3186 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3187 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3188 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3189 NULL, NULL, octetStringMatch,
3190 octetStringIndexer, octetStringFilter,
3193 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3194 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3195 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3196 NULL, dnNormalize, dnMatch,
3197 octetStringIndexer, octetStringFilter,
3200 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3201 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3202 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3203 NULL, dnNormalize, dnRelativeMatch,
3207 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3208 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3209 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3210 NULL, dnNormalize, dnRelativeMatch,
3214 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3215 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3216 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3217 NULL, dnNormalize, dnRelativeMatch,
3221 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3222 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3223 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3224 NULL, dnNormalize, dnRelativeMatch,
3228 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3229 "SYNTAX 1.2.36.79672281.1.5.0 )",
3230 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3231 NULL, rdnNormalize, rdnMatch,
3232 octetStringIndexer, octetStringFilter,
3235 #ifdef LDAP_COMP_MATCH
3236 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3237 "SYNTAX 1.2.36.79672281.1.5.2 )",
3238 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3239 NULL, NULL , componentFilterMatch,
3240 octetStringIndexer, octetStringFilter,
3244 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3245 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3246 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3247 NULL, UTF8StringNormalize, octetStringMatch,
3248 octetStringIndexer, octetStringFilter,
3249 directoryStringApproxMatchOID },
3251 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3252 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3253 SLAP_MR_ORDERING, directoryStringSyntaxes,
3254 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3256 "caseIgnoreMatch" },
3258 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3259 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3260 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3261 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3262 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3263 "caseIgnoreMatch" },
3265 {"( 2.5.13.5 NAME 'caseExactMatch' "
3266 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3267 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3268 NULL, UTF8StringNormalize, octetStringMatch,
3269 octetStringIndexer, octetStringFilter,
3270 directoryStringApproxMatchOID },
3272 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3273 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3274 SLAP_MR_ORDERING, directoryStringSyntaxes,
3275 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3279 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3280 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3281 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3282 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3283 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3286 {"( 2.5.13.8 NAME 'numericStringMatch' "
3287 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3288 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3289 NULL, numericStringNormalize, octetStringMatch,
3290 octetStringIndexer, octetStringFilter,
3293 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3294 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3295 SLAP_MR_ORDERING, NULL,
3296 NULL, numericStringNormalize, octetStringOrderingMatch,
3298 "numericStringMatch" },
3300 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3301 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3302 SLAP_MR_SUBSTR, NULL,
3303 NULL, numericStringNormalize, octetStringSubstringsMatch,
3304 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3305 "numericStringMatch" },
3307 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3308 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3309 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3310 NULL, NULL, NULL, NULL, NULL, NULL },
3312 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3313 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3314 SLAP_MR_SUBSTR, NULL,
3315 NULL, NULL, NULL, NULL, NULL,
3316 "caseIgnoreListMatch" },
3318 {"( 2.5.13.13 NAME 'booleanMatch' "
3319 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3320 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3321 NULL, NULL, booleanMatch,
3322 octetStringIndexer, octetStringFilter,
3325 {"( 2.5.13.14 NAME 'integerMatch' "
3326 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3327 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3328 NULL, NULL, integerMatch,
3329 octetStringIndexer, octetStringFilter,
3332 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3333 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3334 SLAP_MR_ORDERING, NULL,
3335 NULL, NULL, integerMatch,
3339 {"( 2.5.13.16 NAME 'bitStringMatch' "
3340 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3341 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3342 NULL, NULL, octetStringMatch,
3343 octetStringIndexer, octetStringFilter,
3346 {"( 2.5.13.17 NAME 'octetStringMatch' "
3347 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3348 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3349 NULL, NULL, octetStringMatch,
3350 octetStringIndexer, octetStringFilter,
3353 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3354 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3355 SLAP_MR_ORDERING, NULL,
3356 NULL, NULL, octetStringOrderingMatch,
3358 "octetStringMatch" },
3360 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3361 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3362 SLAP_MR_SUBSTR, NULL,
3363 NULL, NULL, octetStringSubstringsMatch,
3364 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3365 "octetStringMatch" },
3367 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3368 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3369 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3371 telephoneNumberNormalize, octetStringMatch,
3372 octetStringIndexer, octetStringFilter,
3375 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3376 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3377 SLAP_MR_SUBSTR, NULL,
3378 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3379 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3380 "telephoneNumberMatch" },
3382 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3383 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3384 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3385 NULL, NULL, NULL, NULL, NULL, NULL },
3387 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3388 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3389 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3390 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3394 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3395 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3396 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3397 NULL, NULL, NULL, NULL, NULL, NULL },
3399 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3400 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3401 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3402 NULL, generalizedTimeNormalize, octetStringMatch,
3406 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3407 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3408 SLAP_MR_ORDERING, NULL,
3409 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3411 "generalizedTimeMatch" },
3413 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3414 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3415 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3416 integerFirstComponentMatchSyntaxes,
3417 NULL, firstComponentNormalize, integerMatch,
3418 octetStringIndexer, octetStringFilter,
3421 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3422 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3423 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3424 objectIdentifierFirstComponentMatchSyntaxes,
3425 NULL, firstComponentNormalize, octetStringMatch,
3426 octetStringIndexer, octetStringFilter,
3429 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3430 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3431 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3433 NULL, certificateExactNormalize, octetStringMatch,
3434 octetStringIndexer, octetStringFilter,
3436 NULL, NULL, NULL, NULL, NULL,
3440 {"( 2.5.13.35 NAME 'certificateMatch' "
3441 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3442 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3444 NULL, NULL, octetStringMatch,
3445 octetStringIndexer, octetStringFilter,
3447 NULL, NULL, NULL, NULL, NULL,
3451 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3453 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3454 NULL, IA5StringNormalize, octetStringMatch,
3455 octetStringIndexer, octetStringFilter,
3456 IA5StringApproxMatchOID },
3458 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3460 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3461 NULL, IA5StringNormalize, octetStringMatch,
3462 octetStringIndexer, octetStringFilter,
3463 IA5StringApproxMatchOID },
3465 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3466 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3467 SLAP_MR_SUBSTR, NULL,
3468 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3469 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3470 "caseIgnoreIA5Match" },
3472 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3473 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3474 SLAP_MR_SUBSTR, NULL,
3475 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3476 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3477 "caseExactIA5Match" },
3479 #ifdef SLAPD_AUTHPASSWD
3480 /* needs updating */
3481 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3482 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3483 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3484 NULL, NULL, authPasswordMatch,
3489 #ifdef SLAPD_ACI_ENABLED
3490 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3491 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3492 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3493 NULL, NULL, OpenLDAPaciMatch,
3498 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3499 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3501 NULL, NULL, integerBitAndMatch,
3505 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3508 NULL, NULL, integerBitOrMatch,
3512 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3513 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3514 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3515 NULL, UUIDNormalize, octetStringMatch,
3516 octetStringIndexer, octetStringFilter,
3519 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3520 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3521 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3522 NULL, UUIDNormalize, octetStringOrderingMatch,
3523 octetStringIndexer, octetStringFilter,
3526 {NULL, SLAP_MR_NONE, NULL,
3527 NULL, NULL, NULL, NULL, NULL,
3532 slap_schema_init( void )
3537 /* we should only be called once (from main) */
3538 assert( schema_init_done == 0 );
3540 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3541 res = register_syntax( &syntax_defs[i] );
3544 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3545 syntax_defs[i].sd_desc );
3550 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3551 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3552 mrule_defs[i].mrd_compat_syntaxes == NULL )
3555 "slap_schema_init: Ignoring unusable matching rule %s\n",
3556 mrule_defs[i].mrd_desc );
3560 res = register_matching_rule( &mrule_defs[i] );
3564 "slap_schema_init: Error registering matching rule %s\n",
3565 mrule_defs[i].mrd_desc );
3570 res = slap_schema_load();
3571 schema_init_done = 1;
3576 schema_destroy( void )