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 ) {
1944 return LDAP_INVALID_SYNTAX;
1947 for( i=0; i<36; i++ ) {
1953 if( in->bv_val[i] != '-' ) {
1954 return LDAP_INVALID_SYNTAX;
1958 if( !ASCII_HEX( in->bv_val[i]) ) {
1959 return LDAP_INVALID_SYNTAX;
1964 return LDAP_SUCCESS;
1973 struct berval *normalized,
1976 unsigned char octet = '\0';
1979 normalized->bv_len = 16;
1980 normalized->bv_val = slap_sl_malloc( normalized->bv_len+1, ctx );
1982 for( i=0, j=0; i<36; i++ ) {
1983 unsigned char nibble;
1984 if( val->bv_val[i] == '-' ) {
1987 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1988 nibble = val->bv_val[i] - '0';
1990 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1991 nibble = val->bv_val[i] - ('a'-10);
1993 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1994 nibble = val->bv_val[i] - ('A'-10);
1997 slap_sl_free( normalized->bv_val, ctx );
1998 return LDAP_INVALID_SYNTAX;
2003 normalized->bv_val[j>>1] = octet;
2005 octet = nibble << 4;
2010 normalized->bv_val[normalized->bv_len] = 0;
2011 return LDAP_SUCCESS;
2017 numericStringValidate(
2023 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2025 for(i=0; i < in->bv_len; i++) {
2026 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2027 return LDAP_INVALID_SYNTAX;
2031 return LDAP_SUCCESS;
2035 numericStringNormalize(
2040 struct berval *normalized,
2043 /* removal all spaces */
2046 assert( val->bv_len );
2048 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2051 q = normalized->bv_val;
2054 if ( ASCII_SPACE( *p ) ) {
2055 /* Ignore whitespace */
2062 /* we should have copied no more then is in val */
2063 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2065 /* null terminate */
2068 normalized->bv_len = q - normalized->bv_val;
2070 if( normalized->bv_len == 0 ) {
2071 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2072 normalized->bv_val[0] = ' ';
2073 normalized->bv_val[1] = '\0';
2074 normalized->bv_len = 1;
2077 return LDAP_SUCCESS;
2081 * Integer conversion macros that will use the largest available
2084 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2085 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2086 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2087 # define SLAP_LONG_MAX LLONG_MAX
2088 # define SLAP_LONG_MIN LLONG_MIN
2089 # define SLAP_LONG long long
2091 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2092 # define SLAP_LONG_MAX LONG_MAX
2093 # define SLAP_LONG_MIN LONG_MIN
2094 # define SLAP_LONG long
2095 #endif /* HAVE_STRTOLL ... */
2103 struct berval *value,
2104 void *assertedValue )
2106 SLAP_LONG lValue, lAssertedValue;
2108 /* safe to assume integers are NUL terminated? */
2109 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2110 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2113 return LDAP_CONSTRAINT_VIOLATION;
2116 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2118 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2121 return LDAP_CONSTRAINT_VIOLATION;
2124 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2125 return LDAP_SUCCESS;
2134 struct berval *value,
2135 void *assertedValue )
2137 SLAP_LONG lValue, lAssertedValue;
2139 /* safe to assume integers are NUL terminated? */
2140 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2141 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2144 return LDAP_CONSTRAINT_VIOLATION;
2147 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2149 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2152 return LDAP_CONSTRAINT_VIOLATION;
2155 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2156 return LDAP_SUCCESS;
2160 serialNumberAndIssuerValidate(
2167 struct berval sn, i;
2168 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2170 i.bv_val = strchr( in->bv_val, '$' );
2171 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2173 sn.bv_val = in->bv_val;
2174 sn.bv_len = i.bv_val - in->bv_val;
2177 i.bv_len = in->bv_len - (sn.bv_len + 1);
2179 /* validate serial number (strict for now) */
2180 for( n=0; n < sn.bv_len; n++ ) {
2181 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2185 rc = dnValidate( NULL, &i );
2186 if( rc ) return LDAP_INVALID_SYNTAX;
2188 return LDAP_SUCCESS;
2192 serialNumberAndIssuerPretty(
2201 struct berval sn, i, newi;
2207 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2208 val->bv_val, 0, 0 );
2210 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2211 val->bv_val, 0, 0 );
2214 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2216 i.bv_val = strchr( val->bv_val, '$' );
2217 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2219 sn.bv_val = val->bv_val;
2220 sn.bv_len = i.bv_val - val->bv_val;
2223 i.bv_len = val->bv_len - (sn.bv_len + 1);
2225 /* eat leading zeros */
2226 for( n=0; n < (sn.bv_len-1); n++ ) {
2227 if( sn.bv_val[n] != '0' ) break;
2232 for( n=0; n < sn.bv_len; n++ ) {
2233 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2237 rc = dnPretty( syntax, &i, &newi, ctx );
2238 if( rc ) return LDAP_INVALID_SYNTAX;
2240 /* make room from sn + "$" */
2241 out->bv_len = sn.bv_len + newi.bv_len + 1;
2242 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2244 if( out->bv_val == NULL ) {
2245 slap_sl_free( newi.bv_val, ctx );
2249 /* push issuer over */
2250 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2251 /* insert sn and "$" */
2252 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2253 out->bv_val[sn.bv_len] = '$';
2255 out->bv_val[out->bv_len] = '\0';
2258 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2259 out->bv_val, 0, 0 );
2261 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2262 out->bv_val, 0, 0 );
2265 return LDAP_SUCCESS;
2269 * This routine is called by certificateExactNormalize when
2270 * certificateExactNormalize receives a search string instead of
2271 * a certificate. This routine checks if the search value is valid
2272 * and then returns the normalized value
2275 serialNumberAndIssuerNormalize(
2286 struct berval sn, i, newi;
2292 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2293 val->bv_val, 0, 0 );
2295 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2296 val->bv_val, 0, 0 );
2299 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2301 i.bv_val = strchr( val->bv_val, '$' );
2302 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2304 sn.bv_val = val->bv_val;
2305 sn.bv_len = i.bv_val - val->bv_val;
2308 i.bv_len = val->bv_len - (sn.bv_len + 1);
2310 /* eat leading zeros */
2311 for( n=0; n < (sn.bv_len-1); n++ ) {
2312 if( sn.bv_val[n] != '0' ) break;
2317 for( n=0; n < sn.bv_len; n++ ) {
2318 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2319 return LDAP_INVALID_SYNTAX;
2324 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2325 if( rc ) return LDAP_INVALID_SYNTAX;
2327 /* make room from sn + "$" */
2328 out->bv_len = sn.bv_len + newi.bv_len + 1;
2329 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2331 if( out->bv_val == NULL ) {
2332 slap_sl_free( newi.bv_val, ctx );
2336 /* push issuer over */
2337 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2338 /* insert sn and "$" */
2339 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2340 out->bv_val[sn.bv_len] = '$';
2342 out->bv_val[out->bv_len] = '\0';
2345 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2346 out->bv_val, 0, 0 );
2348 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2349 out->bv_val, 0, 0 );
2357 certificateExactNormalize(
2362 struct berval *normalized,
2365 int rc = LDAP_INVALID_SYNTAX;
2367 char *serial = NULL;
2368 ber_len_t seriallen;
2369 struct berval issuer_dn = BER_BVNULL;
2370 X509_NAME *name = NULL;
2371 ASN1_INTEGER *sn = NULL;
2374 if( val->bv_len == 0 ) goto done;
2376 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2377 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2380 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2382 p = (unsigned char *)val->bv_val;
2383 xcert = d2i_X509( NULL, &p, val->bv_len);
2384 if( xcert == NULL ) goto done;
2386 sn=X509_get_serialNumber(xcert);
2387 if ( sn == NULL ) goto done;
2388 serial=i2s_ASN1_INTEGER(0, sn );
2389 if( serial == NULL ) goto done;
2390 seriallen=strlen(serial);
2392 name=X509_get_issuer_name(xcert);
2393 if( name == NULL ) goto done;
2394 rc = dnX509normalize( name, &issuer_dn );
2395 if( rc != LDAP_SUCCESS ) goto done;
2397 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2398 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2399 p = (unsigned char *)normalized->bv_val;
2400 AC_MEMCPY(p, serial, seriallen);
2403 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2404 p += issuer_dn.bv_len;
2408 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2409 normalized->bv_val, 0, 0 );
2411 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2412 normalized->bv_val, NULL, NULL );
2416 if (xcert) X509_free(xcert);
2417 if (serial) ch_free(serial);
2418 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2422 #endif /* HAVE_TLS */
2425 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2426 /* slight optimization - does not need the start parameter */
2427 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2432 check_time_syntax (struct berval *val,
2435 struct berval *fraction)
2438 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2439 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2440 * GeneralizedTime supports leap seconds, UTCTime does not.
2442 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2443 static const int mdays[2][12] = {
2444 /* non-leap years */
2445 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2447 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2450 int part, c, c1, c2, tzoffset, leapyear = 0;
2453 e = p + val->bv_len;
2455 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2456 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2458 for (part = start; part < 7 && p < e; part++) {
2460 if (!ASCII_DIGIT(c1)) {
2465 return LDAP_INVALID_SYNTAX;
2468 if (!ASCII_DIGIT(c)) {
2469 return LDAP_INVALID_SYNTAX;
2471 c += c1 * 10 - '0' * 11;
2472 if ((part | 1) == 3) {
2475 return LDAP_INVALID_SYNTAX;
2478 if (c >= ceiling[part]) {
2479 if (! (c == 60 && part == 6 && start == 0))
2480 return LDAP_INVALID_SYNTAX;
2484 if (part < 5 + start) {
2485 return LDAP_INVALID_SYNTAX;
2487 for (; part < 9; part++) {
2491 /* leapyear check for the Gregorian calendar (year>1581) */
2492 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2496 if (parts[3] >= mdays[leapyear][parts[2]]) {
2497 return LDAP_INVALID_SYNTAX;
2501 fraction->bv_val = p;
2502 fraction->bv_len = 0;
2503 if (p < e && (*p == '.' || *p == ',')) {
2505 while (++p < e && ASCII_DIGIT(*p)) {
2508 if (p - fraction->bv_val == 1) {
2509 return LDAP_INVALID_SYNTAX;
2511 for (end_num = p; end_num[-1] == '0'; --end_num) {
2514 c = end_num - fraction->bv_val;
2515 if (c != 1) fraction->bv_len = c;
2521 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2527 return LDAP_INVALID_SYNTAX;
2533 for (part = 7; part < 9 && p < e; part++) {
2535 if (!ASCII_DIGIT(c1)) {
2540 return LDAP_INVALID_SYNTAX;
2543 if (!ASCII_DIGIT(c2)) {
2544 return LDAP_INVALID_SYNTAX;
2546 parts[part] = c1 * 10 + c2 - '0' * 11;
2547 if (parts[part] >= ceiling[part]) {
2548 return LDAP_INVALID_SYNTAX;
2551 if (part < 8 + start) {
2552 return LDAP_INVALID_SYNTAX;
2555 if (tzoffset == '-') {
2556 /* negative offset to UTC, ie west of Greenwich */
2557 parts[4] += parts[7];
2558 parts[5] += parts[8];
2559 /* offset is just hhmm, no seconds */
2560 for (part = 6; --part >= 0; ) {
2564 c = mdays[leapyear][parts[2]];
2566 if (parts[part] >= c) {
2568 return LDAP_INVALID_SYNTAX;
2573 } else if (part != 5) {
2578 /* positive offset to UTC, ie east of Greenwich */
2579 parts[4] -= parts[7];
2580 parts[5] -= parts[8];
2581 for (part = 6; --part >= 0; ) {
2582 if (parts[part] < 0) {
2584 return LDAP_INVALID_SYNTAX;
2589 /* make first arg to % non-negative */
2590 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2595 } else if (part != 5) {
2602 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2605 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2612 struct berval *normalized )
2616 rc = check_time_syntax(val, 1, parts, NULL);
2617 if (rc != LDAP_SUCCESS) {
2621 normalized->bv_val = ch_malloc( 14 );
2622 if ( normalized->bv_val == NULL ) {
2623 return LBER_ERROR_MEMORY;
2626 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2627 parts[1], parts[2] + 1, parts[3] + 1,
2628 parts[4], parts[5], parts[6] );
2629 normalized->bv_len = 13;
2631 return LDAP_SUCCESS;
2641 return check_time_syntax(in, 1, parts, NULL);
2644 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2647 generalizedTimeValidate(
2652 struct berval fraction;
2653 return check_time_syntax(in, 0, parts, &fraction);
2657 generalizedTimeNormalize(
2662 struct berval *normalized,
2667 struct berval fraction;
2669 rc = check_time_syntax(val, 0, parts, &fraction);
2670 if (rc != LDAP_SUCCESS) {
2674 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2675 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2676 if ( normalized->bv_val == NULL ) {
2677 return LBER_ERROR_MEMORY;
2680 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2681 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2682 parts[4], parts[5], parts[6] );
2683 if ( fraction.bv_len ) {
2684 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2685 fraction.bv_val, fraction.bv_len );
2686 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2688 strcpy( normalized->bv_val + len-1, "Z" );
2689 normalized->bv_len = len;
2691 return LDAP_SUCCESS;
2695 generalizedTimeOrderingMatch(
2700 struct berval *value,
2701 void *assertedValue )
2703 struct berval *asserted = (struct berval *) assertedValue;
2704 ber_len_t v_len = value->bv_len;
2705 ber_len_t av_len = asserted->bv_len;
2707 /* ignore trailing 'Z' when comparing */
2708 int match = memcmp( value->bv_val, asserted->bv_val,
2709 (v_len < av_len ? v_len : av_len) - 1 );
2710 if ( match == 0 ) match = v_len - av_len;
2713 return LDAP_SUCCESS;
2717 deliveryMethodValidate(
2719 struct berval *val )
2722 #define LENOF(s) (sizeof(s)-1)
2723 struct berval tmp = *val;
2725 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2726 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2727 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2730 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2732 switch( tmp.bv_val[0] ) {
2735 if(( tmp.bv_len >= LENOF("any") ) &&
2736 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2738 tmp.bv_len -= LENOF("any");
2739 tmp.bv_val += LENOF("any");
2742 return LDAP_INVALID_SYNTAX;
2746 if(( tmp.bv_len >= LENOF("mhs") ) &&
2747 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2749 tmp.bv_len -= LENOF("mhs");
2750 tmp.bv_val += LENOF("mhs");
2753 return LDAP_INVALID_SYNTAX;
2757 if(( tmp.bv_len >= LENOF("physical") ) &&
2758 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2760 tmp.bv_len -= LENOF("physical");
2761 tmp.bv_val += LENOF("physical");
2764 return LDAP_INVALID_SYNTAX;
2767 case 'T': /* telex or teletex or telephone */
2768 if(( tmp.bv_len >= LENOF("telex") ) &&
2769 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2771 tmp.bv_len -= LENOF("telex");
2772 tmp.bv_val += LENOF("telex");
2775 if(( tmp.bv_len >= LENOF("teletex") ) &&
2776 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2778 tmp.bv_len -= LENOF("teletex");
2779 tmp.bv_val += LENOF("teletex");
2782 if(( tmp.bv_len >= LENOF("telephone") ) &&
2783 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2785 tmp.bv_len -= LENOF("telephone");
2786 tmp.bv_val += LENOF("telephone");
2789 return LDAP_INVALID_SYNTAX;
2792 case 'G': /* g3fax or g4fax */
2793 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2794 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2795 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2797 tmp.bv_len -= LENOF("g3fax");
2798 tmp.bv_val += LENOF("g3fax");
2801 return LDAP_INVALID_SYNTAX;
2805 if(( tmp.bv_len >= LENOF("ia5") ) &&
2806 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2808 tmp.bv_len -= LENOF("ia5");
2809 tmp.bv_val += LENOF("ia5");
2812 return LDAP_INVALID_SYNTAX;
2816 if(( tmp.bv_len >= LENOF("videotex") ) &&
2817 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2819 tmp.bv_len -= LENOF("videotex");
2820 tmp.bv_val += LENOF("videotex");
2823 return LDAP_INVALID_SYNTAX;
2826 return LDAP_INVALID_SYNTAX;
2829 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2831 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2835 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2839 return LDAP_INVALID_SYNTAX;
2841 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2850 nisNetgroupTripleValidate(
2852 struct berval *val )
2857 if ( val->bv_len == 0 ) {
2858 return LDAP_INVALID_SYNTAX;
2861 p = (char *)val->bv_val;
2862 e = p + val->bv_len;
2864 if ( *p != '(' /*')'*/ ) {
2865 return LDAP_INVALID_SYNTAX;
2868 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2872 return LDAP_INVALID_SYNTAX;
2875 } else if ( !AD_CHAR( *p ) ) {
2876 return LDAP_INVALID_SYNTAX;
2880 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2881 return LDAP_INVALID_SYNTAX;
2887 return LDAP_INVALID_SYNTAX;
2890 return LDAP_SUCCESS;
2894 bootParameterValidate(
2896 struct berval *val )
2900 if ( val->bv_len == 0 ) {
2901 return LDAP_INVALID_SYNTAX;
2904 p = (char *)val->bv_val;
2905 e = p + val->bv_len;
2908 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2909 if ( !AD_CHAR( *p ) ) {
2910 return LDAP_INVALID_SYNTAX;
2915 return LDAP_INVALID_SYNTAX;
2919 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2920 if ( !AD_CHAR( *p ) ) {
2921 return LDAP_INVALID_SYNTAX;
2926 return LDAP_INVALID_SYNTAX;
2930 for ( p++; p < e; p++ ) {
2931 if ( !SLAP_PRINTABLE( *p ) ) {
2932 return LDAP_INVALID_SYNTAX;
2936 return LDAP_SUCCESS;
2940 firstComponentNormalize(
2945 struct berval *normalized,
2952 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2953 ber_dupbv_x( normalized, val, ctx );
2954 return LDAP_SUCCESS;
2957 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2959 if( val->bv_val[0] != '(' /*')'*/ &&
2960 val->bv_val[0] != '{' /*'}'*/ )
2962 return LDAP_INVALID_SYNTAX;
2965 /* trim leading white space */
2967 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2973 /* grab next word */
2974 comp.bv_val = &val->bv_val[len];
2975 len = val->bv_len - len;
2977 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2983 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2984 rc = numericoidValidate( NULL, &comp );
2985 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2986 rc = integerValidate( NULL, &comp );
2988 rc = LDAP_INVALID_SYNTAX;
2992 if( rc == LDAP_SUCCESS ) {
2993 ber_dupbv_x( normalized, &comp, ctx );
3000 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3001 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3003 static slap_syntax_defs_rec syntax_defs[] = {
3004 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3005 X_BINARY X_NOT_H_R ")",
3006 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3007 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3009 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3011 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3013 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3014 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3016 SLAP_SYNTAX_BER, berValidate, NULL},
3017 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3018 0, bitStringValidate, NULL },
3019 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3020 0, booleanValidate, NULL},
3021 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3022 X_BINARY X_NOT_H_R ")",
3023 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3024 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3025 X_BINARY X_NOT_H_R ")",
3026 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3027 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
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.11 DESC 'Country String' )",
3031 0, countryStringValidate, NULL},
3032 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3033 0, dnValidate, dnPretty},
3034 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3035 0, rdnValidate, rdnPretty},
3036 #ifdef LDAP_COMP_MATCH
3037 {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
3038 0, componentFilterValidate, NULL},
3040 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3042 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3043 0, deliveryMethodValidate, NULL},
3044 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3045 0, UTF8StringValidate, NULL},
3046 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3048 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3050 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3052 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3054 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3056 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3057 0, printablesStringValidate, NULL},
3058 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3059 SLAP_SYNTAX_BLOB, NULL, NULL},
3060 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3061 0, generalizedTimeValidate, NULL},
3062 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3064 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3065 0, IA5StringValidate, NULL},
3066 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3067 0, integerValidate, NULL},
3068 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3069 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3070 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3072 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3074 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3076 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3078 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3080 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3081 0, nameUIDValidate, nameUIDPretty },
3082 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3084 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3085 0, numericStringValidate, NULL},
3086 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3088 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3089 0, numericoidValidate, NULL},
3090 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3091 0, IA5StringValidate, NULL},
3092 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3093 0, blobValidate, NULL},
3094 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3095 0, UTF8StringValidate, NULL},
3096 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3098 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3100 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3101 0, printableStringValidate, NULL},
3102 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3103 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3104 0, subtreeSpecificationValidate, NULL},
3105 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3106 X_BINARY X_NOT_H_R ")",
3107 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3108 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3109 0, printableStringValidate, NULL},
3110 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3112 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3113 0, printablesStringValidate, NULL},
3114 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3115 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3116 0, utcTimeValidate, NULL},
3118 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3120 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3122 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3124 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3126 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3129 /* RFC 2307 NIS Syntaxes */
3130 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3131 0, nisNetgroupTripleValidate, NULL},
3132 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3133 0, bootParameterValidate, NULL},
3135 /* From PKIX *//* This OID is not published yet. */
3136 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3138 serialNumberAndIssuerValidate,
3139 serialNumberAndIssuerPretty},
3141 #ifdef SLAPD_ACI_ENABLED
3142 /* OpenLDAP Experimental Syntaxes */
3143 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3145 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3149 #ifdef SLAPD_AUTHPASSWD
3150 /* needs updating */
3151 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3152 SLAP_SYNTAX_HIDE, NULL, NULL},
3155 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3156 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3158 /* OpenLDAP Void Syntax */
3159 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3160 SLAP_SYNTAX_HIDE, inValidate, NULL},
3161 {NULL, 0, NULL, NULL}
3164 char *certificateExactMatchSyntaxes[] = {
3165 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3168 char *directoryStringSyntaxes[] = {
3169 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3172 char *integerFirstComponentMatchSyntaxes[] = {
3173 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3174 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3177 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3178 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3179 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3180 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3181 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3182 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3183 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3184 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3185 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3190 * Other matching rules in X.520 that we do not use (yet):
3192 * 2.5.13.25 uTCTimeMatch
3193 * 2.5.13.26 uTCTimeOrderingMatch
3194 * 2.5.13.31* directoryStringFirstComponentMatch
3195 * 2.5.13.32* wordMatch
3196 * 2.5.13.33* keywordMatch
3197 * 2.5.13.36 certificatePairExactMatch
3198 * 2.5.13.37 certificatePairMatch
3199 * 2.5.13.38 certificateListExactMatch
3200 * 2.5.13.39 certificateListMatch
3201 * 2.5.13.40 algorithmIdentifierMatch
3202 * 2.5.13.41* storedPrefixMatch
3203 * 2.5.13.42 attributeCertificateMatch
3204 * 2.5.13.43 readerAndKeyIDMatch
3205 * 2.5.13.44 attributeIntegrityMatch
3207 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3209 static slap_mrule_defs_rec mrule_defs[] = {
3211 * EQUALITY matching rules must be listed after associated APPROX
3212 * matching rules. So, we list all APPROX matching rules first.
3214 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3215 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3216 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3217 NULL, NULL, directoryStringApproxMatch,
3218 directoryStringApproxIndexer, directoryStringApproxFilter,
3221 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3222 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3223 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3224 NULL, NULL, IA5StringApproxMatch,
3225 IA5StringApproxIndexer, IA5StringApproxFilter,
3229 * Other matching rules
3232 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3233 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3234 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3235 NULL, NULL, octetStringMatch,
3236 octetStringIndexer, octetStringFilter,
3239 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3240 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3241 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3242 NULL, dnNormalize, dnMatch,
3243 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 #ifdef LDAP_COMP_MATCH
3254 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3255 "SYNTAX 1.2.36.79672281.1.5.2 )",
3256 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3257 NULL, NULL , componentFilterMatch,
3258 octetStringIndexer, octetStringFilter,
3262 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3263 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3264 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3265 NULL, UTF8StringNormalize, octetStringMatch,
3266 octetStringIndexer, octetStringFilter,
3267 directoryStringApproxMatchOID },
3269 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3270 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3271 SLAP_MR_ORDERING, directoryStringSyntaxes,
3272 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3274 "caseIgnoreMatch" },
3276 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3277 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3278 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3279 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3280 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3281 "caseIgnoreMatch" },
3283 {"( 2.5.13.5 NAME 'caseExactMatch' "
3284 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3285 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3286 NULL, UTF8StringNormalize, octetStringMatch,
3287 octetStringIndexer, octetStringFilter,
3288 directoryStringApproxMatchOID },
3290 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3291 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3292 SLAP_MR_ORDERING, directoryStringSyntaxes,
3293 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3297 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3298 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3299 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3300 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3301 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3304 {"( 2.5.13.8 NAME 'numericStringMatch' "
3305 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3306 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3307 NULL, numericStringNormalize, octetStringMatch,
3308 octetStringIndexer, octetStringFilter,
3311 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3312 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3313 SLAP_MR_ORDERING, NULL,
3314 NULL, numericStringNormalize, octetStringOrderingMatch,
3316 "numericStringMatch" },
3318 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3319 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3320 SLAP_MR_SUBSTR, NULL,
3321 NULL, numericStringNormalize, octetStringSubstringsMatch,
3322 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3323 "numericStringMatch" },
3325 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3326 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3327 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3328 NULL, NULL, NULL, NULL, NULL, NULL },
3330 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3331 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3332 SLAP_MR_SUBSTR, NULL,
3333 NULL, NULL, NULL, NULL, NULL,
3334 "caseIgnoreListMatch" },
3336 {"( 2.5.13.13 NAME 'booleanMatch' "
3337 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3338 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3339 NULL, NULL, booleanMatch,
3340 octetStringIndexer, octetStringFilter,
3343 {"( 2.5.13.14 NAME 'integerMatch' "
3344 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3345 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3346 NULL, NULL, integerMatch,
3347 octetStringIndexer, octetStringFilter,
3350 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3351 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3352 SLAP_MR_ORDERING, NULL,
3353 NULL, NULL, integerMatch,
3357 {"( 2.5.13.16 NAME 'bitStringMatch' "
3358 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3359 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3360 NULL, NULL, octetStringMatch,
3361 octetStringIndexer, octetStringFilter,
3364 {"( 2.5.13.17 NAME 'octetStringMatch' "
3365 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3366 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3367 NULL, NULL, octetStringMatch,
3368 octetStringIndexer, octetStringFilter,
3371 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3373 SLAP_MR_ORDERING, NULL,
3374 NULL, NULL, octetStringOrderingMatch,
3376 "octetStringMatch" },
3378 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3379 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3380 SLAP_MR_SUBSTR, NULL,
3381 NULL, NULL, octetStringSubstringsMatch,
3382 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3383 "octetStringMatch" },
3385 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3386 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3387 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3389 telephoneNumberNormalize, octetStringMatch,
3390 octetStringIndexer, octetStringFilter,
3393 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3394 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3395 SLAP_MR_SUBSTR, NULL,
3396 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3397 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3398 "telephoneNumberMatch" },
3400 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3401 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3402 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3403 NULL, NULL, NULL, NULL, NULL, NULL },
3405 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3406 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3407 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3408 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3412 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3413 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3414 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3415 NULL, NULL, NULL, NULL, NULL, NULL },
3417 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3418 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3419 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3420 NULL, generalizedTimeNormalize, octetStringMatch,
3424 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3425 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3426 SLAP_MR_ORDERING, NULL,
3427 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3429 "generalizedTimeMatch" },
3431 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3432 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3433 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3434 integerFirstComponentMatchSyntaxes,
3435 NULL, firstComponentNormalize, integerMatch,
3436 octetStringIndexer, octetStringFilter,
3439 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3440 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3441 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3442 objectIdentifierFirstComponentMatchSyntaxes,
3443 NULL, firstComponentNormalize, octetStringMatch,
3444 octetStringIndexer, octetStringFilter,
3447 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3448 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3449 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3451 NULL, certificateExactNormalize, octetStringMatch,
3452 octetStringIndexer, octetStringFilter,
3454 NULL, NULL, NULL, NULL, NULL,
3458 {"( 2.5.13.35 NAME 'certificateMatch' "
3459 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3460 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3462 NULL, NULL, octetStringMatch,
3463 octetStringIndexer, octetStringFilter,
3465 NULL, NULL, NULL, NULL, NULL,
3469 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3470 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3471 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3472 NULL, IA5StringNormalize, octetStringMatch,
3473 octetStringIndexer, octetStringFilter,
3474 IA5StringApproxMatchOID },
3476 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3477 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3478 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3479 NULL, IA5StringNormalize, octetStringMatch,
3480 octetStringIndexer, octetStringFilter,
3481 IA5StringApproxMatchOID },
3483 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3484 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3485 SLAP_MR_SUBSTR, NULL,
3486 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3487 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3488 "caseIgnoreIA5Match" },
3490 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3492 SLAP_MR_SUBSTR, NULL,
3493 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3494 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3495 "caseExactIA5Match" },
3497 #ifdef SLAPD_AUTHPASSWD
3498 /* needs updating */
3499 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3500 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3501 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3502 NULL, NULL, authPasswordMatch,
3507 #ifdef SLAPD_ACI_ENABLED
3508 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3509 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3510 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3511 NULL, NULL, OpenLDAPaciMatch,
3516 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3517 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3519 NULL, NULL, integerBitAndMatch,
3523 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3524 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3526 NULL, NULL, integerBitOrMatch,
3530 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3531 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3532 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3533 NULL, UUIDNormalize, octetStringMatch,
3534 octetStringIndexer, octetStringFilter,
3537 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3538 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3539 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3540 NULL, UUIDNormalize, octetStringOrderingMatch,
3541 octetStringIndexer, octetStringFilter,
3544 {NULL, SLAP_MR_NONE, NULL,
3545 NULL, NULL, NULL, NULL, NULL,
3550 slap_schema_init( void )
3555 /* we should only be called once (from main) */
3556 assert( schema_init_done == 0 );
3558 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3559 res = register_syntax( &syntax_defs[i] );
3562 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3563 syntax_defs[i].sd_desc );
3568 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3569 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3570 mrule_defs[i].mrd_compat_syntaxes == NULL )
3573 "slap_schema_init: Ignoring unusable matching rule %s\n",
3574 mrule_defs[i].mrd_desc );
3578 res = register_matching_rule( &mrule_defs[i] );
3582 "slap_schema_init: Error registering matching rule %s\n",
3583 mrule_defs[i].mrd_desc );
3588 res = slap_schema_load();
3589 schema_init_done = 1;
3594 schema_destroy( void )