1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
29 #include "ldap_utf8.h"
32 #include <openssl/x509.h>
33 #include <openssl/err.h>
34 #include <openssl/rsa.h>
35 #include <openssl/crypto.h>
36 #include <openssl/pem.h>
37 #include <openssl/bio.h>
38 #include <openssl/asn1.h>
39 #include <openssl/x509v3.h>
40 #include <openssl/ssl.h>
44 #include "lutil_hash.h"
45 #define HASH_BYTES LUTIL_HASH_BYTES
46 #define HASH_CONTEXT lutil_HASH_CTX
47 #define HASH_Init(c) lutil_HASHInit(c)
48 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
49 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
51 #define OpenLDAPaciMatch NULL
53 /* approx matching rules */
54 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
55 #define directoryStringApproxMatch approxMatch
56 #define directoryStringApproxIndexer approxIndexer
57 #define directoryStringApproxFilter approxFilter
58 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
59 #define IA5StringApproxMatch approxMatch
60 #define IA5StringApproxIndexer approxIndexer
61 #define IA5StringApproxFilter approxFilter
63 /* Change Sequence Number (CSN) - much of this will change */
64 #define csnValidate blobValidate
65 #define csnMatch octetStringMatch
66 #define csnOrderingMatch octetStringOrderingMatch
67 #define csnIndexer generalizedTimeIndexer
68 #define csnFilter generalizedTimeFilter
70 unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
71 unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
72 unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
73 unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
80 /* no value allowed */
81 return LDAP_INVALID_SYNTAX;
89 /* any value allowed */
93 #define berValidate blobValidate
100 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
101 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
108 static int certificateValidate( Syntax *syntax, struct berval *in )
111 unsigned char *p = (unsigned char *)in->bv_val;
113 xcert = d2i_X509(NULL, &p, in->bv_len);
114 if ( !xcert ) return LDAP_INVALID_SYNTAX;
119 #define certificateValidate sequenceValidate
128 struct berval *value,
129 void *assertedValue )
131 struct berval *asserted = (struct berval *) assertedValue;
132 int match = value->bv_len - asserted->bv_len;
135 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
143 octetStringOrderingMatch(
148 struct berval *value,
149 void *assertedValue )
151 struct berval *asserted = (struct berval *) assertedValue;
152 ber_len_t v_len = value->bv_len;
153 ber_len_t av_len = asserted->bv_len;
155 int match = memcmp( value->bv_val, asserted->bv_val,
156 (v_len < av_len ? v_len : av_len) );
158 if( match == 0 ) match = v_len - av_len;
165 HASH_CONTEXT *HASHcontext,
166 unsigned char *HASHdigest,
167 struct berval *prefix,
171 unsigned char *value,
174 HASH_Init(HASHcontext);
175 if(prefix && prefix->bv_len > 0) {
176 HASH_Update(HASHcontext,
177 (unsigned char *)prefix->bv_val, prefix->bv_len);
179 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
180 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
181 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
182 HASH_Update(HASHcontext, value, value_len);
183 HASH_Final(HASHdigest, HASHcontext);
187 /* Index generation function */
188 int octetStringIndexer(
193 struct berval *prefix,
201 HASH_CONTEXT HASHcontext;
202 unsigned char HASHdigest[HASH_BYTES];
203 struct berval digest;
204 digest.bv_val = (char *)HASHdigest;
205 digest.bv_len = sizeof(HASHdigest);
207 for( i=0; values[i].bv_val != NULL; i++ ) {
208 /* just count them */
211 /* we should have at least one value at this point */
214 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
216 slen = syntax->ssyn_oidlen;
217 mlen = mr->smr_oidlen;
219 for( i=0; values[i].bv_val != NULL; i++ ) {
220 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
221 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
222 ber_dupbv_x( &keys[i], &digest, ctx );
225 keys[i].bv_val = NULL;
233 /* Index generation function */
234 int octetStringFilter(
239 struct berval *prefix,
240 void * assertedValue,
246 HASH_CONTEXT HASHcontext;
247 unsigned char HASHdigest[HASH_BYTES];
248 struct berval *value = (struct berval *) assertedValue;
249 struct berval digest;
250 digest.bv_val = (char *)HASHdigest;
251 digest.bv_len = sizeof(HASHdigest);
253 slen = syntax->ssyn_oidlen;
254 mlen = mr->smr_oidlen;
256 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
258 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
259 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
261 ber_dupbv_x( keys, &digest, ctx );
262 keys[1].bv_val = NULL;
271 octetStringSubstringsMatch(
276 struct berval *value,
277 void *assertedValue )
280 SubstringsAssertion *sub = assertedValue;
281 struct berval left = *value;
285 /* Add up asserted input length */
286 if( sub->sa_initial.bv_val ) {
287 inlen += sub->sa_initial.bv_len;
290 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
291 inlen += sub->sa_any[i].bv_len;
294 if( sub->sa_final.bv_val ) {
295 inlen += sub->sa_final.bv_len;
298 if( sub->sa_initial.bv_val ) {
299 if( inlen > left.bv_len ) {
304 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
305 sub->sa_initial.bv_len );
311 left.bv_val += sub->sa_initial.bv_len;
312 left.bv_len -= sub->sa_initial.bv_len;
313 inlen -= sub->sa_initial.bv_len;
316 if( sub->sa_final.bv_val ) {
317 if( inlen > left.bv_len ) {
322 match = memcmp( sub->sa_final.bv_val,
323 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
324 sub->sa_final.bv_len );
330 left.bv_len -= sub->sa_final.bv_len;
331 inlen -= sub->sa_final.bv_len;
335 for(i=0; sub->sa_any[i].bv_val; i++) {
340 if( inlen > left.bv_len ) {
341 /* not enough length */
346 if( sub->sa_any[i].bv_len == 0 ) {
350 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
357 idx = p - left.bv_val;
359 if( idx >= left.bv_len ) {
360 /* this shouldn't happen */
367 if( sub->sa_any[i].bv_len > left.bv_len ) {
368 /* not enough left */
373 match = memcmp( left.bv_val,
374 sub->sa_any[i].bv_val,
375 sub->sa_any[i].bv_len );
383 left.bv_val += sub->sa_any[i].bv_len;
384 left.bv_len -= sub->sa_any[i].bv_len;
385 inlen -= sub->sa_any[i].bv_len;
394 /* Substrings Index generation function */
396 octetStringSubstringsIndexer(
401 struct berval *prefix,
406 ber_len_t i, j, len, nkeys;
410 HASH_CONTEXT HASHcontext;
411 unsigned char HASHdigest[HASH_BYTES];
412 struct berval digest;
413 digest.bv_val = (char *)HASHdigest;
414 digest.bv_len = sizeof(HASHdigest);
418 for( i=0; values[i].bv_val != NULL; i++ ) {
419 /* count number of indices to generate */
420 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
421 if( values[i].bv_len >= index_substr_if_maxlen ) {
422 nkeys += index_substr_if_maxlen -
423 (index_substr_if_minlen - 1);
424 } else if( values[i].bv_len >= index_substr_if_minlen ) {
425 nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
429 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
430 if( values[i].bv_len >= index_substr_any_len ) {
431 nkeys += values[i].bv_len - (index_substr_any_len - 1);
435 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
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);
446 /* no keys to generate */
451 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
453 slen = syntax->ssyn_oidlen;
454 mlen = mr->smr_oidlen;
457 for( i=0; values[i].bv_val != NULL; i++ ) {
460 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
461 ( values[i].bv_len >= index_substr_any_len ) )
463 char pre = SLAP_INDEX_SUBSTR_PREFIX;
464 max = values[i].bv_len - (index_substr_any_len - 1);
466 for( j=0; j<max; j++ ) {
467 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
468 syntax, mr, (unsigned char *)&values[i].bv_val[j], index_substr_any_len);
469 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
473 /* skip if too short */
474 if( values[i].bv_len < index_substr_if_minlen ) continue;
476 max = index_substr_if_maxlen < values[i].bv_len
477 ? index_substr_if_maxlen : values[i].bv_len;
479 for( j=index_substr_if_minlen; j<=max; j++ ) {
482 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
483 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
484 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
485 syntax, mr, (unsigned char *)values[i].bv_val, j );
486 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
489 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
490 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
491 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
492 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
493 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
500 keys[nkeys].bv_val = NULL;
511 octetStringSubstringsFilter (
516 struct berval *prefix,
517 void * assertedValue,
521 SubstringsAssertion *sa;
523 ber_len_t len, max, nkeys = 0;
524 size_t slen, mlen, klen;
526 HASH_CONTEXT HASHcontext;
527 unsigned char HASHdigest[HASH_BYTES];
528 struct berval *value;
529 struct berval digest;
531 sa = (SubstringsAssertion *) assertedValue;
533 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
534 sa->sa_initial.bv_val != NULL &&
535 sa->sa_initial.bv_len >= index_substr_if_minlen )
538 if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
539 ( flags & SLAP_INDEX_SUBSTR_ANY ))
541 nkeys += (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
545 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
547 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
548 if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
549 /* don't bother accounting with stepping */
550 nkeys += sa->sa_any[i].bv_len -
551 ( index_substr_any_len - 1 );
556 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
557 sa->sa_final.bv_val != NULL &&
558 sa->sa_final.bv_len >= index_substr_if_minlen )
561 if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
562 ( flags & SLAP_INDEX_SUBSTR_ANY ))
564 nkeys += (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
573 digest.bv_val = (char *)HASHdigest;
574 digest.bv_len = sizeof(HASHdigest);
576 slen = syntax->ssyn_oidlen;
577 mlen = mr->smr_oidlen;
579 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
582 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
583 sa->sa_initial.bv_val != NULL &&
584 sa->sa_initial.bv_len >= index_substr_if_minlen )
586 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
587 value = &sa->sa_initial;
589 klen = index_substr_if_maxlen < value->bv_len
590 ? index_substr_if_maxlen : value->bv_len;
592 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
593 syntax, mr, (unsigned char *)value->bv_val, klen );
594 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
596 /* If initial is too long and we have subany indexed, use it
597 * to match the excess...
599 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
602 pre = SLAP_INDEX_SUBSTR_PREFIX;
603 for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
605 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
606 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
607 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
612 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
614 pre = SLAP_INDEX_SUBSTR_PREFIX;
615 klen = index_substr_any_len;
617 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
618 if( sa->sa_any[i].bv_len < index_substr_any_len ) {
622 value = &sa->sa_any[i];
625 j <= value->bv_len - index_substr_any_len;
626 j += index_substr_any_step )
628 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
629 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
630 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
635 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
636 sa->sa_final.bv_val != NULL &&
637 sa->sa_final.bv_len >= index_substr_if_minlen )
639 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
640 value = &sa->sa_final;
642 klen = index_substr_if_maxlen < value->bv_len
643 ? index_substr_if_maxlen : value->bv_len;
645 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
646 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
647 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
649 /* If final is too long and we have subany indexed, use it
650 * to match the excess...
652 if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
655 pre = SLAP_INDEX_SUBSTR_PREFIX;
656 for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
658 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
659 syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len );
660 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
666 keys[nkeys].bv_val = NULL;
683 /* very unforgiving validation, requires no normalization
684 * before simplistic matching
686 if( in->bv_len < 3 ) {
687 return LDAP_INVALID_SYNTAX;
691 * RFC 2252 section 6.3 Bit String
692 * bitstring = "'" *binary-digit "'B"
693 * binary-digit = "0" / "1"
694 * example: '0101111101'B
697 if( in->bv_val[0] != '\'' ||
698 in->bv_val[in->bv_len-2] != '\'' ||
699 in->bv_val[in->bv_len-1] != 'B' )
701 return LDAP_INVALID_SYNTAX;
704 for( i=in->bv_len-3; i>0; i-- ) {
705 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
706 return LDAP_INVALID_SYNTAX;
714 * Syntax is [RFC2252]:
719 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
721 Values in this syntax are encoded according to the following BNF:
723 bitstring = "'" *binary-digit "'B"
725 binary-digit = "0" / "1"
729 6.21. Name And Optional UID
731 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
733 Values in this syntax are encoded according to the following BNF:
735 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
737 Although the '#' character may occur in a string representation of a
738 distinguished name, no additional special quoting is done. This
739 syntax has been added subsequent to RFC 1778.
743 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
746 * draft-ietf-ldapbis-syntaxes-xx.txt says:
751 A value of the Bit String syntax is a sequence of binary digits. The
752 LDAP-specific encoding of a value of this syntax is defined by the
755 BitString = SQUOTE *binary-digit SQUOTE "B"
757 binary-digit = "0" / "1"
759 The <SQUOTE> rule is defined in [MODELS].
764 The LDAP definition for the Bit String syntax is:
766 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
768 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
772 3.3.21. Name and Optional UID
774 A value of the Name and Optional UID syntax is the distinguished name
775 [MODELS] of an entity optionally accompanied by a unique identifier
776 that serves to differentiate the entity from others with an identical
779 The LDAP-specific encoding of a value of this syntax is defined by
782 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
784 The <BitString> rule is defined in Section 3.3.2. The
785 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
788 Note that although the '#' character may occur in the string
789 representation of a distinguished name, no additional escaping of
790 this character is performed when a <distinguishedName> is encoded in
791 a <NameAndOptionalUID>.
794 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
796 The LDAP definition for the Name and Optional UID syntax is:
798 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
800 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
804 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
807 1.4. Common ABNF Productions
810 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
812 SQUOTE = %x27 ; single quote ("'")
816 * Note: normalization strips any leading "0"s, unless the
817 * bit string is exactly "'0'B", so the normalized example,
818 * in slapd, would result in
820 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
822 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
823 * i.e. "#", doesn't have to be escaped except when at the
824 * beginning of a value, the definition of Name and Optional
825 * UID appears to be flawed, because there is no clear means
826 * to determine whether the UID part is present or not.
830 * cn=Someone,dc=example,dc=com#'1'B
832 * could be either a NameAndOptionalUID with trailing UID, i.e.
834 * DN = "cn=Someone,dc=example,dc=com"
837 * or a NameAndOptionalUID with no trailing UID, and the AVA
838 * in the last RDN made of
841 * attributeValue = com#'1'B
843 * in fact "com#'1'B" is a valid IA5 string.
845 * As a consequence, current slapd code assumes that the
846 * presence of portions of a BitString at the end of the string
847 * representation of a NameAndOptionalUID means a BitString
848 * is expected, and cause an error otherwise. This is quite
849 * arbitrary, and might change in the future.
859 struct berval dn, uid;
861 if( in->bv_len == 0 ) return LDAP_SUCCESS;
863 ber_dupbv( &dn, in );
864 if( !dn.bv_val ) return LDAP_OTHER;
866 /* if there's a "#", try bitStringValidate()... */
867 uid.bv_val = strrchr( dn.bv_val, '#' );
870 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
872 rc = bitStringValidate( NULL, &uid );
873 if ( rc == LDAP_SUCCESS ) {
874 /* in case of success, trim the UID,
875 * otherwise treat it as part of the DN */
876 dn.bv_len -= uid.bv_len + 1;
877 uid.bv_val[-1] = '\0';
881 rc = dnValidate( NULL, &dn );
883 ber_memfree( dn.bv_val );
898 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
900 if( val->bv_len == 0 ) {
901 ber_dupbv_x( out, val, ctx );
903 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
904 return LDAP_INVALID_SYNTAX;
908 struct berval dnval = *val;
909 struct berval uidval = BER_BVNULL;
911 uidval.bv_val = strrchr( val->bv_val, '#' );
912 if ( uidval.bv_val ) {
914 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
916 rc = bitStringValidate( NULL, &uidval );
918 if ( rc == LDAP_SUCCESS ) {
919 ber_dupbv_x( &dnval, val, ctx );
920 dnval.bv_len -= uidval.bv_len + 1;
921 dnval.bv_val[dnval.bv_len] = '\0';
924 uidval.bv_val = NULL;
928 rc = dnPretty( syntax, &dnval, out, ctx );
929 if ( dnval.bv_val != val->bv_val ) {
930 slap_sl_free( dnval.bv_val, ctx );
932 if( rc != LDAP_SUCCESS ) {
936 if( uidval.bv_val ) {
940 tmp = slap_sl_realloc( out->bv_val, out->bv_len
941 + STRLENOF( "#" ) + uidval.bv_len + 1,
944 ber_memfree_x( out->bv_val, ctx );
948 out->bv_val[out->bv_len++] = '#';
949 out->bv_val[out->bv_len++] = '\'';
951 got1 = uidval.bv_len < sizeof("'0'B");
952 for( i = 1; i < uidval.bv_len - 2; i++ ) {
953 c = uidval.bv_val[i];
956 if( got1 ) out->bv_val[out->bv_len++] = c;
960 out->bv_val[out->bv_len++] = c;
965 out->bv_val[out->bv_len++] = '\'';
966 out->bv_val[out->bv_len++] = 'B';
967 out->bv_val[out->bv_len] = '\0';
971 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
977 uniqueMemberNormalize(
982 struct berval *normalized,
988 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
990 ber_dupbv_x( &out, val, ctx );
991 if ( BER_BVISEMPTY( &out ) ) {
995 struct berval uid = BER_BVNULL;
997 uid.bv_val = strrchr( out.bv_val, '#' );
1000 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1002 rc = bitStringValidate( NULL, &uid );
1003 if ( rc == LDAP_SUCCESS ) {
1004 uid.bv_val[-1] = '\0';
1005 out.bv_len -= uid.bv_len + 1;
1011 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1013 if( rc != LDAP_SUCCESS ) {
1014 slap_sl_free( out.bv_val, ctx );
1015 return LDAP_INVALID_SYNTAX;
1021 tmp = ch_realloc( normalized->bv_val,
1022 normalized->bv_len + uid.bv_len
1023 + STRLENOF("#") + 1 );
1024 if ( tmp == NULL ) {
1025 ber_memfree_x( normalized->bv_val, ctx );
1029 normalized->bv_val = tmp;
1031 /* insert the separator */
1032 normalized->bv_val[normalized->bv_len++] = '#';
1034 /* append the UID */
1035 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1036 uid.bv_val, uid.bv_len );
1037 normalized->bv_len += uid.bv_len;
1040 normalized->bv_val[normalized->bv_len] = '\0';
1043 slap_sl_free( out.bv_val, ctx );
1046 return LDAP_SUCCESS;
1055 struct berval *value,
1056 void *assertedValue )
1059 struct berval *asserted = (struct berval *) assertedValue;
1060 struct berval assertedDN = *asserted;
1061 struct berval assertedUID = BER_BVNULL;
1062 struct berval valueDN = BER_BVNULL;
1063 struct berval valueUID = BER_BVNULL;
1065 if ( !BER_BVISEMPTY( asserted ) ) {
1066 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1067 if ( !BER_BVISNULL( &assertedUID ) ) {
1068 assertedUID.bv_val++;
1069 assertedUID.bv_len = assertedDN.bv_len
1070 - ( assertedUID.bv_val - assertedDN.bv_val );
1072 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1073 assertedDN.bv_len -= assertedUID.bv_len + 1;
1076 BER_BVZERO( &assertedUID );
1081 if ( !BER_BVISEMPTY( value ) ) {
1084 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1085 if ( !BER_BVISNULL( &valueUID ) ) {
1087 valueUID.bv_len = valueDN.bv_len
1088 - ( valueUID.bv_val - valueDN.bv_val );
1090 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1091 valueDN.bv_len -= valueUID.bv_len + 1;
1094 BER_BVZERO( &valueUID );
1099 if( valueUID.bv_len && assertedUID.bv_len ) {
1100 match = valueUID.bv_len - assertedUID.bv_len;
1103 return LDAP_SUCCESS;
1106 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1109 return LDAP_SUCCESS;
1113 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1117 * Handling boolean syntax and matching is quite rigid.
1118 * A more flexible approach would be to allow a variety
1119 * of strings to be normalized and prettied into TRUE
1127 /* very unforgiving validation, requires no normalization
1128 * before simplistic matching
1131 if( in->bv_len == 4 ) {
1132 if( bvmatch( in, &slap_true_bv ) ) {
1133 return LDAP_SUCCESS;
1135 } else if( in->bv_len == 5 ) {
1136 if( bvmatch( in, &slap_false_bv ) ) {
1137 return LDAP_SUCCESS;
1141 return LDAP_INVALID_SYNTAX;
1150 struct berval *value,
1151 void *assertedValue )
1153 /* simplistic matching allowed by rigid validation */
1154 struct berval *asserted = (struct berval *) assertedValue;
1155 *matchp = value->bv_len != asserted->bv_len;
1156 return LDAP_SUCCESS;
1159 /*-------------------------------------------------------------------
1160 LDAP/X.500 string syntax / matching rules have a few oddities. This
1161 comment attempts to detail how slapd(8) treats them.
1164 StringSyntax X.500 LDAP Matching/Comments
1165 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1166 PrintableString subset subset i/e + ignore insignificant spaces
1167 PrintableString subset subset i/e + ignore insignificant spaces
1168 NumericString subset subset ignore all spaces
1169 IA5String ASCII ASCII i/e + ignore insignificant spaces
1170 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1172 TelephoneNumber subset subset i + ignore all spaces and "-"
1174 See draft-ietf-ldapbis-strpro for details (once published).
1178 In X.500(93), a directory string can be either a PrintableString,
1179 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1180 In later versions, more CHOICEs were added. In all cases the string
1183 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1184 A directory string cannot be zero length.
1186 For matching, there are both case ignore and exact rules. Both
1187 also require that "insignificant" spaces be ignored.
1188 spaces before the first non-space are ignored;
1189 spaces after the last non-space are ignored;
1190 spaces after a space are ignored.
1191 Note: by these rules (and as clarified in X.520), a string of only
1192 spaces is to be treated as if held one space, not empty (which
1193 would be a syntax error).
1196 In ASN.1, numeric string is just a string of digits and spaces
1197 and could be empty. However, in X.500, all attribute values of
1198 numeric string carry a non-empty constraint. For example:
1200 internationalISDNNumber ATTRIBUTE ::= {
1201 WITH SYNTAX InternationalISDNNumber
1202 EQUALITY MATCHING RULE numericStringMatch
1203 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1204 ID id-at-internationalISDNNumber }
1205 InternationalISDNNumber ::=
1206 NumericString (SIZE(1..ub-international-isdn-number))
1208 Unforunately, some assertion values are don't carry the same
1209 constraint (but its unclear how such an assertion could ever
1210 be true). In LDAP, there is one syntax (numericString) not two
1211 (numericString with constraint, numericString without constraint).
1212 This should be treated as numericString with non-empty constraint.
1213 Note that while someone may have no ISDN number, there are no ISDN
1214 numbers which are zero length.
1216 In matching, spaces are ignored.
1219 In ASN.1, Printable string is just a string of printable characters
1220 and can be empty. In X.500, semantics much like NumericString (see
1221 serialNumber for a like example) excepting uses insignificant space
1222 handling instead of ignore all spaces.
1225 Basically same as PrintableString. There are no examples in X.500,
1226 but same logic applies. So we require them to be non-empty as
1229 -------------------------------------------------------------------*/
1238 unsigned char *u = (unsigned char *)in->bv_val;
1240 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1241 /* directory strings cannot be empty */
1242 return LDAP_INVALID_SYNTAX;
1245 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1246 /* get the length indicated by the first byte */
1247 len = LDAP_UTF8_CHARLEN2( u, len );
1249 /* very basic checks */
1252 if( (u[5] & 0xC0) != 0x80 ) {
1253 return LDAP_INVALID_SYNTAX;
1256 if( (u[4] & 0xC0) != 0x80 ) {
1257 return LDAP_INVALID_SYNTAX;
1260 if( (u[3] & 0xC0) != 0x80 ) {
1261 return LDAP_INVALID_SYNTAX;
1264 if( (u[2] & 0xC0 )!= 0x80 ) {
1265 return LDAP_INVALID_SYNTAX;
1268 if( (u[1] & 0xC0) != 0x80 ) {
1269 return LDAP_INVALID_SYNTAX;
1272 /* CHARLEN already validated it */
1275 return LDAP_INVALID_SYNTAX;
1278 /* make sure len corresponds with the offset
1279 to the next character */
1280 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1284 return LDAP_INVALID_SYNTAX;
1287 return LDAP_SUCCESS;
1291 UTF8StringNormalize(
1296 struct berval *normalized,
1299 struct berval tmp, nvalue;
1303 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1305 if( val->bv_val == NULL ) {
1306 /* assume we're dealing with a syntax (e.g., UTF8String)
1307 * which allows empty strings
1309 normalized->bv_len = 0;
1310 normalized->bv_val = NULL;
1311 return LDAP_SUCCESS;
1314 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1315 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1316 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1317 ? LDAP_UTF8_APPROX : 0;
1319 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1324 /* collapse spaces (in place) */
1326 nvalue.bv_val = tmp.bv_val;
1328 wasspace=1; /* trim leading spaces */
1329 for( i=0; i<tmp.bv_len; i++) {
1330 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1331 if( wasspace++ == 0 ) {
1332 /* trim repeated spaces */
1333 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1337 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1341 if( nvalue.bv_len ) {
1343 /* last character was a space, trim it */
1346 nvalue.bv_val[nvalue.bv_len] = '\0';
1349 /* string of all spaces is treated as one space */
1350 nvalue.bv_val[0] = ' ';
1351 nvalue.bv_val[1] = '\0';
1355 *normalized = nvalue;
1356 return LDAP_SUCCESS;
1359 #if defined(SLAPD_APPROX_INITIALS)
1360 # define SLAPD_APPROX_DELIMITER "._ "
1361 # define SLAPD_APPROX_WORDLEN 2
1363 # define SLAPD_APPROX_DELIMITER " "
1364 # define SLAPD_APPROX_WORDLEN 1
1373 struct berval *value,
1374 void *assertedValue )
1376 struct berval *nval, *assertv;
1377 char *val, **values, **words, *c;
1378 int i, count, len, nextchunk=0, nextavail=0;
1380 /* Yes, this is necessary */
1381 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1382 if( nval == NULL ) {
1384 return LDAP_SUCCESS;
1387 /* Yes, this is necessary */
1388 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1389 NULL, LDAP_UTF8_APPROX, NULL );
1390 if( assertv == NULL ) {
1393 return LDAP_SUCCESS;
1396 /* Isolate how many words there are */
1397 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1398 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1399 if ( c == NULL ) break;
1404 /* Get a phonetic copy of each word */
1405 words = (char **)ch_malloc( count * sizeof(char *) );
1406 values = (char **)ch_malloc( count * sizeof(char *) );
1407 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1409 values[i] = phonetic(c);
1412 /* Work through the asserted value's words, to see if at least some
1413 of the words are there, in the same order. */
1415 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1416 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1421 #if defined(SLAPD_APPROX_INITIALS)
1422 else if( len == 1 ) {
1423 /* Single letter words need to at least match one word's initial */
1424 for( i=nextavail; i<count; i++ )
1425 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1432 /* Isolate the next word in the asserted value and phonetic it */
1433 assertv->bv_val[nextchunk+len] = '\0';
1434 val = phonetic( assertv->bv_val + nextchunk );
1436 /* See if this phonetic chunk is in the remaining words of *value */
1437 for( i=nextavail; i<count; i++ ){
1438 if( !strcmp( val, values[i] ) ){
1446 /* This chunk in the asserted value was NOT within the *value. */
1452 /* Go on to the next word in the asserted value */
1456 /* If some of the words were seen, call it a match */
1457 if( nextavail > 0 ) {
1464 /* Cleanup allocs */
1465 ber_bvfree( assertv );
1466 for( i=0; i<count; i++ ) {
1467 ch_free( values[i] );
1473 return LDAP_SUCCESS;
1482 struct berval *prefix,
1488 int i,j, len, wordcount, keycount=0;
1489 struct berval *newkeys;
1490 BerVarray keys=NULL;
1492 for( j=0; values[j].bv_val != NULL; j++ ) {
1493 struct berval val = BER_BVNULL;
1494 /* Yes, this is necessary */
1495 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1496 assert( val.bv_val != NULL );
1498 /* Isolate how many words there are. There will be a key for each */
1499 for( wordcount = 0, c = val.bv_val; *c; c++) {
1500 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1501 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1503 if (*c == '\0') break;
1507 /* Allocate/increase storage to account for new keys */
1508 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1509 * sizeof(struct berval) );
1510 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1511 if( keys ) ch_free( keys );
1514 /* Get a phonetic copy of each word */
1515 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1517 if( len < SLAPD_APPROX_WORDLEN ) continue;
1518 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1523 ber_memfree( val.bv_val );
1525 keys[keycount].bv_val = NULL;
1528 return LDAP_SUCCESS;
1537 struct berval *prefix,
1538 void * assertedValue,
1547 /* Yes, this is necessary */
1548 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1549 NULL, LDAP_UTF8_APPROX, NULL );
1550 if( val == NULL || val->bv_val == NULL ) {
1551 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1552 keys[0].bv_val = NULL;
1555 return LDAP_SUCCESS;
1558 /* Isolate how many words there are. There will be a key for each */
1559 for( count = 0,c = val->bv_val; *c; c++) {
1560 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1561 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1563 if (*c == '\0') break;
1567 /* Allocate storage for new keys */
1568 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1570 /* Get a phonetic copy of each word */
1571 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1573 if( len < SLAPD_APPROX_WORDLEN ) continue;
1574 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1580 keys[count].bv_val = NULL;
1583 return LDAP_SUCCESS;
1586 /* Remove all spaces and '-' characters */
1588 telephoneNumberNormalize(
1593 struct berval *normalized,
1598 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1600 /* validator should have refused an empty string */
1601 assert( val->bv_len );
1603 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1605 for( p = val->bv_val; *p; p++ ) {
1606 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1612 normalized->bv_len = q - normalized->bv_val;
1614 if( normalized->bv_len == 0 ) {
1615 slap_sl_free( normalized->bv_val, ctx );
1616 normalized->bv_val = NULL;
1617 return LDAP_INVALID_SYNTAX;
1620 return LDAP_SUCCESS;
1628 struct berval val = *in;
1630 if( val.bv_len == 0 ) {
1631 /* disallow empty strings */
1632 return LDAP_INVALID_SYNTAX;
1635 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1636 if ( val.bv_len == 1 ) {
1637 return LDAP_SUCCESS;
1640 if ( val.bv_val[0] == '0' ) {
1647 while ( OID_LEADCHAR( val.bv_val[0] )) {
1651 if ( val.bv_len == 0 ) {
1652 return LDAP_SUCCESS;
1656 if( !OID_SEPARATOR( val.bv_val[0] )) {
1664 return LDAP_INVALID_SYNTAX;
1673 struct berval val = *in;
1675 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1677 if ( val.bv_val[0] == '-' ) {
1681 if( val.bv_len == 0 ) { /* bare "-" */
1682 return LDAP_INVALID_SYNTAX;
1685 if( val.bv_val[0] == '0' ) { /* "-0" */
1686 return LDAP_INVALID_SYNTAX;
1689 } else if ( val.bv_val[0] == '0' ) {
1690 if( val.bv_len > 1 ) { /* "0<more>" */
1691 return LDAP_INVALID_SYNTAX;
1694 return LDAP_SUCCESS;
1697 for( i=0; i < val.bv_len; i++ ) {
1698 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1699 return LDAP_INVALID_SYNTAX;
1703 return LDAP_SUCCESS;
1712 struct berval *value,
1713 void *assertedValue )
1715 struct berval *asserted = (struct berval *) assertedValue;
1716 int vsign = 1, asign = 1; /* default sign = '+' */
1721 if( v.bv_val[0] == '-' ) {
1727 if( v.bv_len == 0 ) vsign = 0;
1730 if( a.bv_val[0] == '-' ) {
1736 if( a.bv_len == 0 ) vsign = 0;
1738 match = vsign - asign;
1740 match = ( v.bv_len != a.bv_len
1741 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1742 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1743 if( vsign < 0 ) match = -match;
1747 return LDAP_SUCCESS;
1751 countryStringValidate(
1753 struct berval *val )
1755 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1757 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1758 return LDAP_INVALID_SYNTAX;
1760 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1761 return LDAP_INVALID_SYNTAX;
1764 return LDAP_SUCCESS;
1768 printableStringValidate(
1770 struct berval *val )
1774 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1776 for(i=0; i < val->bv_len; i++) {
1777 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1778 return LDAP_INVALID_SYNTAX;
1782 return LDAP_SUCCESS;
1786 printablesStringValidate(
1788 struct berval *val )
1792 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1794 for(i=0,len=0; i < val->bv_len; i++) {
1795 int c = val->bv_val[i];
1799 return LDAP_INVALID_SYNTAX;
1803 } else if ( SLAP_PRINTABLE(c) ) {
1806 return LDAP_INVALID_SYNTAX;
1811 return LDAP_INVALID_SYNTAX;
1814 return LDAP_SUCCESS;
1820 struct berval *val )
1824 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1826 for(i=0; i < val->bv_len; i++) {
1827 if( !LDAP_ASCII(val->bv_val[i]) ) {
1828 return LDAP_INVALID_SYNTAX;
1832 return LDAP_SUCCESS;
1841 struct berval *normalized,
1845 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1847 assert( val->bv_len );
1849 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1853 /* Ignore initial whitespace */
1854 while ( ASCII_SPACE( *p ) ) p++;
1856 normalized->bv_val = ber_strdup_x( p, ctx );
1857 p = q = normalized->bv_val;
1860 if ( ASCII_SPACE( *p ) ) {
1863 /* Ignore the extra whitespace */
1864 while ( ASCII_SPACE( *p ) ) {
1868 } else if ( casefold ) {
1869 /* Most IA5 rules require casefolding */
1870 *q++ = TOLOWER(*p); p++;
1877 assert( normalized->bv_val <= p );
1881 * If the string ended in space, backup the pointer one
1882 * position. One is enough because the above loop collapsed
1883 * all whitespace to a single space.
1885 if ( ASCII_SPACE( q[-1] ) ) --q;
1887 /* null terminate */
1890 normalized->bv_len = q - normalized->bv_val;
1891 if( normalized->bv_len == 0 ) {
1892 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1893 normalized->bv_val[0] = ' ';
1894 normalized->bv_val[1] = '\0';
1895 normalized->bv_len = 1;
1898 return LDAP_SUCCESS;
1907 if( in->bv_len != 36 ) {
1908 return LDAP_INVALID_SYNTAX;
1911 for( i=0; i<36; i++ ) {
1917 if( in->bv_val[i] != '-' ) {
1918 return LDAP_INVALID_SYNTAX;
1922 if( !ASCII_HEX( in->bv_val[i]) ) {
1923 return LDAP_INVALID_SYNTAX;
1928 return LDAP_SUCCESS;
1937 struct berval *normalized,
1940 unsigned char octet = '\0';
1943 normalized->bv_len = 16;
1944 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1946 for( i=0, j=0; i<36; i++ ) {
1947 unsigned char nibble;
1948 if( val->bv_val[i] == '-' ) {
1951 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1952 nibble = val->bv_val[i] - '0';
1954 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1955 nibble = val->bv_val[i] - ('a'-10);
1957 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1958 nibble = val->bv_val[i] - ('A'-10);
1961 slap_sl_free( normalized->bv_val, ctx );
1962 return LDAP_INVALID_SYNTAX;
1967 normalized->bv_val[j>>1] = octet;
1969 octet = nibble << 4;
1974 normalized->bv_val[normalized->bv_len] = 0;
1975 return LDAP_SUCCESS;
1981 numericStringValidate(
1987 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1989 for(i=0; i < in->bv_len; i++) {
1990 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1991 return LDAP_INVALID_SYNTAX;
1995 return LDAP_SUCCESS;
1999 numericStringNormalize(
2004 struct berval *normalized,
2007 /* removal all spaces */
2010 assert( val->bv_len );
2012 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2015 q = normalized->bv_val;
2018 if ( ASCII_SPACE( *p ) ) {
2019 /* Ignore whitespace */
2026 /* we should have copied no more then is in val */
2027 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2029 /* null terminate */
2032 normalized->bv_len = q - normalized->bv_val;
2034 if( normalized->bv_len == 0 ) {
2035 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2036 normalized->bv_val[0] = ' ';
2037 normalized->bv_val[1] = '\0';
2038 normalized->bv_len = 1;
2041 return LDAP_SUCCESS;
2045 * Integer conversion macros that will use the largest available
2048 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2049 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2050 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2051 # define SLAP_LONG_MAX LLONG_MAX
2052 # define SLAP_LONG_MIN LLONG_MIN
2053 # define SLAP_LONG long long
2055 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2056 # define SLAP_LONG_MAX LONG_MAX
2057 # define SLAP_LONG_MIN LONG_MIN
2058 # define SLAP_LONG long
2059 #endif /* HAVE_STRTOLL ... */
2067 struct berval *value,
2068 void *assertedValue )
2070 SLAP_LONG lValue, lAssertedValue;
2072 /* safe to assume integers are NUL terminated? */
2073 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2074 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2077 return LDAP_CONSTRAINT_VIOLATION;
2080 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2082 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2085 return LDAP_CONSTRAINT_VIOLATION;
2088 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2089 return LDAP_SUCCESS;
2098 struct berval *value,
2099 void *assertedValue )
2101 SLAP_LONG lValue, lAssertedValue;
2103 /* safe to assume integers are NUL terminated? */
2104 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2105 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2108 return LDAP_CONSTRAINT_VIOLATION;
2111 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2113 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2116 return LDAP_CONSTRAINT_VIOLATION;
2119 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2120 return LDAP_SUCCESS;
2124 serialNumberAndIssuerValidate(
2131 struct berval sn, i;
2132 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2134 i.bv_val = strchr( in->bv_val, '$' );
2135 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2137 sn.bv_val = in->bv_val;
2138 sn.bv_len = i.bv_val - in->bv_val;
2141 i.bv_len = in->bv_len - (sn.bv_len + 1);
2143 /* validate serial number (strict for now) */
2144 for( n=0; n < sn.bv_len; n++ ) {
2145 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2149 rc = dnValidate( NULL, &i );
2150 if( rc ) return LDAP_INVALID_SYNTAX;
2152 return LDAP_SUCCESS;
2156 serialNumberAndIssuerPretty(
2165 struct berval sn, i, newi;
2170 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2171 val->bv_val, 0, 0 );
2173 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2175 i.bv_val = strchr( val->bv_val, '$' );
2176 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2178 sn.bv_val = val->bv_val;
2179 sn.bv_len = i.bv_val - val->bv_val;
2182 i.bv_len = val->bv_len - (sn.bv_len + 1);
2184 /* eat leading zeros */
2185 for( n=0; n < (sn.bv_len-1); n++ ) {
2186 if( sn.bv_val[n] != '0' ) break;
2191 for( n=0; n < sn.bv_len; n++ ) {
2192 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2196 rc = dnPretty( syntax, &i, &newi, ctx );
2197 if( rc ) return LDAP_INVALID_SYNTAX;
2199 /* make room from sn + "$" */
2200 out->bv_len = sn.bv_len + newi.bv_len + 1;
2201 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2203 if( out->bv_val == NULL ) {
2204 slap_sl_free( newi.bv_val, ctx );
2208 /* push issuer over */
2209 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2210 /* insert sn and "$" */
2211 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2212 out->bv_val[sn.bv_len] = '$';
2214 out->bv_val[out->bv_len] = '\0';
2216 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2217 out->bv_val, 0, 0 );
2219 return LDAP_SUCCESS;
2223 * This routine is called by certificateExactNormalize when
2224 * certificateExactNormalize receives a search string instead of
2225 * a certificate. This routine checks if the search value is valid
2226 * and then returns the normalized value
2229 serialNumberAndIssuerNormalize(
2240 struct berval sn, i, newi;
2245 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2246 val->bv_val, 0, 0 );
2248 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2250 i.bv_val = strchr( val->bv_val, '$' );
2251 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2253 sn.bv_val = val->bv_val;
2254 sn.bv_len = i.bv_val - val->bv_val;
2257 i.bv_len = val->bv_len - (sn.bv_len + 1);
2259 /* eat leading zeros */
2260 for( n=0; n < (sn.bv_len-1); n++ ) {
2261 if( sn.bv_val[n] != '0' ) break;
2266 for( n=0; n < sn.bv_len; n++ ) {
2267 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2268 return LDAP_INVALID_SYNTAX;
2273 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2274 if( rc ) return LDAP_INVALID_SYNTAX;
2276 /* make room from sn + "$" */
2277 out->bv_len = sn.bv_len + newi.bv_len + 1;
2278 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2280 if( out->bv_val == NULL ) {
2281 slap_sl_free( newi.bv_val, ctx );
2285 /* push issuer over */
2286 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2287 /* insert sn and "$" */
2288 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2289 out->bv_val[sn.bv_len] = '$';
2291 out->bv_val[out->bv_len] = '\0';
2293 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2294 out->bv_val, 0, 0 );
2301 certificateExactNormalize(
2306 struct berval *normalized,
2309 int rc = LDAP_INVALID_SYNTAX;
2311 char *serial = NULL;
2312 ber_len_t seriallen;
2313 struct berval issuer_dn = BER_BVNULL;
2314 X509_NAME *name = NULL;
2315 ASN1_INTEGER *sn = NULL;
2318 if( val->bv_len == 0 ) goto done;
2320 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2321 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2324 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2326 p = (unsigned char *)val->bv_val;
2327 xcert = d2i_X509( NULL, &p, val->bv_len);
2328 if( xcert == NULL ) goto done;
2330 sn=X509_get_serialNumber(xcert);
2331 if ( sn == NULL ) goto done;
2332 serial=i2s_ASN1_INTEGER(0, sn );
2333 if( serial == NULL ) goto done;
2334 seriallen=strlen(serial);
2336 name=X509_get_issuer_name(xcert);
2337 if( name == NULL ) goto done;
2338 rc = dnX509normalize( name, &issuer_dn );
2339 if( rc != LDAP_SUCCESS ) goto done;
2341 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2342 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2343 p = (unsigned char *)normalized->bv_val;
2344 AC_MEMCPY(p, serial, seriallen);
2347 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2348 p += issuer_dn.bv_len;
2351 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2352 normalized->bv_val, NULL, NULL );
2355 if (xcert) X509_free(xcert);
2356 if (serial) ch_free(serial);
2357 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2361 #endif /* HAVE_TLS */
2364 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2365 /* slight optimization - does not need the start parameter */
2366 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2371 check_time_syntax (struct berval *val,
2374 struct berval *fraction)
2377 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2378 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2379 * GeneralizedTime supports leap seconds, UTCTime does not.
2381 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2382 static const int mdays[2][12] = {
2383 /* non-leap years */
2384 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2386 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2389 int part, c, c1, c2, tzoffset, leapyear = 0;
2392 e = p + val->bv_len;
2394 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2395 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2397 for (part = start; part < 7 && p < e; part++) {
2399 if (!ASCII_DIGIT(c1)) {
2404 return LDAP_INVALID_SYNTAX;
2407 if (!ASCII_DIGIT(c)) {
2408 return LDAP_INVALID_SYNTAX;
2410 c += c1 * 10 - '0' * 11;
2411 if ((part | 1) == 3) {
2414 return LDAP_INVALID_SYNTAX;
2417 if (c >= ceiling[part]) {
2418 if (! (c == 60 && part == 6 && start == 0))
2419 return LDAP_INVALID_SYNTAX;
2423 if (part < 5 + start) {
2424 return LDAP_INVALID_SYNTAX;
2426 for (; part < 9; part++) {
2430 /* leapyear check for the Gregorian calendar (year>1581) */
2431 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2435 if (parts[3] >= mdays[leapyear][parts[2]]) {
2436 return LDAP_INVALID_SYNTAX;
2440 fraction->bv_val = p;
2441 fraction->bv_len = 0;
2442 if (p < e && (*p == '.' || *p == ',')) {
2444 while (++p < e && ASCII_DIGIT(*p)) {
2447 if (p - fraction->bv_val == 1) {
2448 return LDAP_INVALID_SYNTAX;
2450 for (end_num = p; end_num[-1] == '0'; --end_num) {
2453 c = end_num - fraction->bv_val;
2454 if (c != 1) fraction->bv_len = c;
2460 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2466 return LDAP_INVALID_SYNTAX;
2472 for (part = 7; part < 9 && p < e; part++) {
2474 if (!ASCII_DIGIT(c1)) {
2479 return LDAP_INVALID_SYNTAX;
2482 if (!ASCII_DIGIT(c2)) {
2483 return LDAP_INVALID_SYNTAX;
2485 parts[part] = c1 * 10 + c2 - '0' * 11;
2486 if (parts[part] >= ceiling[part]) {
2487 return LDAP_INVALID_SYNTAX;
2490 if (part < 8 + start) {
2491 return LDAP_INVALID_SYNTAX;
2494 if (tzoffset == '-') {
2495 /* negative offset to UTC, ie west of Greenwich */
2496 parts[4] += parts[7];
2497 parts[5] += parts[8];
2498 /* offset is just hhmm, no seconds */
2499 for (part = 6; --part >= 0; ) {
2503 c = mdays[leapyear][parts[2]];
2505 if (parts[part] >= c) {
2507 return LDAP_INVALID_SYNTAX;
2512 } else if (part != 5) {
2517 /* positive offset to UTC, ie east of Greenwich */
2518 parts[4] -= parts[7];
2519 parts[5] -= parts[8];
2520 for (part = 6; --part >= 0; ) {
2521 if (parts[part] < 0) {
2523 return LDAP_INVALID_SYNTAX;
2528 /* make first arg to % non-negative */
2529 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2534 } else if (part != 5) {
2541 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2544 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2551 struct berval *normalized )
2555 rc = check_time_syntax(val, 1, parts, NULL);
2556 if (rc != LDAP_SUCCESS) {
2560 normalized->bv_val = ch_malloc( 14 );
2561 if ( normalized->bv_val == NULL ) {
2562 return LBER_ERROR_MEMORY;
2565 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2566 parts[1], parts[2] + 1, parts[3] + 1,
2567 parts[4], parts[5], parts[6] );
2568 normalized->bv_len = 13;
2570 return LDAP_SUCCESS;
2580 return check_time_syntax(in, 1, parts, NULL);
2583 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2586 generalizedTimeValidate(
2591 struct berval fraction;
2592 return check_time_syntax(in, 0, parts, &fraction);
2596 generalizedTimeNormalize(
2601 struct berval *normalized,
2606 struct berval fraction;
2608 rc = check_time_syntax(val, 0, parts, &fraction);
2609 if (rc != LDAP_SUCCESS) {
2613 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2614 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2615 if ( normalized->bv_val == NULL ) {
2616 return LBER_ERROR_MEMORY;
2619 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2620 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2621 parts[4], parts[5], parts[6] );
2622 if ( fraction.bv_len ) {
2623 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2624 fraction.bv_val, fraction.bv_len );
2625 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2627 strcpy( normalized->bv_val + len-1, "Z" );
2628 normalized->bv_len = len;
2630 return LDAP_SUCCESS;
2634 generalizedTimeOrderingMatch(
2639 struct berval *value,
2640 void *assertedValue )
2642 struct berval *asserted = (struct berval *) assertedValue;
2643 ber_len_t v_len = value->bv_len;
2644 ber_len_t av_len = asserted->bv_len;
2646 /* ignore trailing 'Z' when comparing */
2647 int match = memcmp( value->bv_val, asserted->bv_val,
2648 (v_len < av_len ? v_len : av_len) - 1 );
2649 if ( match == 0 ) match = v_len - av_len;
2652 return LDAP_SUCCESS;
2655 /* Index generation function */
2656 int generalizedTimeIndexer(
2661 struct berval *prefix,
2670 BerValue bvtmp; /* 40 bit index */
2672 struct lutil_timet tt;
2674 bvtmp.bv_len = sizeof(tmp);
2676 for( i=0; values[i].bv_val != NULL; i++ ) {
2677 /* just count them */
2680 /* we should have at least one value at this point */
2683 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2685 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2686 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2687 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2688 /* Use 40 bits of time for key */
2689 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2690 lutil_tm2time( &tm, &tt );
2691 tmp[0] = tt.tt_gsec & 0xff;
2692 tmp[4] = tt.tt_sec & 0xff;
2694 tmp[3] = tt.tt_sec & 0xff;
2696 tmp[2] = tt.tt_sec & 0xff;
2698 tmp[1] = tt.tt_sec & 0xff;
2700 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2704 keys[j].bv_val = NULL;
2709 return LDAP_SUCCESS;
2712 /* Index generation function */
2713 int generalizedTimeFilter(
2718 struct berval *prefix,
2719 void * assertedValue,
2725 BerValue bvtmp; /* 40 bit index */
2726 BerValue *value = (BerValue *) assertedValue;
2728 struct lutil_timet tt;
2730 bvtmp.bv_len = sizeof(tmp);
2732 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2733 /* Use 40 bits of time for key */
2734 if ( value->bv_val && value->bv_len >= 10 &&
2735 lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2737 lutil_tm2time( &tm, &tt );
2738 tmp[0] = tt.tt_gsec & 0xff;
2739 tmp[4] = tt.tt_sec & 0xff;
2741 tmp[3] = tt.tt_sec & 0xff;
2743 tmp[2] = tt.tt_sec & 0xff;
2745 tmp[1] = tt.tt_sec & 0xff;
2747 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2748 ber_dupbv_x(keys, &bvtmp, ctx );
2749 keys[1].bv_val = NULL;
2757 return LDAP_SUCCESS;
2761 deliveryMethodValidate(
2763 struct berval *val )
2766 #define LENOF(s) (sizeof(s)-1)
2767 struct berval tmp = *val;
2769 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2770 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2771 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2774 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2776 switch( tmp.bv_val[0] ) {
2779 if(( tmp.bv_len >= LENOF("any") ) &&
2780 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2782 tmp.bv_len -= LENOF("any");
2783 tmp.bv_val += LENOF("any");
2786 return LDAP_INVALID_SYNTAX;
2790 if(( tmp.bv_len >= LENOF("mhs") ) &&
2791 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2793 tmp.bv_len -= LENOF("mhs");
2794 tmp.bv_val += LENOF("mhs");
2797 return LDAP_INVALID_SYNTAX;
2801 if(( tmp.bv_len >= LENOF("physical") ) &&
2802 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2804 tmp.bv_len -= LENOF("physical");
2805 tmp.bv_val += LENOF("physical");
2808 return LDAP_INVALID_SYNTAX;
2811 case 'T': /* telex or teletex or telephone */
2812 if(( tmp.bv_len >= LENOF("telex") ) &&
2813 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2815 tmp.bv_len -= LENOF("telex");
2816 tmp.bv_val += LENOF("telex");
2819 if(( tmp.bv_len >= LENOF("teletex") ) &&
2820 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2822 tmp.bv_len -= LENOF("teletex");
2823 tmp.bv_val += LENOF("teletex");
2826 if(( tmp.bv_len >= LENOF("telephone") ) &&
2827 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2829 tmp.bv_len -= LENOF("telephone");
2830 tmp.bv_val += LENOF("telephone");
2833 return LDAP_INVALID_SYNTAX;
2836 case 'G': /* g3fax or g4fax */
2837 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2838 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2839 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2841 tmp.bv_len -= LENOF("g3fax");
2842 tmp.bv_val += LENOF("g3fax");
2845 return LDAP_INVALID_SYNTAX;
2849 if(( tmp.bv_len >= LENOF("ia5") ) &&
2850 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2852 tmp.bv_len -= LENOF("ia5");
2853 tmp.bv_val += LENOF("ia5");
2856 return LDAP_INVALID_SYNTAX;
2860 if(( tmp.bv_len >= LENOF("videotex") ) &&
2861 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2863 tmp.bv_len -= LENOF("videotex");
2864 tmp.bv_val += LENOF("videotex");
2867 return LDAP_INVALID_SYNTAX;
2870 return LDAP_INVALID_SYNTAX;
2873 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2875 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2879 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2883 return LDAP_INVALID_SYNTAX;
2885 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2894 nisNetgroupTripleValidate(
2896 struct berval *val )
2901 if ( val->bv_len == 0 ) {
2902 return LDAP_INVALID_SYNTAX;
2905 p = (char *)val->bv_val;
2906 e = p + val->bv_len;
2908 if ( *p != '(' /*')'*/ ) {
2909 return LDAP_INVALID_SYNTAX;
2912 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2916 return LDAP_INVALID_SYNTAX;
2919 } else if ( !AD_CHAR( *p ) ) {
2920 return LDAP_INVALID_SYNTAX;
2924 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2925 return LDAP_INVALID_SYNTAX;
2931 return LDAP_INVALID_SYNTAX;
2934 return LDAP_SUCCESS;
2938 bootParameterValidate(
2940 struct berval *val )
2944 if ( val->bv_len == 0 ) {
2945 return LDAP_INVALID_SYNTAX;
2948 p = (char *)val->bv_val;
2949 e = p + val->bv_len;
2952 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2953 if ( !AD_CHAR( *p ) ) {
2954 return LDAP_INVALID_SYNTAX;
2959 return LDAP_INVALID_SYNTAX;
2963 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2964 if ( !AD_CHAR( *p ) ) {
2965 return LDAP_INVALID_SYNTAX;
2970 return LDAP_INVALID_SYNTAX;
2974 for ( p++; p < e; p++ ) {
2975 if ( !SLAP_PRINTABLE( *p ) ) {
2976 return LDAP_INVALID_SYNTAX;
2980 return LDAP_SUCCESS;
2984 firstComponentNormalize(
2989 struct berval *normalized,
2996 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2997 ber_dupbv_x( normalized, val, ctx );
2998 return LDAP_SUCCESS;
3001 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
3003 if( val->bv_val[0] != '(' /*')'*/ &&
3004 val->bv_val[0] != '{' /*'}'*/ )
3006 return LDAP_INVALID_SYNTAX;
3009 /* trim leading white space */
3011 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3017 /* grab next word */
3018 comp.bv_val = &val->bv_val[len];
3019 len = val->bv_len - len;
3021 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3027 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3028 rc = numericoidValidate( NULL, &comp );
3029 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3030 rc = integerValidate( NULL, &comp );
3032 rc = LDAP_INVALID_SYNTAX;
3036 if( rc == LDAP_SUCCESS ) {
3037 ber_dupbv_x( normalized, &comp, ctx );
3044 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3045 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3047 static slap_syntax_defs_rec syntax_defs[] = {
3048 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3049 X_BINARY X_NOT_H_R ")",
3050 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3051 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3053 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3055 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3057 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3058 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3060 SLAP_SYNTAX_BER, berValidate, NULL},
3061 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3062 0, bitStringValidate, NULL },
3063 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3064 0, booleanValidate, NULL},
3065 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3066 X_BINARY X_NOT_H_R ")",
3067 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3068 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3069 X_BINARY X_NOT_H_R ")",
3070 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3071 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3072 X_BINARY X_NOT_H_R ")",
3073 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3074 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3075 0, countryStringValidate, NULL},
3076 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3077 0, dnValidate, dnPretty},
3078 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3079 0, rdnValidate, rdnPretty},
3080 #ifdef LDAP_COMP_MATCH
3081 {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
3082 0, allComponentsValidate, NULL},
3083 {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
3084 0, componentFilterValidate, NULL},
3086 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3088 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3089 0, deliveryMethodValidate, NULL},
3090 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3091 0, UTF8StringValidate, NULL},
3092 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3094 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3096 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3098 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3100 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3102 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3103 0, printablesStringValidate, NULL},
3104 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3105 SLAP_SYNTAX_BLOB, NULL, NULL},
3106 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3107 0, generalizedTimeValidate, NULL},
3108 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3110 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3111 0, IA5StringValidate, NULL},
3112 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3113 0, integerValidate, NULL},
3114 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3115 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3116 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3118 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3120 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3122 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3124 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3126 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3127 0, nameUIDValidate, nameUIDPretty },
3128 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3130 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3131 0, numericStringValidate, NULL},
3132 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3134 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3135 0, numericoidValidate, NULL},
3136 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3137 0, IA5StringValidate, NULL},
3138 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3139 0, blobValidate, NULL},
3140 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3141 0, UTF8StringValidate, NULL},
3142 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3144 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3146 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3147 0, printableStringValidate, NULL},
3148 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3149 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3150 0, subtreeSpecificationValidate, NULL},
3151 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3152 X_BINARY X_NOT_H_R ")",
3153 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3154 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3155 0, printableStringValidate, NULL},
3156 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3158 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3159 0, printablesStringValidate, NULL},
3160 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3161 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3162 0, utcTimeValidate, NULL},
3164 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3166 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3168 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3170 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3172 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3175 /* RFC 2307 NIS Syntaxes */
3176 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3177 0, nisNetgroupTripleValidate, NULL},
3178 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3179 0, bootParameterValidate, NULL},
3181 /* From PKIX *//* This OID is not published yet. */
3182 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3184 serialNumberAndIssuerValidate,
3185 serialNumberAndIssuerPretty},
3187 #ifdef SLAPD_ACI_ENABLED
3188 /* OpenLDAP Experimental Syntaxes */
3189 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3191 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3195 #ifdef SLAPD_AUTHPASSWD
3196 /* needs updating */
3197 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3198 SLAP_SYNTAX_HIDE, NULL, NULL},
3201 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3202 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3204 {"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
3205 SLAP_SYNTAX_HIDE, csnValidate, NULL},
3207 /* OpenLDAP Void Syntax */
3208 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3209 SLAP_SYNTAX_HIDE, inValidate, NULL},
3210 {NULL, 0, NULL, NULL}
3213 char *certificateExactMatchSyntaxes[] = {
3214 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3217 #ifdef LDAP_COMP_MATCH
3218 char *componentFilterMatchSyntaxes[] = {
3219 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3223 char *directoryStringSyntaxes[] = {
3224 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3227 char *integerFirstComponentMatchSyntaxes[] = {
3228 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3229 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3232 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3233 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3234 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3235 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3236 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3237 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3238 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3239 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3240 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3245 * Other matching rules in X.520 that we do not use (yet):
3247 * 2.5.13.25 uTCTimeMatch
3248 * 2.5.13.26 uTCTimeOrderingMatch
3249 * 2.5.13.31* directoryStringFirstComponentMatch
3250 * 2.5.13.32* wordMatch
3251 * 2.5.13.33* keywordMatch
3252 * 2.5.13.36 certificatePairExactMatch
3253 * 2.5.13.37 certificatePairMatch
3254 * 2.5.13.38 certificateListExactMatch
3255 * 2.5.13.39 certificateListMatch
3256 * 2.5.13.40 algorithmIdentifierMatch
3257 * 2.5.13.41* storedPrefixMatch
3258 * 2.5.13.42 attributeCertificateMatch
3259 * 2.5.13.43 readerAndKeyIDMatch
3260 * 2.5.13.44 attributeIntegrityMatch
3262 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3264 static slap_mrule_defs_rec mrule_defs[] = {
3266 * EQUALITY matching rules must be listed after associated APPROX
3267 * matching rules. So, we list all APPROX matching rules first.
3269 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3270 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3271 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3272 NULL, NULL, directoryStringApproxMatch,
3273 directoryStringApproxIndexer, directoryStringApproxFilter,
3276 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3277 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3278 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3279 NULL, NULL, IA5StringApproxMatch,
3280 IA5StringApproxIndexer, IA5StringApproxFilter,
3284 * Other matching rules
3287 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3288 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3289 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3290 NULL, NULL, octetStringMatch,
3291 octetStringIndexer, octetStringFilter,
3294 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3295 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3296 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3297 NULL, dnNormalize, dnMatch,
3298 octetStringIndexer, octetStringFilter,
3301 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3302 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3303 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3304 NULL, dnNormalize, dnRelativeMatch,
3308 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3309 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3310 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3311 NULL, dnNormalize, dnRelativeMatch,
3315 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3316 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3317 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3318 NULL, dnNormalize, dnRelativeMatch,
3322 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3323 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3324 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3325 NULL, dnNormalize, dnRelativeMatch,
3329 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3330 "SYNTAX 1.2.36.79672281.1.5.0 )",
3331 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3332 NULL, rdnNormalize, rdnMatch,
3333 octetStringIndexer, octetStringFilter,
3336 #ifdef LDAP_COMP_MATCH
3337 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3338 "SYNTAX 1.2.36.79672281.1.5.2 )",
3339 SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
3340 NULL, NULL , componentFilterMatch,
3341 octetStringIndexer, octetStringFilter,
3344 {"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
3345 "SYNTAX 1.2.36.79672281.1.5.3 )",
3346 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3347 NULL, NULL , allComponentsMatch,
3348 octetStringIndexer, octetStringFilter,
3351 {"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
3352 "SYNTAX 1.2.36.79672281.1.5.3 )",
3353 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3354 NULL, NULL , directoryComponentsMatch,
3355 octetStringIndexer, octetStringFilter,
3359 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3360 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3361 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3362 NULL, UTF8StringNormalize, octetStringMatch,
3363 octetStringIndexer, octetStringFilter,
3364 directoryStringApproxMatchOID },
3366 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3367 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3368 SLAP_MR_ORDERING, directoryStringSyntaxes,
3369 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3371 "caseIgnoreMatch" },
3373 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3374 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3375 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3376 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3377 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3378 "caseIgnoreMatch" },
3380 {"( 2.5.13.5 NAME 'caseExactMatch' "
3381 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3382 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3383 NULL, UTF8StringNormalize, octetStringMatch,
3384 octetStringIndexer, octetStringFilter,
3385 directoryStringApproxMatchOID },
3387 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3388 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3389 SLAP_MR_ORDERING, directoryStringSyntaxes,
3390 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3394 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3395 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3396 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3397 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3398 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3401 {"( 2.5.13.8 NAME 'numericStringMatch' "
3402 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3403 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3404 NULL, numericStringNormalize, octetStringMatch,
3405 octetStringIndexer, octetStringFilter,
3408 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3409 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3410 SLAP_MR_ORDERING, NULL,
3411 NULL, numericStringNormalize, octetStringOrderingMatch,
3413 "numericStringMatch" },
3415 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3416 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3417 SLAP_MR_SUBSTR, NULL,
3418 NULL, numericStringNormalize, octetStringSubstringsMatch,
3419 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3420 "numericStringMatch" },
3422 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3423 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3424 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3425 NULL, NULL, NULL, NULL, NULL, NULL },
3427 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3428 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3429 SLAP_MR_SUBSTR, NULL,
3430 NULL, NULL, NULL, NULL, NULL,
3431 "caseIgnoreListMatch" },
3433 {"( 2.5.13.13 NAME 'booleanMatch' "
3434 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3435 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3436 NULL, NULL, booleanMatch,
3437 octetStringIndexer, octetStringFilter,
3440 {"( 2.5.13.14 NAME 'integerMatch' "
3441 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3442 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3443 NULL, NULL, integerMatch,
3444 octetStringIndexer, octetStringFilter,
3447 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3448 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3449 SLAP_MR_ORDERING, NULL,
3450 NULL, NULL, integerMatch,
3454 {"( 2.5.13.16 NAME 'bitStringMatch' "
3455 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3456 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3457 NULL, NULL, octetStringMatch,
3458 octetStringIndexer, octetStringFilter,
3461 {"( 2.5.13.17 NAME 'octetStringMatch' "
3462 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3463 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3464 NULL, NULL, octetStringMatch,
3465 octetStringIndexer, octetStringFilter,
3468 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3470 SLAP_MR_ORDERING, NULL,
3471 NULL, NULL, octetStringOrderingMatch,
3473 "octetStringMatch" },
3475 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3476 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3477 SLAP_MR_SUBSTR, NULL,
3478 NULL, NULL, octetStringSubstringsMatch,
3479 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3480 "octetStringMatch" },
3482 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3483 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3484 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3486 telephoneNumberNormalize, octetStringMatch,
3487 octetStringIndexer, octetStringFilter,
3490 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3492 SLAP_MR_SUBSTR, NULL,
3493 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3494 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3495 "telephoneNumberMatch" },
3497 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3498 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3499 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3500 NULL, NULL, NULL, NULL, NULL, NULL },
3502 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3503 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3504 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3505 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3509 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3510 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3511 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3512 NULL, NULL, NULL, NULL, NULL, NULL },
3514 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3515 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3516 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3517 NULL, generalizedTimeNormalize, octetStringMatch,
3518 generalizedTimeIndexer, generalizedTimeFilter,
3521 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3522 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3523 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3524 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3526 "generalizedTimeMatch" },
3528 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3529 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3530 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3531 integerFirstComponentMatchSyntaxes,
3532 NULL, firstComponentNormalize, integerMatch,
3533 octetStringIndexer, octetStringFilter,
3536 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3537 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3538 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3539 objectIdentifierFirstComponentMatchSyntaxes,
3540 NULL, firstComponentNormalize, octetStringMatch,
3541 octetStringIndexer, octetStringFilter,
3544 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3545 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3546 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3548 NULL, certificateExactNormalize, octetStringMatch,
3549 octetStringIndexer, octetStringFilter,
3551 NULL, NULL, NULL, NULL, NULL,
3555 {"( 2.5.13.35 NAME 'certificateMatch' "
3556 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3557 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3559 NULL, NULL, octetStringMatch,
3560 octetStringIndexer, octetStringFilter,
3562 NULL, NULL, NULL, NULL, NULL,
3566 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3567 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3568 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3569 NULL, IA5StringNormalize, octetStringMatch,
3570 octetStringIndexer, octetStringFilter,
3571 IA5StringApproxMatchOID },
3573 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3574 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3575 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3576 NULL, IA5StringNormalize, octetStringMatch,
3577 octetStringIndexer, octetStringFilter,
3578 IA5StringApproxMatchOID },
3580 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3581 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3582 SLAP_MR_SUBSTR, NULL,
3583 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3584 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3585 "caseIgnoreIA5Match" },
3587 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3588 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3589 SLAP_MR_SUBSTR, NULL,
3590 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3591 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3592 "caseExactIA5Match" },
3594 #ifdef SLAPD_AUTHPASSWD
3595 /* needs updating */
3596 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3597 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3598 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3599 NULL, NULL, authPasswordMatch,
3604 #ifdef SLAPD_ACI_ENABLED
3605 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3606 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3607 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3608 NULL, NULL, OpenLDAPaciMatch,
3613 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3614 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3616 NULL, NULL, integerBitAndMatch,
3620 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3621 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3623 NULL, NULL, integerBitOrMatch,
3627 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3628 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3629 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3630 NULL, UUIDNormalize, octetStringMatch,
3631 octetStringIndexer, octetStringFilter,
3634 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3635 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3636 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3637 NULL, UUIDNormalize, octetStringOrderingMatch,
3638 octetStringIndexer, octetStringFilter,
3641 {"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
3642 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3643 SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
3644 NULL, NULL, csnMatch,
3645 csnIndexer, csnFilter,
3648 {"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
3649 "SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
3650 SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3651 NULL, NULL, csnOrderingMatch,
3655 {NULL, SLAP_MR_NONE, NULL,
3656 NULL, NULL, NULL, NULL, NULL,
3661 slap_schema_init( void )
3666 /* we should only be called once (from main) */
3667 assert( schema_init_done == 0 );
3669 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3670 res = register_syntax( &syntax_defs[i] );
3673 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3674 syntax_defs[i].sd_desc );
3679 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3680 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3681 mrule_defs[i].mrd_compat_syntaxes == NULL )
3684 "slap_schema_init: Ignoring unusable matching rule %s\n",
3685 mrule_defs[i].mrd_desc );
3689 res = register_matching_rule( &mrule_defs[i] );
3693 "slap_schema_init: Error registering matching rule %s\n",
3694 mrule_defs[i].mrd_desc );
3699 res = slap_schema_load();
3700 schema_init_done = 1;
3705 schema_destroy( void )