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>
31 #include "ldap_utf8.h"
34 #include <openssl/x509.h>
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/crypto.h>
38 #include <openssl/pem.h>
39 #include <openssl/bio.h>
40 #include <openssl/asn1.h>
41 #include <openssl/x509v3.h>
42 #include <openssl/ssl.h>
45 #include "lutil_hash.h"
46 #define HASH_BYTES LUTIL_HASH_BYTES
47 #define HASH_CONTEXT lutil_HASH_CTX
48 #define HASH_Init(c) lutil_HASHInit(c)
49 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
50 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
52 #define OpenLDAPaciMatch NULL
54 /* approx matching rules */
55 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
56 #define directoryStringApproxMatch approxMatch
57 #define directoryStringApproxIndexer approxIndexer
58 #define directoryStringApproxFilter approxFilter
59 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
60 #define IA5StringApproxMatch approxMatch
61 #define IA5StringApproxIndexer approxIndexer
62 #define IA5StringApproxFilter approxFilter
69 /* no value allowed */
70 return LDAP_INVALID_SYNTAX;
78 /* any value allowed */
82 #define berValidate blobValidate
89 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
90 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
97 static int certificateValidate( Syntax *syntax, struct berval *in )
100 unsigned char *p = (unsigned char *)in->bv_val;
102 xcert = d2i_X509(NULL, &p, in->bv_len);
103 if ( !xcert ) return LDAP_INVALID_SYNTAX;
108 #define certificateValidate sequenceValidate
117 struct berval *value,
118 void *assertedValue )
120 struct berval *asserted = (struct berval *) assertedValue;
121 int match = value->bv_len - asserted->bv_len;
124 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
132 octetStringOrderingMatch(
137 struct berval *value,
138 void *assertedValue )
140 struct berval *asserted = (struct berval *) assertedValue;
141 ber_len_t v_len = value->bv_len;
142 ber_len_t av_len = asserted->bv_len;
144 int match = memcmp( value->bv_val, asserted->bv_val,
145 (v_len < av_len ? v_len : av_len) );
147 if( match == 0 ) match = v_len - av_len;
153 /* Index generation function */
154 int octetStringIndexer(
159 struct berval *prefix,
167 HASH_CONTEXT HASHcontext;
168 unsigned char HASHdigest[HASH_BYTES];
169 struct berval digest;
170 digest.bv_val = (char *)HASHdigest;
171 digest.bv_len = sizeof(HASHdigest);
173 for( i=0; values[i].bv_val != NULL; i++ ) {
174 /* just count them */
177 /* we should have at least one value at this point */
180 keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
182 slen = syntax->ssyn_oidlen;
183 mlen = mr->smr_oidlen;
185 for( i=0; values[i].bv_val != NULL; i++ ) {
186 HASH_Init( &HASHcontext );
187 if( prefix != NULL && prefix->bv_len > 0 ) {
188 HASH_Update( &HASHcontext,
189 (unsigned char *)prefix->bv_val,
192 HASH_Update( &HASHcontext,
193 (unsigned char *)syntax->ssyn_oid, slen );
194 HASH_Update( &HASHcontext,
195 (unsigned char *)mr->smr_oid, mlen );
196 HASH_Update( &HASHcontext,
197 (unsigned char *)values[i].bv_val, values[i].bv_len );
198 HASH_Final( HASHdigest, &HASHcontext );
200 ber_dupbv_x( &keys[i], &digest, ctx );
203 keys[i].bv_val = NULL;
211 /* Index generation function */
212 int octetStringFilter(
217 struct berval *prefix,
218 void * assertedValue,
224 HASH_CONTEXT HASHcontext;
225 unsigned char HASHdigest[HASH_BYTES];
226 struct berval *value = (struct berval *) assertedValue;
227 struct berval digest;
228 digest.bv_val = (char *)HASHdigest;
229 digest.bv_len = sizeof(HASHdigest);
231 slen = syntax->ssyn_oidlen;
232 mlen = mr->smr_oidlen;
234 keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
236 HASH_Init( &HASHcontext );
237 if( prefix != NULL && prefix->bv_len > 0 ) {
238 HASH_Update( &HASHcontext,
239 (unsigned char *)prefix->bv_val, prefix->bv_len );
241 HASH_Update( &HASHcontext,
242 (unsigned char *)syntax->ssyn_oid, slen );
243 HASH_Update( &HASHcontext,
244 (unsigned char *)mr->smr_oid, mlen );
245 HASH_Update( &HASHcontext,
246 (unsigned char *)value->bv_val, value->bv_len );
247 HASH_Final( HASHdigest, &HASHcontext );
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, 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 >= SLAP_INDEX_SUBSTR_IF_MAXLEN ) {
410 nkeys += SLAP_INDEX_SUBSTR_IF_MAXLEN -
411 (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
412 } else if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN ) {
413 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
417 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
418 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) {
419 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_ANY_LEN - 1);
423 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
424 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MAXLEN ) {
425 nkeys += SLAP_INDEX_SUBSTR_IF_MAXLEN -
426 ( SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
427 } else if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN ) {
428 nkeys += values[i].bv_len - (SLAP_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 >= SLAP_INDEX_SUBSTR_ANY_LEN ) )
451 char pre = SLAP_INDEX_SUBSTR_PREFIX;
452 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_ANY_LEN - 1);
454 for( j=0; j<max; j++ ) {
455 HASH_Init( &HASHcontext );
456 if( prefix != NULL && prefix->bv_len > 0 ) {
457 HASH_Update( &HASHcontext,
458 (unsigned char *)prefix->bv_val, prefix->bv_len );
461 HASH_Update( &HASHcontext,
462 (unsigned char *)&pre, sizeof( pre ) );
463 HASH_Update( &HASHcontext,
464 (unsigned char *)syntax->ssyn_oid, slen );
465 HASH_Update( &HASHcontext,
466 (unsigned char *)mr->smr_oid, mlen );
467 HASH_Update( &HASHcontext,
468 (unsigned char *)&values[i].bv_val[j],
469 SLAP_INDEX_SUBSTR_ANY_LEN );
470 HASH_Final( HASHdigest, &HASHcontext );
472 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
476 /* skip if too short */
477 if( values[i].bv_len < SLAP_INDEX_SUBSTR_IF_MINLEN ) continue;
479 max = SLAP_INDEX_SUBSTR_IF_MAXLEN < values[i].bv_len
480 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : values[i].bv_len;
482 for( j=SLAP_INDEX_SUBSTR_IF_MINLEN; j<=max; j++ ) {
485 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
486 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
487 HASH_Init( &HASHcontext );
488 if( prefix != NULL && prefix->bv_len > 0 ) {
489 HASH_Update( &HASHcontext,
490 (unsigned char *)prefix->bv_val, prefix->bv_len );
492 HASH_Update( &HASHcontext,
493 (unsigned char *)&pre, sizeof( pre ) );
494 HASH_Update( &HASHcontext,
495 (unsigned char *)syntax->ssyn_oid, slen );
496 HASH_Update( &HASHcontext,
497 (unsigned char *)mr->smr_oid, mlen );
498 HASH_Update( &HASHcontext,
499 (unsigned char *)values[i].bv_val, j );
500 HASH_Final( HASHdigest, &HASHcontext );
502 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
505 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
506 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
507 HASH_Init( &HASHcontext );
508 if( prefix != NULL && prefix->bv_len > 0 ) {
509 HASH_Update( &HASHcontext,
510 (unsigned char *)prefix->bv_val, prefix->bv_len );
512 HASH_Update( &HASHcontext,
513 (unsigned char *)&pre, sizeof( pre ) );
514 HASH_Update( &HASHcontext,
515 (unsigned char *)syntax->ssyn_oid, slen );
516 HASH_Update( &HASHcontext,
517 (unsigned char *)mr->smr_oid, mlen );
518 HASH_Update( &HASHcontext,
519 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
520 HASH_Final( HASHdigest, &HASHcontext );
522 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
529 keys[nkeys].bv_val = NULL;
540 octetStringSubstringsFilter (
545 struct berval *prefix,
546 void * assertedValue,
550 SubstringsAssertion *sa;
553 size_t slen, mlen, klen;
555 HASH_CONTEXT HASHcontext;
556 unsigned char HASHdigest[HASH_BYTES];
557 struct berval *value;
558 struct berval digest;
560 sa = (SubstringsAssertion *) assertedValue;
562 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
563 sa->sa_initial.bv_val != NULL &&
564 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
569 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
571 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
572 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) {
573 /* don't bother accounting with stepping */
574 nkeys += sa->sa_any[i].bv_len -
575 ( SLAP_INDEX_SUBSTR_ANY_LEN - 1 );
580 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
581 sa->sa_final.bv_val != NULL &&
582 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
592 digest.bv_val = (char *)HASHdigest;
593 digest.bv_len = sizeof(HASHdigest);
595 slen = syntax->ssyn_oidlen;
596 mlen = mr->smr_oidlen;
598 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
601 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
602 sa->sa_initial.bv_val != NULL &&
603 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
605 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
606 value = &sa->sa_initial;
608 klen = SLAP_INDEX_SUBSTR_IF_MAXLEN < value->bv_len
609 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : value->bv_len;
611 HASH_Init( &HASHcontext );
612 if( prefix != NULL && prefix->bv_len > 0 ) {
613 HASH_Update( &HASHcontext,
614 (unsigned char *)prefix->bv_val, prefix->bv_len );
616 HASH_Update( &HASHcontext,
617 (unsigned char *)&pre, sizeof( pre ) );
618 HASH_Update( &HASHcontext,
619 (unsigned char *)syntax->ssyn_oid, slen );
620 HASH_Update( &HASHcontext,
621 (unsigned char *)mr->smr_oid, mlen );
622 HASH_Update( &HASHcontext,
623 (unsigned char *)value->bv_val, klen );
624 HASH_Final( HASHdigest, &HASHcontext );
626 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
629 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
631 pre = SLAP_INDEX_SUBSTR_PREFIX;
632 klen = SLAP_INDEX_SUBSTR_ANY_LEN;
634 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
635 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_ANY_LEN ) {
639 value = &sa->sa_any[i];
642 j <= value->bv_len - SLAP_INDEX_SUBSTR_ANY_LEN;
643 j += SLAP_INDEX_SUBSTR_ANY_STEP )
645 HASH_Init( &HASHcontext );
646 if( prefix != NULL && prefix->bv_len > 0 ) {
647 HASH_Update( &HASHcontext,
648 (unsigned char *)prefix->bv_val, prefix->bv_len );
650 HASH_Update( &HASHcontext,
651 (unsigned char *)&pre, sizeof( pre ) );
652 HASH_Update( &HASHcontext,
653 (unsigned char *)syntax->ssyn_oid, slen );
654 HASH_Update( &HASHcontext,
655 (unsigned char *)mr->smr_oid, mlen );
656 HASH_Update( &HASHcontext,
657 (unsigned char *)&value->bv_val[j], klen );
658 HASH_Final( HASHdigest, &HASHcontext );
660 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
665 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
666 sa->sa_final.bv_val != NULL &&
667 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
669 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
670 value = &sa->sa_final;
672 klen = SLAP_INDEX_SUBSTR_IF_MAXLEN < value->bv_len
673 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : value->bv_len;
675 HASH_Init( &HASHcontext );
676 if( prefix != NULL && prefix->bv_len > 0 ) {
677 HASH_Update( &HASHcontext,
678 (unsigned char *)prefix->bv_val, prefix->bv_len );
680 HASH_Update( &HASHcontext,
681 (unsigned char *)&pre, sizeof( pre ) );
682 HASH_Update( &HASHcontext,
683 (unsigned char *)syntax->ssyn_oid, slen );
684 HASH_Update( &HASHcontext,
685 (unsigned char *)mr->smr_oid, mlen );
686 HASH_Update( &HASHcontext,
687 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
688 HASH_Final( HASHdigest, &HASHcontext );
690 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
694 keys[nkeys].bv_val = NULL;
711 /* very unforgiving validation, requires no normalization
712 * before simplistic matching
714 if( in->bv_len < 3 ) {
715 return LDAP_INVALID_SYNTAX;
719 * RFC 2252 section 6.3 Bit String
720 * bitstring = "'" *binary-digit "'B"
721 * binary-digit = "0" / "1"
722 * example: '0101111101'B
725 if( in->bv_val[0] != '\'' ||
726 in->bv_val[in->bv_len-2] != '\'' ||
727 in->bv_val[in->bv_len-1] != 'B' )
729 return LDAP_INVALID_SYNTAX;
732 for( i=in->bv_len-3; i>0; i-- ) {
733 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
734 return LDAP_INVALID_SYNTAX;
742 * Syntax is [RFC2252]:
747 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
749 Values in this syntax are encoded according to the following BNF:
751 bitstring = "'" *binary-digit "'B"
753 binary-digit = "0" / "1"
757 6.21. Name And Optional UID
759 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
761 Values in this syntax are encoded according to the following BNF:
763 NameAndOptionalUID = DistinguishedName [ "#" bitstring ]
765 Although the '#' character may occur in a string representation of a
766 distinguished name, no additional special quoting is done. This
767 syntax has been added subsequent to RFC 1778.
771 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
774 * draft-ietf-ldapbis-syntaxes-xx.txt says:
779 A value of the Bit String syntax is a sequence of binary digits. The
780 LDAP-specific encoding of a value of this syntax is defined by the
783 BitString = SQUOTE *binary-digit SQUOTE "B"
785 binary-digit = "0" / "1"
787 The <SQUOTE> rule is defined in [MODELS].
792 The LDAP definition for the Bit String syntax is:
794 ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )
796 This syntax corresponds to the BIT STRING ASN.1 type from [ASN.1].
800 3.3.21. Name and Optional UID
802 A value of the Name and Optional UID syntax is the distinguished name
803 [MODELS] of an entity optionally accompanied by a unique identifier
804 that serves to differentiate the entity from others with an identical
807 The LDAP-specific encoding of a value of this syntax is defined by
810 NameAndOptionalUID = distinguishedName [ SHARP BitString ]
812 The <BitString> rule is defined in Section 3.3.2. The
813 <distinguishedName> rule is defined in [LDAPDN]. The <SHARP> rule is
816 Note that although the '#' character may occur in the string
817 representation of a distinguished name, no additional escaping of
818 this character is performed when a <distinguishedName> is encoded in
819 a <NameAndOptionalUID>.
822 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B
824 The LDAP definition for the Name and Optional UID syntax is:
826 ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )
828 This syntax corresponds to the NameAndOptionalUID ASN.1 type from
832 * draft-ietf-ldapbis-models-xx.txt [MODELS] says:
835 1.4. Common ABNF Productions
838 SHARP = %x23 ; octothorpe (or sharp sign) ("#")
840 SQUOTE = %x27 ; single quote ("'")
844 * Note: normalization strips any leading "0"s, unless the
845 * bit string is exactly "'0'B", so the normalized example,
846 * in slapd, would result in
848 * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B
850 * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP,
851 * i.e. "#", doesn't have to be escaped except when at the
852 * beginning of a value, the definition of Name and Optional
853 * UID appears to be flawed, because there is no clear means
854 * to determine whether the UID part is present or not.
858 * cn=Someone,dc=example,dc=com#'1'B
860 * could be either a NameAndOptionalUID with trailing UID, i.e.
862 * DN = "cn=Someone,dc=example,dc=com"
865 * or a NameAndOptionalUID with no trailing UID, and the AVA
866 * in the last RDN made of
869 * attributeValue = com#'1'B
871 * in fact "com#'1'B" is a valid IA5 string.
873 * As a consequence, current slapd code assumes that the
874 * presence of portions of a BitString at the end of the string
875 * representation of a NameAndOptionalUID means a BitString
876 * is expected, and cause an error otherwise. This is quite
877 * arbitrary, and might change in the future.
887 struct berval dn, uid;
889 if( in->bv_len == 0 ) return LDAP_SUCCESS;
891 ber_dupbv( &dn, in );
892 if( !dn.bv_val ) return LDAP_OTHER;
894 /* if there's a "#", try bitStringValidate()... */
895 uid.bv_val = strrchr( dn.bv_val, '#' );
898 uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
900 rc = bitStringValidate( NULL, &uid );
901 if ( rc == LDAP_SUCCESS ) {
902 /* in case of success, trim the UID,
903 * otherwise treat it as part of the DN */
904 dn.bv_len -= uid.bv_len + 1;
905 uid.bv_val[-1] = '\0';
909 rc = dnValidate( NULL, &dn );
911 ber_memfree( dn.bv_val );
927 LDAP_LOG( OPERATION, ARGS, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
929 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
932 if( val->bv_len == 0 ) {
933 ber_dupbv_x( out, val, ctx );
935 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
936 return LDAP_INVALID_SYNTAX;
940 struct berval dnval = *val;
941 struct berval uidval = BER_BVNULL;
943 uidval.bv_val = strrchr( val->bv_val, '#' );
944 if ( uidval.bv_val ) {
946 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
948 rc = bitStringValidate( NULL, &uidval );
950 if ( rc == LDAP_SUCCESS ) {
951 ber_dupbv_x( &dnval, val, ctx );
952 dnval.bv_len -= uidval.bv_len + 1;
953 dnval.bv_val[dnval.bv_len] = '\0';
956 uidval.bv_val = NULL;
960 rc = dnPretty( syntax, &dnval, out, ctx );
961 if ( dnval.bv_val != val->bv_val ) {
962 slap_sl_free( dnval.bv_val, ctx );
964 if( rc != LDAP_SUCCESS ) {
968 if( uidval.bv_val ) {
972 tmp = slap_sl_realloc( out->bv_val, out->bv_len
973 + STRLENOF( "#" ) + uidval.bv_len + 1,
976 ber_memfree_x( out->bv_val, ctx );
980 out->bv_val[out->bv_len++] = '#';
981 out->bv_val[out->bv_len++] = '\'';
983 got1 = uidval.bv_len < sizeof("'0'B");
984 for( i = 1; i < uidval.bv_len - 2; i++ ) {
985 c = uidval.bv_val[i];
988 if( got1 ) out->bv_val[out->bv_len++] = c;
992 out->bv_val[out->bv_len++] = c;
997 out->bv_val[out->bv_len++] = '\'';
998 out->bv_val[out->bv_len++] = 'B';
999 out->bv_val[out->bv_len] = '\0';
1004 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1006 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1009 return LDAP_SUCCESS;
1013 uniqueMemberNormalize(
1018 struct berval *normalized,
1024 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1026 ber_dupbv_x( &out, val, ctx );
1027 if ( BER_BVISEMPTY( &out ) ) {
1031 struct berval uid = BER_BVNULL;
1033 uid.bv_val = strrchr( out.bv_val, '#' );
1036 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1038 rc = bitStringValidate( NULL, &uid );
1039 if ( rc == LDAP_SUCCESS ) {
1040 uid.bv_val[-1] = '\0';
1041 out.bv_len -= uid.bv_len + 1;
1047 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1049 if( rc != LDAP_SUCCESS ) {
1050 slap_sl_free( out.bv_val, ctx );
1051 return LDAP_INVALID_SYNTAX;
1057 tmp = ch_realloc( normalized->bv_val,
1058 normalized->bv_len + uid.bv_len
1059 + STRLENOF("#") + 1 );
1060 if ( tmp == NULL ) {
1061 ber_memfree_x( normalized->bv_val, ctx );
1065 normalized->bv_val = tmp;
1067 /* insert the separator */
1068 normalized->bv_val[normalized->bv_len++] = '#';
1070 /* append the UID */
1071 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1072 uid.bv_val, uid.bv_len );
1073 normalized->bv_len += uid.bv_len;
1076 normalized->bv_val[normalized->bv_len] = '\0';
1079 slap_sl_free( out.bv_val, ctx );
1082 return LDAP_SUCCESS;
1091 struct berval *value,
1092 void *assertedValue )
1095 struct berval *asserted = (struct berval *) assertedValue;
1096 struct berval assertedDN = *asserted;
1097 struct berval assertedUID = BER_BVNULL;
1098 struct berval valueDN = BER_BVNULL;
1099 struct berval valueUID = BER_BVNULL;
1101 if ( !BER_BVISEMPTY( asserted ) ) {
1102 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1103 if ( !BER_BVISNULL( &assertedUID ) ) {
1104 assertedUID.bv_val++;
1105 assertedUID.bv_len = assertedDN.bv_len
1106 - ( assertedUID.bv_val - assertedDN.bv_val );
1108 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1109 assertedDN.bv_len -= assertedUID.bv_len + 1;
1112 BER_BVZERO( &assertedUID );
1117 if ( !BER_BVISEMPTY( value ) ) {
1120 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1121 if ( !BER_BVISNULL( &valueUID ) ) {
1123 valueUID.bv_len = valueDN.bv_len
1124 - ( valueUID.bv_val - valueDN.bv_val );
1126 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1127 valueDN.bv_len -= valueUID.bv_len + 1;
1130 BER_BVZERO( &valueUID );
1135 if( valueUID.bv_len && assertedUID.bv_len ) {
1136 match = valueUID.bv_len - assertedUID.bv_len;
1139 return LDAP_SUCCESS;
1142 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1145 return LDAP_SUCCESS;
1149 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1153 * Handling boolean syntax and matching is quite rigid.
1154 * A more flexible approach would be to allow a variety
1155 * of strings to be normalized and prettied into TRUE
1163 /* very unforgiving validation, requires no normalization
1164 * before simplistic matching
1167 if( in->bv_len == 4 ) {
1168 if( bvmatch( in, &slap_true_bv ) ) {
1169 return LDAP_SUCCESS;
1171 } else if( in->bv_len == 5 ) {
1172 if( bvmatch( in, &slap_false_bv ) ) {
1173 return LDAP_SUCCESS;
1177 return LDAP_INVALID_SYNTAX;
1186 struct berval *value,
1187 void *assertedValue )
1189 /* simplistic matching allowed by rigid validation */
1190 struct berval *asserted = (struct berval *) assertedValue;
1191 *matchp = value->bv_len != asserted->bv_len;
1192 return LDAP_SUCCESS;
1195 /*-------------------------------------------------------------------
1196 LDAP/X.500 string syntax / matching rules have a few oddities. This
1197 comment attempts to detail how slapd(8) treats them.
1200 StringSyntax X.500 LDAP Matching/Comments
1201 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1202 PrintableString subset subset i/e + ignore insignificant spaces
1203 PrintableString subset subset i/e + ignore insignificant spaces
1204 NumericString subset subset ignore all spaces
1205 IA5String ASCII ASCII i/e + ignore insignificant spaces
1206 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1208 TelephoneNumber subset subset i + ignore all spaces and "-"
1210 See draft-ietf-ldapbis-strpro for details (once published).
1214 In X.500(93), a directory string can be either a PrintableString,
1215 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1216 In later versions, more CHOICEs were added. In all cases the string
1219 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1220 A directory string cannot be zero length.
1222 For matching, there are both case ignore and exact rules. Both
1223 also require that "insignificant" spaces be ignored.
1224 spaces before the first non-space are ignored;
1225 spaces after the last non-space are ignored;
1226 spaces after a space are ignored.
1227 Note: by these rules (and as clarified in X.520), a string of only
1228 spaces is to be treated as if held one space, not empty (which
1229 would be a syntax error).
1232 In ASN.1, numeric string is just a string of digits and spaces
1233 and could be empty. However, in X.500, all attribute values of
1234 numeric string carry a non-empty constraint. For example:
1236 internationalISDNNumber ATTRIBUTE ::= {
1237 WITH SYNTAX InternationalISDNNumber
1238 EQUALITY MATCHING RULE numericStringMatch
1239 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1240 ID id-at-internationalISDNNumber }
1241 InternationalISDNNumber ::=
1242 NumericString (SIZE(1..ub-international-isdn-number))
1244 Unforunately, some assertion values are don't carry the same
1245 constraint (but its unclear how such an assertion could ever
1246 be true). In LDAP, there is one syntax (numericString) not two
1247 (numericString with constraint, numericString without constraint).
1248 This should be treated as numericString with non-empty constraint.
1249 Note that while someone may have no ISDN number, there are no ISDN
1250 numbers which are zero length.
1252 In matching, spaces are ignored.
1255 In ASN.1, Printable string is just a string of printable characters
1256 and can be empty. In X.500, semantics much like NumericString (see
1257 serialNumber for a like example) excepting uses insignificant space
1258 handling instead of ignore all spaces.
1261 Basically same as PrintableString. There are no examples in X.500,
1262 but same logic applies. So we require them to be non-empty as
1265 -------------------------------------------------------------------*/
1274 unsigned char *u = (unsigned char *)in->bv_val;
1276 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1277 /* directory strings cannot be empty */
1278 return LDAP_INVALID_SYNTAX;
1281 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1282 /* get the length indicated by the first byte */
1283 len = LDAP_UTF8_CHARLEN2( u, len );
1285 /* very basic checks */
1288 if( (u[5] & 0xC0) != 0x80 ) {
1289 return LDAP_INVALID_SYNTAX;
1292 if( (u[4] & 0xC0) != 0x80 ) {
1293 return LDAP_INVALID_SYNTAX;
1296 if( (u[3] & 0xC0) != 0x80 ) {
1297 return LDAP_INVALID_SYNTAX;
1300 if( (u[2] & 0xC0 )!= 0x80 ) {
1301 return LDAP_INVALID_SYNTAX;
1304 if( (u[1] & 0xC0) != 0x80 ) {
1305 return LDAP_INVALID_SYNTAX;
1308 /* CHARLEN already validated it */
1311 return LDAP_INVALID_SYNTAX;
1314 /* make sure len corresponds with the offset
1315 to the next character */
1316 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1320 return LDAP_INVALID_SYNTAX;
1323 return LDAP_SUCCESS;
1327 UTF8StringNormalize(
1332 struct berval *normalized,
1335 struct berval tmp, nvalue;
1339 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1341 if( val->bv_val == NULL ) {
1342 /* assume we're dealing with a syntax (e.g., UTF8String)
1343 * which allows empty strings
1345 normalized->bv_len = 0;
1346 normalized->bv_val = NULL;
1347 return LDAP_SUCCESS;
1350 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1351 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1352 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1353 ? LDAP_UTF8_APPROX : 0;
1355 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1360 /* collapse spaces (in place) */
1362 nvalue.bv_val = tmp.bv_val;
1364 wasspace=1; /* trim leading spaces */
1365 for( i=0; i<tmp.bv_len; i++) {
1366 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1367 if( wasspace++ == 0 ) {
1368 /* trim repeated spaces */
1369 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1373 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1377 if( nvalue.bv_len ) {
1379 /* last character was a space, trim it */
1382 nvalue.bv_val[nvalue.bv_len] = '\0';
1385 /* string of all spaces is treated as one space */
1386 nvalue.bv_val[0] = ' ';
1387 nvalue.bv_val[1] = '\0';
1391 *normalized = nvalue;
1392 return LDAP_SUCCESS;
1395 #if defined(SLAPD_APPROX_INITIALS)
1396 # define SLAPD_APPROX_DELIMITER "._ "
1397 # define SLAPD_APPROX_WORDLEN 2
1399 # define SLAPD_APPROX_DELIMITER " "
1400 # define SLAPD_APPROX_WORDLEN 1
1409 struct berval *value,
1410 void *assertedValue )
1412 struct berval *nval, *assertv;
1413 char *val, **values, **words, *c;
1414 int i, count, len, nextchunk=0, nextavail=0;
1416 /* Yes, this is necessary */
1417 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1418 if( nval == NULL ) {
1420 return LDAP_SUCCESS;
1423 /* Yes, this is necessary */
1424 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1425 NULL, LDAP_UTF8_APPROX, NULL );
1426 if( assertv == NULL ) {
1429 return LDAP_SUCCESS;
1432 /* Isolate how many words there are */
1433 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1434 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1435 if ( c == NULL ) break;
1440 /* Get a phonetic copy of each word */
1441 words = (char **)ch_malloc( count * sizeof(char *) );
1442 values = (char **)ch_malloc( count * sizeof(char *) );
1443 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1445 values[i] = phonetic(c);
1448 /* Work through the asserted value's words, to see if at least some
1449 of the words are there, in the same order. */
1451 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1452 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1457 #if defined(SLAPD_APPROX_INITIALS)
1458 else if( len == 1 ) {
1459 /* Single letter words need to at least match one word's initial */
1460 for( i=nextavail; i<count; i++ )
1461 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1468 /* Isolate the next word in the asserted value and phonetic it */
1469 assertv->bv_val[nextchunk+len] = '\0';
1470 val = phonetic( assertv->bv_val + nextchunk );
1472 /* See if this phonetic chunk is in the remaining words of *value */
1473 for( i=nextavail; i<count; i++ ){
1474 if( !strcmp( val, values[i] ) ){
1482 /* This chunk in the asserted value was NOT within the *value. */
1488 /* Go on to the next word in the asserted value */
1492 /* If some of the words were seen, call it a match */
1493 if( nextavail > 0 ) {
1500 /* Cleanup allocs */
1501 ber_bvfree( assertv );
1502 for( i=0; i<count; i++ ) {
1503 ch_free( values[i] );
1509 return LDAP_SUCCESS;
1518 struct berval *prefix,
1524 int i,j, len, wordcount, keycount=0;
1525 struct berval *newkeys;
1526 BerVarray keys=NULL;
1528 for( j=0; values[j].bv_val != NULL; j++ ) {
1529 struct berval val = BER_BVNULL;
1530 /* Yes, this is necessary */
1531 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1532 assert( val.bv_val != NULL );
1534 /* Isolate how many words there are. There will be a key for each */
1535 for( wordcount = 0, c = val.bv_val; *c; c++) {
1536 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1537 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1539 if (*c == '\0') break;
1543 /* Allocate/increase storage to account for new keys */
1544 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1545 * sizeof(struct berval) );
1546 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1547 if( keys ) ch_free( keys );
1550 /* Get a phonetic copy of each word */
1551 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1553 if( len < SLAPD_APPROX_WORDLEN ) continue;
1554 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1559 ber_memfree( val.bv_val );
1561 keys[keycount].bv_val = NULL;
1564 return LDAP_SUCCESS;
1573 struct berval *prefix,
1574 void * assertedValue,
1583 /* Yes, this is necessary */
1584 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1585 NULL, LDAP_UTF8_APPROX, NULL );
1586 if( val == NULL || val->bv_val == NULL ) {
1587 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1588 keys[0].bv_val = NULL;
1591 return LDAP_SUCCESS;
1594 /* Isolate how many words there are. There will be a key for each */
1595 for( count = 0,c = val->bv_val; *c; c++) {
1596 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1597 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1599 if (*c == '\0') break;
1603 /* Allocate storage for new keys */
1604 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1606 /* Get a phonetic copy of each word */
1607 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1609 if( len < SLAPD_APPROX_WORDLEN ) continue;
1610 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1616 keys[count].bv_val = NULL;
1619 return LDAP_SUCCESS;
1622 /* Remove all spaces and '-' characters */
1624 telephoneNumberNormalize(
1629 struct berval *normalized,
1634 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1636 /* validator should have refused an empty string */
1637 assert( val->bv_len );
1639 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1641 for( p = val->bv_val; *p; p++ ) {
1642 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1648 normalized->bv_len = q - normalized->bv_val;
1650 if( normalized->bv_len == 0 ) {
1651 slap_sl_free( normalized->bv_val, ctx );
1652 normalized->bv_val = NULL;
1653 return LDAP_INVALID_SYNTAX;
1656 return LDAP_SUCCESS;
1664 struct berval val = *in;
1666 if( val.bv_len == 0 ) {
1667 /* disallow empty strings */
1668 return LDAP_INVALID_SYNTAX;
1671 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1672 if ( val.bv_len == 1 ) {
1673 return LDAP_SUCCESS;
1676 if ( val.bv_val[0] == '0' ) {
1683 while ( OID_LEADCHAR( val.bv_val[0] )) {
1687 if ( val.bv_len == 0 ) {
1688 return LDAP_SUCCESS;
1692 if( !OID_SEPARATOR( val.bv_val[0] )) {
1700 return LDAP_INVALID_SYNTAX;
1709 struct berval val = *in;
1711 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1713 if ( val.bv_val[0] == '-' ) {
1717 if( val.bv_len == 0 ) { /* bare "-" */
1718 return LDAP_INVALID_SYNTAX;
1721 if( val.bv_val[0] == '0' ) { /* "-0" */
1722 return LDAP_INVALID_SYNTAX;
1725 } else if ( val.bv_val[0] == '0' ) {
1726 if( val.bv_len > 1 ) { /* "0<more>" */
1727 return LDAP_INVALID_SYNTAX;
1730 return LDAP_SUCCESS;
1733 for( i=0; i < val.bv_len; i++ ) {
1734 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1735 return LDAP_INVALID_SYNTAX;
1739 return LDAP_SUCCESS;
1748 struct berval *value,
1749 void *assertedValue )
1751 struct berval *asserted = (struct berval *) assertedValue;
1752 int vsign = 1, asign = 1; /* default sign = '+' */
1757 if( v.bv_val[0] == '-' ) {
1763 if( v.bv_len == 0 ) vsign = 0;
1766 if( a.bv_val[0] == '-' ) {
1772 if( a.bv_len == 0 ) vsign = 0;
1774 match = vsign - asign;
1776 match = ( v.bv_len != a.bv_len
1777 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1778 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1779 if( vsign < 0 ) match = -match;
1783 return LDAP_SUCCESS;
1787 countryStringValidate(
1789 struct berval *val )
1791 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1793 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1794 return LDAP_INVALID_SYNTAX;
1796 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1797 return LDAP_INVALID_SYNTAX;
1800 return LDAP_SUCCESS;
1804 printableStringValidate(
1806 struct berval *val )
1810 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1812 for(i=0; i < val->bv_len; i++) {
1813 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1814 return LDAP_INVALID_SYNTAX;
1818 return LDAP_SUCCESS;
1822 printablesStringValidate(
1824 struct berval *val )
1828 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1830 for(i=0,len=0; i < val->bv_len; i++) {
1831 int c = val->bv_val[i];
1835 return LDAP_INVALID_SYNTAX;
1839 } else if ( SLAP_PRINTABLE(c) ) {
1842 return LDAP_INVALID_SYNTAX;
1847 return LDAP_INVALID_SYNTAX;
1850 return LDAP_SUCCESS;
1856 struct berval *val )
1860 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1862 for(i=0; i < val->bv_len; i++) {
1863 if( !LDAP_ASCII(val->bv_val[i]) ) {
1864 return LDAP_INVALID_SYNTAX;
1868 return LDAP_SUCCESS;
1877 struct berval *normalized,
1881 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1883 assert( val->bv_len );
1885 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1889 /* Ignore initial whitespace */
1890 while ( ASCII_SPACE( *p ) ) p++;
1892 normalized->bv_val = ber_strdup_x( p, ctx );
1893 p = q = normalized->bv_val;
1896 if ( ASCII_SPACE( *p ) ) {
1899 /* Ignore the extra whitespace */
1900 while ( ASCII_SPACE( *p ) ) {
1904 } else if ( casefold ) {
1905 /* Most IA5 rules require casefolding */
1906 *q++ = TOLOWER(*p); p++;
1913 assert( normalized->bv_val <= p );
1917 * If the string ended in space, backup the pointer one
1918 * position. One is enough because the above loop collapsed
1919 * all whitespace to a single space.
1921 if ( ASCII_SPACE( q[-1] ) ) --q;
1923 /* null terminate */
1926 normalized->bv_len = q - normalized->bv_val;
1927 if( normalized->bv_len == 0 ) {
1928 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1929 normalized->bv_val[0] = ' ';
1930 normalized->bv_val[1] = '\0';
1931 normalized->bv_len = 1;
1934 return LDAP_SUCCESS;
1943 if( in->bv_len != 36 ) {
1945 return LDAP_INVALID_SYNTAX;
1948 for( i=0; i<36; i++ ) {
1954 if( in->bv_val[i] != '-' ) {
1955 return LDAP_INVALID_SYNTAX;
1959 if( !ASCII_HEX( in->bv_val[i]) ) {
1960 return LDAP_INVALID_SYNTAX;
1965 return LDAP_SUCCESS;
1974 struct berval *normalized,
1977 unsigned char octet = '\0';
1980 normalized->bv_len = 16;
1981 normalized->bv_val = slap_sl_malloc( normalized->bv_len+1, ctx );
1983 for( i=0, j=0; i<36; i++ ) {
1984 unsigned char nibble;
1985 if( val->bv_val[i] == '-' ) {
1988 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1989 nibble = val->bv_val[i] - '0';
1991 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1992 nibble = val->bv_val[i] - ('a'-10);
1994 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1995 nibble = val->bv_val[i] - ('A'-10);
1998 slap_sl_free( normalized->bv_val, ctx );
1999 return LDAP_INVALID_SYNTAX;
2004 normalized->bv_val[j>>1] = octet;
2006 octet = nibble << 4;
2011 normalized->bv_val[normalized->bv_len] = 0;
2012 return LDAP_SUCCESS;
2018 numericStringValidate(
2024 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2026 for(i=0; i < in->bv_len; i++) {
2027 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2028 return LDAP_INVALID_SYNTAX;
2032 return LDAP_SUCCESS;
2036 numericStringNormalize(
2041 struct berval *normalized,
2044 /* removal all spaces */
2047 assert( val->bv_len );
2049 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2052 q = normalized->bv_val;
2055 if ( ASCII_SPACE( *p ) ) {
2056 /* Ignore whitespace */
2063 /* we should have copied no more then is in val */
2064 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2066 /* null terminate */
2069 normalized->bv_len = q - normalized->bv_val;
2071 if( normalized->bv_len == 0 ) {
2072 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2073 normalized->bv_val[0] = ' ';
2074 normalized->bv_val[1] = '\0';
2075 normalized->bv_len = 1;
2078 return LDAP_SUCCESS;
2082 * Integer conversion macros that will use the largest available
2085 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2086 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2087 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2088 # define SLAP_LONG_MAX LLONG_MAX
2089 # define SLAP_LONG_MIN LLONG_MIN
2090 # define SLAP_LONG long long
2092 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2093 # define SLAP_LONG_MAX LONG_MAX
2094 # define SLAP_LONG_MIN LONG_MIN
2095 # define SLAP_LONG long
2096 #endif /* HAVE_STRTOLL ... */
2104 struct berval *value,
2105 void *assertedValue )
2107 SLAP_LONG lValue, lAssertedValue;
2109 /* safe to assume integers are NUL terminated? */
2110 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2111 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2114 return LDAP_CONSTRAINT_VIOLATION;
2117 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2119 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2122 return LDAP_CONSTRAINT_VIOLATION;
2125 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2126 return LDAP_SUCCESS;
2135 struct berval *value,
2136 void *assertedValue )
2138 SLAP_LONG lValue, lAssertedValue;
2140 /* safe to assume integers are NUL terminated? */
2141 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2142 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2145 return LDAP_CONSTRAINT_VIOLATION;
2148 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2150 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2153 return LDAP_CONSTRAINT_VIOLATION;
2156 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2157 return LDAP_SUCCESS;
2161 serialNumberAndIssuerValidate(
2168 struct berval sn, i;
2169 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2171 i.bv_val = strchr( in->bv_val, '$' );
2172 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2174 sn.bv_val = in->bv_val;
2175 sn.bv_len = i.bv_val - in->bv_val;
2178 i.bv_len = in->bv_len - (sn.bv_len + 1);
2180 /* validate serial number (strict for now) */
2181 for( n=0; n < sn.bv_len; n++ ) {
2182 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2186 rc = dnValidate( NULL, &i );
2187 if( rc ) return LDAP_INVALID_SYNTAX;
2189 return LDAP_SUCCESS;
2193 serialNumberAndIssuerPretty(
2202 struct berval sn, i, newi;
2208 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2209 val->bv_val, 0, 0 );
2211 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2212 val->bv_val, 0, 0 );
2215 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2217 i.bv_val = strchr( val->bv_val, '$' );
2218 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2220 sn.bv_val = val->bv_val;
2221 sn.bv_len = i.bv_val - val->bv_val;
2224 i.bv_len = val->bv_len - (sn.bv_len + 1);
2226 /* eat leading zeros */
2227 for( n=0; n < (sn.bv_len-1); n++ ) {
2228 if( sn.bv_val[n] != '0' ) break;
2233 for( n=0; n < sn.bv_len; n++ ) {
2234 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2238 rc = dnPretty( syntax, &i, &newi, ctx );
2239 if( rc ) return LDAP_INVALID_SYNTAX;
2241 /* make room from sn + "$" */
2242 out->bv_len = sn.bv_len + newi.bv_len + 1;
2243 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2245 if( out->bv_val == NULL ) {
2246 slap_sl_free( newi.bv_val, ctx );
2250 /* push issuer over */
2251 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2252 /* insert sn and "$" */
2253 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2254 out->bv_val[sn.bv_len] = '$';
2256 out->bv_val[out->bv_len] = '\0';
2259 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2260 out->bv_val, 0, 0 );
2262 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2263 out->bv_val, 0, 0 );
2266 return LDAP_SUCCESS;
2270 * This routine is called by certificateExactNormalize when
2271 * certificateExactNormalize receives a search string instead of
2272 * a certificate. This routine checks if the search value is valid
2273 * and then returns the normalized value
2276 serialNumberAndIssuerNormalize(
2287 struct berval sn, i, newi;
2293 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2294 val->bv_val, 0, 0 );
2296 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2297 val->bv_val, 0, 0 );
2300 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2302 i.bv_val = strchr( val->bv_val, '$' );
2303 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2305 sn.bv_val = val->bv_val;
2306 sn.bv_len = i.bv_val - val->bv_val;
2309 i.bv_len = val->bv_len - (sn.bv_len + 1);
2311 /* eat leading zeros */
2312 for( n=0; n < (sn.bv_len-1); n++ ) {
2313 if( sn.bv_val[n] != '0' ) break;
2318 for( n=0; n < sn.bv_len; n++ ) {
2319 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2320 return LDAP_INVALID_SYNTAX;
2325 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2326 if( rc ) return LDAP_INVALID_SYNTAX;
2328 /* make room from sn + "$" */
2329 out->bv_len = sn.bv_len + newi.bv_len + 1;
2330 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2332 if( out->bv_val == NULL ) {
2333 slap_sl_free( newi.bv_val, ctx );
2337 /* push issuer over */
2338 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2339 /* insert sn and "$" */
2340 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2341 out->bv_val[sn.bv_len] = '$';
2343 out->bv_val[out->bv_len] = '\0';
2346 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2347 out->bv_val, 0, 0 );
2349 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2350 out->bv_val, 0, 0 );
2358 certificateExactNormalize(
2363 struct berval *normalized,
2366 int rc = LDAP_INVALID_SYNTAX;
2368 char *serial = NULL;
2369 ber_len_t seriallen;
2370 struct berval issuer_dn = BER_BVNULL;
2371 X509_NAME *name = NULL;
2372 ASN1_INTEGER *sn = NULL;
2375 if( val->bv_len == 0 ) goto done;
2377 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2378 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2381 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2383 p = (unsigned char *)val->bv_val;
2384 xcert = d2i_X509( NULL, &p, val->bv_len);
2385 if( xcert == NULL ) goto done;
2387 sn=X509_get_serialNumber(xcert);
2388 if ( sn == NULL ) goto done;
2389 serial=i2s_ASN1_INTEGER(0, sn );
2390 if( serial == NULL ) goto done;
2391 seriallen=strlen(serial);
2393 name=X509_get_issuer_name(xcert);
2394 if( name == NULL ) goto done;
2395 rc = dnX509normalize( name, &issuer_dn );
2396 if( rc != LDAP_SUCCESS ) goto done;
2398 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2399 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2400 p = (unsigned char *)normalized->bv_val;
2401 AC_MEMCPY(p, serial, seriallen);
2404 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2405 p += issuer_dn.bv_len;
2409 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2410 normalized->bv_val, 0, 0 );
2412 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2413 normalized->bv_val, NULL, NULL );
2417 if (xcert) X509_free(xcert);
2418 if (serial) ch_free(serial);
2419 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2423 #endif /* HAVE_TLS */
2426 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2427 /* slight optimization - does not need the start parameter */
2428 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2433 check_time_syntax (struct berval *val,
2436 struct berval *fraction)
2439 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2440 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2441 * GeneralizedTime supports leap seconds, UTCTime does not.
2443 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2444 static const int mdays[2][12] = {
2445 /* non-leap years */
2446 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2448 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2451 int part, c, c1, c2, tzoffset, leapyear = 0;
2454 e = p + val->bv_len;
2456 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2457 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2459 for (part = start; part < 7 && p < e; part++) {
2461 if (!ASCII_DIGIT(c1)) {
2466 return LDAP_INVALID_SYNTAX;
2469 if (!ASCII_DIGIT(c)) {
2470 return LDAP_INVALID_SYNTAX;
2472 c += c1 * 10 - '0' * 11;
2473 if ((part | 1) == 3) {
2476 return LDAP_INVALID_SYNTAX;
2479 if (c >= ceiling[part]) {
2480 if (! (c == 60 && part == 6 && start == 0))
2481 return LDAP_INVALID_SYNTAX;
2485 if (part < 5 + start) {
2486 return LDAP_INVALID_SYNTAX;
2488 for (; part < 9; part++) {
2492 /* leapyear check for the Gregorian calendar (year>1581) */
2493 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2498 if (parts[3] >= mdays[leapyear][parts[2]]) {
2499 return LDAP_INVALID_SYNTAX;
2503 fraction->bv_val = p;
2504 fraction->bv_len = 0;
2505 if (p < e && (*p == '.' || *p == ',')) {
2507 while (++p < e && ASCII_DIGIT(*p))
2509 if (p - fraction->bv_val == 1) {
2510 return LDAP_INVALID_SYNTAX;
2512 for (end_num = p; end_num[-1] == '0'; --end_num)
2514 c = end_num - fraction->bv_val;
2516 fraction->bv_len = c;
2522 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2528 return LDAP_INVALID_SYNTAX;
2534 for (part = 7; part < 9 && p < e; part++) {
2536 if (!ASCII_DIGIT(c1)) {
2541 return LDAP_INVALID_SYNTAX;
2544 if (!ASCII_DIGIT(c2)) {
2545 return LDAP_INVALID_SYNTAX;
2547 parts[part] = c1 * 10 + c2 - '0' * 11;
2548 if (parts[part] >= ceiling[part]) {
2549 return LDAP_INVALID_SYNTAX;
2552 if (part < 8 + start) {
2553 return LDAP_INVALID_SYNTAX;
2556 if (tzoffset == '-') {
2557 /* negative offset to UTC, ie west of Greenwich */
2558 parts[4] += parts[7];
2559 parts[5] += parts[8];
2560 /* offset is just hhmm, no seconds */
2561 for (part = 6; --part >= 0; ) {
2565 c = mdays[leapyear][parts[2]];
2567 if (parts[part] >= c) {
2569 return LDAP_INVALID_SYNTAX;
2574 } else if (part != 5) {
2579 /* positive offset to UTC, ie east of Greenwich */
2580 parts[4] -= parts[7];
2581 parts[5] -= parts[8];
2582 for (part = 6; --part >= 0; ) {
2583 if (parts[part] < 0) {
2585 return LDAP_INVALID_SYNTAX;
2590 /* make first arg to % non-negative */
2591 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2596 } else if (part != 5) {
2603 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2606 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2613 struct berval *normalized )
2617 rc = check_time_syntax(val, 1, parts, NULL);
2618 if (rc != LDAP_SUCCESS) {
2622 normalized->bv_val = ch_malloc( 14 );
2623 if ( normalized->bv_val == NULL ) {
2624 return LBER_ERROR_MEMORY;
2627 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2628 parts[1], parts[2] + 1, parts[3] + 1,
2629 parts[4], parts[5], parts[6] );
2630 normalized->bv_len = 13;
2632 return LDAP_SUCCESS;
2642 return check_time_syntax(in, 1, parts, NULL);
2645 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2648 generalizedTimeValidate(
2653 struct berval fraction;
2654 return check_time_syntax(in, 0, parts, &fraction);
2658 generalizedTimeNormalize(
2663 struct berval *normalized,
2668 struct berval fraction;
2670 rc = check_time_syntax(val, 0, parts, &fraction);
2671 if (rc != LDAP_SUCCESS) {
2675 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2676 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2677 if ( normalized->bv_val == NULL ) {
2678 return LBER_ERROR_MEMORY;
2681 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2682 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2683 parts[4], parts[5], parts[6] );
2684 if ( fraction.bv_len ) {
2685 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2686 fraction.bv_val, fraction.bv_len );
2687 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2689 strcpy( normalized->bv_val + len-1, "Z" );
2690 normalized->bv_len = len;
2692 return LDAP_SUCCESS;
2696 generalizedTimeOrderingMatch(
2701 struct berval *value,
2702 void *assertedValue )
2704 struct berval *asserted = (struct berval *) assertedValue;
2705 ber_len_t v_len = value->bv_len;
2706 ber_len_t av_len = asserted->bv_len;
2708 /* ignore trailing 'Z' when comparing */
2709 int match = memcmp( value->bv_val, asserted->bv_val,
2710 (v_len < av_len ? v_len : av_len) - 1 );
2711 if ( match == 0 ) match = v_len - av_len;
2714 return LDAP_SUCCESS;
2718 deliveryMethodValidate(
2720 struct berval *val )
2723 #define LENOF(s) (sizeof(s)-1)
2724 struct berval tmp = *val;
2726 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2727 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2728 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2731 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2733 switch( tmp.bv_val[0] ) {
2736 if(( tmp.bv_len >= LENOF("any") ) &&
2737 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2739 tmp.bv_len -= LENOF("any");
2740 tmp.bv_val += LENOF("any");
2743 return LDAP_INVALID_SYNTAX;
2747 if(( tmp.bv_len >= LENOF("mhs") ) &&
2748 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2750 tmp.bv_len -= LENOF("mhs");
2751 tmp.bv_val += LENOF("mhs");
2754 return LDAP_INVALID_SYNTAX;
2758 if(( tmp.bv_len >= LENOF("physical") ) &&
2759 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2761 tmp.bv_len -= LENOF("physical");
2762 tmp.bv_val += LENOF("physical");
2765 return LDAP_INVALID_SYNTAX;
2768 case 'T': /* telex or teletex or telephone */
2769 if(( tmp.bv_len >= LENOF("telex") ) &&
2770 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2772 tmp.bv_len -= LENOF("telex");
2773 tmp.bv_val += LENOF("telex");
2776 if(( tmp.bv_len >= LENOF("teletex") ) &&
2777 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2779 tmp.bv_len -= LENOF("teletex");
2780 tmp.bv_val += LENOF("teletex");
2783 if(( tmp.bv_len >= LENOF("telephone") ) &&
2784 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2786 tmp.bv_len -= LENOF("telephone");
2787 tmp.bv_val += LENOF("telephone");
2790 return LDAP_INVALID_SYNTAX;
2793 case 'G': /* g3fax or g4fax */
2794 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2795 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2796 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2798 tmp.bv_len -= LENOF("g3fax");
2799 tmp.bv_val += LENOF("g3fax");
2802 return LDAP_INVALID_SYNTAX;
2806 if(( tmp.bv_len >= LENOF("ia5") ) &&
2807 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2809 tmp.bv_len -= LENOF("ia5");
2810 tmp.bv_val += LENOF("ia5");
2813 return LDAP_INVALID_SYNTAX;
2817 if(( tmp.bv_len >= LENOF("videotex") ) &&
2818 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2820 tmp.bv_len -= LENOF("videotex");
2821 tmp.bv_val += LENOF("videotex");
2824 return LDAP_INVALID_SYNTAX;
2827 return LDAP_INVALID_SYNTAX;
2830 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2832 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2836 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2840 return LDAP_INVALID_SYNTAX;
2842 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2851 nisNetgroupTripleValidate(
2853 struct berval *val )
2858 if ( val->bv_len == 0 ) {
2859 return LDAP_INVALID_SYNTAX;
2862 p = (char *)val->bv_val;
2863 e = p + val->bv_len;
2865 if ( *p != '(' /*')'*/ ) {
2866 return LDAP_INVALID_SYNTAX;
2869 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2873 return LDAP_INVALID_SYNTAX;
2876 } else if ( !AD_CHAR( *p ) ) {
2877 return LDAP_INVALID_SYNTAX;
2881 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2882 return LDAP_INVALID_SYNTAX;
2888 return LDAP_INVALID_SYNTAX;
2891 return LDAP_SUCCESS;
2895 bootParameterValidate(
2897 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;
2909 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2910 if ( !AD_CHAR( *p ) ) {
2911 return LDAP_INVALID_SYNTAX;
2916 return LDAP_INVALID_SYNTAX;
2920 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2921 if ( !AD_CHAR( *p ) ) {
2922 return LDAP_INVALID_SYNTAX;
2927 return LDAP_INVALID_SYNTAX;
2931 for ( p++; p < e; p++ ) {
2932 if ( !SLAP_PRINTABLE( *p ) ) {
2933 return LDAP_INVALID_SYNTAX;
2937 return LDAP_SUCCESS;
2941 firstComponentNormalize(
2946 struct berval *normalized,
2953 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2954 ber_dupbv_x( normalized, val, ctx );
2955 return LDAP_SUCCESS;
2958 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2960 if( val->bv_val[0] != '(' /*')'*/ &&
2961 val->bv_val[0] != '{' /*'}'*/ )
2963 return LDAP_INVALID_SYNTAX;
2966 /* trim leading white space */
2968 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2974 /* grab next word */
2975 comp.bv_val = &val->bv_val[len];
2976 len = val->bv_len - len;
2978 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2984 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2985 rc = numericoidValidate( NULL, &comp );
2986 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2987 rc = integerValidate( NULL, &comp );
2989 rc = LDAP_INVALID_SYNTAX;
2993 if( rc == LDAP_SUCCESS ) {
2994 ber_dupbv_x( normalized, &comp, ctx );
3001 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3002 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3004 static slap_syntax_defs_rec syntax_defs[] = {
3005 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3006 X_BINARY X_NOT_H_R ")",
3007 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3008 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3010 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3012 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3014 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3015 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3017 SLAP_SYNTAX_BER, berValidate, NULL},
3018 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3019 0, bitStringValidate, NULL },
3020 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3021 0, booleanValidate, NULL},
3022 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3023 X_BINARY X_NOT_H_R ")",
3024 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3025 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3026 X_BINARY X_NOT_H_R ")",
3027 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3028 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3029 X_BINARY X_NOT_H_R ")",
3030 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3031 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3032 0, countryStringValidate, NULL},
3033 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3034 0, dnValidate, dnPretty},
3036 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3037 0, rdnValidate, rdnPretty},
3039 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3041 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3042 0, deliveryMethodValidate, NULL},
3043 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3044 0, UTF8StringValidate, NULL},
3045 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3047 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3049 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3051 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3053 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3055 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3056 0, printablesStringValidate, NULL},
3057 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3058 SLAP_SYNTAX_BLOB, NULL, NULL},
3059 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3060 0, generalizedTimeValidate, NULL},
3061 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3063 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3064 0, IA5StringValidate, NULL},
3065 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3066 0, integerValidate, NULL},
3067 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3068 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3069 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3071 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3073 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3075 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3077 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3079 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3080 0, nameUIDValidate, nameUIDPretty },
3081 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3083 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3084 0, numericStringValidate, NULL},
3085 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3087 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3088 0, numericoidValidate, NULL},
3089 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3090 0, IA5StringValidate, NULL},
3091 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3092 0, blobValidate, NULL},
3093 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3094 0, UTF8StringValidate, NULL},
3095 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3097 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3099 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3100 0, printableStringValidate, NULL},
3101 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3102 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3103 0, subtreeSpecificationValidate, NULL},
3104 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3105 X_BINARY X_NOT_H_R ")",
3106 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3107 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3108 0, printableStringValidate, NULL},
3109 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3111 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3112 0, printablesStringValidate, NULL},
3113 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3114 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3115 0, utcTimeValidate, NULL},
3117 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3119 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3121 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3123 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3125 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3128 /* RFC 2307 NIS Syntaxes */
3129 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3130 0, nisNetgroupTripleValidate, NULL},
3131 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3132 0, bootParameterValidate, NULL},
3134 /* From PKIX *//* This OID is not published yet. */
3135 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3137 serialNumberAndIssuerValidate,
3138 serialNumberAndIssuerPretty},
3140 #ifdef SLAPD_ACI_ENABLED
3141 /* OpenLDAP Experimental Syntaxes */
3142 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3144 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3148 #ifdef SLAPD_AUTHPASSWD
3149 /* needs updating */
3150 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3151 SLAP_SYNTAX_HIDE, NULL, NULL},
3154 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3155 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3157 /* OpenLDAP Void Syntax */
3158 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3159 SLAP_SYNTAX_HIDE, inValidate, NULL},
3160 {NULL, 0, NULL, NULL}
3163 char *certificateExactMatchSyntaxes[] = {
3164 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3167 char *directoryStringSyntaxes[] = {
3168 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3171 char *integerFirstComponentMatchSyntaxes[] = {
3172 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3173 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3176 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3177 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3178 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3179 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3180 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3181 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3182 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3183 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3184 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3189 * Other matching rules in X.520 that we do not use (yet):
3191 * 2.5.13.25 uTCTimeMatch
3192 * 2.5.13.26 uTCTimeOrderingMatch
3193 * 2.5.13.31* directoryStringFirstComponentMatch
3194 * 2.5.13.32* wordMatch
3195 * 2.5.13.33* keywordMatch
3196 * 2.5.13.36 certificatePairExactMatch
3197 * 2.5.13.37 certificatePairMatch
3198 * 2.5.13.38 certificateListExactMatch
3199 * 2.5.13.39 certificateListMatch
3200 * 2.5.13.40 algorithmIdentifierMatch
3201 * 2.5.13.41* storedPrefixMatch
3202 * 2.5.13.42 attributeCertificateMatch
3203 * 2.5.13.43 readerAndKeyIDMatch
3204 * 2.5.13.44 attributeIntegrityMatch
3206 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3208 static slap_mrule_defs_rec mrule_defs[] = {
3210 * EQUALITY matching rules must be listed after associated APPROX
3211 * matching rules. So, we list all APPROX matching rules first.
3213 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3214 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3215 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3216 NULL, NULL, directoryStringApproxMatch,
3217 directoryStringApproxIndexer, directoryStringApproxFilter,
3220 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3221 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3222 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3223 NULL, NULL, IA5StringApproxMatch,
3224 IA5StringApproxIndexer, IA5StringApproxFilter,
3228 * Other matching rules
3231 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3232 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3233 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3234 NULL, NULL, octetStringMatch,
3235 octetStringIndexer, octetStringFilter,
3238 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3239 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3240 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3241 NULL, dnNormalize, dnMatch,
3242 octetStringIndexer, octetStringFilter,
3244 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3245 "SYNTAX 1.2.36.79672281.1.5.0 )",
3246 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3247 NULL, rdnNormalize, rdnMatch,
3248 octetStringIndexer, octetStringFilter,
3251 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3252 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3253 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3254 NULL, UTF8StringNormalize, octetStringMatch,
3255 octetStringIndexer, octetStringFilter,
3256 directoryStringApproxMatchOID },
3258 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3259 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3260 SLAP_MR_ORDERING, directoryStringSyntaxes,
3261 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3263 "caseIgnoreMatch" },
3265 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3266 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3267 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3268 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3269 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3270 "caseIgnoreMatch" },
3272 {"( 2.5.13.5 NAME 'caseExactMatch' "
3273 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3274 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3275 NULL, UTF8StringNormalize, octetStringMatch,
3276 octetStringIndexer, octetStringFilter,
3277 directoryStringApproxMatchOID },
3279 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3280 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3281 SLAP_MR_ORDERING, directoryStringSyntaxes,
3282 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3286 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3287 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3288 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3289 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3290 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3293 {"( 2.5.13.8 NAME 'numericStringMatch' "
3294 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3295 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3296 NULL, numericStringNormalize, octetStringMatch,
3297 octetStringIndexer, octetStringFilter,
3300 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3301 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3302 SLAP_MR_ORDERING, NULL,
3303 NULL, numericStringNormalize, octetStringOrderingMatch,
3305 "numericStringMatch" },
3307 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3308 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3309 SLAP_MR_SUBSTR, NULL,
3310 NULL, numericStringNormalize, octetStringSubstringsMatch,
3311 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3312 "numericStringMatch" },
3314 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3315 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3316 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3317 NULL, NULL, NULL, NULL, NULL, NULL },
3319 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3320 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3321 SLAP_MR_SUBSTR, NULL,
3322 NULL, NULL, NULL, NULL, NULL,
3323 "caseIgnoreListMatch" },
3325 {"( 2.5.13.13 NAME 'booleanMatch' "
3326 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3327 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3328 NULL, NULL, booleanMatch,
3329 octetStringIndexer, octetStringFilter,
3332 {"( 2.5.13.14 NAME 'integerMatch' "
3333 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3334 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3335 NULL, NULL, integerMatch,
3336 octetStringIndexer, octetStringFilter,
3339 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3340 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3341 SLAP_MR_ORDERING, NULL,
3342 NULL, NULL, integerMatch,
3346 {"( 2.5.13.16 NAME 'bitStringMatch' "
3347 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3348 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3349 NULL, NULL, octetStringMatch,
3350 octetStringIndexer, octetStringFilter,
3353 {"( 2.5.13.17 NAME 'octetStringMatch' "
3354 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3355 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3356 NULL, NULL, octetStringMatch,
3357 octetStringIndexer, octetStringFilter,
3360 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3361 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3362 SLAP_MR_ORDERING, NULL,
3363 NULL, NULL, octetStringOrderingMatch,
3365 "octetStringMatch" },
3367 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3368 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3369 SLAP_MR_SUBSTR, NULL,
3370 NULL, NULL, octetStringSubstringsMatch,
3371 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3372 "octetStringMatch" },
3374 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3375 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3376 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3378 telephoneNumberNormalize, octetStringMatch,
3379 octetStringIndexer, octetStringFilter,
3382 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3383 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3384 SLAP_MR_SUBSTR, NULL,
3385 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3386 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3387 "telephoneNumberMatch" },
3389 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3390 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3391 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3392 NULL, NULL, NULL, NULL, NULL, NULL },
3394 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3395 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3396 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3397 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3401 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3402 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3403 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3404 NULL, NULL, NULL, NULL, NULL, NULL },
3406 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3407 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3408 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3409 NULL, generalizedTimeNormalize, octetStringMatch,
3413 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3414 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3415 SLAP_MR_ORDERING, NULL,
3416 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3418 "generalizedTimeMatch" },
3420 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3421 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3422 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3423 integerFirstComponentMatchSyntaxes,
3424 NULL, firstComponentNormalize, integerMatch,
3425 octetStringIndexer, octetStringFilter,
3428 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3429 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3430 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3431 objectIdentifierFirstComponentMatchSyntaxes,
3432 NULL, firstComponentNormalize, octetStringMatch,
3433 octetStringIndexer, octetStringFilter,
3436 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3437 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3438 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3440 NULL, certificateExactNormalize, octetStringMatch,
3441 octetStringIndexer, octetStringFilter,
3443 NULL, NULL, NULL, NULL, NULL,
3447 {"( 2.5.13.35 NAME 'certificateMatch' "
3448 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3449 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3451 NULL, NULL, octetStringMatch,
3452 octetStringIndexer, octetStringFilter,
3454 NULL, NULL, NULL, NULL, NULL,
3458 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3460 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3461 NULL, IA5StringNormalize, octetStringMatch,
3462 octetStringIndexer, octetStringFilter,
3463 IA5StringApproxMatchOID },
3465 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3466 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3467 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3468 NULL, IA5StringNormalize, octetStringMatch,
3469 octetStringIndexer, octetStringFilter,
3470 IA5StringApproxMatchOID },
3472 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3473 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3474 SLAP_MR_SUBSTR, NULL,
3475 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3476 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3477 "caseIgnoreIA5Match" },
3479 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3480 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3481 SLAP_MR_SUBSTR, NULL,
3482 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3483 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3484 "caseExactIA5Match" },
3486 #ifdef SLAPD_AUTHPASSWD
3487 /* needs updating */
3488 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3489 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3490 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3491 NULL, NULL, authPasswordMatch,
3496 #ifdef SLAPD_ACI_ENABLED
3497 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3498 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3499 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3500 NULL, NULL, OpenLDAPaciMatch,
3505 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3508 NULL, NULL, integerBitAndMatch,
3512 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3515 NULL, NULL, integerBitOrMatch,
3519 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3520 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3521 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3522 NULL, UUIDNormalize, octetStringMatch,
3523 octetStringIndexer, octetStringFilter,
3526 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3527 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3528 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3529 NULL, UUIDNormalize, octetStringOrderingMatch,
3530 octetStringIndexer, octetStringFilter,
3533 {NULL, SLAP_MR_NONE, NULL,
3534 NULL, NULL, NULL, NULL, NULL,
3539 slap_schema_init( void )
3544 /* we should only be called once (from main) */
3545 assert( schema_init_done == 0 );
3547 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3548 res = register_syntax( &syntax_defs[i] );
3551 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3552 syntax_defs[i].sd_desc );
3557 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3558 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3559 mrule_defs[i].mrd_compat_syntaxes == NULL )
3562 "slap_schema_init: Ignoring unusable matching rule %s\n",
3563 mrule_defs[i].mrd_desc );
3567 res = register_matching_rule( &mrule_defs[i] );
3571 "slap_schema_init: Error registering matching rule %s\n",
3572 mrule_defs[i].mrd_desc );
3577 res = slap_schema_load();
3578 schema_init_done = 1;
3583 schema_destroy( void )