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 = BER_BVNULL;
1097 struct berval assertedUID = BER_BVNULL;
1098 struct berval valueDN = BER_BVNULL;
1099 struct berval valueUID = BER_BVNULL;
1101 if( !BER_BVISEMPTY( asserted ) ) {
1102 assertedDN = *asserted;
1104 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1105 if ( !BER_BVISNULL( &assertedUID ) ) {
1106 assertedUID.bv_val++;
1107 assertedUID.bv_len = assertedDN.bv_len
1108 - ( assertedUID.bv_val - assertedDN.bv_val );
1110 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1111 assertedDN.bv_len -= assertedUID.bv_len + 1;
1114 BER_BVZERO( &assertedUID );
1119 if ( !BER_BVISEMPTY( value ) ) {
1122 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1123 if ( !BER_BVISNULL( &valueUID ) ) {
1125 valueUID.bv_len = valueDN.bv_len
1126 - ( valueUID.bv_val - valueDN.bv_val );
1128 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1129 valueDN.bv_len -= valueUID.bv_len + 1;
1132 BER_BVZERO( &valueUID );
1137 if( valueUID.bv_len && assertedUID.bv_len ) {
1138 match = valueUID.bv_len - assertedUID.bv_len;
1141 return LDAP_SUCCESS;
1144 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1147 return LDAP_SUCCESS;
1151 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1155 * Handling boolean syntax and matching is quite rigid.
1156 * A more flexible approach would be to allow a variety
1157 * of strings to be normalized and prettied into TRUE
1165 /* very unforgiving validation, requires no normalization
1166 * before simplistic matching
1169 if( in->bv_len == 4 ) {
1170 if( bvmatch( in, &slap_true_bv ) ) {
1171 return LDAP_SUCCESS;
1173 } else if( in->bv_len == 5 ) {
1174 if( bvmatch( in, &slap_false_bv ) ) {
1175 return LDAP_SUCCESS;
1179 return LDAP_INVALID_SYNTAX;
1188 struct berval *value,
1189 void *assertedValue )
1191 /* simplistic matching allowed by rigid validation */
1192 struct berval *asserted = (struct berval *) assertedValue;
1193 *matchp = value->bv_len != asserted->bv_len;
1194 return LDAP_SUCCESS;
1197 /*-------------------------------------------------------------------
1198 LDAP/X.500 string syntax / matching rules have a few oddities. This
1199 comment attempts to detail how slapd(8) treats them.
1202 StringSyntax X.500 LDAP Matching/Comments
1203 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1204 PrintableString subset subset i/e + ignore insignificant spaces
1205 PrintableString subset subset i/e + ignore insignificant spaces
1206 NumericString subset subset ignore all spaces
1207 IA5String ASCII ASCII i/e + ignore insignificant spaces
1208 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1210 TelephoneNumber subset subset i + ignore all spaces and "-"
1212 See draft-ietf-ldapbis-strpro for details (once published).
1216 In X.500(93), a directory string can be either a PrintableString,
1217 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1218 In later versions, more CHOICEs were added. In all cases the string
1221 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1222 A directory string cannot be zero length.
1224 For matching, there are both case ignore and exact rules. Both
1225 also require that "insignificant" spaces be ignored.
1226 spaces before the first non-space are ignored;
1227 spaces after the last non-space are ignored;
1228 spaces after a space are ignored.
1229 Note: by these rules (and as clarified in X.520), a string of only
1230 spaces is to be treated as if held one space, not empty (which
1231 would be a syntax error).
1234 In ASN.1, numeric string is just a string of digits and spaces
1235 and could be empty. However, in X.500, all attribute values of
1236 numeric string carry a non-empty constraint. For example:
1238 internationalISDNNumber ATTRIBUTE ::= {
1239 WITH SYNTAX InternationalISDNNumber
1240 EQUALITY MATCHING RULE numericStringMatch
1241 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1242 ID id-at-internationalISDNNumber }
1243 InternationalISDNNumber ::=
1244 NumericString (SIZE(1..ub-international-isdn-number))
1246 Unforunately, some assertion values are don't carry the same
1247 constraint (but its unclear how such an assertion could ever
1248 be true). In LDAP, there is one syntax (numericString) not two
1249 (numericString with constraint, numericString without constraint).
1250 This should be treated as numericString with non-empty constraint.
1251 Note that while someone may have no ISDN number, there are no ISDN
1252 numbers which are zero length.
1254 In matching, spaces are ignored.
1257 In ASN.1, Printable string is just a string of printable characters
1258 and can be empty. In X.500, semantics much like NumericString (see
1259 serialNumber for a like example) excepting uses insignificant space
1260 handling instead of ignore all spaces.
1263 Basically same as PrintableString. There are no examples in X.500,
1264 but same logic applies. So we require them to be non-empty as
1267 -------------------------------------------------------------------*/
1276 unsigned char *u = (unsigned char *)in->bv_val;
1278 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1279 /* directory strings cannot be empty */
1280 return LDAP_INVALID_SYNTAX;
1283 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1284 /* get the length indicated by the first byte */
1285 len = LDAP_UTF8_CHARLEN2( u, len );
1287 /* very basic checks */
1290 if( (u[5] & 0xC0) != 0x80 ) {
1291 return LDAP_INVALID_SYNTAX;
1294 if( (u[4] & 0xC0) != 0x80 ) {
1295 return LDAP_INVALID_SYNTAX;
1298 if( (u[3] & 0xC0) != 0x80 ) {
1299 return LDAP_INVALID_SYNTAX;
1302 if( (u[2] & 0xC0 )!= 0x80 ) {
1303 return LDAP_INVALID_SYNTAX;
1306 if( (u[1] & 0xC0) != 0x80 ) {
1307 return LDAP_INVALID_SYNTAX;
1310 /* CHARLEN already validated it */
1313 return LDAP_INVALID_SYNTAX;
1316 /* make sure len corresponds with the offset
1317 to the next character */
1318 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1322 return LDAP_INVALID_SYNTAX;
1325 return LDAP_SUCCESS;
1329 UTF8StringNormalize(
1334 struct berval *normalized,
1337 struct berval tmp, nvalue;
1341 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1343 if( val->bv_val == NULL ) {
1344 /* assume we're dealing with a syntax (e.g., UTF8String)
1345 * which allows empty strings
1347 normalized->bv_len = 0;
1348 normalized->bv_val = NULL;
1349 return LDAP_SUCCESS;
1352 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1353 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1354 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1355 ? LDAP_UTF8_APPROX : 0;
1357 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1362 /* collapse spaces (in place) */
1364 nvalue.bv_val = tmp.bv_val;
1366 wasspace=1; /* trim leading spaces */
1367 for( i=0; i<tmp.bv_len; i++) {
1368 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1369 if( wasspace++ == 0 ) {
1370 /* trim repeated spaces */
1371 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1375 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1379 if( nvalue.bv_len ) {
1381 /* last character was a space, trim it */
1384 nvalue.bv_val[nvalue.bv_len] = '\0';
1387 /* string of all spaces is treated as one space */
1388 nvalue.bv_val[0] = ' ';
1389 nvalue.bv_val[1] = '\0';
1393 *normalized = nvalue;
1394 return LDAP_SUCCESS;
1397 #if defined(SLAPD_APPROX_INITIALS)
1398 # define SLAPD_APPROX_DELIMITER "._ "
1399 # define SLAPD_APPROX_WORDLEN 2
1401 # define SLAPD_APPROX_DELIMITER " "
1402 # define SLAPD_APPROX_WORDLEN 1
1411 struct berval *value,
1412 void *assertedValue )
1414 struct berval *nval, *assertv;
1415 char *val, **values, **words, *c;
1416 int i, count, len, nextchunk=0, nextavail=0;
1418 /* Yes, this is necessary */
1419 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1420 if( nval == NULL ) {
1422 return LDAP_SUCCESS;
1425 /* Yes, this is necessary */
1426 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1427 NULL, LDAP_UTF8_APPROX, NULL );
1428 if( assertv == NULL ) {
1431 return LDAP_SUCCESS;
1434 /* Isolate how many words there are */
1435 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1436 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1437 if ( c == NULL ) break;
1442 /* Get a phonetic copy of each word */
1443 words = (char **)ch_malloc( count * sizeof(char *) );
1444 values = (char **)ch_malloc( count * sizeof(char *) );
1445 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1447 values[i] = phonetic(c);
1450 /* Work through the asserted value's words, to see if at least some
1451 of the words are there, in the same order. */
1453 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1454 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1459 #if defined(SLAPD_APPROX_INITIALS)
1460 else if( len == 1 ) {
1461 /* Single letter words need to at least match one word's initial */
1462 for( i=nextavail; i<count; i++ )
1463 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1470 /* Isolate the next word in the asserted value and phonetic it */
1471 assertv->bv_val[nextchunk+len] = '\0';
1472 val = phonetic( assertv->bv_val + nextchunk );
1474 /* See if this phonetic chunk is in the remaining words of *value */
1475 for( i=nextavail; i<count; i++ ){
1476 if( !strcmp( val, values[i] ) ){
1484 /* This chunk in the asserted value was NOT within the *value. */
1490 /* Go on to the next word in the asserted value */
1494 /* If some of the words were seen, call it a match */
1495 if( nextavail > 0 ) {
1502 /* Cleanup allocs */
1503 ber_bvfree( assertv );
1504 for( i=0; i<count; i++ ) {
1505 ch_free( values[i] );
1511 return LDAP_SUCCESS;
1520 struct berval *prefix,
1526 int i,j, len, wordcount, keycount=0;
1527 struct berval *newkeys;
1528 BerVarray keys=NULL;
1530 for( j=0; values[j].bv_val != NULL; j++ ) {
1531 struct berval val = BER_BVNULL;
1532 /* Yes, this is necessary */
1533 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1534 assert( val.bv_val != NULL );
1536 /* Isolate how many words there are. There will be a key for each */
1537 for( wordcount = 0, c = val.bv_val; *c; c++) {
1538 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1539 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1541 if (*c == '\0') break;
1545 /* Allocate/increase storage to account for new keys */
1546 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1547 * sizeof(struct berval) );
1548 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1549 if( keys ) ch_free( keys );
1552 /* Get a phonetic copy of each word */
1553 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1555 if( len < SLAPD_APPROX_WORDLEN ) continue;
1556 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1561 ber_memfree( val.bv_val );
1563 keys[keycount].bv_val = NULL;
1566 return LDAP_SUCCESS;
1575 struct berval *prefix,
1576 void * assertedValue,
1585 /* Yes, this is necessary */
1586 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1587 NULL, LDAP_UTF8_APPROX, NULL );
1588 if( val == NULL || val->bv_val == NULL ) {
1589 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1590 keys[0].bv_val = NULL;
1593 return LDAP_SUCCESS;
1596 /* Isolate how many words there are. There will be a key for each */
1597 for( count = 0,c = val->bv_val; *c; c++) {
1598 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1599 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1601 if (*c == '\0') break;
1605 /* Allocate storage for new keys */
1606 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1608 /* Get a phonetic copy of each word */
1609 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1611 if( len < SLAPD_APPROX_WORDLEN ) continue;
1612 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1618 keys[count].bv_val = NULL;
1621 return LDAP_SUCCESS;
1624 /* Remove all spaces and '-' characters */
1626 telephoneNumberNormalize(
1631 struct berval *normalized,
1636 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1638 /* validator should have refused an empty string */
1639 assert( val->bv_len );
1641 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1643 for( p = val->bv_val; *p; p++ ) {
1644 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1650 normalized->bv_len = q - normalized->bv_val;
1652 if( normalized->bv_len == 0 ) {
1653 slap_sl_free( normalized->bv_val, ctx );
1654 normalized->bv_val = NULL;
1655 return LDAP_INVALID_SYNTAX;
1658 return LDAP_SUCCESS;
1666 struct berval val = *in;
1668 if( val.bv_len == 0 ) {
1669 /* disallow empty strings */
1670 return LDAP_INVALID_SYNTAX;
1673 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1674 if ( val.bv_len == 1 ) {
1675 return LDAP_SUCCESS;
1678 if ( val.bv_val[0] == '0' ) {
1685 while ( OID_LEADCHAR( val.bv_val[0] )) {
1689 if ( val.bv_len == 0 ) {
1690 return LDAP_SUCCESS;
1694 if( !OID_SEPARATOR( val.bv_val[0] )) {
1702 return LDAP_INVALID_SYNTAX;
1711 struct berval val = *in;
1713 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1715 if ( val.bv_val[0] == '-' ) {
1719 if( val.bv_len == 0 ) { /* bare "-" */
1720 return LDAP_INVALID_SYNTAX;
1723 if( val.bv_val[0] == '0' ) { /* "-0" */
1724 return LDAP_INVALID_SYNTAX;
1727 } else if ( val.bv_val[0] == '0' ) {
1728 if( val.bv_len > 1 ) { /* "0<more>" */
1729 return LDAP_INVALID_SYNTAX;
1732 return LDAP_SUCCESS;
1735 for( i=0; i < val.bv_len; i++ ) {
1736 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1737 return LDAP_INVALID_SYNTAX;
1741 return LDAP_SUCCESS;
1750 struct berval *value,
1751 void *assertedValue )
1753 struct berval *asserted = (struct berval *) assertedValue;
1754 int vsign = 1, asign = 1; /* default sign = '+' */
1759 if( v.bv_val[0] == '-' ) {
1765 if( v.bv_len == 0 ) vsign = 0;
1768 if( a.bv_val[0] == '-' ) {
1774 if( a.bv_len == 0 ) vsign = 0;
1776 match = vsign - asign;
1778 match = ( v.bv_len != a.bv_len
1779 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1780 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1781 if( vsign < 0 ) match = -match;
1785 return LDAP_SUCCESS;
1789 countryStringValidate(
1791 struct berval *val )
1793 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1795 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1796 return LDAP_INVALID_SYNTAX;
1798 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1799 return LDAP_INVALID_SYNTAX;
1802 return LDAP_SUCCESS;
1806 printableStringValidate(
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( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1816 return LDAP_INVALID_SYNTAX;
1820 return LDAP_SUCCESS;
1824 printablesStringValidate(
1826 struct berval *val )
1830 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1832 for(i=0,len=0; i < val->bv_len; i++) {
1833 int c = val->bv_val[i];
1837 return LDAP_INVALID_SYNTAX;
1841 } else if ( SLAP_PRINTABLE(c) ) {
1844 return LDAP_INVALID_SYNTAX;
1849 return LDAP_INVALID_SYNTAX;
1852 return LDAP_SUCCESS;
1858 struct berval *val )
1862 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1864 for(i=0; i < val->bv_len; i++) {
1865 if( !LDAP_ASCII(val->bv_val[i]) ) {
1866 return LDAP_INVALID_SYNTAX;
1870 return LDAP_SUCCESS;
1879 struct berval *normalized,
1883 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1885 assert( val->bv_len );
1887 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1891 /* Ignore initial whitespace */
1892 while ( ASCII_SPACE( *p ) ) p++;
1894 normalized->bv_val = ber_strdup_x( p, ctx );
1895 p = q = normalized->bv_val;
1898 if ( ASCII_SPACE( *p ) ) {
1901 /* Ignore the extra whitespace */
1902 while ( ASCII_SPACE( *p ) ) {
1906 } else if ( casefold ) {
1907 /* Most IA5 rules require casefolding */
1908 *q++ = TOLOWER(*p); p++;
1915 assert( normalized->bv_val <= p );
1919 * If the string ended in space, backup the pointer one
1920 * position. One is enough because the above loop collapsed
1921 * all whitespace to a single space.
1923 if ( ASCII_SPACE( q[-1] ) ) --q;
1925 /* null terminate */
1928 normalized->bv_len = q - normalized->bv_val;
1929 if( normalized->bv_len == 0 ) {
1930 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1931 normalized->bv_val[0] = ' ';
1932 normalized->bv_val[1] = '\0';
1933 normalized->bv_len = 1;
1936 return LDAP_SUCCESS;
1945 if( in->bv_len != 36 ) {
1947 return LDAP_INVALID_SYNTAX;
1950 for( i=0; i<36; i++ ) {
1956 if( in->bv_val[i] != '-' ) {
1957 return LDAP_INVALID_SYNTAX;
1961 if( !ASCII_HEX( in->bv_val[i]) ) {
1962 return LDAP_INVALID_SYNTAX;
1967 return LDAP_SUCCESS;
1976 struct berval *normalized,
1979 unsigned char octet = '\0';
1982 normalized->bv_len = 16;
1983 normalized->bv_val = slap_sl_malloc( normalized->bv_len+1, ctx );
1985 for( i=0, j=0; i<36; i++ ) {
1986 unsigned char nibble;
1987 if( val->bv_val[i] == '-' ) {
1990 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1991 nibble = val->bv_val[i] - '0';
1993 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1994 nibble = val->bv_val[i] - ('a'-10);
1996 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1997 nibble = val->bv_val[i] - ('A'-10);
2000 slap_sl_free( normalized->bv_val, ctx );
2001 return LDAP_INVALID_SYNTAX;
2006 normalized->bv_val[j>>1] = octet;
2008 octet = nibble << 4;
2013 normalized->bv_val[normalized->bv_len] = 0;
2014 return LDAP_SUCCESS;
2020 numericStringValidate(
2026 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2028 for(i=0; i < in->bv_len; i++) {
2029 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2030 return LDAP_INVALID_SYNTAX;
2034 return LDAP_SUCCESS;
2038 numericStringNormalize(
2043 struct berval *normalized,
2046 /* removal all spaces */
2049 assert( val->bv_len );
2051 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2054 q = normalized->bv_val;
2057 if ( ASCII_SPACE( *p ) ) {
2058 /* Ignore whitespace */
2065 /* we should have copied no more then is in val */
2066 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2068 /* null terminate */
2071 normalized->bv_len = q - normalized->bv_val;
2073 if( normalized->bv_len == 0 ) {
2074 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2075 normalized->bv_val[0] = ' ';
2076 normalized->bv_val[1] = '\0';
2077 normalized->bv_len = 1;
2080 return LDAP_SUCCESS;
2084 * Integer conversion macros that will use the largest available
2087 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2088 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2089 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2090 # define SLAP_LONG_MAX LLONG_MAX
2091 # define SLAP_LONG_MIN LLONG_MIN
2092 # define SLAP_LONG long long
2094 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2095 # define SLAP_LONG_MAX LONG_MAX
2096 # define SLAP_LONG_MIN LONG_MIN
2097 # define SLAP_LONG long
2098 #endif /* HAVE_STRTOLL ... */
2106 struct berval *value,
2107 void *assertedValue )
2109 SLAP_LONG lValue, lAssertedValue;
2111 /* safe to assume integers are NUL terminated? */
2112 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2113 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2116 return LDAP_CONSTRAINT_VIOLATION;
2119 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2121 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2124 return LDAP_CONSTRAINT_VIOLATION;
2127 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2128 return LDAP_SUCCESS;
2137 struct berval *value,
2138 void *assertedValue )
2140 SLAP_LONG lValue, lAssertedValue;
2142 /* safe to assume integers are NUL terminated? */
2143 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2144 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2147 return LDAP_CONSTRAINT_VIOLATION;
2150 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2152 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2155 return LDAP_CONSTRAINT_VIOLATION;
2158 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2159 return LDAP_SUCCESS;
2163 serialNumberAndIssuerValidate(
2170 struct berval sn, i;
2171 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2173 i.bv_val = strchr( in->bv_val, '$' );
2174 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2176 sn.bv_val = in->bv_val;
2177 sn.bv_len = i.bv_val - in->bv_val;
2180 i.bv_len = in->bv_len - (sn.bv_len + 1);
2182 /* validate serial number (strict for now) */
2183 for( n=0; n < sn.bv_len; n++ ) {
2184 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2188 rc = dnValidate( NULL, &i );
2189 if( rc ) return LDAP_INVALID_SYNTAX;
2191 return LDAP_SUCCESS;
2195 serialNumberAndIssuerPretty(
2204 struct berval sn, i, newi;
2210 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2211 val->bv_val, 0, 0 );
2213 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2214 val->bv_val, 0, 0 );
2217 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2219 i.bv_val = strchr( val->bv_val, '$' );
2220 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2222 sn.bv_val = val->bv_val;
2223 sn.bv_len = i.bv_val - val->bv_val;
2226 i.bv_len = val->bv_len - (sn.bv_len + 1);
2228 /* eat leading zeros */
2229 for( n=0; n < (sn.bv_len-1); n++ ) {
2230 if( sn.bv_val[n] != '0' ) break;
2235 for( n=0; n < sn.bv_len; n++ ) {
2236 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2240 rc = dnPretty( syntax, &i, &newi, ctx );
2241 if( rc ) return LDAP_INVALID_SYNTAX;
2243 /* make room from sn + "$" */
2244 out->bv_len = sn.bv_len + newi.bv_len + 1;
2245 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2247 if( out->bv_val == NULL ) {
2248 slap_sl_free( newi.bv_val, ctx );
2252 /* push issuer over */
2253 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2254 /* insert sn and "$" */
2255 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2256 out->bv_val[sn.bv_len] = '$';
2258 out->bv_val[out->bv_len] = '\0';
2261 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2262 out->bv_val, 0, 0 );
2264 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2265 out->bv_val, 0, 0 );
2268 return LDAP_SUCCESS;
2272 * This routine is called by certificateExactNormalize when
2273 * certificateExactNormalize receives a search string instead of
2274 * a certificate. This routine checks if the search value is valid
2275 * and then returns the normalized value
2278 serialNumberAndIssuerNormalize(
2289 struct berval sn, i, newi;
2295 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2296 val->bv_val, 0, 0 );
2298 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2299 val->bv_val, 0, 0 );
2302 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2304 i.bv_val = strchr( val->bv_val, '$' );
2305 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2307 sn.bv_val = val->bv_val;
2308 sn.bv_len = i.bv_val - val->bv_val;
2311 i.bv_len = val->bv_len - (sn.bv_len + 1);
2313 /* eat leading zeros */
2314 for( n=0; n < (sn.bv_len-1); n++ ) {
2315 if( sn.bv_val[n] != '0' ) break;
2320 for( n=0; n < sn.bv_len; n++ ) {
2321 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2322 return LDAP_INVALID_SYNTAX;
2327 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2328 if( rc ) return LDAP_INVALID_SYNTAX;
2330 /* make room from sn + "$" */
2331 out->bv_len = sn.bv_len + newi.bv_len + 1;
2332 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2334 if( out->bv_val == NULL ) {
2335 slap_sl_free( newi.bv_val, ctx );
2339 /* push issuer over */
2340 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2341 /* insert sn and "$" */
2342 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2343 out->bv_val[sn.bv_len] = '$';
2345 out->bv_val[out->bv_len] = '\0';
2348 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2349 out->bv_val, 0, 0 );
2351 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2352 out->bv_val, 0, 0 );
2360 certificateExactNormalize(
2365 struct berval *normalized,
2368 int rc = LDAP_INVALID_SYNTAX;
2370 char *serial = NULL;
2371 ber_len_t seriallen;
2372 struct berval issuer_dn = BER_BVNULL;
2373 X509_NAME *name = NULL;
2374 ASN1_INTEGER *sn = NULL;
2377 if( val->bv_len == 0 ) goto done;
2379 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2380 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2383 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2385 p = (unsigned char *)val->bv_val;
2386 xcert = d2i_X509( NULL, &p, val->bv_len);
2387 if( xcert == NULL ) goto done;
2389 sn=X509_get_serialNumber(xcert);
2390 if ( sn == NULL ) goto done;
2391 serial=i2s_ASN1_INTEGER(0, sn );
2392 if( serial == NULL ) goto done;
2393 seriallen=strlen(serial);
2395 name=X509_get_issuer_name(xcert);
2396 if( name == NULL ) goto done;
2397 rc = dnX509normalize( name, &issuer_dn );
2398 if( rc != LDAP_SUCCESS ) goto done;
2400 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2401 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2402 p = (unsigned char *)normalized->bv_val;
2403 AC_MEMCPY(p, serial, seriallen);
2406 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2407 p += issuer_dn.bv_len;
2411 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2412 normalized->bv_val, 0, 0 );
2414 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2415 normalized->bv_val, NULL, NULL );
2419 if (xcert) X509_free(xcert);
2420 if (serial) ch_free(serial);
2421 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2425 #endif /* HAVE_TLS */
2428 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2429 /* slight optimization - does not need the start parameter */
2430 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2435 check_time_syntax (struct berval *val,
2438 struct berval *fraction)
2441 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2442 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2443 * GeneralizedTime supports leap seconds, UTCTime does not.
2445 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2446 static const int mdays[2][12] = {
2447 /* non-leap years */
2448 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2450 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2453 int part, c, c1, c2, tzoffset, leapyear = 0;
2456 e = p + val->bv_len;
2458 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2459 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2461 for (part = start; part < 7 && p < e; part++) {
2463 if (!ASCII_DIGIT(c1)) {
2468 return LDAP_INVALID_SYNTAX;
2471 if (!ASCII_DIGIT(c)) {
2472 return LDAP_INVALID_SYNTAX;
2474 c += c1 * 10 - '0' * 11;
2475 if ((part | 1) == 3) {
2478 return LDAP_INVALID_SYNTAX;
2481 if (c >= ceiling[part]) {
2482 if (! (c == 60 && part == 6 && start == 0))
2483 return LDAP_INVALID_SYNTAX;
2487 if (part < 5 + start) {
2488 return LDAP_INVALID_SYNTAX;
2490 for (; part < 9; part++) {
2494 /* leapyear check for the Gregorian calendar (year>1581) */
2495 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2500 if (parts[3] >= mdays[leapyear][parts[2]]) {
2501 return LDAP_INVALID_SYNTAX;
2505 fraction->bv_val = p;
2506 fraction->bv_len = 0;
2507 if (p < e && (*p == '.' || *p == ',')) {
2509 while (++p < e && ASCII_DIGIT(*p))
2511 if (p - fraction->bv_val == 1) {
2512 return LDAP_INVALID_SYNTAX;
2514 for (end_num = p; end_num[-1] == '0'; --end_num)
2516 c = end_num - fraction->bv_val;
2518 fraction->bv_len = c;
2524 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2530 return LDAP_INVALID_SYNTAX;
2536 for (part = 7; part < 9 && p < e; part++) {
2538 if (!ASCII_DIGIT(c1)) {
2543 return LDAP_INVALID_SYNTAX;
2546 if (!ASCII_DIGIT(c2)) {
2547 return LDAP_INVALID_SYNTAX;
2549 parts[part] = c1 * 10 + c2 - '0' * 11;
2550 if (parts[part] >= ceiling[part]) {
2551 return LDAP_INVALID_SYNTAX;
2554 if (part < 8 + start) {
2555 return LDAP_INVALID_SYNTAX;
2558 if (tzoffset == '-') {
2559 /* negative offset to UTC, ie west of Greenwich */
2560 parts[4] += parts[7];
2561 parts[5] += parts[8];
2562 /* offset is just hhmm, no seconds */
2563 for (part = 6; --part >= 0; ) {
2567 c = mdays[leapyear][parts[2]];
2569 if (parts[part] >= c) {
2571 return LDAP_INVALID_SYNTAX;
2576 } else if (part != 5) {
2581 /* positive offset to UTC, ie east of Greenwich */
2582 parts[4] -= parts[7];
2583 parts[5] -= parts[8];
2584 for (part = 6; --part >= 0; ) {
2585 if (parts[part] < 0) {
2587 return LDAP_INVALID_SYNTAX;
2592 /* make first arg to % non-negative */
2593 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2598 } else if (part != 5) {
2605 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2608 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2615 struct berval *normalized )
2619 rc = check_time_syntax(val, 1, parts, NULL);
2620 if (rc != LDAP_SUCCESS) {
2624 normalized->bv_val = ch_malloc( 14 );
2625 if ( normalized->bv_val == NULL ) {
2626 return LBER_ERROR_MEMORY;
2629 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2630 parts[1], parts[2] + 1, parts[3] + 1,
2631 parts[4], parts[5], parts[6] );
2632 normalized->bv_len = 13;
2634 return LDAP_SUCCESS;
2644 return check_time_syntax(in, 1, parts, NULL);
2647 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2650 generalizedTimeValidate(
2655 struct berval fraction;
2656 return check_time_syntax(in, 0, parts, &fraction);
2660 generalizedTimeNormalize(
2665 struct berval *normalized,
2670 struct berval fraction;
2672 rc = check_time_syntax(val, 0, parts, &fraction);
2673 if (rc != LDAP_SUCCESS) {
2677 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2678 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2679 if ( normalized->bv_val == NULL ) {
2680 return LBER_ERROR_MEMORY;
2683 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2684 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2685 parts[4], parts[5], parts[6] );
2686 if ( fraction.bv_len ) {
2687 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2688 fraction.bv_val, fraction.bv_len );
2689 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2691 strcpy( normalized->bv_val + len-1, "Z" );
2692 normalized->bv_len = len;
2694 return LDAP_SUCCESS;
2698 generalizedTimeOrderingMatch(
2703 struct berval *value,
2704 void *assertedValue )
2706 struct berval *asserted = (struct berval *) assertedValue;
2707 ber_len_t v_len = value->bv_len;
2708 ber_len_t av_len = asserted->bv_len;
2710 /* ignore trailing 'Z' when comparing */
2711 int match = memcmp( value->bv_val, asserted->bv_val,
2712 (v_len < av_len ? v_len : av_len) - 1 );
2713 if ( match == 0 ) match = v_len - av_len;
2716 return LDAP_SUCCESS;
2720 deliveryMethodValidate(
2722 struct berval *val )
2725 #define LENOF(s) (sizeof(s)-1)
2726 struct berval tmp = *val;
2728 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2729 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2730 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2733 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2735 switch( tmp.bv_val[0] ) {
2738 if(( tmp.bv_len >= LENOF("any") ) &&
2739 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2741 tmp.bv_len -= LENOF("any");
2742 tmp.bv_val += LENOF("any");
2745 return LDAP_INVALID_SYNTAX;
2749 if(( tmp.bv_len >= LENOF("mhs") ) &&
2750 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2752 tmp.bv_len -= LENOF("mhs");
2753 tmp.bv_val += LENOF("mhs");
2756 return LDAP_INVALID_SYNTAX;
2760 if(( tmp.bv_len >= LENOF("physical") ) &&
2761 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2763 tmp.bv_len -= LENOF("physical");
2764 tmp.bv_val += LENOF("physical");
2767 return LDAP_INVALID_SYNTAX;
2770 case 'T': /* telex or teletex or telephone */
2771 if(( tmp.bv_len >= LENOF("telex") ) &&
2772 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2774 tmp.bv_len -= LENOF("telex");
2775 tmp.bv_val += LENOF("telex");
2778 if(( tmp.bv_len >= LENOF("teletex") ) &&
2779 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2781 tmp.bv_len -= LENOF("teletex");
2782 tmp.bv_val += LENOF("teletex");
2785 if(( tmp.bv_len >= LENOF("telephone") ) &&
2786 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2788 tmp.bv_len -= LENOF("telephone");
2789 tmp.bv_val += LENOF("telephone");
2792 return LDAP_INVALID_SYNTAX;
2795 case 'G': /* g3fax or g4fax */
2796 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2797 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2798 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2800 tmp.bv_len -= LENOF("g3fax");
2801 tmp.bv_val += LENOF("g3fax");
2804 return LDAP_INVALID_SYNTAX;
2808 if(( tmp.bv_len >= LENOF("ia5") ) &&
2809 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2811 tmp.bv_len -= LENOF("ia5");
2812 tmp.bv_val += LENOF("ia5");
2815 return LDAP_INVALID_SYNTAX;
2819 if(( tmp.bv_len >= LENOF("videotex") ) &&
2820 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2822 tmp.bv_len -= LENOF("videotex");
2823 tmp.bv_val += LENOF("videotex");
2826 return LDAP_INVALID_SYNTAX;
2829 return LDAP_INVALID_SYNTAX;
2832 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2834 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2838 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2842 return LDAP_INVALID_SYNTAX;
2844 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2853 nisNetgroupTripleValidate(
2855 struct berval *val )
2860 if ( val->bv_len == 0 ) {
2861 return LDAP_INVALID_SYNTAX;
2864 p = (char *)val->bv_val;
2865 e = p + val->bv_len;
2867 if ( *p != '(' /*')'*/ ) {
2868 return LDAP_INVALID_SYNTAX;
2871 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2875 return LDAP_INVALID_SYNTAX;
2878 } else if ( !AD_CHAR( *p ) ) {
2879 return LDAP_INVALID_SYNTAX;
2883 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2884 return LDAP_INVALID_SYNTAX;
2890 return LDAP_INVALID_SYNTAX;
2893 return LDAP_SUCCESS;
2897 bootParameterValidate(
2899 struct berval *val )
2903 if ( val->bv_len == 0 ) {
2904 return LDAP_INVALID_SYNTAX;
2907 p = (char *)val->bv_val;
2908 e = p + val->bv_len;
2911 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2912 if ( !AD_CHAR( *p ) ) {
2913 return LDAP_INVALID_SYNTAX;
2918 return LDAP_INVALID_SYNTAX;
2922 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2923 if ( !AD_CHAR( *p ) ) {
2924 return LDAP_INVALID_SYNTAX;
2929 return LDAP_INVALID_SYNTAX;
2933 for ( p++; p < e; p++ ) {
2934 if ( !SLAP_PRINTABLE( *p ) ) {
2935 return LDAP_INVALID_SYNTAX;
2939 return LDAP_SUCCESS;
2943 firstComponentNormalize(
2948 struct berval *normalized,
2955 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2956 ber_dupbv_x( normalized, val, ctx );
2957 return LDAP_SUCCESS;
2960 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2962 if( val->bv_val[0] != '(' /*')'*/ &&
2963 val->bv_val[0] != '{' /*'}'*/ )
2965 return LDAP_INVALID_SYNTAX;
2968 /* trim leading white space */
2970 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2976 /* grab next word */
2977 comp.bv_val = &val->bv_val[len];
2978 len = val->bv_len - len;
2980 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2986 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2987 rc = numericoidValidate( NULL, &comp );
2988 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2989 rc = integerValidate( NULL, &comp );
2991 rc = LDAP_INVALID_SYNTAX;
2995 if( rc == LDAP_SUCCESS ) {
2996 ber_dupbv_x( normalized, &comp, ctx );
3003 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3004 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3006 static slap_syntax_defs_rec syntax_defs[] = {
3007 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3008 X_BINARY X_NOT_H_R ")",
3009 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3010 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3012 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3014 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3016 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3017 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3019 SLAP_SYNTAX_BER, berValidate, NULL},
3020 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3021 0, bitStringValidate, NULL },
3022 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3023 0, booleanValidate, NULL},
3024 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3025 X_BINARY X_NOT_H_R ")",
3026 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3027 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3028 X_BINARY X_NOT_H_R ")",
3029 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3030 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3031 X_BINARY X_NOT_H_R ")",
3032 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3033 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3034 0, countryStringValidate, NULL},
3035 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3036 0, dnValidate, dnPretty},
3038 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3039 0, rdnValidate, rdnPretty},
3041 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3043 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3044 0, deliveryMethodValidate, NULL},
3045 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3046 0, UTF8StringValidate, NULL},
3047 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3049 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3051 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3053 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3055 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3057 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3058 0, printablesStringValidate, NULL},
3059 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3060 SLAP_SYNTAX_BLOB, NULL, NULL},
3061 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3062 0, generalizedTimeValidate, NULL},
3063 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3065 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3066 0, IA5StringValidate, NULL},
3067 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3068 0, integerValidate, NULL},
3069 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3070 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3071 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3073 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3075 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3077 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3079 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3081 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3082 0, nameUIDValidate, nameUIDPretty },
3083 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3085 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3086 0, numericStringValidate, NULL},
3087 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3089 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3090 0, numericoidValidate, NULL},
3091 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3092 0, IA5StringValidate, NULL},
3093 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3094 0, blobValidate, NULL},
3095 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3096 0, UTF8StringValidate, NULL},
3097 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3099 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3101 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3102 0, printableStringValidate, NULL},
3103 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3104 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3105 0, subtreeSpecificationValidate, NULL},
3106 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3107 X_BINARY X_NOT_H_R ")",
3108 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3109 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3110 0, printableStringValidate, NULL},
3111 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3113 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3114 0, printablesStringValidate, NULL},
3115 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3116 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3117 0, utcTimeValidate, NULL},
3119 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3121 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3123 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3125 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3127 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3130 /* RFC 2307 NIS Syntaxes */
3131 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3132 0, nisNetgroupTripleValidate, NULL},
3133 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3134 0, bootParameterValidate, NULL},
3136 /* From PKIX *//* This OID is not published yet. */
3137 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3139 serialNumberAndIssuerValidate,
3140 serialNumberAndIssuerPretty},
3142 #ifdef SLAPD_ACI_ENABLED
3143 /* OpenLDAP Experimental Syntaxes */
3144 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3146 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3150 #ifdef SLAPD_AUTHPASSWD
3151 /* needs updating */
3152 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3153 SLAP_SYNTAX_HIDE, NULL, NULL},
3156 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3157 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3159 /* OpenLDAP Void Syntax */
3160 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3161 SLAP_SYNTAX_HIDE, inValidate, NULL},
3162 {NULL, 0, NULL, NULL}
3165 char *certificateExactMatchSyntaxes[] = {
3166 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3169 char *directoryStringSyntaxes[] = {
3170 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3173 char *integerFirstComponentMatchSyntaxes[] = {
3174 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3175 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3178 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3179 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3180 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3181 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3182 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3183 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3184 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3185 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3186 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3191 * Other matching rules in X.520 that we do not use (yet):
3193 * 2.5.13.25 uTCTimeMatch
3194 * 2.5.13.26 uTCTimeOrderingMatch
3195 * 2.5.13.31* directoryStringFirstComponentMatch
3196 * 2.5.13.32* wordMatch
3197 * 2.5.13.33* keywordMatch
3198 * 2.5.13.36 certificatePairExactMatch
3199 * 2.5.13.37 certificatePairMatch
3200 * 2.5.13.38 certificateListExactMatch
3201 * 2.5.13.39 certificateListMatch
3202 * 2.5.13.40 algorithmIdentifierMatch
3203 * 2.5.13.41* storedPrefixMatch
3204 * 2.5.13.42 attributeCertificateMatch
3205 * 2.5.13.43 readerAndKeyIDMatch
3206 * 2.5.13.44 attributeIntegrityMatch
3208 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3210 static slap_mrule_defs_rec mrule_defs[] = {
3212 * EQUALITY matching rules must be listed after associated APPROX
3213 * matching rules. So, we list all APPROX matching rules first.
3215 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3216 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3217 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3218 NULL, NULL, directoryStringApproxMatch,
3219 directoryStringApproxIndexer, directoryStringApproxFilter,
3222 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3223 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3224 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3225 NULL, NULL, IA5StringApproxMatch,
3226 IA5StringApproxIndexer, IA5StringApproxFilter,
3230 * Other matching rules
3233 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3234 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3235 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3236 NULL, NULL, octetStringMatch,
3237 octetStringIndexer, octetStringFilter,
3240 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3241 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3242 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3243 NULL, dnNormalize, dnMatch,
3244 octetStringIndexer, octetStringFilter,
3246 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3247 "SYNTAX 1.2.36.79672281.1.5.0 )",
3248 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3249 NULL, rdnNormalize, rdnMatch,
3250 octetStringIndexer, octetStringFilter,
3253 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3254 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3255 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3256 NULL, UTF8StringNormalize, octetStringMatch,
3257 octetStringIndexer, octetStringFilter,
3258 directoryStringApproxMatchOID },
3260 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3261 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3262 SLAP_MR_ORDERING, directoryStringSyntaxes,
3263 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3265 "caseIgnoreMatch" },
3267 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3268 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3269 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3270 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3271 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3272 "caseIgnoreMatch" },
3274 {"( 2.5.13.5 NAME 'caseExactMatch' "
3275 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3276 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3277 NULL, UTF8StringNormalize, octetStringMatch,
3278 octetStringIndexer, octetStringFilter,
3279 directoryStringApproxMatchOID },
3281 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3282 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3283 SLAP_MR_ORDERING, directoryStringSyntaxes,
3284 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3288 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3289 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3290 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3291 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3292 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3295 {"( 2.5.13.8 NAME 'numericStringMatch' "
3296 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3297 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3298 NULL, numericStringNormalize, octetStringMatch,
3299 octetStringIndexer, octetStringFilter,
3302 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3303 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3304 SLAP_MR_ORDERING, NULL,
3305 NULL, numericStringNormalize, octetStringOrderingMatch,
3307 "numericStringMatch" },
3309 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3310 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3311 SLAP_MR_SUBSTR, NULL,
3312 NULL, numericStringNormalize, octetStringSubstringsMatch,
3313 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3314 "numericStringMatch" },
3316 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3317 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3318 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3319 NULL, NULL, NULL, NULL, NULL, NULL },
3321 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3322 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3323 SLAP_MR_SUBSTR, NULL,
3324 NULL, NULL, NULL, NULL, NULL,
3325 "caseIgnoreListMatch" },
3327 {"( 2.5.13.13 NAME 'booleanMatch' "
3328 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3329 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3330 NULL, NULL, booleanMatch,
3331 octetStringIndexer, octetStringFilter,
3334 {"( 2.5.13.14 NAME 'integerMatch' "
3335 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3336 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3337 NULL, NULL, integerMatch,
3338 octetStringIndexer, octetStringFilter,
3341 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3342 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3343 SLAP_MR_ORDERING, NULL,
3344 NULL, NULL, integerMatch,
3348 {"( 2.5.13.16 NAME 'bitStringMatch' "
3349 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3350 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3351 NULL, NULL, octetStringMatch,
3352 octetStringIndexer, octetStringFilter,
3355 {"( 2.5.13.17 NAME 'octetStringMatch' "
3356 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3357 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3358 NULL, NULL, octetStringMatch,
3359 octetStringIndexer, octetStringFilter,
3362 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3363 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3364 SLAP_MR_ORDERING, NULL,
3365 NULL, NULL, octetStringOrderingMatch,
3367 "octetStringMatch" },
3369 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3370 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3371 SLAP_MR_SUBSTR, NULL,
3372 NULL, NULL, octetStringSubstringsMatch,
3373 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3374 "octetStringMatch" },
3376 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3377 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3378 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3380 telephoneNumberNormalize, octetStringMatch,
3381 octetStringIndexer, octetStringFilter,
3384 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3385 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3386 SLAP_MR_SUBSTR, NULL,
3387 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3388 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3389 "telephoneNumberMatch" },
3391 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3392 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3393 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3394 NULL, NULL, NULL, NULL, NULL, NULL },
3396 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3397 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3398 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3399 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3403 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3404 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3405 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3406 NULL, NULL, NULL, NULL, NULL, NULL },
3408 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3409 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3410 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3411 NULL, generalizedTimeNormalize, octetStringMatch,
3415 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3416 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3417 SLAP_MR_ORDERING, NULL,
3418 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3420 "generalizedTimeMatch" },
3422 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3423 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3424 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3425 integerFirstComponentMatchSyntaxes,
3426 NULL, firstComponentNormalize, integerMatch,
3427 octetStringIndexer, octetStringFilter,
3430 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3432 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3433 objectIdentifierFirstComponentMatchSyntaxes,
3434 NULL, firstComponentNormalize, octetStringMatch,
3435 octetStringIndexer, octetStringFilter,
3438 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3439 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3440 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3442 NULL, certificateExactNormalize, octetStringMatch,
3443 octetStringIndexer, octetStringFilter,
3445 NULL, NULL, NULL, NULL, NULL,
3449 {"( 2.5.13.35 NAME 'certificateMatch' "
3450 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3451 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3453 NULL, NULL, octetStringMatch,
3454 octetStringIndexer, octetStringFilter,
3456 NULL, NULL, NULL, NULL, NULL,
3460 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3461 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3462 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3463 NULL, IA5StringNormalize, octetStringMatch,
3464 octetStringIndexer, octetStringFilter,
3465 IA5StringApproxMatchOID },
3467 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3468 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3469 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3470 NULL, IA5StringNormalize, octetStringMatch,
3471 octetStringIndexer, octetStringFilter,
3472 IA5StringApproxMatchOID },
3474 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3475 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3476 SLAP_MR_SUBSTR, NULL,
3477 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3478 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3479 "caseIgnoreIA5Match" },
3481 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3482 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3483 SLAP_MR_SUBSTR, NULL,
3484 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3485 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3486 "caseExactIA5Match" },
3488 #ifdef SLAPD_AUTHPASSWD
3489 /* needs updating */
3490 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3492 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3493 NULL, NULL, authPasswordMatch,
3498 #ifdef SLAPD_ACI_ENABLED
3499 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3500 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3501 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3502 NULL, NULL, OpenLDAPaciMatch,
3507 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3508 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3510 NULL, NULL, integerBitAndMatch,
3514 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3515 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3517 NULL, NULL, integerBitOrMatch,
3521 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3522 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3523 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3524 NULL, UUIDNormalize, octetStringMatch,
3525 octetStringIndexer, octetStringFilter,
3528 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3529 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3530 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3531 NULL, UUIDNormalize, octetStringOrderingMatch,
3532 octetStringIndexer, octetStringFilter,
3535 {NULL, SLAP_MR_NONE, NULL,
3536 NULL, NULL, NULL, NULL, NULL,
3541 slap_schema_init( void )
3546 /* we should only be called once (from main) */
3547 assert( schema_init_done == 0 );
3549 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3550 res = register_syntax( &syntax_defs[i] );
3553 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3554 syntax_defs[i].sd_desc );
3559 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3560 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3561 mrule_defs[i].mrd_compat_syntaxes == NULL )
3564 "slap_schema_init: Ignoring unusable matching rule %s\n",
3565 mrule_defs[i].mrd_desc );
3569 res = register_matching_rule( &mrule_defs[i] );
3573 "slap_schema_init: Error registering matching rule %s\n",
3574 mrule_defs[i].mrd_desc );
3579 res = slap_schema_load();
3580 schema_init_done = 1;
3585 schema_destroy( void )