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 for( i=0; values[i].bv_val != NULL; i++ ) {
212 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
213 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
214 ber_dupbv_x( &keys[i], &digest, ctx );
217 keys[i].bv_val = NULL;
225 /* Index generation function */
226 int octetStringFilter(
231 struct berval *prefix,
232 void * assertedValue,
238 HASH_CONTEXT HASHcontext;
239 unsigned char HASHdigest[HASH_BYTES];
240 struct berval *value = (struct berval *) assertedValue;
241 struct berval digest;
242 digest.bv_val = (char *)HASHdigest;
243 digest.bv_len = sizeof(HASHdigest);
245 slen = syntax->ssyn_oidlen;
246 mlen = mr->smr_oidlen;
248 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
250 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
251 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
253 ber_dupbv_x( keys, &digest, ctx );
254 keys[1].bv_val = NULL;
263 octetStringSubstringsMatch(
268 struct berval *value,
269 void *assertedValue )
272 SubstringsAssertion *sub = assertedValue;
273 struct berval left = *value;
277 /* Add up asserted input length */
278 if( sub->sa_initial.bv_val ) {
279 inlen += sub->sa_initial.bv_len;
282 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
283 inlen += sub->sa_any[i].bv_len;
286 if( sub->sa_final.bv_val ) {
287 inlen += sub->sa_final.bv_len;
290 if( sub->sa_initial.bv_val ) {
291 if( inlen > left.bv_len ) {
296 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
297 sub->sa_initial.bv_len );
303 left.bv_val += sub->sa_initial.bv_len;
304 left.bv_len -= sub->sa_initial.bv_len;
305 inlen -= sub->sa_initial.bv_len;
308 if( sub->sa_final.bv_val ) {
309 if( inlen > left.bv_len ) {
314 match = memcmp( sub->sa_final.bv_val,
315 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
316 sub->sa_final.bv_len );
322 left.bv_len -= sub->sa_final.bv_len;
323 inlen -= sub->sa_final.bv_len;
327 for(i=0; sub->sa_any[i].bv_val; i++) {
332 if( inlen > left.bv_len ) {
333 /* not enough length */
338 if( sub->sa_any[i].bv_len == 0 ) {
342 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
349 idx = p - left.bv_val;
351 if( idx >= left.bv_len ) {
352 /* this shouldn't happen */
359 if( sub->sa_any[i].bv_len > left.bv_len ) {
360 /* not enough left */
365 match = memcmp( left.bv_val,
366 sub->sa_any[i].bv_val,
367 sub->sa_any[i].bv_len );
375 left.bv_val += sub->sa_any[i].bv_len;
376 left.bv_len -= sub->sa_any[i].bv_len;
377 inlen -= sub->sa_any[i].bv_len;
386 /* Substrings Index generation function */
388 octetStringSubstringsIndexer(
393 struct berval *prefix,
398 ber_len_t i, j, len, nkeys;
402 HASH_CONTEXT HASHcontext;
403 unsigned char HASHdigest[HASH_BYTES];
404 struct berval digest;
405 digest.bv_val = (char *)HASHdigest;
406 digest.bv_len = sizeof(HASHdigest);
410 for( i=0; values[i].bv_val != NULL; i++ ) {
411 /* count number of indices to generate */
412 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
413 if( values[i].bv_len >= index_substr_if_maxlen ) {
414 nkeys += index_substr_if_maxlen -
415 (index_substr_if_minlen - 1);
416 } else if( values[i].bv_len >= index_substr_if_minlen ) {
417 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
421 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
422 if( values[i].bv_len >= index_substr_any_len ) {
423 nkeys += values[i].bv_len - (index_substr_any_len - 1);
427 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
428 if( values[i].bv_len >= index_substr_if_maxlen ) {
429 nkeys += index_substr_if_maxlen -
430 (index_substr_if_minlen - 1);
431 } else if( values[i].bv_len >= index_substr_if_minlen ) {
432 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
438 /* no keys to generate */
443 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
445 slen = syntax->ssyn_oidlen;
446 mlen = mr->smr_oidlen;
449 for( i=0; values[i].bv_val != NULL; i++ ) {
452 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
453 ( values[i].bv_len >= index_substr_any_len ) )
455 char pre = SLAP_INDEX_SUBSTR_PREFIX;
456 max = values[i].bv_len - (index_substr_any_len - 1);
458 for( j=0; j<max; j++ ) {
459 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
460 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
461 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
465 /* skip if too short */
466 if( values[i].bv_len < index_substr_if_minlen ) continue;
468 max = index_substr_if_maxlen < values[i].bv_len
469 ? index_substr_if_maxlen : values[i].bv_len;
471 for( j=index_substr_if_minlen; j<=max; j++ ) {
474 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
475 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
476 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
477 syntax, mr, (unsigned char *)values[i].bv_val, j );
478 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
481 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
482 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
483 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
484 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
485 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
492 keys[nkeys].bv_val = NULL;
503 octetStringSubstringsFilter (
508 struct berval *prefix,
509 void * assertedValue,
513 SubstringsAssertion *sa;
515 ber_len_t len, max, nkeys = 0;
516 size_t slen, mlen, klen;
518 HASH_CONTEXT HASHcontext;
519 unsigned char HASHdigest[HASH_BYTES];
520 struct berval *value;
521 struct berval digest;
523 sa = (SubstringsAssertion *) assertedValue;
525 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
526 sa->sa_initial.bv_val != NULL &&
527 sa->sa_initial.bv_len >= index_substr_if_minlen )
530 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
531 ( flags & SLAP_INDEX_SUBSTR_ANY ))
533 nkeys += (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
537 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
539 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
540 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
541 /* don't bother accounting with stepping */
542 nkeys += sa->sa_any[i].bv_len -
543 ( index_substr_any_len - 1 );
548 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
549 sa->sa_final.bv_val != NULL &&
550 sa->sa_final.bv_len >= index_substr_if_minlen )
553 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
554 ( flags & SLAP_INDEX_SUBSTR_ANY ))
556 nkeys += (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
565 digest.bv_val = (char *)HASHdigest;
566 digest.bv_len = sizeof(HASHdigest);
568 slen = syntax->ssyn_oidlen;
569 mlen = mr->smr_oidlen;
571 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
574 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
575 sa->sa_initial.bv_val != NULL &&
576 sa->sa_initial.bv_len >= index_substr_if_minlen )
578 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
579 value = &sa->sa_initial;
581 klen = index_substr_if_maxlen < value->bv_len
582 ? index_substr_if_maxlen : value->bv_len;
584 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
585 syntax, mr, (unsigned char *)value->bv_val, klen );
586 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
588 /* If initial is too long and we have subany indexed, use it
589 * to match the excess...
591 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
594 pre = SLAP_INDEX_SUBSTR_PREFIX;
595 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
597 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
598 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
599 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
604 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
606 pre = SLAP_INDEX_SUBSTR_PREFIX;
607 klen = index_substr_any_len;
609 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
610 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
614 value = &sa->sa_any[i];
617 j <= value->bv_len - index_substr_any_len;
618 j += index_substr_any_step )
620 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
621 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
622 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
627 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
628 sa->sa_final.bv_val != NULL &&
629 sa->sa_final.bv_len >= index_substr_if_minlen )
631 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
632 value = &sa->sa_final;
634 klen = index_substr_if_maxlen < value->bv_len
635 ? index_substr_if_maxlen : value->bv_len;
637 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
638 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
639 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
641 /* If final is too long and we have subany indexed, use it
642 * to match the excess...
644 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
647 pre = SLAP_INDEX_SUBSTR_PREFIX;
648 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
650 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
651 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
652 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
658 keys[nkeys].bv_val = NULL;
675 /* very unforgiving validation, requires no normalization
676 * before simplistic matching
678 if( in->bv_len < 3 ) {
679 return LDAP_INVALID_SYNTAX;
683 * RFC 2252 section 6.3 Bit String
684 * bitstring = "'" *binary-digit "'B"
685 * binary-digit = "0" / "1"
686 * example: '0101111101'B
689 if( in->bv_val[0] != '\'' ||
690 in->bv_val[in->bv_len-2] != '\'' ||
691 in->bv_val[in->bv_len-1] != 'B' )
693 return LDAP_INVALID_SYNTAX;
696 for( i=in->bv_len-3; i>0; i-- ) {
697 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
698 return LDAP_INVALID_SYNTAX;
706 * Syntax is [RFC2252]:
711 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
713 Values in this syntax are encoded according to the following BNF:
715 bitstring = "'" *binary-digit "'B"
717 binary-digit = "0" / "1"
721 6.21. Name And Optional UID
723 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
725 Values in this syntax are encoded according to the following BNF:
727 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
729 Although the '#' character may occur in a string representation of a
730 distinguished name, no additional special quoting is done. This
731 syntax has been added subsequent to RFC 1778.
735 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
738 * draft-ietf-ldapbis-syntaxes-xx.txt says:
743 A value of the Bit String syntax is a sequence of binary digits. The
744 LDAP-specific encoding of a value of this syntax is defined by the
747 BitString = SQUOTE *binary-digit SQUOTE "B"
749 binary-digit = "0" / "1"
751 The <SQUOTE> rule is defined in [MODELS].
756 The LDAP definition for the Bit String syntax is:
758 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
760 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
764 3.3.21. Name and Optional UID
766 A value of the Name and Optional UID syntax is the distinguished name
767 [MODELS] of an entity optionally accompanied by a unique identifier
768 that serves to differentiate the entity from others with an identical
771 The LDAP-specific encoding of a value of this syntax is defined by
774 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
776 The <BitString> rule is defined in Section 3.3.2. The
777 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
780 Note that although the '#' character may occur in the string
781 representation of a distinguished name, no additional escaping of
782 this character is performed when a <distinguishedName> is encoded in
783 a <NameAndOptionalUID>.
786 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
788 The LDAP definition for the Name and Optional UID syntax is:
790 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
792 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
796 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
799 1.4. Common ABNF Productions
802 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
804 SQUOTE = %x27 ; single quote ("'")
808 * Note: normalization strips any leading "0"s, unless the
809 * bit string is exactly "'0'B", so the normalized example,
810 * in slapd, would result in
812 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
814 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
815 * i.e. "#", doesn't have to be escaped except when at the
816 * beginning of a value, the definition of Name and Optional
817 * UID appears to be flawed, because there is no clear means
818 * to determine whether the UID part is present or not.
822 * cn=Someone,dc=example,dc=com#'1'B
824 * could be either a NameAndOptionalUID with trailing UID, i.e.
826 * DN = "cn=Someone,dc=example,dc=com"
829 * or a NameAndOptionalUID with no trailing UID, and the AVA
830 * in the last RDN made of
833 * attributeValue = com#'1'B
835 * in fact "com#'1'B" is a valid IA5 string.
837 * As a consequence, current slapd code assumes that the
838 * presence of portions of a BitString at the end of the string
839 * representation of a NameAndOptionalUID means a BitString
840 * is expected, and cause an error otherwise. This is quite
841 * arbitrary, and might change in the future.
851 struct berval dn, uid;
853 if( in->bv_len == 0 ) return LDAP_SUCCESS;
855 ber_dupbv( &dn, in );
856 if( !dn.bv_val ) return LDAP_OTHER;
858 /* if there's a "#", try bitStringValidate()... */
859 uid.bv_val = strrchr( dn.bv_val, '#' );
862 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
864 rc = bitStringValidate( NULL, &uid );
865 if ( rc == LDAP_SUCCESS ) {
866 /* in case of success, trim the UID,
867 * otherwise treat it as part of the DN */
868 dn.bv_len -= uid.bv_len + 1;
869 uid.bv_val[-1] = '\0';
873 rc = dnValidate( NULL, &dn );
875 ber_memfree( dn.bv_val );
890 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
892 if( val->bv_len == 0 ) {
893 ber_dupbv_x( out, val, ctx );
895 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
896 return LDAP_INVALID_SYNTAX;
900 struct berval dnval = *val;
901 struct berval uidval = BER_BVNULL;
903 uidval.bv_val = strrchr( val->bv_val, '#' );
904 if ( uidval.bv_val ) {
906 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
908 rc = bitStringValidate( NULL, &uidval );
910 if ( rc == LDAP_SUCCESS ) {
911 ber_dupbv_x( &dnval, val, ctx );
912 dnval.bv_len -= uidval.bv_len + 1;
913 dnval.bv_val[dnval.bv_len] = '\0';
916 uidval.bv_val = NULL;
920 rc = dnPretty( syntax, &dnval, out, ctx );
921 if ( dnval.bv_val != val->bv_val ) {
922 slap_sl_free( dnval.bv_val, ctx );
924 if( rc != LDAP_SUCCESS ) {
928 if( uidval.bv_val ) {
932 tmp = slap_sl_realloc( out->bv_val, out->bv_len
933 + STRLENOF( "#" ) + uidval.bv_len + 1,
936 ber_memfree_x( out->bv_val, ctx );
940 out->bv_val[out->bv_len++] = '#';
941 out->bv_val[out->bv_len++] = '\'';
943 got1 = uidval.bv_len < sizeof("'0'B");
944 for( i = 1; i < uidval.bv_len - 2; i++ ) {
945 c = uidval.bv_val[i];
948 if( got1 ) out->bv_val[out->bv_len++] = c;
952 out->bv_val[out->bv_len++] = c;
957 out->bv_val[out->bv_len++] = '\'';
958 out->bv_val[out->bv_len++] = 'B';
959 out->bv_val[out->bv_len] = '\0';
963 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
969 uniqueMemberNormalize(
974 struct berval *normalized,
980 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
982 ber_dupbv_x( &out, val, ctx );
983 if ( BER_BVISEMPTY( &out ) ) {
987 struct berval uid = BER_BVNULL;
989 uid.bv_val = strrchr( out.bv_val, '#' );
992 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
994 rc = bitStringValidate( NULL, &uid );
995 if ( rc == LDAP_SUCCESS ) {
996 uid.bv_val[-1] = '\0';
997 out.bv_len -= uid.bv_len + 1;
1003 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1005 if( rc != LDAP_SUCCESS ) {
1006 slap_sl_free( out.bv_val, ctx );
1007 return LDAP_INVALID_SYNTAX;
1013 tmp = ch_realloc( normalized->bv_val,
1014 normalized->bv_len + uid.bv_len
1015 + STRLENOF("#") + 1 );
1016 if ( tmp == NULL ) {
1017 ber_memfree_x( normalized->bv_val, ctx );
1021 normalized->bv_val = tmp;
1023 /* insert the separator */
1024 normalized->bv_val[normalized->bv_len++] = '#';
1026 /* append the UID */
1027 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1028 uid.bv_val, uid.bv_len );
1029 normalized->bv_len += uid.bv_len;
1032 normalized->bv_val[normalized->bv_len] = '\0';
1035 slap_sl_free( out.bv_val, ctx );
1038 return LDAP_SUCCESS;
1047 struct berval *value,
1048 void *assertedValue )
1051 struct berval *asserted = (struct berval *) assertedValue;
1052 struct berval assertedDN = *asserted;
1053 struct berval assertedUID = BER_BVNULL;
1054 struct berval valueDN = BER_BVNULL;
1055 struct berval valueUID = BER_BVNULL;
1057 if ( !BER_BVISEMPTY( asserted ) ) {
1058 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1059 if ( !BER_BVISNULL( &assertedUID ) ) {
1060 assertedUID.bv_val++;
1061 assertedUID.bv_len = assertedDN.bv_len
1062 - ( assertedUID.bv_val - assertedDN.bv_val );
1064 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1065 assertedDN.bv_len -= assertedUID.bv_len + 1;
1068 BER_BVZERO( &assertedUID );
1073 if ( !BER_BVISEMPTY( value ) ) {
1076 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1077 if ( !BER_BVISNULL( &valueUID ) ) {
1079 valueUID.bv_len = valueDN.bv_len
1080 - ( valueUID.bv_val - valueDN.bv_val );
1082 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1083 valueDN.bv_len -= valueUID.bv_len + 1;
1086 BER_BVZERO( &valueUID );
1091 if( valueUID.bv_len && assertedUID.bv_len ) {
1092 match = valueUID.bv_len - assertedUID.bv_len;
1095 return LDAP_SUCCESS;
1098 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1101 return LDAP_SUCCESS;
1105 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1109 * Handling boolean syntax and matching is quite rigid.
1110 * A more flexible approach would be to allow a variety
1111 * of strings to be normalized and prettied into TRUE
1119 /* very unforgiving validation, requires no normalization
1120 * before simplistic matching
1123 if( in->bv_len == 4 ) {
1124 if( bvmatch( in, &slap_true_bv ) ) {
1125 return LDAP_SUCCESS;
1127 } else if( in->bv_len == 5 ) {
1128 if( bvmatch( in, &slap_false_bv ) ) {
1129 return LDAP_SUCCESS;
1133 return LDAP_INVALID_SYNTAX;
1142 struct berval *value,
1143 void *assertedValue )
1145 /* simplistic matching allowed by rigid validation */
1146 struct berval *asserted = (struct berval *) assertedValue;
1147 *matchp = value->bv_len != asserted->bv_len;
1148 return LDAP_SUCCESS;
1151 /*-------------------------------------------------------------------
1152 LDAP/X.500 string syntax / matching rules have a few oddities. This
1153 comment attempts to detail how slapd(8) treats them.
1156 StringSyntax X.500 LDAP Matching/Comments
1157 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1158 PrintableString subset subset i/e + ignore insignificant spaces
1159 PrintableString subset subset i/e + ignore insignificant spaces
1160 NumericString subset subset ignore all spaces
1161 IA5String ASCII ASCII i/e + ignore insignificant spaces
1162 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1164 TelephoneNumber subset subset i + ignore all spaces and "-"
1166 See draft-ietf-ldapbis-strpro for details (once published).
1170 In X.500(93), a directory string can be either a PrintableString,
1171 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1172 In later versions, more CHOICEs were added. In all cases the string
1175 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1176 A directory string cannot be zero length.
1178 For matching, there are both case ignore and exact rules. Both
1179 also require that "insignificant" spaces be ignored.
1180 spaces before the first non-space are ignored;
1181 spaces after the last non-space are ignored;
1182 spaces after a space are ignored.
1183 Note: by these rules (and as clarified in X.520), a string of only
1184 spaces is to be treated as if held one space, not empty (which
1185 would be a syntax error).
1188 In ASN.1, numeric string is just a string of digits and spaces
1189 and could be empty. However, in X.500, all attribute values of
1190 numeric string carry a non-empty constraint. For example:
1192 internationalISDNNumber ATTRIBUTE ::= {
1193 WITH SYNTAX InternationalISDNNumber
1194 EQUALITY MATCHING RULE numericStringMatch
1195 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1196 ID id-at-internationalISDNNumber }
1197 InternationalISDNNumber ::=
1198 NumericString (SIZE(1..ub-international-isdn-number))
1200 Unforunately, some assertion values are don't carry the same
1201 constraint (but its unclear how such an assertion could ever
1202 be true). In LDAP, there is one syntax (numericString) not two
1203 (numericString with constraint, numericString without constraint).
1204 This should be treated as numericString with non-empty constraint.
1205 Note that while someone may have no ISDN number, there are no ISDN
1206 numbers which are zero length.
1208 In matching, spaces are ignored.
1211 In ASN.1, Printable string is just a string of printable characters
1212 and can be empty. In X.500, semantics much like NumericString (see
1213 serialNumber for a like example) excepting uses insignificant space
1214 handling instead of ignore all spaces.
1217 Basically same as PrintableString. There are no examples in X.500,
1218 but same logic applies. So we require them to be non-empty as
1221 -------------------------------------------------------------------*/
1230 unsigned char *u = (unsigned char *)in->bv_val;
1232 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1233 /* directory strings cannot be empty */
1234 return LDAP_INVALID_SYNTAX;
1237 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1238 /* get the length indicated by the first byte */
1239 len = LDAP_UTF8_CHARLEN2( u, len );
1241 /* very basic checks */
1244 if( (u[5] & 0xC0) != 0x80 ) {
1245 return LDAP_INVALID_SYNTAX;
1248 if( (u[4] & 0xC0) != 0x80 ) {
1249 return LDAP_INVALID_SYNTAX;
1252 if( (u[3] & 0xC0) != 0x80 ) {
1253 return LDAP_INVALID_SYNTAX;
1256 if( (u[2] & 0xC0 )!= 0x80 ) {
1257 return LDAP_INVALID_SYNTAX;
1260 if( (u[1] & 0xC0) != 0x80 ) {
1261 return LDAP_INVALID_SYNTAX;
1264 /* CHARLEN already validated it */
1267 return LDAP_INVALID_SYNTAX;
1270 /* make sure len corresponds with the offset
1271 to the next character */
1272 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1276 return LDAP_INVALID_SYNTAX;
1279 return LDAP_SUCCESS;
1283 UTF8StringNormalize(
1288 struct berval *normalized,
1291 struct berval tmp, nvalue;
1295 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1297 if( val->bv_val == NULL ) {
1298 /* assume we're dealing with a syntax (e.g., UTF8String)
1299 * which allows empty strings
1301 normalized->bv_len = 0;
1302 normalized->bv_val = NULL;
1303 return LDAP_SUCCESS;
1306 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1307 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1308 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1309 ? LDAP_UTF8_APPROX : 0;
1311 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1316 /* collapse spaces (in place) */
1318 nvalue.bv_val = tmp.bv_val;
1320 wasspace=1; /* trim leading spaces */
1321 for( i=0; i<tmp.bv_len; i++) {
1322 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1323 if( wasspace++ == 0 ) {
1324 /* trim repeated spaces */
1325 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1329 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1333 if( nvalue.bv_len ) {
1335 /* last character was a space, trim it */
1338 nvalue.bv_val[nvalue.bv_len] = '\0';
1341 /* string of all spaces is treated as one space */
1342 nvalue.bv_val[0] = ' ';
1343 nvalue.bv_val[1] = '\0';
1347 *normalized = nvalue;
1348 return LDAP_SUCCESS;
1351 #if defined(SLAPD_APPROX_INITIALS)
1352 # define SLAPD_APPROX_DELIMITER "._ "
1353 # define SLAPD_APPROX_WORDLEN 2
1355 # define SLAPD_APPROX_DELIMITER " "
1356 # define SLAPD_APPROX_WORDLEN 1
1365 struct berval *value,
1366 void *assertedValue )
1368 struct berval *nval, *assertv;
1369 char *val, **values, **words, *c;
1370 int i, count, len, nextchunk=0, nextavail=0;
1372 /* Yes, this is necessary */
1373 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1374 if( nval == NULL ) {
1376 return LDAP_SUCCESS;
1379 /* Yes, this is necessary */
1380 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1381 NULL, LDAP_UTF8_APPROX, NULL );
1382 if( assertv == NULL ) {
1385 return LDAP_SUCCESS;
1388 /* Isolate how many words there are */
1389 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1390 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1391 if ( c == NULL ) break;
1396 /* Get a phonetic copy of each word */
1397 words = (char **)ch_malloc( count * sizeof(char *) );
1398 values = (char **)ch_malloc( count * sizeof(char *) );
1399 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1401 values[i] = phonetic(c);
1404 /* Work through the asserted value's words, to see if at least some
1405 of the words are there, in the same order. */
1407 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1408 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1413 #if defined(SLAPD_APPROX_INITIALS)
1414 else if( len == 1 ) {
1415 /* Single letter words need to at least match one word's initial */
1416 for( i=nextavail; i<count; i++ )
1417 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1424 /* Isolate the next word in the asserted value and phonetic it */
1425 assertv->bv_val[nextchunk+len] = '\0';
1426 val = phonetic( assertv->bv_val + nextchunk );
1428 /* See if this phonetic chunk is in the remaining words of *value */
1429 for( i=nextavail; i<count; i++ ){
1430 if( !strcmp( val, values[i] ) ){
1438 /* This chunk in the asserted value was NOT within the *value. */
1444 /* Go on to the next word in the asserted value */
1448 /* If some of the words were seen, call it a match */
1449 if( nextavail > 0 ) {
1456 /* Cleanup allocs */
1457 ber_bvfree( assertv );
1458 for( i=0; i<count; i++ ) {
1459 ch_free( values[i] );
1465 return LDAP_SUCCESS;
1474 struct berval *prefix,
1480 int i,j, len, wordcount, keycount=0;
1481 struct berval *newkeys;
1482 BerVarray keys=NULL;
1484 for( j=0; values[j].bv_val != NULL; j++ ) {
1485 struct berval val = BER_BVNULL;
1486 /* Yes, this is necessary */
1487 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1488 assert( val.bv_val != NULL );
1490 /* Isolate how many words there are. There will be a key for each */
1491 for( wordcount = 0, c = val.bv_val; *c; c++) {
1492 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1493 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1495 if (*c == '\0') break;
1499 /* Allocate/increase storage to account for new keys */
1500 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1501 * sizeof(struct berval) );
1502 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1503 if( keys ) ch_free( keys );
1506 /* Get a phonetic copy of each word */
1507 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1509 if( len < SLAPD_APPROX_WORDLEN ) continue;
1510 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1515 ber_memfree( val.bv_val );
1517 keys[keycount].bv_val = NULL;
1520 return LDAP_SUCCESS;
1529 struct berval *prefix,
1530 void * assertedValue,
1539 /* Yes, this is necessary */
1540 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1541 NULL, LDAP_UTF8_APPROX, NULL );
1542 if( val == NULL || val->bv_val == NULL ) {
1543 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1544 keys[0].bv_val = NULL;
1547 return LDAP_SUCCESS;
1550 /* Isolate how many words there are. There will be a key for each */
1551 for( count = 0,c = val->bv_val; *c; c++) {
1552 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1553 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1555 if (*c == '\0') break;
1559 /* Allocate storage for new keys */
1560 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1562 /* Get a phonetic copy of each word */
1563 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1565 if( len < SLAPD_APPROX_WORDLEN ) continue;
1566 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1572 keys[count].bv_val = NULL;
1575 return LDAP_SUCCESS;
1578 /* Remove all spaces and '-' characters */
1580 telephoneNumberNormalize(
1585 struct berval *normalized,
1590 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1592 /* validator should have refused an empty string */
1593 assert( val->bv_len );
1595 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1597 for( p = val->bv_val; *p; p++ ) {
1598 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1604 normalized->bv_len = q - normalized->bv_val;
1606 if( normalized->bv_len == 0 ) {
1607 slap_sl_free( normalized->bv_val, ctx );
1608 normalized->bv_val = NULL;
1609 return LDAP_INVALID_SYNTAX;
1612 return LDAP_SUCCESS;
1620 struct berval val = *in;
1622 if( val.bv_len == 0 ) {
1623 /* disallow empty strings */
1624 return LDAP_INVALID_SYNTAX;
1627 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1628 if ( val.bv_len == 1 ) {
1629 return LDAP_SUCCESS;
1632 if ( val.bv_val[0] == '0' ) {
1639 while ( OID_LEADCHAR( val.bv_val[0] )) {
1643 if ( val.bv_len == 0 ) {
1644 return LDAP_SUCCESS;
1648 if( !OID_SEPARATOR( val.bv_val[0] )) {
1656 return LDAP_INVALID_SYNTAX;
1665 struct berval val = *in;
1667 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1669 if ( val.bv_val[0] == '-' ) {
1673 if( val.bv_len == 0 ) { /* bare "-" */
1674 return LDAP_INVALID_SYNTAX;
1677 if( val.bv_val[0] == '0' ) { /* "-0" */
1678 return LDAP_INVALID_SYNTAX;
1681 } else if ( val.bv_val[0] == '0' ) {
1682 if( val.bv_len > 1 ) { /* "0<more>" */
1683 return LDAP_INVALID_SYNTAX;
1686 return LDAP_SUCCESS;
1689 for( i=0; i < val.bv_len; i++ ) {
1690 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1691 return LDAP_INVALID_SYNTAX;
1695 return LDAP_SUCCESS;
1704 struct berval *value,
1705 void *assertedValue )
1707 struct berval *asserted = (struct berval *) assertedValue;
1708 int vsign = 1, asign = 1; /* default sign = '+' */
1713 if( v.bv_val[0] == '-' ) {
1719 if( v.bv_len == 0 ) vsign = 0;
1722 if( a.bv_val[0] == '-' ) {
1728 if( a.bv_len == 0 ) vsign = 0;
1730 match = vsign - asign;
1732 match = ( v.bv_len != a.bv_len
1733 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1734 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1735 if( vsign < 0 ) match = -match;
1739 return LDAP_SUCCESS;
1743 countryStringValidate(
1745 struct berval *val )
1747 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1749 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1750 return LDAP_INVALID_SYNTAX;
1752 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1753 return LDAP_INVALID_SYNTAX;
1756 return LDAP_SUCCESS;
1760 printableStringValidate(
1762 struct berval *val )
1766 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1768 for(i=0; i < val->bv_len; i++) {
1769 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1770 return LDAP_INVALID_SYNTAX;
1774 return LDAP_SUCCESS;
1778 printablesStringValidate(
1780 struct berval *val )
1784 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1786 for(i=0,len=0; i < val->bv_len; i++) {
1787 int c = val->bv_val[i];
1791 return LDAP_INVALID_SYNTAX;
1795 } else if ( SLAP_PRINTABLE(c) ) {
1798 return LDAP_INVALID_SYNTAX;
1803 return LDAP_INVALID_SYNTAX;
1806 return LDAP_SUCCESS;
1812 struct berval *val )
1816 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1818 for(i=0; i < val->bv_len; i++) {
1819 if( !LDAP_ASCII(val->bv_val[i]) ) {
1820 return LDAP_INVALID_SYNTAX;
1824 return LDAP_SUCCESS;
1833 struct berval *normalized,
1837 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1839 assert( val->bv_len );
1841 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1845 /* Ignore initial whitespace */
1846 while ( ASCII_SPACE( *p ) ) p++;
1848 normalized->bv_val = ber_strdup_x( p, ctx );
1849 p = q = normalized->bv_val;
1852 if ( ASCII_SPACE( *p ) ) {
1855 /* Ignore the extra whitespace */
1856 while ( ASCII_SPACE( *p ) ) {
1860 } else if ( casefold ) {
1861 /* Most IA5 rules require casefolding */
1862 *q++ = TOLOWER(*p); p++;
1869 assert( normalized->bv_val <= p );
1873 * If the string ended in space, backup the pointer one
1874 * position. One is enough because the above loop collapsed
1875 * all whitespace to a single space.
1877 if ( ASCII_SPACE( q[-1] ) ) --q;
1879 /* null terminate */
1882 normalized->bv_len = q - normalized->bv_val;
1883 if( normalized->bv_len == 0 ) {
1884 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1885 normalized->bv_val[0] = ' ';
1886 normalized->bv_val[1] = '\0';
1887 normalized->bv_len = 1;
1890 return LDAP_SUCCESS;
1899 if( in->bv_len != 36 ) {
1900 return LDAP_INVALID_SYNTAX;
1903 for( i=0; i<36; i++ ) {
1909 if( in->bv_val[i] != '-' ) {
1910 return LDAP_INVALID_SYNTAX;
1914 if( !ASCII_HEX( in->bv_val[i]) ) {
1915 return LDAP_INVALID_SYNTAX;
1920 return LDAP_SUCCESS;
1929 struct berval *normalized,
1932 unsigned char octet = '\0';
1935 normalized->bv_len = 16;
1936 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1938 for( i=0, j=0; i<36; i++ ) {
1939 unsigned char nibble;
1940 if( val->bv_val[i] == '-' ) {
1943 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1944 nibble = val->bv_val[i] - '0';
1946 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1947 nibble = val->bv_val[i] - ('a'-10);
1949 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1950 nibble = val->bv_val[i] - ('A'-10);
1953 slap_sl_free( normalized->bv_val, ctx );
1954 return LDAP_INVALID_SYNTAX;
1959 normalized->bv_val[j>>1] = octet;
1961 octet = nibble << 4;
1966 normalized->bv_val[normalized->bv_len] = 0;
1967 return LDAP_SUCCESS;
1973 numericStringValidate(
1979 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1981 for(i=0; i < in->bv_len; i++) {
1982 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1983 return LDAP_INVALID_SYNTAX;
1987 return LDAP_SUCCESS;
1991 numericStringNormalize(
1996 struct berval *normalized,
1999 /* removal all spaces */
2002 assert( val->bv_len );
2004 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2007 q = normalized->bv_val;
2010 if ( ASCII_SPACE( *p ) ) {
2011 /* Ignore whitespace */
2018 /* we should have copied no more then is in val */
2019 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2021 /* null terminate */
2024 normalized->bv_len = q - normalized->bv_val;
2026 if( normalized->bv_len == 0 ) {
2027 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2028 normalized->bv_val[0] = ' ';
2029 normalized->bv_val[1] = '\0';
2030 normalized->bv_len = 1;
2033 return LDAP_SUCCESS;
2037 * Integer conversion macros that will use the largest available
2040 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2041 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2042 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2043 # define SLAP_LONG_MAX LLONG_MAX
2044 # define SLAP_LONG_MIN LLONG_MIN
2045 # define SLAP_LONG long long
2047 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2048 # define SLAP_LONG_MAX LONG_MAX
2049 # define SLAP_LONG_MIN LONG_MIN
2050 # define SLAP_LONG long
2051 #endif /* HAVE_STRTOLL ... */
2059 struct berval *value,
2060 void *assertedValue )
2062 SLAP_LONG lValue, lAssertedValue;
2064 /* safe to assume integers are NUL terminated? */
2065 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2066 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2069 return LDAP_CONSTRAINT_VIOLATION;
2072 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2074 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2077 return LDAP_CONSTRAINT_VIOLATION;
2080 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2081 return LDAP_SUCCESS;
2090 struct berval *value,
2091 void *assertedValue )
2093 SLAP_LONG lValue, lAssertedValue;
2095 /* safe to assume integers are NUL terminated? */
2096 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2097 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2100 return LDAP_CONSTRAINT_VIOLATION;
2103 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2105 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2108 return LDAP_CONSTRAINT_VIOLATION;
2111 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2112 return LDAP_SUCCESS;
2116 serialNumberAndIssuerValidate(
2123 struct berval sn, i;
2124 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2126 i.bv_val = strchr( in->bv_val, '$' );
2127 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2129 sn.bv_val = in->bv_val;
2130 sn.bv_len = i.bv_val - in->bv_val;
2133 i.bv_len = in->bv_len - (sn.bv_len + 1);
2135 /* validate serial number (strict for now) */
2136 for( n=0; n < sn.bv_len; n++ ) {
2137 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2141 rc = dnValidate( NULL, &i );
2142 if( rc ) return LDAP_INVALID_SYNTAX;
2144 return LDAP_SUCCESS;
2148 serialNumberAndIssuerPretty(
2157 struct berval sn, i, newi;
2162 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2163 val->bv_val, 0, 0 );
2165 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2167 i.bv_val = strchr( val->bv_val, '$' );
2168 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2170 sn.bv_val = val->bv_val;
2171 sn.bv_len = i.bv_val - val->bv_val;
2174 i.bv_len = val->bv_len - (sn.bv_len + 1);
2176 /* eat leading zeros */
2177 for( n=0; n < (sn.bv_len-1); n++ ) {
2178 if( sn.bv_val[n] != '0' ) break;
2183 for( n=0; n < sn.bv_len; n++ ) {
2184 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2188 rc = dnPretty( syntax, &i, &newi, ctx );
2189 if( rc ) return LDAP_INVALID_SYNTAX;
2191 /* make room from sn + "$" */
2192 out->bv_len = sn.bv_len + newi.bv_len + 1;
2193 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2195 if( out->bv_val == NULL ) {
2196 slap_sl_free( newi.bv_val, ctx );
2200 /* push issuer over */
2201 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2202 /* insert sn and "$" */
2203 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2204 out->bv_val[sn.bv_len] = '$';
2206 out->bv_val[out->bv_len] = '\0';
2208 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2209 out->bv_val, 0, 0 );
2211 return LDAP_SUCCESS;
2215 * This routine is called by certificateExactNormalize when
2216 * certificateExactNormalize receives a search string instead of
2217 * a certificate. This routine checks if the search value is valid
2218 * and then returns the normalized value
2221 serialNumberAndIssuerNormalize(
2232 struct berval sn, i, newi;
2237 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2238 val->bv_val, 0, 0 );
2240 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2242 i.bv_val = strchr( val->bv_val, '$' );
2243 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2245 sn.bv_val = val->bv_val;
2246 sn.bv_len = i.bv_val - val->bv_val;
2249 i.bv_len = val->bv_len - (sn.bv_len + 1);
2251 /* eat leading zeros */
2252 for( n=0; n < (sn.bv_len-1); n++ ) {
2253 if( sn.bv_val[n] != '0' ) break;
2258 for( n=0; n < sn.bv_len; n++ ) {
2259 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2260 return LDAP_INVALID_SYNTAX;
2265 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2266 if( rc ) return LDAP_INVALID_SYNTAX;
2268 /* make room from sn + "$" */
2269 out->bv_len = sn.bv_len + newi.bv_len + 1;
2270 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2272 if( out->bv_val == NULL ) {
2273 slap_sl_free( newi.bv_val, ctx );
2277 /* push issuer over */
2278 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2279 /* insert sn and "$" */
2280 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2281 out->bv_val[sn.bv_len] = '$';
2283 out->bv_val[out->bv_len] = '\0';
2285 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2286 out->bv_val, 0, 0 );
2293 certificateExactNormalize(
2298 struct berval *normalized,
2301 int rc = LDAP_INVALID_SYNTAX;
2303 char *serial = NULL;
2304 ber_len_t seriallen;
2305 struct berval issuer_dn = BER_BVNULL;
2306 X509_NAME *name = NULL;
2307 ASN1_INTEGER *sn = NULL;
2310 if( val->bv_len == 0 ) goto done;
2312 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2313 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2316 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2318 p = (unsigned char *)val->bv_val;
2319 xcert = d2i_X509( NULL, &p, val->bv_len);
2320 if( xcert == NULL ) goto done;
2322 sn=X509_get_serialNumber(xcert);
2323 if ( sn == NULL ) goto done;
2324 serial=i2s_ASN1_INTEGER(0, sn );
2325 if( serial == NULL ) goto done;
2326 seriallen=strlen(serial);
2328 name=X509_get_issuer_name(xcert);
2329 if( name == NULL ) goto done;
2330 rc = dnX509normalize( name, &issuer_dn );
2331 if( rc != LDAP_SUCCESS ) goto done;
2333 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2334 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2335 p = (unsigned char *)normalized->bv_val;
2336 AC_MEMCPY(p, serial, seriallen);
2339 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2340 p += issuer_dn.bv_len;
2343 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2344 normalized->bv_val, NULL, NULL );
2347 if (xcert) X509_free(xcert);
2348 if (serial) ch_free(serial);
2349 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2353 #endif /* HAVE_TLS */
2356 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2357 /* slight optimization - does not need the start parameter */
2358 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2363 check_time_syntax (struct berval *val,
2366 struct berval *fraction)
2369 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2370 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2371 * GeneralizedTime supports leap seconds, UTCTime does not.
2373 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2374 static const int mdays[2][12] = {
2375 /* non-leap years */
2376 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2378 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2381 int part, c, c1, c2, tzoffset, leapyear = 0;
2384 e = p + val->bv_len;
2386 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2387 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2389 for (part = start; part < 7 && p < e; part++) {
2391 if (!ASCII_DIGIT(c1)) {
2396 return LDAP_INVALID_SYNTAX;
2399 if (!ASCII_DIGIT(c)) {
2400 return LDAP_INVALID_SYNTAX;
2402 c += c1 * 10 - '0' * 11;
2403 if ((part | 1) == 3) {
2406 return LDAP_INVALID_SYNTAX;
2409 if (c >= ceiling[part]) {
2410 if (! (c == 60 && part == 6 && start == 0))
2411 return LDAP_INVALID_SYNTAX;
2415 if (part < 5 + start) {
2416 return LDAP_INVALID_SYNTAX;
2418 for (; part < 9; part++) {
2422 /* leapyear check for the Gregorian calendar (year>1581) */
2423 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2427 if (parts[3] >= mdays[leapyear][parts[2]]) {
2428 return LDAP_INVALID_SYNTAX;
2432 fraction->bv_val = p;
2433 fraction->bv_len = 0;
2434 if (p < e && (*p == '.' || *p == ',')) {
2436 while (++p < e && ASCII_DIGIT(*p)) {
2439 if (p - fraction->bv_val == 1) {
2440 return LDAP_INVALID_SYNTAX;
2442 for (end_num = p; end_num[-1] == '0'; --end_num) {
2445 c = end_num - fraction->bv_val;
2446 if (c != 1) fraction->bv_len = c;
2452 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2458 return LDAP_INVALID_SYNTAX;
2464 for (part = 7; part < 9 && p < e; part++) {
2466 if (!ASCII_DIGIT(c1)) {
2471 return LDAP_INVALID_SYNTAX;
2474 if (!ASCII_DIGIT(c2)) {
2475 return LDAP_INVALID_SYNTAX;
2477 parts[part] = c1 * 10 + c2 - '0' * 11;
2478 if (parts[part] >= ceiling[part]) {
2479 return LDAP_INVALID_SYNTAX;
2482 if (part < 8 + start) {
2483 return LDAP_INVALID_SYNTAX;
2486 if (tzoffset == '-') {
2487 /* negative offset to UTC, ie west of Greenwich */
2488 parts[4] += parts[7];
2489 parts[5] += parts[8];
2490 /* offset is just hhmm, no seconds */
2491 for (part = 6; --part >= 0; ) {
2495 c = mdays[leapyear][parts[2]];
2497 if (parts[part] >= c) {
2499 return LDAP_INVALID_SYNTAX;
2504 } else if (part != 5) {
2509 /* positive offset to UTC, ie east of Greenwich */
2510 parts[4] -= parts[7];
2511 parts[5] -= parts[8];
2512 for (part = 6; --part >= 0; ) {
2513 if (parts[part] < 0) {
2515 return LDAP_INVALID_SYNTAX;
2520 /* make first arg to % non-negative */
2521 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2526 } else if (part != 5) {
2533 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2536 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2543 struct berval *normalized )
2547 rc = check_time_syntax(val, 1, parts, NULL);
2548 if (rc != LDAP_SUCCESS) {
2552 normalized->bv_val = ch_malloc( 14 );
2553 if ( normalized->bv_val == NULL ) {
2554 return LBER_ERROR_MEMORY;
2557 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2558 parts[1], parts[2] + 1, parts[3] + 1,
2559 parts[4], parts[5], parts[6] );
2560 normalized->bv_len = 13;
2562 return LDAP_SUCCESS;
2572 return check_time_syntax(in, 1, parts, NULL);
2575 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2578 generalizedTimeValidate(
2583 struct berval fraction;
2584 return check_time_syntax(in, 0, parts, &fraction);
2588 generalizedTimeNormalize(
2593 struct berval *normalized,
2598 struct berval fraction;
2600 rc = check_time_syntax(val, 0, parts, &fraction);
2601 if (rc != LDAP_SUCCESS) {
2605 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2606 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2607 if ( normalized->bv_val == NULL ) {
2608 return LBER_ERROR_MEMORY;
2611 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2612 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2613 parts[4], parts[5], parts[6] );
2614 if ( fraction.bv_len ) {
2615 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2616 fraction.bv_val, fraction.bv_len );
2617 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2619 strcpy( normalized->bv_val + len-1, "Z" );
2620 normalized->bv_len = len;
2622 return LDAP_SUCCESS;
2626 generalizedTimeOrderingMatch(
2631 struct berval *value,
2632 void *assertedValue )
2634 struct berval *asserted = (struct berval *) assertedValue;
2635 ber_len_t v_len = value->bv_len;
2636 ber_len_t av_len = asserted->bv_len;
2638 /* ignore trailing 'Z' when comparing */
2639 int match = memcmp( value->bv_val, asserted->bv_val,
2640 (v_len < av_len ? v_len : av_len) - 1 );
2641 if ( match == 0 ) match = v_len - av_len;
2644 return LDAP_SUCCESS;
2648 deliveryMethodValidate(
2650 struct berval *val )
2653 #define LENOF(s) (sizeof(s)-1)
2654 struct berval tmp = *val;
2656 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2657 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2658 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2661 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2663 switch( tmp.bv_val[0] ) {
2666 if(( tmp.bv_len >= LENOF("any") ) &&
2667 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2669 tmp.bv_len -= LENOF("any");
2670 tmp.bv_val += LENOF("any");
2673 return LDAP_INVALID_SYNTAX;
2677 if(( tmp.bv_len >= LENOF("mhs") ) &&
2678 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2680 tmp.bv_len -= LENOF("mhs");
2681 tmp.bv_val += LENOF("mhs");
2684 return LDAP_INVALID_SYNTAX;
2688 if(( tmp.bv_len >= LENOF("physical") ) &&
2689 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2691 tmp.bv_len -= LENOF("physical");
2692 tmp.bv_val += LENOF("physical");
2695 return LDAP_INVALID_SYNTAX;
2698 case 'T': /* telex or teletex or telephone */
2699 if(( tmp.bv_len >= LENOF("telex") ) &&
2700 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2702 tmp.bv_len -= LENOF("telex");
2703 tmp.bv_val += LENOF("telex");
2706 if(( tmp.bv_len >= LENOF("teletex") ) &&
2707 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2709 tmp.bv_len -= LENOF("teletex");
2710 tmp.bv_val += LENOF("teletex");
2713 if(( tmp.bv_len >= LENOF("telephone") ) &&
2714 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2716 tmp.bv_len -= LENOF("telephone");
2717 tmp.bv_val += LENOF("telephone");
2720 return LDAP_INVALID_SYNTAX;
2723 case 'G': /* g3fax or g4fax */
2724 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2725 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2726 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2728 tmp.bv_len -= LENOF("g3fax");
2729 tmp.bv_val += LENOF("g3fax");
2732 return LDAP_INVALID_SYNTAX;
2736 if(( tmp.bv_len >= LENOF("ia5") ) &&
2737 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2739 tmp.bv_len -= LENOF("ia5");
2740 tmp.bv_val += LENOF("ia5");
2743 return LDAP_INVALID_SYNTAX;
2747 if(( tmp.bv_len >= LENOF("videotex") ) &&
2748 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2750 tmp.bv_len -= LENOF("videotex");
2751 tmp.bv_val += LENOF("videotex");
2754 return LDAP_INVALID_SYNTAX;
2757 return LDAP_INVALID_SYNTAX;
2760 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2762 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2766 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2770 return LDAP_INVALID_SYNTAX;
2772 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2781 nisNetgroupTripleValidate(
2783 struct berval *val )
2788 if ( val->bv_len == 0 ) {
2789 return LDAP_INVALID_SYNTAX;
2792 p = (char *)val->bv_val;
2793 e = p + val->bv_len;
2795 if ( *p != '(' /*')'*/ ) {
2796 return LDAP_INVALID_SYNTAX;
2799 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2803 return LDAP_INVALID_SYNTAX;
2806 } else if ( !AD_CHAR( *p ) ) {
2807 return LDAP_INVALID_SYNTAX;
2811 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2812 return LDAP_INVALID_SYNTAX;
2818 return LDAP_INVALID_SYNTAX;
2821 return LDAP_SUCCESS;
2825 bootParameterValidate(
2827 struct berval *val )
2831 if ( val->bv_len == 0 ) {
2832 return LDAP_INVALID_SYNTAX;
2835 p = (char *)val->bv_val;
2836 e = p + val->bv_len;
2839 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2840 if ( !AD_CHAR( *p ) ) {
2841 return LDAP_INVALID_SYNTAX;
2846 return LDAP_INVALID_SYNTAX;
2850 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2851 if ( !AD_CHAR( *p ) ) {
2852 return LDAP_INVALID_SYNTAX;
2857 return LDAP_INVALID_SYNTAX;
2861 for ( p++; p < e; p++ ) {
2862 if ( !SLAP_PRINTABLE( *p ) ) {
2863 return LDAP_INVALID_SYNTAX;
2867 return LDAP_SUCCESS;
2871 firstComponentNormalize(
2876 struct berval *normalized,
2883 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2884 ber_dupbv_x( normalized, val, ctx );
2885 return LDAP_SUCCESS;
2888 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2890 if( val->bv_val[0] != '(' /*')'*/ &&
2891 val->bv_val[0] != '{' /*'}'*/ )
2893 return LDAP_INVALID_SYNTAX;
2896 /* trim leading white space */
2898 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2904 /* grab next word */
2905 comp.bv_val = &val->bv_val[len];
2906 len = val->bv_len - len;
2908 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2914 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2915 rc = numericoidValidate( NULL, &comp );
2916 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2917 rc = integerValidate( NULL, &comp );
2919 rc = LDAP_INVALID_SYNTAX;
2923 if( rc == LDAP_SUCCESS ) {
2924 ber_dupbv_x( normalized, &comp, ctx );
2931 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2932 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2934 static slap_syntax_defs_rec syntax_defs[] = {
2935 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2936 X_BINARY X_NOT_H_R ")",
2937 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2938 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2940 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2942 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2944 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2945 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2947 SLAP_SYNTAX_BER, berValidate, NULL},
2948 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2949 0, bitStringValidate, NULL },
2950 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2951 0, booleanValidate, NULL},
2952 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2953 X_BINARY X_NOT_H_R ")",
2954 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2955 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2956 X_BINARY X_NOT_H_R ")",
2957 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2958 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2959 X_BINARY X_NOT_H_R ")",
2960 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2961 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2962 0, countryStringValidate, NULL},
2963 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2964 0, dnValidate, dnPretty},
2965 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
2966 0, rdnValidate, rdnPretty},
2967 #ifdef LDAP_COMP_MATCH
2968 {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
2969 0, componentFilterValidate, NULL},
2971 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2973 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2974 0, deliveryMethodValidate, NULL},
2975 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2976 0, UTF8StringValidate, NULL},
2977 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2979 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2981 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2983 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2985 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2987 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2988 0, printablesStringValidate, NULL},
2989 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2990 SLAP_SYNTAX_BLOB, NULL, NULL},
2991 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2992 0, generalizedTimeValidate, NULL},
2993 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2995 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2996 0, IA5StringValidate, NULL},
2997 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2998 0, integerValidate, NULL},
2999 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3000 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3001 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3003 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3005 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3007 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3009 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3011 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3012 0, nameUIDValidate, nameUIDPretty },
3013 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3015 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3016 0, numericStringValidate, NULL},
3017 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3019 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3020 0, numericoidValidate, NULL},
3021 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3022 0, IA5StringValidate, NULL},
3023 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3024 0, blobValidate, NULL},
3025 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3026 0, UTF8StringValidate, NULL},
3027 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3029 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3031 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3032 0, printableStringValidate, NULL},
3033 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3034 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3035 0, subtreeSpecificationValidate, NULL},
3036 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3037 X_BINARY X_NOT_H_R ")",
3038 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3039 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3040 0, printableStringValidate, NULL},
3041 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3043 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3044 0, printablesStringValidate, NULL},
3045 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3046 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3047 0, utcTimeValidate, NULL},
3049 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3051 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3053 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3055 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3057 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3060 /* RFC 2307 NIS Syntaxes */
3061 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3062 0, nisNetgroupTripleValidate, NULL},
3063 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3064 0, bootParameterValidate, NULL},
3066 /* From PKIX *//* This OID is not published yet. */
3067 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3069 serialNumberAndIssuerValidate,
3070 serialNumberAndIssuerPretty},
3072 #ifdef SLAPD_ACI_ENABLED
3073 /* OpenLDAP Experimental Syntaxes */
3074 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3076 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3080 #ifdef SLAPD_AUTHPASSWD
3081 /* needs updating */
3082 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3083 SLAP_SYNTAX_HIDE, NULL, NULL},
3086 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3087 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3089 /* OpenLDAP Void Syntax */
3090 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3091 SLAP_SYNTAX_HIDE, inValidate, NULL},
3092 {NULL, 0, NULL, NULL}
3095 char *certificateExactMatchSyntaxes[] = {
3096 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3099 char *directoryStringSyntaxes[] = {
3100 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3103 char *integerFirstComponentMatchSyntaxes[] = {
3104 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3105 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3108 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3109 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3110 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3111 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3112 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3113 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3114 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3115 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3116 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3121 * Other matching rules in X.520 that we do not use (yet):
3123 * 2.5.13.25 uTCTimeMatch
3124 * 2.5.13.26 uTCTimeOrderingMatch
3125 * 2.5.13.31* directoryStringFirstComponentMatch
3126 * 2.5.13.32* wordMatch
3127 * 2.5.13.33* keywordMatch
3128 * 2.5.13.36 certificatePairExactMatch
3129 * 2.5.13.37 certificatePairMatch
3130 * 2.5.13.38 certificateListExactMatch
3131 * 2.5.13.39 certificateListMatch
3132 * 2.5.13.40 algorithmIdentifierMatch
3133 * 2.5.13.41* storedPrefixMatch
3134 * 2.5.13.42 attributeCertificateMatch
3135 * 2.5.13.43 readerAndKeyIDMatch
3136 * 2.5.13.44 attributeIntegrityMatch
3138 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3140 static slap_mrule_defs_rec mrule_defs[] = {
3142 * EQUALITY matching rules must be listed after associated APPROX
3143 * matching rules. So, we list all APPROX matching rules first.
3145 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3146 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3147 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3148 NULL, NULL, directoryStringApproxMatch,
3149 directoryStringApproxIndexer, directoryStringApproxFilter,
3152 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3153 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3154 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3155 NULL, NULL, IA5StringApproxMatch,
3156 IA5StringApproxIndexer, IA5StringApproxFilter,
3160 * Other matching rules
3163 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3164 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3165 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3166 NULL, NULL, octetStringMatch,
3167 octetStringIndexer, octetStringFilter,
3170 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3171 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3172 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3173 NULL, dnNormalize, dnMatch,
3174 octetStringIndexer, octetStringFilter,
3177 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3178 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3179 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3180 NULL, dnNormalize, dnRelativeMatch,
3184 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3185 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3186 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3187 NULL, dnNormalize, dnRelativeMatch,
3191 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3192 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3193 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3194 NULL, dnNormalize, dnRelativeMatch,
3198 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3199 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3200 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3201 NULL, dnNormalize, dnRelativeMatch,
3205 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3206 "SYNTAX 1.2.36.79672281.1.5.0 )",
3207 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3208 NULL, rdnNormalize, rdnMatch,
3209 octetStringIndexer, octetStringFilter,
3212 #ifdef LDAP_COMP_MATCH
3213 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3214 "SYNTAX 1.2.36.79672281.1.5.2 )",
3215 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3216 NULL, NULL , componentFilterMatch,
3217 octetStringIndexer, octetStringFilter,
3221 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3222 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3223 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3224 NULL, UTF8StringNormalize, octetStringMatch,
3225 octetStringIndexer, octetStringFilter,
3226 directoryStringApproxMatchOID },
3228 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3229 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3230 SLAP_MR_ORDERING, directoryStringSyntaxes,
3231 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3233 "caseIgnoreMatch" },
3235 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3236 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3237 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3238 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3239 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3240 "caseIgnoreMatch" },
3242 {"( 2.5.13.5 NAME 'caseExactMatch' "
3243 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3244 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3245 NULL, UTF8StringNormalize, octetStringMatch,
3246 octetStringIndexer, octetStringFilter,
3247 directoryStringApproxMatchOID },
3249 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3250 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3251 SLAP_MR_ORDERING, directoryStringSyntaxes,
3252 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3256 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3257 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3258 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3259 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3260 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3263 {"( 2.5.13.8 NAME 'numericStringMatch' "
3264 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3265 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3266 NULL, numericStringNormalize, octetStringMatch,
3267 octetStringIndexer, octetStringFilter,
3270 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3271 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3272 SLAP_MR_ORDERING, NULL,
3273 NULL, numericStringNormalize, octetStringOrderingMatch,
3275 "numericStringMatch" },
3277 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3278 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3279 SLAP_MR_SUBSTR, NULL,
3280 NULL, numericStringNormalize, octetStringSubstringsMatch,
3281 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3282 "numericStringMatch" },
3284 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3285 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3286 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3287 NULL, NULL, NULL, NULL, NULL, NULL },
3289 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3290 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3291 SLAP_MR_SUBSTR, NULL,
3292 NULL, NULL, NULL, NULL, NULL,
3293 "caseIgnoreListMatch" },
3295 {"( 2.5.13.13 NAME 'booleanMatch' "
3296 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3297 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3298 NULL, NULL, booleanMatch,
3299 octetStringIndexer, octetStringFilter,
3302 {"( 2.5.13.14 NAME 'integerMatch' "
3303 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3304 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3305 NULL, NULL, integerMatch,
3306 octetStringIndexer, octetStringFilter,
3309 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3310 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3311 SLAP_MR_ORDERING, NULL,
3312 NULL, NULL, integerMatch,
3316 {"( 2.5.13.16 NAME 'bitStringMatch' "
3317 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3318 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3319 NULL, NULL, octetStringMatch,
3320 octetStringIndexer, octetStringFilter,
3323 {"( 2.5.13.17 NAME 'octetStringMatch' "
3324 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3325 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3326 NULL, NULL, octetStringMatch,
3327 octetStringIndexer, octetStringFilter,
3330 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3331 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3332 SLAP_MR_ORDERING, NULL,
3333 NULL, NULL, octetStringOrderingMatch,
3335 "octetStringMatch" },
3337 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3338 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3339 SLAP_MR_SUBSTR, NULL,
3340 NULL, NULL, octetStringSubstringsMatch,
3341 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3342 "octetStringMatch" },
3344 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3345 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3346 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3348 telephoneNumberNormalize, octetStringMatch,
3349 octetStringIndexer, octetStringFilter,
3352 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3353 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3354 SLAP_MR_SUBSTR, NULL,
3355 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3356 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3357 "telephoneNumberMatch" },
3359 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3360 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3361 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3362 NULL, NULL, NULL, NULL, NULL, NULL },
3364 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3365 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3366 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3367 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3371 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3373 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3374 NULL, NULL, NULL, NULL, NULL, NULL },
3376 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3377 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3378 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3379 NULL, generalizedTimeNormalize, octetStringMatch,
3383 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3384 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3385 SLAP_MR_ORDERING, NULL,
3386 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3388 "generalizedTimeMatch" },
3390 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3391 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3392 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3393 integerFirstComponentMatchSyntaxes,
3394 NULL, firstComponentNormalize, integerMatch,
3395 octetStringIndexer, octetStringFilter,
3398 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3400 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3401 objectIdentifierFirstComponentMatchSyntaxes,
3402 NULL, firstComponentNormalize, octetStringMatch,
3403 octetStringIndexer, octetStringFilter,
3406 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3407 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3408 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3410 NULL, certificateExactNormalize, octetStringMatch,
3411 octetStringIndexer, octetStringFilter,
3413 NULL, NULL, NULL, NULL, NULL,
3417 {"( 2.5.13.35 NAME 'certificateMatch' "
3418 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3419 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3421 NULL, NULL, octetStringMatch,
3422 octetStringIndexer, octetStringFilter,
3424 NULL, NULL, NULL, NULL, NULL,
3428 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3429 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3430 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3431 NULL, IA5StringNormalize, octetStringMatch,
3432 octetStringIndexer, octetStringFilter,
3433 IA5StringApproxMatchOID },
3435 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3436 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3437 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3438 NULL, IA5StringNormalize, octetStringMatch,
3439 octetStringIndexer, octetStringFilter,
3440 IA5StringApproxMatchOID },
3442 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3443 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3444 SLAP_MR_SUBSTR, NULL,
3445 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3446 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3447 "caseIgnoreIA5Match" },
3449 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3450 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3451 SLAP_MR_SUBSTR, NULL,
3452 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3453 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3454 "caseExactIA5Match" },
3456 #ifdef SLAPD_AUTHPASSWD
3457 /* needs updating */
3458 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3460 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3461 NULL, NULL, authPasswordMatch,
3466 #ifdef SLAPD_ACI_ENABLED
3467 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3468 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3469 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3470 NULL, NULL, OpenLDAPaciMatch,
3475 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3476 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3478 NULL, NULL, integerBitAndMatch,
3482 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3483 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3485 NULL, NULL, integerBitOrMatch,
3489 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3490 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3491 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3492 NULL, UUIDNormalize, octetStringMatch,
3493 octetStringIndexer, octetStringFilter,
3496 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3497 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3498 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3499 NULL, UUIDNormalize, octetStringOrderingMatch,
3500 octetStringIndexer, octetStringFilter,
3503 {NULL, SLAP_MR_NONE, NULL,
3504 NULL, NULL, NULL, NULL, NULL,
3509 slap_schema_init( void )
3514 /* we should only be called once (from main) */
3515 assert( schema_init_done == 0 );
3517 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3518 res = register_syntax( &syntax_defs[i] );
3521 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3522 syntax_defs[i].sd_desc );
3527 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3528 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3529 mrule_defs[i].mrd_compat_syntaxes == NULL )
3532 "slap_schema_init: Ignoring unusable matching rule %s\n",
3533 mrule_defs[i].mrd_desc );
3537 res = register_matching_rule( &mrule_defs[i] );
3541 "slap_schema_init: Error registering matching rule %s\n",
3542 mrule_defs[i].mrd_desc );
3547 res = slap_schema_load();
3548 schema_init_done = 1;
3553 schema_destroy( void )