1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
29 #include "ldap_utf8.h"
32 #include <openssl/x509.h>
33 #include <openssl/err.h>
34 #include <openssl/rsa.h>
35 #include <openssl/crypto.h>
36 #include <openssl/pem.h>
37 #include <openssl/bio.h>
38 #include <openssl/asn1.h>
39 #include <openssl/x509v3.h>
40 #include <openssl/ssl.h>
44 #include "lutil_hash.h"
45 #define HASH_BYTES LUTIL_HASH_BYTES
46 #define HASH_CONTEXT lutil_HASH_CTX
47 #define HASH_Init(c) lutil_HASHInit(c)
48 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
49 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
51 #define OpenLDAPaciMatch NULL
53 /* approx matching rules */
54 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
55 #define directoryStringApproxMatch approxMatch
56 #define directoryStringApproxIndexer approxIndexer
57 #define directoryStringApproxFilter approxFilter
58 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
59 #define IA5StringApproxMatch approxMatch
60 #define IA5StringApproxIndexer approxIndexer
61 #define IA5StringApproxFilter approxFilter
68 /* no value allowed */
69 return LDAP_INVALID_SYNTAX;
77 /* any value allowed */
81 #define berValidate blobValidate
88 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
89 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
96 static int certificateValidate( Syntax *syntax, struct berval *in )
99 unsigned char *p = (unsigned char *)in->bv_val;
101 xcert = d2i_X509(NULL, &p, in->bv_len);
102 if ( !xcert ) return LDAP_INVALID_SYNTAX;
107 #define certificateValidate sequenceValidate
116 struct berval *value,
117 void *assertedValue )
119 struct berval *asserted = (struct berval *) assertedValue;
120 int match = value->bv_len - asserted->bv_len;
123 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
131 octetStringOrderingMatch(
136 struct berval *value,
137 void *assertedValue )
139 struct berval *asserted = (struct berval *) assertedValue;
140 ber_len_t v_len = value->bv_len;
141 ber_len_t av_len = asserted->bv_len;
143 int match = memcmp( value->bv_val, asserted->bv_val,
144 (v_len < av_len ? v_len : av_len) );
146 if( match == 0 ) match = v_len - av_len;
153 HASH_CONTEXT *HASHcontext,
154 unsigned char *HASHdigest,
155 struct berval *prefix,
159 unsigned char *value,
162 HASH_Init(HASHcontext);
163 if(prefix && prefix->bv_len > 0) {
164 HASH_Update(HASHcontext,
165 (unsigned char *)prefix->bv_val, prefix->bv_len);
167 if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
168 HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
169 HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
170 HASH_Update(HASHcontext, value, value_len);
171 HASH_Final(HASHdigest, HASHcontext);
175 /* Index generation function */
176 int octetStringIndexer(
181 struct berval *prefix,
189 HASH_CONTEXT HASHcontext;
190 unsigned char HASHdigest[HASH_BYTES];
191 struct berval digest;
192 digest.bv_val = (char *)HASHdigest;
193 digest.bv_len = sizeof(HASHdigest);
195 for( i=0; values[i].bv_val != NULL; i++ ) {
196 /* just count them */
199 /* we should have at least one value at this point */
202 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
204 slen = syntax->ssyn_oidlen;
205 mlen = mr->smr_oidlen;
207 for( i=0; values[i].bv_val != NULL; i++ ) {
208 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
209 syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len );
210 ber_dupbv_x( &keys[i], &digest, ctx );
213 keys[i].bv_val = NULL;
221 /* Index generation function */
222 int octetStringFilter(
227 struct berval *prefix,
228 void * assertedValue,
234 HASH_CONTEXT HASHcontext;
235 unsigned char HASHdigest[HASH_BYTES];
236 struct berval *value = (struct berval *) assertedValue;
237 struct berval digest;
238 digest.bv_val = (char *)HASHdigest;
239 digest.bv_len = sizeof(HASHdigest);
241 slen = syntax->ssyn_oidlen;
242 mlen = mr->smr_oidlen;
244 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
246 hashDigestify( &HASHcontext, HASHdigest, prefix, 0,
247 syntax, mr, (unsigned char *)value->bv_val, value->bv_len );
249 ber_dupbv_x( keys, &digest, ctx );
250 keys[1].bv_val = NULL;
259 octetStringSubstringsMatch(
264 struct berval *value,
265 void *assertedValue )
268 SubstringsAssertion *sub = assertedValue;
269 struct berval left = *value;
273 /* Add up asserted input length */
274 if( sub->sa_initial.bv_val ) {
275 inlen += sub->sa_initial.bv_len;
278 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
279 inlen += sub->sa_any[i].bv_len;
282 if( sub->sa_final.bv_val ) {
283 inlen += sub->sa_final.bv_len;
286 if( sub->sa_initial.bv_val ) {
287 if( inlen > left.bv_len ) {
292 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
293 sub->sa_initial.bv_len );
299 left.bv_val += sub->sa_initial.bv_len;
300 left.bv_len -= sub->sa_initial.bv_len;
301 inlen -= sub->sa_initial.bv_len;
304 if( sub->sa_final.bv_val ) {
305 if( inlen > left.bv_len ) {
310 match = memcmp( sub->sa_final.bv_val,
311 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
312 sub->sa_final.bv_len );
318 left.bv_len -= sub->sa_final.bv_len;
319 inlen -= sub->sa_final.bv_len;
323 for(i=0; sub->sa_any[i].bv_val; i++) {
328 if( inlen > left.bv_len ) {
329 /* not enough length */
334 if( sub->sa_any[i].bv_len == 0 ) {
338 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
345 idx = p - left.bv_val;
347 if( idx >= left.bv_len ) {
348 /* this shouldn't happen */
355 if( sub->sa_any[i].bv_len > left.bv_len ) {
356 /* not enough left */
361 match = memcmp( left.bv_val,
362 sub->sa_any[i].bv_val,
363 sub->sa_any[i].bv_len );
371 left.bv_val += sub->sa_any[i].bv_len;
372 left.bv_len -= sub->sa_any[i].bv_len;
373 inlen -= sub->sa_any[i].bv_len;
382 /* Substrings Index generation function */
384 octetStringSubstringsIndexer(
389 struct berval *prefix,
394 ber_len_t i, j, len, nkeys;
398 HASH_CONTEXT HASHcontext;
399 unsigned char HASHdigest[HASH_BYTES];
400 struct berval digest;
401 digest.bv_val = (char *)HASHdigest;
402 digest.bv_len = sizeof(HASHdigest);
406 for( i=0; values[i].bv_val != NULL; i++ ) {
407 /* count number of indices to generate */
408 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
409 if( values[i].bv_len >= SLAPD_GLOBAL(index_substr_if_maxlen) ) {
410 nkeys += SLAPD_GLOBAL(index_substr_if_maxlen) -
411 (SLAPD_GLOBAL(index_substr_if_minlen) - 1);
412 } else if( values[i].bv_len >= SLAPD_GLOBAL(index_substr_if_minlen) ) {
413 nkeys += values[i].bv_len - (SLAPD_GLOBAL(index_substr_if_minlen) - 1);
417 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
418 if( values[i].bv_len >= SLAPD_GLOBAL(index_substr_any_len) ) {
419 nkeys += values[i].bv_len - (SLAPD_GLOBAL(index_substr_any_len) - 1);
423 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
424 if( values[i].bv_len >= SLAPD_GLOBAL(index_substr_if_maxlen) ) {
425 nkeys += SLAPD_GLOBAL(index_substr_if_maxlen) -
426 (SLAPD_GLOBAL(index_substr_if_minlen) - 1);
427 } else if( values[i].bv_len >= SLAPD_GLOBAL(index_substr_if_minlen) ) {
428 nkeys += values[i].bv_len - (SLAPD_GLOBAL(index_substr_if_minlen) - 1);
434 /* no keys to generate */
439 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
441 slen = syntax->ssyn_oidlen;
442 mlen = mr->smr_oidlen;
445 for( i=0; values[i].bv_val != NULL; i++ ) {
448 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
449 ( values[i].bv_len >= SLAPD_GLOBAL(index_substr_any_len) ) )
451 char pre = SLAP_INDEX_SUBSTR_PREFIX;
452 max = values[i].bv_len - (SLAPD_GLOBAL(index_substr_any_len) - 1);
454 for( j=0; j<max; j++ ) {
455 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
456 syntax, mr, (unsigned char *)&values[i].bv_val[j], SLAPD_GLOBAL(index_substr_any_len));
457 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
461 /* skip if too short */
462 if( values[i].bv_len < SLAPD_GLOBAL(index_substr_if_minlen) ) continue;
464 max = SLAPD_GLOBAL(index_substr_if_maxlen) < values[i].bv_len
465 ? SLAPD_GLOBAL(index_substr_if_maxlen) : values[i].bv_len;
467 for( j=SLAPD_GLOBAL(index_substr_if_minlen); j<=max; j++ ) {
470 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
471 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
472 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
473 syntax, mr, (unsigned char *)values[i].bv_val, j );
474 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
477 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
478 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
479 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
480 syntax, mr, (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
481 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
488 keys[nkeys].bv_val = NULL;
499 octetStringSubstringsFilter (
504 struct berval *prefix,
505 void * assertedValue,
509 SubstringsAssertion *sa;
511 ber_len_t len, max, nkeys = 0;
512 size_t slen, mlen, klen;
514 HASH_CONTEXT HASHcontext;
515 unsigned char HASHdigest[HASH_BYTES];
516 struct berval *value;
517 struct berval digest;
519 sa = (SubstringsAssertion *) assertedValue;
521 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
522 sa->sa_initial.bv_val != NULL &&
523 sa->sa_initial.bv_len >= SLAPD_GLOBAL(index_substr_if_minlen) )
526 if ( sa->sa_initial.bv_len > SLAPD_GLOBAL(index_substr_if_maxlen) &&
527 ( flags & SLAP_INDEX_SUBSTR_ANY ))
529 nkeys += (sa->sa_initial.bv_len - SLAPD_GLOBAL(index_substr_if_maxlen)) / SLAPD_GLOBAL(index_substr_any_step);
533 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
535 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
536 if( sa->sa_any[i].bv_len >= SLAPD_GLOBAL(index_substr_any_len) ) {
537 /* don't bother accounting with stepping */
538 nkeys += sa->sa_any[i].bv_len -
539 ( SLAPD_GLOBAL(index_substr_any_len) - 1 );
544 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
545 sa->sa_final.bv_val != NULL &&
546 sa->sa_final.bv_len >= SLAPD_GLOBAL(index_substr_if_minlen) )
549 if ( sa->sa_final.bv_len > SLAPD_GLOBAL(index_substr_if_maxlen) &&
550 ( flags & SLAP_INDEX_SUBSTR_ANY ))
552 nkeys += (sa->sa_final.bv_len - SLAPD_GLOBAL(index_substr_if_maxlen)) / SLAPD_GLOBAL(index_substr_any_step);
561 digest.bv_val = (char *)HASHdigest;
562 digest.bv_len = sizeof(HASHdigest);
564 slen = syntax->ssyn_oidlen;
565 mlen = mr->smr_oidlen;
567 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
570 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
571 sa->sa_initial.bv_val != NULL &&
572 sa->sa_initial.bv_len >= SLAPD_GLOBAL(index_substr_if_minlen) )
574 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
575 value = &sa->sa_initial;
577 klen = SLAPD_GLOBAL(index_substr_if_maxlen) < value->bv_len
578 ? SLAPD_GLOBAL(index_substr_if_maxlen) : value->bv_len;
580 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
581 syntax, mr, (unsigned char *)value->bv_val, klen );
582 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
584 /* If initial is too long and we have subany indexed, use it
585 * to match the excess...
587 if (value->bv_len > SLAPD_GLOBAL(index_substr_if_maxlen) && (flags & SLAP_INDEX_SUBSTR_ANY))
590 pre = SLAP_INDEX_SUBSTR_PREFIX;
591 for ( j=SLAPD_GLOBAL(index_substr_if_maxlen)-1; j <= value->bv_len - SLAPD_GLOBAL(index_substr_any_len); j+=SLAPD_GLOBAL(index_substr_any_step) )
593 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
594 syntax, mr, (unsigned char *)&value->bv_val[j], SLAPD_GLOBAL(index_substr_any_len) );
595 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
600 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
602 pre = SLAP_INDEX_SUBSTR_PREFIX;
603 klen = SLAPD_GLOBAL(index_substr_any_len);
605 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
606 if( sa->sa_any[i].bv_len < SLAPD_GLOBAL(index_substr_any_len) ) {
610 value = &sa->sa_any[i];
613 j <= value->bv_len - SLAPD_GLOBAL(index_substr_any_len);
614 j += SLAPD_GLOBAL(index_substr_any_step) )
616 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
617 syntax, mr, (unsigned char *)&value->bv_val[j], klen );
618 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
623 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
624 sa->sa_final.bv_val != NULL &&
625 sa->sa_final.bv_len >= SLAPD_GLOBAL(index_substr_if_minlen) )
627 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
628 value = &sa->sa_final;
630 klen = SLAPD_GLOBAL(index_substr_if_maxlen) < value->bv_len
631 ? SLAPD_GLOBAL(index_substr_if_maxlen) : value->bv_len;
633 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
634 syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
635 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
637 /* If final is too long and we have subany indexed, use it
638 * to match the excess...
640 if (value->bv_len > SLAPD_GLOBAL(index_substr_if_maxlen) && (flags & SLAP_INDEX_SUBSTR_ANY))
643 pre = SLAP_INDEX_SUBSTR_PREFIX;
644 for ( j=0; j <= value->bv_len - SLAPD_GLOBAL(index_substr_if_maxlen); j+=SLAPD_GLOBAL(index_substr_any_step) )
646 hashDigestify( &HASHcontext, HASHdigest, prefix, pre,
647 syntax, mr, (unsigned char *)&value->bv_val[j], SLAPD_GLOBAL(index_substr_any_len) );
648 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
654 keys[nkeys].bv_val = NULL;
671 /* very unforgiving validation, requires no normalization
672 * before simplistic matching
674 if( in->bv_len < 3 ) {
675 return LDAP_INVALID_SYNTAX;
679 * RFC 2252 section 6.3 Bit String
680 * bitstring = "'" *binary-digit "'B"
681 * binary-digit = "0" / "1"
682 * example: '0101111101'B
685 if( in->bv_val[0] != '\'' ||
686 in->bv_val[in->bv_len-2] != '\'' ||
687 in->bv_val[in->bv_len-1] != 'B' )
689 return LDAP_INVALID_SYNTAX;
692 for( i=in->bv_len-3; i>0; i-- ) {
693 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
694 return LDAP_INVALID_SYNTAX;
702 * Syntax is [RFC2252]:
707 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
709 Values in this syntax are encoded according to the following BNF:
711 bitstring = "'" *binary-digit "'B"
713 binary-digit = "0" / "1"
717 6.21. Name And Optional UID
719 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
721 Values in this syntax are encoded according to the following BNF:
723 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
725 Although the '#' character may occur in a string representation of a
726 distinguished name, no additional special quoting is done. This
727 syntax has been added subsequent to RFC 1778.
731 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
734 * draft-ietf-ldapbis-syntaxes-xx.txt says:
739 A value of the Bit String syntax is a sequence of binary digits. The
740 LDAP-specific encoding of a value of this syntax is defined by the
743 BitString = SQUOTE *binary-digit SQUOTE "B"
745 binary-digit = "0" / "1"
747 The <SQUOTE> rule is defined in [MODELS].
752 The LDAP definition for the Bit String syntax is:
754 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
756 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
760 3.3.21. Name and Optional UID
762 A value of the Name and Optional UID syntax is the distinguished name
763 [MODELS] of an entity optionally accompanied by a unique identifier
764 that serves to differentiate the entity from others with an identical
767 The LDAP-specific encoding of a value of this syntax is defined by
770 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
772 The <BitString> rule is defined in Section 3.3.2. The
773 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
776 Note that although the '#' character may occur in the string
777 representation of a distinguished name, no additional escaping of
778 this character is performed when a <distinguishedName> is encoded in
779 a <NameAndOptionalUID>.
782 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
784 The LDAP definition for the Name and Optional UID syntax is:
786 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
788 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
792 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
795 1.4. Common ABNF Productions
798 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
800 SQUOTE = %x27 ; single quote ("'")
804 * Note: normalization strips any leading "0"s, unless the
805 * bit string is exactly "'0'B", so the normalized example,
806 * in slapd, would result in
808 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
810 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
811 * i.e. "#", doesn't have to be escaped except when at the
812 * beginning of a value, the definition of Name and Optional
813 * UID appears to be flawed, because there is no clear means
814 * to determine whether the UID part is present or not.
818 * cn=Someone,dc=example,dc=com#'1'B
820 * could be either a NameAndOptionalUID with trailing UID, i.e.
822 * DN = "cn=Someone,dc=example,dc=com"
825 * or a NameAndOptionalUID with no trailing UID, and the AVA
826 * in the last RDN made of
829 * attributeValue = com#'1'B
831 * in fact "com#'1'B" is a valid IA5 string.
833 * As a consequence, current slapd code assumes that the
834 * presence of portions of a BitString at the end of the string
835 * representation of a NameAndOptionalUID means a BitString
836 * is expected, and cause an error otherwise. This is quite
837 * arbitrary, and might change in the future.
847 struct berval dn, uid;
849 if( in->bv_len == 0 ) return LDAP_SUCCESS;
851 ber_dupbv( &dn, in );
852 if( !dn.bv_val ) return LDAP_OTHER;
854 /* if there's a "#", try bitStringValidate()... */
855 uid.bv_val = strrchr( dn.bv_val, '#' );
858 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
860 rc = bitStringValidate( NULL, &uid );
861 if ( rc == LDAP_SUCCESS ) {
862 /* in case of success, trim the UID,
863 * otherwise treat it as part of the DN */
864 dn.bv_len -= uid.bv_len + 1;
865 uid.bv_val[-1] = '\0';
869 rc = dnValidate( NULL, &dn );
871 ber_memfree( dn.bv_val );
886 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
888 if( val->bv_len == 0 ) {
889 ber_dupbv_x( out, val, ctx );
891 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
892 return LDAP_INVALID_SYNTAX;
896 struct berval dnval = *val;
897 struct berval uidval = BER_BVNULL;
899 uidval.bv_val = strrchr( val->bv_val, '#' );
900 if ( uidval.bv_val ) {
902 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
904 rc = bitStringValidate( NULL, &uidval );
906 if ( rc == LDAP_SUCCESS ) {
907 ber_dupbv_x( &dnval, val, ctx );
908 dnval.bv_len -= uidval.bv_len + 1;
909 dnval.bv_val[dnval.bv_len] = '\0';
912 uidval.bv_val = NULL;
916 rc = dnPretty( syntax, &dnval, out, ctx );
917 if ( dnval.bv_val != val->bv_val ) {
918 slap_sl_free( dnval.bv_val, ctx );
920 if( rc != LDAP_SUCCESS ) {
924 if( uidval.bv_val ) {
928 tmp = slap_sl_realloc( out->bv_val, out->bv_len
929 + STRLENOF( "#" ) + uidval.bv_len + 1,
932 ber_memfree_x( out->bv_val, ctx );
936 out->bv_val[out->bv_len++] = '#';
937 out->bv_val[out->bv_len++] = '\'';
939 got1 = uidval.bv_len < sizeof("'0'B");
940 for( i = 1; i < uidval.bv_len - 2; i++ ) {
941 c = uidval.bv_val[i];
944 if( got1 ) out->bv_val[out->bv_len++] = c;
948 out->bv_val[out->bv_len++] = c;
953 out->bv_val[out->bv_len++] = '\'';
954 out->bv_val[out->bv_len++] = 'B';
955 out->bv_val[out->bv_len] = '\0';
959 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
965 uniqueMemberNormalize(
970 struct berval *normalized,
976 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
978 ber_dupbv_x( &out, val, ctx );
979 if ( BER_BVISEMPTY( &out ) ) {
983 struct berval uid = BER_BVNULL;
985 uid.bv_val = strrchr( out.bv_val, '#' );
988 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
990 rc = bitStringValidate( NULL, &uid );
991 if ( rc == LDAP_SUCCESS ) {
992 uid.bv_val[-1] = '\0';
993 out.bv_len -= uid.bv_len + 1;
999 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1001 if( rc != LDAP_SUCCESS ) {
1002 slap_sl_free( out.bv_val, ctx );
1003 return LDAP_INVALID_SYNTAX;
1009 tmp = ch_realloc( normalized->bv_val,
1010 normalized->bv_len + uid.bv_len
1011 + STRLENOF("#") + 1 );
1012 if ( tmp == NULL ) {
1013 ber_memfree_x( normalized->bv_val, ctx );
1017 normalized->bv_val = tmp;
1019 /* insert the separator */
1020 normalized->bv_val[normalized->bv_len++] = '#';
1022 /* append the UID */
1023 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1024 uid.bv_val, uid.bv_len );
1025 normalized->bv_len += uid.bv_len;
1028 normalized->bv_val[normalized->bv_len] = '\0';
1031 slap_sl_free( out.bv_val, ctx );
1034 return LDAP_SUCCESS;
1043 struct berval *value,
1044 void *assertedValue )
1047 struct berval *asserted = (struct berval *) assertedValue;
1048 struct berval assertedDN = *asserted;
1049 struct berval assertedUID = BER_BVNULL;
1050 struct berval valueDN = BER_BVNULL;
1051 struct berval valueUID = BER_BVNULL;
1053 if ( !BER_BVISEMPTY( asserted ) ) {
1054 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1055 if ( !BER_BVISNULL( &assertedUID ) ) {
1056 assertedUID.bv_val++;
1057 assertedUID.bv_len = assertedDN.bv_len
1058 - ( assertedUID.bv_val - assertedDN.bv_val );
1060 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1061 assertedDN.bv_len -= assertedUID.bv_len + 1;
1064 BER_BVZERO( &assertedUID );
1069 if ( !BER_BVISEMPTY( value ) ) {
1072 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1073 if ( !BER_BVISNULL( &valueUID ) ) {
1075 valueUID.bv_len = valueDN.bv_len
1076 - ( valueUID.bv_val - valueDN.bv_val );
1078 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1079 valueDN.bv_len -= valueUID.bv_len + 1;
1082 BER_BVZERO( &valueUID );
1087 if( valueUID.bv_len && assertedUID.bv_len ) {
1088 match = valueUID.bv_len - assertedUID.bv_len;
1091 return LDAP_SUCCESS;
1094 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1097 return LDAP_SUCCESS;
1101 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1105 * Handling boolean syntax and matching is quite rigid.
1106 * A more flexible approach would be to allow a variety
1107 * of strings to be normalized and prettied into TRUE
1115 /* very unforgiving validation, requires no normalization
1116 * before simplistic matching
1119 if( in->bv_len == 4 ) {
1120 if( bvmatch( in, &slap_true_bv ) ) {
1121 return LDAP_SUCCESS;
1123 } else if( in->bv_len == 5 ) {
1124 if( bvmatch( in, &slap_false_bv ) ) {
1125 return LDAP_SUCCESS;
1129 return LDAP_INVALID_SYNTAX;
1138 struct berval *value,
1139 void *assertedValue )
1141 /* simplistic matching allowed by rigid validation */
1142 struct berval *asserted = (struct berval *) assertedValue;
1143 *matchp = value->bv_len != asserted->bv_len;
1144 return LDAP_SUCCESS;
1147 /*-------------------------------------------------------------------
1148 LDAP/X.500 string syntax / matching rules have a few oddities. This
1149 comment attempts to detail how slapd(8) treats them.
1152 StringSyntax X.500 LDAP Matching/Comments
1153 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1154 PrintableString subset subset i/e + ignore insignificant spaces
1155 PrintableString subset subset i/e + ignore insignificant spaces
1156 NumericString subset subset ignore all spaces
1157 IA5String ASCII ASCII i/e + ignore insignificant spaces
1158 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1160 TelephoneNumber subset subset i + ignore all spaces and "-"
1162 See draft-ietf-ldapbis-strpro for details (once published).
1166 In X.500(93), a directory string can be either a PrintableString,
1167 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1168 In later versions, more CHOICEs were added. In all cases the string
1171 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1172 A directory string cannot be zero length.
1174 For matching, there are both case ignore and exact rules. Both
1175 also require that "insignificant" spaces be ignored.
1176 spaces before the first non-space are ignored;
1177 spaces after the last non-space are ignored;
1178 spaces after a space are ignored.
1179 Note: by these rules (and as clarified in X.520), a string of only
1180 spaces is to be treated as if held one space, not empty (which
1181 would be a syntax error).
1184 In ASN.1, numeric string is just a string of digits and spaces
1185 and could be empty. However, in X.500, all attribute values of
1186 numeric string carry a non-empty constraint. For example:
1188 internationalISDNNumber ATTRIBUTE ::= {
1189 WITH SYNTAX InternationalISDNNumber
1190 EQUALITY MATCHING RULE numericStringMatch
1191 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1192 ID id-at-internationalISDNNumber }
1193 InternationalISDNNumber ::=
1194 NumericString (SIZE(1..ub-international-isdn-number))
1196 Unforunately, some assertion values are don't carry the same
1197 constraint (but its unclear how such an assertion could ever
1198 be true). In LDAP, there is one syntax (numericString) not two
1199 (numericString with constraint, numericString without constraint).
1200 This should be treated as numericString with non-empty constraint.
1201 Note that while someone may have no ISDN number, there are no ISDN
1202 numbers which are zero length.
1204 In matching, spaces are ignored.
1207 In ASN.1, Printable string is just a string of printable characters
1208 and can be empty. In X.500, semantics much like NumericString (see
1209 serialNumber for a like example) excepting uses insignificant space
1210 handling instead of ignore all spaces.
1213 Basically same as PrintableString. There are no examples in X.500,
1214 but same logic applies. So we require them to be non-empty as
1217 -------------------------------------------------------------------*/
1226 unsigned char *u = (unsigned char *)in->bv_val;
1228 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1229 /* directory strings cannot be empty */
1230 return LDAP_INVALID_SYNTAX;
1233 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1234 /* get the length indicated by the first byte */
1235 len = LDAP_UTF8_CHARLEN2( u, len );
1237 /* very basic checks */
1240 if( (u[5] & 0xC0) != 0x80 ) {
1241 return LDAP_INVALID_SYNTAX;
1244 if( (u[4] & 0xC0) != 0x80 ) {
1245 return LDAP_INVALID_SYNTAX;
1248 if( (u[3] & 0xC0) != 0x80 ) {
1249 return LDAP_INVALID_SYNTAX;
1252 if( (u[2] & 0xC0 )!= 0x80 ) {
1253 return LDAP_INVALID_SYNTAX;
1256 if( (u[1] & 0xC0) != 0x80 ) {
1257 return LDAP_INVALID_SYNTAX;
1260 /* CHARLEN already validated it */
1263 return LDAP_INVALID_SYNTAX;
1266 /* make sure len corresponds with the offset
1267 to the next character */
1268 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1272 return LDAP_INVALID_SYNTAX;
1275 return LDAP_SUCCESS;
1279 UTF8StringNormalize(
1284 struct berval *normalized,
1287 struct berval tmp, nvalue;
1291 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1293 if( val->bv_val == NULL ) {
1294 /* assume we're dealing with a syntax (e.g., UTF8String)
1295 * which allows empty strings
1297 normalized->bv_len = 0;
1298 normalized->bv_val = NULL;
1299 return LDAP_SUCCESS;
1302 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1303 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1304 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1305 ? LDAP_UTF8_APPROX : 0;
1307 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1312 /* collapse spaces (in place) */
1314 nvalue.bv_val = tmp.bv_val;
1316 wasspace=1; /* trim leading spaces */
1317 for( i=0; i<tmp.bv_len; i++) {
1318 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1319 if( wasspace++ == 0 ) {
1320 /* trim repeated spaces */
1321 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1325 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1329 if( nvalue.bv_len ) {
1331 /* last character was a space, trim it */
1334 nvalue.bv_val[nvalue.bv_len] = '\0';
1337 /* string of all spaces is treated as one space */
1338 nvalue.bv_val[0] = ' ';
1339 nvalue.bv_val[1] = '\0';
1343 *normalized = nvalue;
1344 return LDAP_SUCCESS;
1347 #if defined(SLAPD_APPROX_INITIALS)
1348 # define SLAPD_APPROX_DELIMITER "._ "
1349 # define SLAPD_APPROX_WORDLEN 2
1351 # define SLAPD_APPROX_DELIMITER " "
1352 # define SLAPD_APPROX_WORDLEN 1
1361 struct berval *value,
1362 void *assertedValue )
1364 struct berval *nval, *assertv;
1365 char *val, **values, **words, *c;
1366 int i, count, len, nextchunk=0, nextavail=0;
1368 /* Yes, this is necessary */
1369 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1370 if( nval == NULL ) {
1372 return LDAP_SUCCESS;
1375 /* Yes, this is necessary */
1376 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1377 NULL, LDAP_UTF8_APPROX, NULL );
1378 if( assertv == NULL ) {
1381 return LDAP_SUCCESS;
1384 /* Isolate how many words there are */
1385 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1386 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1387 if ( c == NULL ) break;
1392 /* Get a phonetic copy of each word */
1393 words = (char **)ch_malloc( count * sizeof(char *) );
1394 values = (char **)ch_malloc( count * sizeof(char *) );
1395 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1397 values[i] = phonetic(c);
1400 /* Work through the asserted value's words, to see if at least some
1401 of the words are there, in the same order. */
1403 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1404 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1409 #if defined(SLAPD_APPROX_INITIALS)
1410 else if( len == 1 ) {
1411 /* Single letter words need to at least match one word's initial */
1412 for( i=nextavail; i<count; i++ )
1413 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1420 /* Isolate the next word in the asserted value and phonetic it */
1421 assertv->bv_val[nextchunk+len] = '\0';
1422 val = phonetic( assertv->bv_val + nextchunk );
1424 /* See if this phonetic chunk is in the remaining words of *value */
1425 for( i=nextavail; i<count; i++ ){
1426 if( !strcmp( val, values[i] ) ){
1434 /* This chunk in the asserted value was NOT within the *value. */
1440 /* Go on to the next word in the asserted value */
1444 /* If some of the words were seen, call it a match */
1445 if( nextavail > 0 ) {
1452 /* Cleanup allocs */
1453 ber_bvfree( assertv );
1454 for( i=0; i<count; i++ ) {
1455 ch_free( values[i] );
1461 return LDAP_SUCCESS;
1470 struct berval *prefix,
1476 int i,j, len, wordcount, keycount=0;
1477 struct berval *newkeys;
1478 BerVarray keys=NULL;
1480 for( j=0; values[j].bv_val != NULL; j++ ) {
1481 struct berval val = BER_BVNULL;
1482 /* Yes, this is necessary */
1483 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1484 assert( val.bv_val != NULL );
1486 /* Isolate how many words there are. There will be a key for each */
1487 for( wordcount = 0, c = val.bv_val; *c; c++) {
1488 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1489 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1491 if (*c == '\0') break;
1495 /* Allocate/increase storage to account for new keys */
1496 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1497 * sizeof(struct berval) );
1498 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1499 if( keys ) ch_free( keys );
1502 /* Get a phonetic copy of each word */
1503 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1505 if( len < SLAPD_APPROX_WORDLEN ) continue;
1506 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1511 ber_memfree( val.bv_val );
1513 keys[keycount].bv_val = NULL;
1516 return LDAP_SUCCESS;
1525 struct berval *prefix,
1526 void * assertedValue,
1535 /* Yes, this is necessary */
1536 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1537 NULL, LDAP_UTF8_APPROX, NULL );
1538 if( val == NULL || val->bv_val == NULL ) {
1539 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1540 keys[0].bv_val = NULL;
1543 return LDAP_SUCCESS;
1546 /* Isolate how many words there are. There will be a key for each */
1547 for( count = 0,c = val->bv_val; *c; c++) {
1548 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1549 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1551 if (*c == '\0') break;
1555 /* Allocate storage for new keys */
1556 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1558 /* Get a phonetic copy of each word */
1559 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1561 if( len < SLAPD_APPROX_WORDLEN ) continue;
1562 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1568 keys[count].bv_val = NULL;
1571 return LDAP_SUCCESS;
1574 /* Remove all spaces and '-' characters */
1576 telephoneNumberNormalize(
1581 struct berval *normalized,
1586 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1588 /* validator should have refused an empty string */
1589 assert( val->bv_len );
1591 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1593 for( p = val->bv_val; *p; p++ ) {
1594 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1600 normalized->bv_len = q - normalized->bv_val;
1602 if( normalized->bv_len == 0 ) {
1603 slap_sl_free( normalized->bv_val, ctx );
1604 normalized->bv_val = NULL;
1605 return LDAP_INVALID_SYNTAX;
1608 return LDAP_SUCCESS;
1616 struct berval val = *in;
1618 if( val.bv_len == 0 ) {
1619 /* disallow empty strings */
1620 return LDAP_INVALID_SYNTAX;
1623 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1624 if ( val.bv_len == 1 ) {
1625 return LDAP_SUCCESS;
1628 if ( val.bv_val[0] == '0' ) {
1635 while ( OID_LEADCHAR( val.bv_val[0] )) {
1639 if ( val.bv_len == 0 ) {
1640 return LDAP_SUCCESS;
1644 if( !OID_SEPARATOR( val.bv_val[0] )) {
1652 return LDAP_INVALID_SYNTAX;
1661 struct berval val = *in;
1663 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1665 if ( val.bv_val[0] == '-' ) {
1669 if( val.bv_len == 0 ) { /* bare "-" */
1670 return LDAP_INVALID_SYNTAX;
1673 if( val.bv_val[0] == '0' ) { /* "-0" */
1674 return LDAP_INVALID_SYNTAX;
1677 } else if ( val.bv_val[0] == '0' ) {
1678 if( val.bv_len > 1 ) { /* "0<more>" */
1679 return LDAP_INVALID_SYNTAX;
1682 return LDAP_SUCCESS;
1685 for( i=0; i < val.bv_len; i++ ) {
1686 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1687 return LDAP_INVALID_SYNTAX;
1691 return LDAP_SUCCESS;
1700 struct berval *value,
1701 void *assertedValue )
1703 struct berval *asserted = (struct berval *) assertedValue;
1704 int vsign = 1, asign = 1; /* default sign = '+' */
1709 if( v.bv_val[0] == '-' ) {
1715 if( v.bv_len == 0 ) vsign = 0;
1718 if( a.bv_val[0] == '-' ) {
1724 if( a.bv_len == 0 ) vsign = 0;
1726 match = vsign - asign;
1728 match = ( v.bv_len != a.bv_len
1729 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1730 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1731 if( vsign < 0 ) match = -match;
1735 return LDAP_SUCCESS;
1739 countryStringValidate(
1741 struct berval *val )
1743 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1745 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1746 return LDAP_INVALID_SYNTAX;
1748 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1749 return LDAP_INVALID_SYNTAX;
1752 return LDAP_SUCCESS;
1756 printableStringValidate(
1758 struct berval *val )
1762 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1764 for(i=0; i < val->bv_len; i++) {
1765 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1766 return LDAP_INVALID_SYNTAX;
1770 return LDAP_SUCCESS;
1774 printablesStringValidate(
1776 struct berval *val )
1780 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1782 for(i=0,len=0; i < val->bv_len; i++) {
1783 int c = val->bv_val[i];
1787 return LDAP_INVALID_SYNTAX;
1791 } else if ( SLAP_PRINTABLE(c) ) {
1794 return LDAP_INVALID_SYNTAX;
1799 return LDAP_INVALID_SYNTAX;
1802 return LDAP_SUCCESS;
1808 struct berval *val )
1812 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1814 for(i=0; i < val->bv_len; i++) {
1815 if( !LDAP_ASCII(val->bv_val[i]) ) {
1816 return LDAP_INVALID_SYNTAX;
1820 return LDAP_SUCCESS;
1829 struct berval *normalized,
1833 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1835 assert( val->bv_len );
1837 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1841 /* Ignore initial whitespace */
1842 while ( ASCII_SPACE( *p ) ) p++;
1844 normalized->bv_val = ber_strdup_x( p, ctx );
1845 p = q = normalized->bv_val;
1848 if ( ASCII_SPACE( *p ) ) {
1851 /* Ignore the extra whitespace */
1852 while ( ASCII_SPACE( *p ) ) {
1856 } else if ( casefold ) {
1857 /* Most IA5 rules require casefolding */
1858 *q++ = TOLOWER(*p); p++;
1865 assert( normalized->bv_val <= p );
1869 * If the string ended in space, backup the pointer one
1870 * position. One is enough because the above loop collapsed
1871 * all whitespace to a single space.
1873 if ( ASCII_SPACE( q[-1] ) ) --q;
1875 /* null terminate */
1878 normalized->bv_len = q - normalized->bv_val;
1879 if( normalized->bv_len == 0 ) {
1880 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1881 normalized->bv_val[0] = ' ';
1882 normalized->bv_val[1] = '\0';
1883 normalized->bv_len = 1;
1886 return LDAP_SUCCESS;
1895 if( in->bv_len != 36 ) {
1896 return LDAP_INVALID_SYNTAX;
1899 for( i=0; i<36; i++ ) {
1905 if( in->bv_val[i] != '-' ) {
1906 return LDAP_INVALID_SYNTAX;
1910 if( !ASCII_HEX( in->bv_val[i]) ) {
1911 return LDAP_INVALID_SYNTAX;
1916 return LDAP_SUCCESS;
1925 struct berval *normalized,
1928 unsigned char octet = '\0';
1931 normalized->bv_len = 16;
1932 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1934 for( i=0, j=0; i<36; i++ ) {
1935 unsigned char nibble;
1936 if( val->bv_val[i] == '-' ) {
1939 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1940 nibble = val->bv_val[i] - '0';
1942 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1943 nibble = val->bv_val[i] - ('a'-10);
1945 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1946 nibble = val->bv_val[i] - ('A'-10);
1949 slap_sl_free( normalized->bv_val, ctx );
1950 return LDAP_INVALID_SYNTAX;
1955 normalized->bv_val[j>>1] = octet;
1957 octet = nibble << 4;
1962 normalized->bv_val[normalized->bv_len] = 0;
1963 return LDAP_SUCCESS;
1969 numericStringValidate(
1975 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1977 for(i=0; i < in->bv_len; i++) {
1978 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1979 return LDAP_INVALID_SYNTAX;
1983 return LDAP_SUCCESS;
1987 numericStringNormalize(
1992 struct berval *normalized,
1995 /* removal all spaces */
1998 assert( val->bv_len );
2000 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2003 q = normalized->bv_val;
2006 if ( ASCII_SPACE( *p ) ) {
2007 /* Ignore whitespace */
2014 /* we should have copied no more then is in val */
2015 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2017 /* null terminate */
2020 normalized->bv_len = q - normalized->bv_val;
2022 if( normalized->bv_len == 0 ) {
2023 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2024 normalized->bv_val[0] = ' ';
2025 normalized->bv_val[1] = '\0';
2026 normalized->bv_len = 1;
2029 return LDAP_SUCCESS;
2033 * Integer conversion macros that will use the largest available
2036 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2037 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2038 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2039 # define SLAP_LONG_MAX LLONG_MAX
2040 # define SLAP_LONG_MIN LLONG_MIN
2041 # define SLAP_LONG long long
2043 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2044 # define SLAP_LONG_MAX LONG_MAX
2045 # define SLAP_LONG_MIN LONG_MIN
2046 # define SLAP_LONG long
2047 #endif /* HAVE_STRTOLL ... */
2055 struct berval *value,
2056 void *assertedValue )
2058 SLAP_LONG lValue, lAssertedValue;
2060 /* safe to assume integers are NUL terminated? */
2061 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2062 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2065 return LDAP_CONSTRAINT_VIOLATION;
2068 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2070 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2073 return LDAP_CONSTRAINT_VIOLATION;
2076 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2077 return LDAP_SUCCESS;
2086 struct berval *value,
2087 void *assertedValue )
2089 SLAP_LONG lValue, lAssertedValue;
2091 /* safe to assume integers are NUL terminated? */
2092 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2093 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2096 return LDAP_CONSTRAINT_VIOLATION;
2099 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2101 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2104 return LDAP_CONSTRAINT_VIOLATION;
2107 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2108 return LDAP_SUCCESS;
2112 serialNumberAndIssuerValidate(
2119 struct berval sn, i;
2120 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2122 i.bv_val = strchr( in->bv_val, '$' );
2123 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2125 sn.bv_val = in->bv_val;
2126 sn.bv_len = i.bv_val - in->bv_val;
2129 i.bv_len = in->bv_len - (sn.bv_len + 1);
2131 /* validate serial number (strict for now) */
2132 for( n=0; n < sn.bv_len; n++ ) {
2133 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2137 rc = dnValidate( NULL, &i );
2138 if( rc ) return LDAP_INVALID_SYNTAX;
2140 return LDAP_SUCCESS;
2144 serialNumberAndIssuerPretty(
2153 struct berval sn, i, newi;
2158 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2159 val->bv_val, 0, 0 );
2161 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2163 i.bv_val = strchr( val->bv_val, '$' );
2164 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2166 sn.bv_val = val->bv_val;
2167 sn.bv_len = i.bv_val - val->bv_val;
2170 i.bv_len = val->bv_len - (sn.bv_len + 1);
2172 /* eat leading zeros */
2173 for( n=0; n < (sn.bv_len-1); n++ ) {
2174 if( sn.bv_val[n] != '0' ) break;
2179 for( n=0; n < sn.bv_len; n++ ) {
2180 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2184 rc = dnPretty( syntax, &i, &newi, ctx );
2185 if( rc ) return LDAP_INVALID_SYNTAX;
2187 /* make room from sn + "$" */
2188 out->bv_len = sn.bv_len + newi.bv_len + 1;
2189 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2191 if( out->bv_val == NULL ) {
2192 slap_sl_free( newi.bv_val, ctx );
2196 /* push issuer over */
2197 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2198 /* insert sn and "$" */
2199 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2200 out->bv_val[sn.bv_len] = '$';
2202 out->bv_val[out->bv_len] = '\0';
2204 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2205 out->bv_val, 0, 0 );
2207 return LDAP_SUCCESS;
2211 * This routine is called by certificateExactNormalize when
2212 * certificateExactNormalize receives a search string instead of
2213 * a certificate. This routine checks if the search value is valid
2214 * and then returns the normalized value
2217 serialNumberAndIssuerNormalize(
2228 struct berval sn, i, newi;
2233 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2234 val->bv_val, 0, 0 );
2236 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2238 i.bv_val = strchr( val->bv_val, '$' );
2239 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2241 sn.bv_val = val->bv_val;
2242 sn.bv_len = i.bv_val - val->bv_val;
2245 i.bv_len = val->bv_len - (sn.bv_len + 1);
2247 /* eat leading zeros */
2248 for( n=0; n < (sn.bv_len-1); n++ ) {
2249 if( sn.bv_val[n] != '0' ) break;
2254 for( n=0; n < sn.bv_len; n++ ) {
2255 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2256 return LDAP_INVALID_SYNTAX;
2261 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2262 if( rc ) return LDAP_INVALID_SYNTAX;
2264 /* make room from sn + "$" */
2265 out->bv_len = sn.bv_len + newi.bv_len + 1;
2266 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2268 if( out->bv_val == NULL ) {
2269 slap_sl_free( newi.bv_val, ctx );
2273 /* push issuer over */
2274 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2275 /* insert sn and "$" */
2276 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2277 out->bv_val[sn.bv_len] = '$';
2279 out->bv_val[out->bv_len] = '\0';
2281 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2282 out->bv_val, 0, 0 );
2289 certificateExactNormalize(
2294 struct berval *normalized,
2297 int rc = LDAP_INVALID_SYNTAX;
2299 char *serial = NULL;
2300 ber_len_t seriallen;
2301 struct berval issuer_dn = BER_BVNULL;
2302 X509_NAME *name = NULL;
2303 ASN1_INTEGER *sn = NULL;
2306 if( val->bv_len == 0 ) goto done;
2308 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2309 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2312 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2314 p = (unsigned char *)val->bv_val;
2315 xcert = d2i_X509( NULL, &p, val->bv_len);
2316 if( xcert == NULL ) goto done;
2318 sn=X509_get_serialNumber(xcert);
2319 if ( sn == NULL ) goto done;
2320 serial=i2s_ASN1_INTEGER(0, sn );
2321 if( serial == NULL ) goto done;
2322 seriallen=strlen(serial);
2324 name=X509_get_issuer_name(xcert);
2325 if( name == NULL ) goto done;
2326 rc = dnX509normalize( name, &issuer_dn );
2327 if( rc != LDAP_SUCCESS ) goto done;
2329 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2330 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2331 p = (unsigned char *)normalized->bv_val;
2332 AC_MEMCPY(p, serial, seriallen);
2335 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2336 p += issuer_dn.bv_len;
2339 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2340 normalized->bv_val, NULL, NULL );
2343 if (xcert) X509_free(xcert);
2344 if (serial) ch_free(serial);
2345 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2349 #endif /* HAVE_TLS */
2352 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2353 /* slight optimization - does not need the start parameter */
2354 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2359 check_time_syntax (struct berval *val,
2362 struct berval *fraction)
2365 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2366 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2367 * GeneralizedTime supports leap seconds, UTCTime does not.
2369 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2370 static const int mdays[2][12] = {
2371 /* non-leap years */
2372 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2374 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2377 int part, c, c1, c2, tzoffset, leapyear = 0;
2380 e = p + val->bv_len;
2382 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2383 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2385 for (part = start; part < 7 && p < e; part++) {
2387 if (!ASCII_DIGIT(c1)) {
2392 return LDAP_INVALID_SYNTAX;
2395 if (!ASCII_DIGIT(c)) {
2396 return LDAP_INVALID_SYNTAX;
2398 c += c1 * 10 - '0' * 11;
2399 if ((part | 1) == 3) {
2402 return LDAP_INVALID_SYNTAX;
2405 if (c >= ceiling[part]) {
2406 if (! (c == 60 && part == 6 && start == 0))
2407 return LDAP_INVALID_SYNTAX;
2411 if (part < 5 + start) {
2412 return LDAP_INVALID_SYNTAX;
2414 for (; part < 9; part++) {
2418 /* leapyear check for the Gregorian calendar (year>1581) */
2419 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2423 if (parts[3] >= mdays[leapyear][parts[2]]) {
2424 return LDAP_INVALID_SYNTAX;
2428 fraction->bv_val = p;
2429 fraction->bv_len = 0;
2430 if (p < e && (*p == '.' || *p == ',')) {
2432 while (++p < e && ASCII_DIGIT(*p)) {
2435 if (p - fraction->bv_val == 1) {
2436 return LDAP_INVALID_SYNTAX;
2438 for (end_num = p; end_num[-1] == '0'; --end_num) {
2441 c = end_num - fraction->bv_val;
2442 if (c != 1) fraction->bv_len = c;
2448 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2454 return LDAP_INVALID_SYNTAX;
2460 for (part = 7; part < 9 && p < e; part++) {
2462 if (!ASCII_DIGIT(c1)) {
2467 return LDAP_INVALID_SYNTAX;
2470 if (!ASCII_DIGIT(c2)) {
2471 return LDAP_INVALID_SYNTAX;
2473 parts[part] = c1 * 10 + c2 - '0' * 11;
2474 if (parts[part] >= ceiling[part]) {
2475 return LDAP_INVALID_SYNTAX;
2478 if (part < 8 + start) {
2479 return LDAP_INVALID_SYNTAX;
2482 if (tzoffset == '-') {
2483 /* negative offset to UTC, ie west of Greenwich */
2484 parts[4] += parts[7];
2485 parts[5] += parts[8];
2486 /* offset is just hhmm, no seconds */
2487 for (part = 6; --part >= 0; ) {
2491 c = mdays[leapyear][parts[2]];
2493 if (parts[part] >= c) {
2495 return LDAP_INVALID_SYNTAX;
2500 } else if (part != 5) {
2505 /* positive offset to UTC, ie east of Greenwich */
2506 parts[4] -= parts[7];
2507 parts[5] -= parts[8];
2508 for (part = 6; --part >= 0; ) {
2509 if (parts[part] < 0) {
2511 return LDAP_INVALID_SYNTAX;
2516 /* make first arg to % non-negative */
2517 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2522 } else if (part != 5) {
2529 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2532 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2539 struct berval *normalized )
2543 rc = check_time_syntax(val, 1, parts, NULL);
2544 if (rc != LDAP_SUCCESS) {
2548 normalized->bv_val = ch_malloc( 14 );
2549 if ( normalized->bv_val == NULL ) {
2550 return LBER_ERROR_MEMORY;
2553 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2554 parts[1], parts[2] + 1, parts[3] + 1,
2555 parts[4], parts[5], parts[6] );
2556 normalized->bv_len = 13;
2558 return LDAP_SUCCESS;
2568 return check_time_syntax(in, 1, parts, NULL);
2571 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2574 generalizedTimeValidate(
2579 struct berval fraction;
2580 return check_time_syntax(in, 0, parts, &fraction);
2584 generalizedTimeNormalize(
2589 struct berval *normalized,
2594 struct berval fraction;
2596 rc = check_time_syntax(val, 0, parts, &fraction);
2597 if (rc != LDAP_SUCCESS) {
2601 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2602 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2603 if ( normalized->bv_val == NULL ) {
2604 return LBER_ERROR_MEMORY;
2607 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2608 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2609 parts[4], parts[5], parts[6] );
2610 if ( fraction.bv_len ) {
2611 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2612 fraction.bv_val, fraction.bv_len );
2613 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2615 strcpy( normalized->bv_val + len-1, "Z" );
2616 normalized->bv_len = len;
2618 return LDAP_SUCCESS;
2622 generalizedTimeOrderingMatch(
2627 struct berval *value,
2628 void *assertedValue )
2630 struct berval *asserted = (struct berval *) assertedValue;
2631 ber_len_t v_len = value->bv_len;
2632 ber_len_t av_len = asserted->bv_len;
2634 /* ignore trailing 'Z' when comparing */
2635 int match = memcmp( value->bv_val, asserted->bv_val,
2636 (v_len < av_len ? v_len : av_len) - 1 );
2637 if ( match == 0 ) match = v_len - av_len;
2640 return LDAP_SUCCESS;
2643 /* Index generation function */
2644 int generalizedTimeIndexer(
2649 struct berval *prefix,
2658 BerValue bvtmp; /* 40 bit index */
2660 struct lutil_timet tt;
2662 bvtmp.bv_len = sizeof(tmp);
2664 for( i=0; values[i].bv_val != NULL; i++ ) {
2665 /* just count them */
2668 /* we should have at least one value at this point */
2671 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
2673 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2674 for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
2675 assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
2676 /* Use 40 bits of time for key */
2677 if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
2678 lutil_tm2time( &tm, &tt );
2679 tmp[0] = tt.tt_gsec & 0xff;
2680 tmp[4] = tt.tt_sec & 0xff;
2682 tmp[3] = tt.tt_sec & 0xff;
2684 tmp[2] = tt.tt_sec & 0xff;
2686 tmp[1] = tt.tt_sec & 0xff;
2688 ber_dupbv_x(&keys[j++], &bvtmp, ctx );
2692 keys[j].bv_val = NULL;
2697 return LDAP_SUCCESS;
2700 /* Index generation function */
2701 int generalizedTimeFilter(
2706 struct berval *prefix,
2707 void * assertedValue,
2713 BerValue bvtmp; /* 40 bit index */
2714 BerValue *value = (BerValue *) assertedValue;
2716 struct lutil_timet tt;
2718 bvtmp.bv_len = sizeof(tmp);
2720 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
2722 /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */
2723 assert(value->bv_val != NULL && value->bv_len >= 10);
2724 /* Use 40 bits of time for key */
2725 if ( lutil_parsetime( value->bv_val, &tm ) == 0 ) {
2726 lutil_tm2time( &tm, &tt );
2727 tmp[0] = tt.tt_gsec & 0xff;
2728 tmp[4] = tt.tt_sec & 0xff;
2730 tmp[3] = tt.tt_sec & 0xff;
2732 tmp[2] = tt.tt_sec & 0xff;
2734 tmp[1] = tt.tt_sec & 0xff;
2736 ber_dupbv_x(keys, &bvtmp, ctx );
2738 keys[0].bv_val = NULL;
2742 keys[1].bv_val = NULL;
2747 return LDAP_SUCCESS;
2751 deliveryMethodValidate(
2753 struct berval *val )
2756 #define LENOF(s) (sizeof(s)-1)
2757 struct berval tmp = *val;
2759 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2760 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2761 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2764 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2766 switch( tmp.bv_val[0] ) {
2769 if(( tmp.bv_len >= LENOF("any") ) &&
2770 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2772 tmp.bv_len -= LENOF("any");
2773 tmp.bv_val += LENOF("any");
2776 return LDAP_INVALID_SYNTAX;
2780 if(( tmp.bv_len >= LENOF("mhs") ) &&
2781 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2783 tmp.bv_len -= LENOF("mhs");
2784 tmp.bv_val += LENOF("mhs");
2787 return LDAP_INVALID_SYNTAX;
2791 if(( tmp.bv_len >= LENOF("physical") ) &&
2792 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2794 tmp.bv_len -= LENOF("physical");
2795 tmp.bv_val += LENOF("physical");
2798 return LDAP_INVALID_SYNTAX;
2801 case 'T': /* telex or teletex or telephone */
2802 if(( tmp.bv_len >= LENOF("telex") ) &&
2803 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2805 tmp.bv_len -= LENOF("telex");
2806 tmp.bv_val += LENOF("telex");
2809 if(( tmp.bv_len >= LENOF("teletex") ) &&
2810 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2812 tmp.bv_len -= LENOF("teletex");
2813 tmp.bv_val += LENOF("teletex");
2816 if(( tmp.bv_len >= LENOF("telephone") ) &&
2817 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2819 tmp.bv_len -= LENOF("telephone");
2820 tmp.bv_val += LENOF("telephone");
2823 return LDAP_INVALID_SYNTAX;
2826 case 'G': /* g3fax or g4fax */
2827 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2828 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2829 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2831 tmp.bv_len -= LENOF("g3fax");
2832 tmp.bv_val += LENOF("g3fax");
2835 return LDAP_INVALID_SYNTAX;
2839 if(( tmp.bv_len >= LENOF("ia5") ) &&
2840 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2842 tmp.bv_len -= LENOF("ia5");
2843 tmp.bv_val += LENOF("ia5");
2846 return LDAP_INVALID_SYNTAX;
2850 if(( tmp.bv_len >= LENOF("videotex") ) &&
2851 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2853 tmp.bv_len -= LENOF("videotex");
2854 tmp.bv_val += LENOF("videotex");
2857 return LDAP_INVALID_SYNTAX;
2860 return LDAP_INVALID_SYNTAX;
2863 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2865 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2869 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2873 return LDAP_INVALID_SYNTAX;
2875 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2884 nisNetgroupTripleValidate(
2886 struct berval *val )
2891 if ( val->bv_len == 0 ) {
2892 return LDAP_INVALID_SYNTAX;
2895 p = (char *)val->bv_val;
2896 e = p + val->bv_len;
2898 if ( *p != '(' /*')'*/ ) {
2899 return LDAP_INVALID_SYNTAX;
2902 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2906 return LDAP_INVALID_SYNTAX;
2909 } else if ( !AD_CHAR( *p ) ) {
2910 return LDAP_INVALID_SYNTAX;
2914 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2915 return LDAP_INVALID_SYNTAX;
2921 return LDAP_INVALID_SYNTAX;
2924 return LDAP_SUCCESS;
2928 bootParameterValidate(
2930 struct berval *val )
2934 if ( val->bv_len == 0 ) {
2935 return LDAP_INVALID_SYNTAX;
2938 p = (char *)val->bv_val;
2939 e = p + val->bv_len;
2942 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2943 if ( !AD_CHAR( *p ) ) {
2944 return LDAP_INVALID_SYNTAX;
2949 return LDAP_INVALID_SYNTAX;
2953 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2954 if ( !AD_CHAR( *p ) ) {
2955 return LDAP_INVALID_SYNTAX;
2960 return LDAP_INVALID_SYNTAX;
2964 for ( p++; p < e; p++ ) {
2965 if ( !SLAP_PRINTABLE( *p ) ) {
2966 return LDAP_INVALID_SYNTAX;
2970 return LDAP_SUCCESS;
2974 firstComponentNormalize(
2979 struct berval *normalized,
2986 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2987 ber_dupbv_x( normalized, val, ctx );
2988 return LDAP_SUCCESS;
2991 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2993 if( val->bv_val[0] != '(' /*')'*/ &&
2994 val->bv_val[0] != '{' /*'}'*/ )
2996 return LDAP_INVALID_SYNTAX;
2999 /* trim leading white space */
3001 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
3007 /* grab next word */
3008 comp.bv_val = &val->bv_val[len];
3009 len = val->bv_len - len;
3011 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3017 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3018 rc = numericoidValidate( NULL, &comp );
3019 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3020 rc = integerValidate( NULL, &comp );
3022 rc = LDAP_INVALID_SYNTAX;
3026 if( rc == LDAP_SUCCESS ) {
3027 ber_dupbv_x( normalized, &comp, ctx );
3034 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3035 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3037 static slap_syntax_defs_rec syntax_defs[] = {
3038 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3039 X_BINARY X_NOT_H_R ")",
3040 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3041 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3043 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3045 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3047 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3048 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3050 SLAP_SYNTAX_BER, berValidate, NULL},
3051 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3052 0, bitStringValidate, NULL },
3053 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3054 0, booleanValidate, NULL},
3055 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3056 X_BINARY X_NOT_H_R ")",
3057 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3058 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3059 X_BINARY X_NOT_H_R ")",
3060 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3061 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3062 X_BINARY X_NOT_H_R ")",
3063 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3064 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3065 0, countryStringValidate, NULL},
3066 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3067 0, dnValidate, dnPretty},
3068 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3069 0, rdnValidate, rdnPretty},
3070 #ifdef LDAP_COMP_MATCH
3071 {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
3072 0, componentFilterValidate, NULL},
3074 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3076 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3077 0, deliveryMethodValidate, NULL},
3078 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3079 0, UTF8StringValidate, NULL},
3080 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3082 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3084 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3086 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3088 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3090 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3091 0, printablesStringValidate, NULL},
3092 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3093 SLAP_SYNTAX_BLOB, NULL, NULL},
3094 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3095 0, generalizedTimeValidate, NULL},
3096 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3098 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3099 0, IA5StringValidate, NULL},
3100 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3101 0, integerValidate, NULL},
3102 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3103 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3104 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3106 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3108 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3110 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3112 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3114 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3115 0, nameUIDValidate, nameUIDPretty },
3116 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3118 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3119 0, numericStringValidate, NULL},
3120 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3122 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3123 0, numericoidValidate, NULL},
3124 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3125 0, IA5StringValidate, NULL},
3126 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3127 0, blobValidate, NULL},
3128 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3129 0, UTF8StringValidate, NULL},
3130 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3132 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3134 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3135 0, printableStringValidate, NULL},
3136 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3137 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3138 0, subtreeSpecificationValidate, NULL},
3139 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3140 X_BINARY X_NOT_H_R ")",
3141 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3142 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3143 0, printableStringValidate, NULL},
3144 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3146 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3147 0, printablesStringValidate, NULL},
3148 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3149 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3150 0, utcTimeValidate, NULL},
3152 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3154 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3156 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3158 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3160 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3163 /* RFC 2307 NIS Syntaxes */
3164 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3165 0, nisNetgroupTripleValidate, NULL},
3166 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3167 0, bootParameterValidate, NULL},
3169 /* From PKIX *//* This OID is not published yet. */
3170 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3172 serialNumberAndIssuerValidate,
3173 serialNumberAndIssuerPretty},
3175 #ifdef SLAPD_ACI_ENABLED
3176 /* OpenLDAP Experimental Syntaxes */
3177 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3179 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3183 #ifdef SLAPD_AUTHPASSWD
3184 /* needs updating */
3185 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3186 SLAP_SYNTAX_HIDE, NULL, NULL},
3189 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3190 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3192 /* OpenLDAP Void Syntax */
3193 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3194 SLAP_SYNTAX_HIDE, inValidate, NULL},
3195 {NULL, 0, NULL, NULL}
3198 char *certificateExactMatchSyntaxes[] = {
3199 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3202 char *directoryStringSyntaxes[] = {
3203 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3206 char *integerFirstComponentMatchSyntaxes[] = {
3207 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3208 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3211 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3212 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3213 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3214 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3215 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3216 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3217 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3218 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3219 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3224 * Other matching rules in X.520 that we do not use (yet):
3226 * 2.5.13.25 uTCTimeMatch
3227 * 2.5.13.26 uTCTimeOrderingMatch
3228 * 2.5.13.31* directoryStringFirstComponentMatch
3229 * 2.5.13.32* wordMatch
3230 * 2.5.13.33* keywordMatch
3231 * 2.5.13.36 certificatePairExactMatch
3232 * 2.5.13.37 certificatePairMatch
3233 * 2.5.13.38 certificateListExactMatch
3234 * 2.5.13.39 certificateListMatch
3235 * 2.5.13.40 algorithmIdentifierMatch
3236 * 2.5.13.41* storedPrefixMatch
3237 * 2.5.13.42 attributeCertificateMatch
3238 * 2.5.13.43 readerAndKeyIDMatch
3239 * 2.5.13.44 attributeIntegrityMatch
3241 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3243 static slap_mrule_defs_rec mrule_defs[] = {
3245 * EQUALITY matching rules must be listed after associated APPROX
3246 * matching rules. So, we list all APPROX matching rules first.
3248 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3249 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3250 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3251 NULL, NULL, directoryStringApproxMatch,
3252 directoryStringApproxIndexer, directoryStringApproxFilter,
3255 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3256 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3257 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3258 NULL, NULL, IA5StringApproxMatch,
3259 IA5StringApproxIndexer, IA5StringApproxFilter,
3263 * Other matching rules
3266 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3267 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3268 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3269 NULL, NULL, octetStringMatch,
3270 octetStringIndexer, octetStringFilter,
3273 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3274 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3275 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3276 NULL, dnNormalize, dnMatch,
3277 octetStringIndexer, octetStringFilter,
3280 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3281 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3282 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3283 NULL, dnNormalize, dnRelativeMatch,
3287 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3288 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3289 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3290 NULL, dnNormalize, dnRelativeMatch,
3294 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3295 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3296 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3297 NULL, dnNormalize, dnRelativeMatch,
3301 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
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.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3309 "SYNTAX 1.2.36.79672281.1.5.0 )",
3310 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3311 NULL, rdnNormalize, rdnMatch,
3312 octetStringIndexer, octetStringFilter,
3315 #ifdef LDAP_COMP_MATCH
3316 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3317 "SYNTAX 1.2.36.79672281.1.5.2 )",
3318 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3319 NULL, NULL , componentFilterMatch,
3320 octetStringIndexer, octetStringFilter,
3324 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3325 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3326 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3327 NULL, UTF8StringNormalize, octetStringMatch,
3328 octetStringIndexer, octetStringFilter,
3329 directoryStringApproxMatchOID },
3331 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3332 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3333 SLAP_MR_ORDERING, directoryStringSyntaxes,
3334 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3336 "caseIgnoreMatch" },
3338 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3339 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3340 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3341 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3342 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3343 "caseIgnoreMatch" },
3345 {"( 2.5.13.5 NAME 'caseExactMatch' "
3346 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3347 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3348 NULL, UTF8StringNormalize, octetStringMatch,
3349 octetStringIndexer, octetStringFilter,
3350 directoryStringApproxMatchOID },
3352 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3353 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3354 SLAP_MR_ORDERING, directoryStringSyntaxes,
3355 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3359 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3360 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3361 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3362 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3363 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3366 {"( 2.5.13.8 NAME 'numericStringMatch' "
3367 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3368 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3369 NULL, numericStringNormalize, octetStringMatch,
3370 octetStringIndexer, octetStringFilter,
3373 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3374 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3375 SLAP_MR_ORDERING, NULL,
3376 NULL, numericStringNormalize, octetStringOrderingMatch,
3378 "numericStringMatch" },
3380 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3381 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3382 SLAP_MR_SUBSTR, NULL,
3383 NULL, numericStringNormalize, octetStringSubstringsMatch,
3384 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3385 "numericStringMatch" },
3387 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3388 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3389 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3390 NULL, NULL, NULL, NULL, NULL, NULL },
3392 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3393 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3394 SLAP_MR_SUBSTR, NULL,
3395 NULL, NULL, NULL, NULL, NULL,
3396 "caseIgnoreListMatch" },
3398 {"( 2.5.13.13 NAME 'booleanMatch' "
3399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3400 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3401 NULL, NULL, booleanMatch,
3402 octetStringIndexer, octetStringFilter,
3405 {"( 2.5.13.14 NAME 'integerMatch' "
3406 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3407 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3408 NULL, NULL, integerMatch,
3409 octetStringIndexer, octetStringFilter,
3412 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3413 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3414 SLAP_MR_ORDERING, NULL,
3415 NULL, NULL, integerMatch,
3419 {"( 2.5.13.16 NAME 'bitStringMatch' "
3420 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3421 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3422 NULL, NULL, octetStringMatch,
3423 octetStringIndexer, octetStringFilter,
3426 {"( 2.5.13.17 NAME 'octetStringMatch' "
3427 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3428 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3429 NULL, NULL, octetStringMatch,
3430 octetStringIndexer, octetStringFilter,
3433 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3434 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3435 SLAP_MR_ORDERING, NULL,
3436 NULL, NULL, octetStringOrderingMatch,
3438 "octetStringMatch" },
3440 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3441 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3442 SLAP_MR_SUBSTR, NULL,
3443 NULL, NULL, octetStringSubstringsMatch,
3444 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3445 "octetStringMatch" },
3447 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3448 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3449 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3451 telephoneNumberNormalize, octetStringMatch,
3452 octetStringIndexer, octetStringFilter,
3455 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3456 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3457 SLAP_MR_SUBSTR, NULL,
3458 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3459 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3460 "telephoneNumberMatch" },
3462 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3463 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3464 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3465 NULL, NULL, NULL, NULL, NULL, NULL },
3467 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3468 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3469 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3470 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3474 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3475 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3476 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3477 NULL, NULL, NULL, NULL, NULL, NULL },
3479 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3480 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3481 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
3482 NULL, generalizedTimeNormalize, octetStringMatch,
3483 generalizedTimeIndexer, generalizedTimeFilter,
3486 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3487 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3488 SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
3489 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3491 "generalizedTimeMatch" },
3493 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3495 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3496 integerFirstComponentMatchSyntaxes,
3497 NULL, firstComponentNormalize, integerMatch,
3498 octetStringIndexer, octetStringFilter,
3501 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3503 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3504 objectIdentifierFirstComponentMatchSyntaxes,
3505 NULL, firstComponentNormalize, octetStringMatch,
3506 octetStringIndexer, octetStringFilter,
3509 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3510 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3511 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3513 NULL, certificateExactNormalize, octetStringMatch,
3514 octetStringIndexer, octetStringFilter,
3516 NULL, NULL, NULL, NULL, NULL,
3520 {"( 2.5.13.35 NAME 'certificateMatch' "
3521 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3522 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3524 NULL, NULL, octetStringMatch,
3525 octetStringIndexer, octetStringFilter,
3527 NULL, NULL, NULL, NULL, NULL,
3531 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3532 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3533 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3534 NULL, IA5StringNormalize, octetStringMatch,
3535 octetStringIndexer, octetStringFilter,
3536 IA5StringApproxMatchOID },
3538 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3539 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3540 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3541 NULL, IA5StringNormalize, octetStringMatch,
3542 octetStringIndexer, octetStringFilter,
3543 IA5StringApproxMatchOID },
3545 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3546 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3547 SLAP_MR_SUBSTR, NULL,
3548 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3549 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3550 "caseIgnoreIA5Match" },
3552 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3553 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3554 SLAP_MR_SUBSTR, NULL,
3555 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3556 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3557 "caseExactIA5Match" },
3559 #ifdef SLAPD_AUTHPASSWD
3560 /* needs updating */
3561 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3562 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3563 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3564 NULL, NULL, authPasswordMatch,
3569 #ifdef SLAPD_ACI_ENABLED
3570 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3571 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3572 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3573 NULL, NULL, OpenLDAPaciMatch,
3578 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3579 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3581 NULL, NULL, integerBitAndMatch,
3585 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3586 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3588 NULL, NULL, integerBitOrMatch,
3592 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3593 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3594 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3595 NULL, UUIDNormalize, octetStringMatch,
3596 octetStringIndexer, octetStringFilter,
3599 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3600 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3601 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3602 NULL, UUIDNormalize, octetStringOrderingMatch,
3603 octetStringIndexer, octetStringFilter,
3606 {NULL, SLAP_MR_NONE, NULL,
3607 NULL, NULL, NULL, NULL, NULL,
3612 slap_schema_init( void )
3617 /* we should only be called once (from main) */
3618 assert( SLAPD_GLOBAL(schema_init_done) == 0 );
3620 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3621 res = register_syntax( &syntax_defs[i] );
3624 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3625 syntax_defs[i].sd_desc );
3630 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3631 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3632 mrule_defs[i].mrd_compat_syntaxes == NULL )
3635 "slap_schema_init: Ignoring unusable matching rule %s\n",
3636 mrule_defs[i].mrd_desc );
3640 res = register_matching_rule( &mrule_defs[i] );
3644 "slap_schema_init: Error registering matching rule %s\n",
3645 mrule_defs[i].mrd_desc );
3650 res = slap_schema_load();
3651 SLAPD_GLOBAL(schema_init_done) = 1;
3656 schema_destroy( void )