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( asserted->bv_len != 0 ) {
1102 assertedDN = *asserted;
1104 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
1105 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
1107 /* assume presence of optional UID */
1108 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1110 if( assertedUID.bv_val == NULL ||
1111 assertedUID.bv_val < assertedDN.bv_val ||
1112 ( assertedUID.bv_val > assertedDN.bv_val &&
1113 assertedUID.bv_val[-1] == '\\' ))
1115 return LDAP_INVALID_SYNTAX;
1118 assertedUID.bv_len = assertedDN.bv_len -
1119 (assertedUID.bv_val - assertedDN.bv_val);
1120 assertedDN.bv_len -= assertedUID.bv_len;
1122 /* trim the separator */
1123 assertedUID.bv_len--;
1124 assertedUID.bv_val++;
1128 if( value->bv_len != 0 ) {
1131 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
1132 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
1134 /* assume presence of optional UID */
1135 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1137 if( valueUID.bv_val == NULL ||
1138 valueUID.bv_val < valueDN.bv_val ||
1139 ( valueUID.bv_val > valueDN.bv_val &&
1140 valueUID.bv_val[-1] == '\\' ) )
1142 return LDAP_INVALID_SYNTAX;
1145 valueUID.bv_len = valueDN.bv_len -
1146 (valueUID.bv_val - valueDN.bv_val);
1147 valueDN.bv_len -= valueUID.bv_len;
1149 /* trim the separator */
1155 if( valueUID.bv_len && assertedUID.bv_len ) {
1156 match = valueUID.bv_len - assertedUID.bv_len;
1159 return LDAP_SUCCESS;
1162 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1165 return LDAP_SUCCESS;
1169 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1173 * Handling boolean syntax and matching is quite rigid.
1174 * A more flexible approach would be to allow a variety
1175 * of strings to be normalized and prettied into TRUE
1183 /* very unforgiving validation, requires no normalization
1184 * before simplistic matching
1187 if( in->bv_len == 4 ) {
1188 if( bvmatch( in, &slap_true_bv ) ) {
1189 return LDAP_SUCCESS;
1191 } else if( in->bv_len == 5 ) {
1192 if( bvmatch( in, &slap_false_bv ) ) {
1193 return LDAP_SUCCESS;
1197 return LDAP_INVALID_SYNTAX;
1206 struct berval *value,
1207 void *assertedValue )
1209 /* simplistic matching allowed by rigid validation */
1210 struct berval *asserted = (struct berval *) assertedValue;
1211 *matchp = value->bv_len != asserted->bv_len;
1212 return LDAP_SUCCESS;
1215 /*-------------------------------------------------------------------
1216 LDAP/X.500 string syntax / matching rules have a few oddities. This
1217 comment attempts to detail how slapd(8) treats them.
1220 StringSyntax X.500 LDAP Matching/Comments
1221 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1222 PrintableString subset subset i/e + ignore insignificant spaces
1223 PrintableString subset subset i/e + ignore insignificant spaces
1224 NumericString subset subset ignore all spaces
1225 IA5String ASCII ASCII i/e + ignore insignificant spaces
1226 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1228 TelephoneNumber subset subset i + ignore all spaces and "-"
1230 See draft-ietf-ldapbis-strpro for details (once published).
1234 In X.500(93), a directory string can be either a PrintableString,
1235 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1236 In later versions, more CHOICEs were added. In all cases the string
1239 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1240 A directory string cannot be zero length.
1242 For matching, there are both case ignore and exact rules. Both
1243 also require that "insignificant" spaces be ignored.
1244 spaces before the first non-space are ignored;
1245 spaces after the last non-space are ignored;
1246 spaces after a space are ignored.
1247 Note: by these rules (and as clarified in X.520), a string of only
1248 spaces is to be treated as if held one space, not empty (which
1249 would be a syntax error).
1252 In ASN.1, numeric string is just a string of digits and spaces
1253 and could be empty. However, in X.500, all attribute values of
1254 numeric string carry a non-empty constraint. For example:
1256 internationalISDNNumber ATTRIBUTE ::= {
1257 WITH SYNTAX InternationalISDNNumber
1258 EQUALITY MATCHING RULE numericStringMatch
1259 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1260 ID id-at-internationalISDNNumber }
1261 InternationalISDNNumber ::=
1262 NumericString (SIZE(1..ub-international-isdn-number))
1264 Unforunately, some assertion values are don't carry the same
1265 constraint (but its unclear how such an assertion could ever
1266 be true). In LDAP, there is one syntax (numericString) not two
1267 (numericString with constraint, numericString without constraint).
1268 This should be treated as numericString with non-empty constraint.
1269 Note that while someone may have no ISDN number, there are no ISDN
1270 numbers which are zero length.
1272 In matching, spaces are ignored.
1275 In ASN.1, Printable string is just a string of printable characters
1276 and can be empty. In X.500, semantics much like NumericString (see
1277 serialNumber for a like example) excepting uses insignificant space
1278 handling instead of ignore all spaces.
1281 Basically same as PrintableString. There are no examples in X.500,
1282 but same logic applies. So we require them to be non-empty as
1285 -------------------------------------------------------------------*/
1294 unsigned char *u = (unsigned char *)in->bv_val;
1296 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1297 /* directory strings cannot be empty */
1298 return LDAP_INVALID_SYNTAX;
1301 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1302 /* get the length indicated by the first byte */
1303 len = LDAP_UTF8_CHARLEN2( u, len );
1305 /* very basic checks */
1308 if( (u[5] & 0xC0) != 0x80 ) {
1309 return LDAP_INVALID_SYNTAX;
1312 if( (u[4] & 0xC0) != 0x80 ) {
1313 return LDAP_INVALID_SYNTAX;
1316 if( (u[3] & 0xC0) != 0x80 ) {
1317 return LDAP_INVALID_SYNTAX;
1320 if( (u[2] & 0xC0 )!= 0x80 ) {
1321 return LDAP_INVALID_SYNTAX;
1324 if( (u[1] & 0xC0) != 0x80 ) {
1325 return LDAP_INVALID_SYNTAX;
1328 /* CHARLEN already validated it */
1331 return LDAP_INVALID_SYNTAX;
1334 /* make sure len corresponds with the offset
1335 to the next character */
1336 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1340 return LDAP_INVALID_SYNTAX;
1343 return LDAP_SUCCESS;
1347 UTF8StringNormalize(
1352 struct berval *normalized,
1355 struct berval tmp, nvalue;
1359 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1361 if( val->bv_val == NULL ) {
1362 /* assume we're dealing with a syntax (e.g., UTF8String)
1363 * which allows empty strings
1365 normalized->bv_len = 0;
1366 normalized->bv_val = NULL;
1367 return LDAP_SUCCESS;
1370 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1371 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1372 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1373 ? LDAP_UTF8_APPROX : 0;
1375 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1380 /* collapse spaces (in place) */
1382 nvalue.bv_val = tmp.bv_val;
1384 wasspace=1; /* trim leading spaces */
1385 for( i=0; i<tmp.bv_len; i++) {
1386 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1387 if( wasspace++ == 0 ) {
1388 /* trim repeated spaces */
1389 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1393 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1397 if( nvalue.bv_len ) {
1399 /* last character was a space, trim it */
1402 nvalue.bv_val[nvalue.bv_len] = '\0';
1405 /* string of all spaces is treated as one space */
1406 nvalue.bv_val[0] = ' ';
1407 nvalue.bv_val[1] = '\0';
1411 *normalized = nvalue;
1412 return LDAP_SUCCESS;
1415 #if defined(SLAPD_APPROX_INITIALS)
1416 # define SLAPD_APPROX_DELIMITER "._ "
1417 # define SLAPD_APPROX_WORDLEN 2
1419 # define SLAPD_APPROX_DELIMITER " "
1420 # define SLAPD_APPROX_WORDLEN 1
1429 struct berval *value,
1430 void *assertedValue )
1432 struct berval *nval, *assertv;
1433 char *val, **values, **words, *c;
1434 int i, count, len, nextchunk=0, nextavail=0;
1436 /* Yes, this is necessary */
1437 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1438 if( nval == NULL ) {
1440 return LDAP_SUCCESS;
1443 /* Yes, this is necessary */
1444 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1445 NULL, LDAP_UTF8_APPROX, NULL );
1446 if( assertv == NULL ) {
1449 return LDAP_SUCCESS;
1452 /* Isolate how many words there are */
1453 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1454 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1455 if ( c == NULL ) break;
1460 /* Get a phonetic copy of each word */
1461 words = (char **)ch_malloc( count * sizeof(char *) );
1462 values = (char **)ch_malloc( count * sizeof(char *) );
1463 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1465 values[i] = phonetic(c);
1468 /* Work through the asserted value's words, to see if at least some
1469 of the words are there, in the same order. */
1471 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1472 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1477 #if defined(SLAPD_APPROX_INITIALS)
1478 else if( len == 1 ) {
1479 /* Single letter words need to at least match one word's initial */
1480 for( i=nextavail; i<count; i++ )
1481 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1488 /* Isolate the next word in the asserted value and phonetic it */
1489 assertv->bv_val[nextchunk+len] = '\0';
1490 val = phonetic( assertv->bv_val + nextchunk );
1492 /* See if this phonetic chunk is in the remaining words of *value */
1493 for( i=nextavail; i<count; i++ ){
1494 if( !strcmp( val, values[i] ) ){
1502 /* This chunk in the asserted value was NOT within the *value. */
1508 /* Go on to the next word in the asserted value */
1512 /* If some of the words were seen, call it a match */
1513 if( nextavail > 0 ) {
1520 /* Cleanup allocs */
1521 ber_bvfree( assertv );
1522 for( i=0; i<count; i++ ) {
1523 ch_free( values[i] );
1529 return LDAP_SUCCESS;
1538 struct berval *prefix,
1544 int i,j, len, wordcount, keycount=0;
1545 struct berval *newkeys;
1546 BerVarray keys=NULL;
1548 for( j=0; values[j].bv_val != NULL; j++ ) {
1549 struct berval val = BER_BVNULL;
1550 /* Yes, this is necessary */
1551 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1552 assert( val.bv_val != NULL );
1554 /* Isolate how many words there are. There will be a key for each */
1555 for( wordcount = 0, c = val.bv_val; *c; c++) {
1556 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1557 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1559 if (*c == '\0') break;
1563 /* Allocate/increase storage to account for new keys */
1564 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1565 * sizeof(struct berval) );
1566 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1567 if( keys ) ch_free( keys );
1570 /* Get a phonetic copy of each word */
1571 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1573 if( len < SLAPD_APPROX_WORDLEN ) continue;
1574 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1579 ber_memfree( val.bv_val );
1581 keys[keycount].bv_val = NULL;
1584 return LDAP_SUCCESS;
1593 struct berval *prefix,
1594 void * assertedValue,
1603 /* Yes, this is necessary */
1604 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1605 NULL, LDAP_UTF8_APPROX, NULL );
1606 if( val == NULL || val->bv_val == NULL ) {
1607 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1608 keys[0].bv_val = NULL;
1611 return LDAP_SUCCESS;
1614 /* Isolate how many words there are. There will be a key for each */
1615 for( count = 0,c = val->bv_val; *c; c++) {
1616 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1617 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1619 if (*c == '\0') break;
1623 /* Allocate storage for new keys */
1624 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1626 /* Get a phonetic copy of each word */
1627 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1629 if( len < SLAPD_APPROX_WORDLEN ) continue;
1630 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1636 keys[count].bv_val = NULL;
1639 return LDAP_SUCCESS;
1642 /* Remove all spaces and '-' characters */
1644 telephoneNumberNormalize(
1649 struct berval *normalized,
1654 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1656 /* validator should have refused an empty string */
1657 assert( val->bv_len );
1659 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1661 for( p = val->bv_val; *p; p++ ) {
1662 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1668 normalized->bv_len = q - normalized->bv_val;
1670 if( normalized->bv_len == 0 ) {
1671 slap_sl_free( normalized->bv_val, ctx );
1672 normalized->bv_val = NULL;
1673 return LDAP_INVALID_SYNTAX;
1676 return LDAP_SUCCESS;
1684 struct berval val = *in;
1686 if( val.bv_len == 0 ) {
1687 /* disallow empty strings */
1688 return LDAP_INVALID_SYNTAX;
1691 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1692 if ( val.bv_len == 1 ) {
1693 return LDAP_SUCCESS;
1696 if ( val.bv_val[0] == '0' ) {
1703 while ( OID_LEADCHAR( val.bv_val[0] )) {
1707 if ( val.bv_len == 0 ) {
1708 return LDAP_SUCCESS;
1712 if( !OID_SEPARATOR( val.bv_val[0] )) {
1720 return LDAP_INVALID_SYNTAX;
1729 struct berval val = *in;
1731 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1733 if ( val.bv_val[0] == '-' ) {
1737 if( val.bv_len == 0 ) { /* bare "-" */
1738 return LDAP_INVALID_SYNTAX;
1741 if( val.bv_val[0] == '0' ) { /* "-0" */
1742 return LDAP_INVALID_SYNTAX;
1745 } else if ( val.bv_val[0] == '0' ) {
1746 if( val.bv_len > 1 ) { /* "0<more>" */
1747 return LDAP_INVALID_SYNTAX;
1750 return LDAP_SUCCESS;
1753 for( i=0; i < val.bv_len; i++ ) {
1754 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1755 return LDAP_INVALID_SYNTAX;
1759 return LDAP_SUCCESS;
1768 struct berval *value,
1769 void *assertedValue )
1771 struct berval *asserted = (struct berval *) assertedValue;
1772 int vsign = 1, asign = 1; /* default sign = '+' */
1777 if( v.bv_val[0] == '-' ) {
1783 if( v.bv_len == 0 ) vsign = 0;
1786 if( a.bv_val[0] == '-' ) {
1792 if( a.bv_len == 0 ) vsign = 0;
1794 match = vsign - asign;
1796 match = ( v.bv_len != a.bv_len
1797 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1798 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1799 if( vsign < 0 ) match = -match;
1803 return LDAP_SUCCESS;
1807 countryStringValidate(
1809 struct berval *val )
1811 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1813 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1814 return LDAP_INVALID_SYNTAX;
1816 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1817 return LDAP_INVALID_SYNTAX;
1820 return LDAP_SUCCESS;
1824 printableStringValidate(
1826 struct berval *val )
1830 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1832 for(i=0; i < val->bv_len; i++) {
1833 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1834 return LDAP_INVALID_SYNTAX;
1838 return LDAP_SUCCESS;
1842 printablesStringValidate(
1844 struct berval *val )
1848 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1850 for(i=0,len=0; i < val->bv_len; i++) {
1851 int c = val->bv_val[i];
1855 return LDAP_INVALID_SYNTAX;
1859 } else if ( SLAP_PRINTABLE(c) ) {
1862 return LDAP_INVALID_SYNTAX;
1867 return LDAP_INVALID_SYNTAX;
1870 return LDAP_SUCCESS;
1876 struct berval *val )
1880 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1882 for(i=0; i < val->bv_len; i++) {
1883 if( !LDAP_ASCII(val->bv_val[i]) ) {
1884 return LDAP_INVALID_SYNTAX;
1888 return LDAP_SUCCESS;
1897 struct berval *normalized,
1901 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1903 assert( val->bv_len );
1905 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1909 /* Ignore initial whitespace */
1910 while ( ASCII_SPACE( *p ) ) p++;
1912 normalized->bv_val = ber_strdup_x( p, ctx );
1913 p = q = normalized->bv_val;
1916 if ( ASCII_SPACE( *p ) ) {
1919 /* Ignore the extra whitespace */
1920 while ( ASCII_SPACE( *p ) ) {
1924 } else if ( casefold ) {
1925 /* Most IA5 rules require casefolding */
1926 *q++ = TOLOWER(*p); p++;
1933 assert( normalized->bv_val <= p );
1937 * If the string ended in space, backup the pointer one
1938 * position. One is enough because the above loop collapsed
1939 * all whitespace to a single space.
1941 if ( ASCII_SPACE( q[-1] ) ) --q;
1943 /* null terminate */
1946 normalized->bv_len = q - normalized->bv_val;
1947 if( normalized->bv_len == 0 ) {
1948 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1949 normalized->bv_val[0] = ' ';
1950 normalized->bv_val[1] = '\0';
1951 normalized->bv_len = 1;
1954 return LDAP_SUCCESS;
1963 if( in->bv_len != 36 ) {
1965 return LDAP_INVALID_SYNTAX;
1968 for( i=0; i<36; i++ ) {
1974 if( in->bv_val[i] != '-' ) {
1975 return LDAP_INVALID_SYNTAX;
1979 if( !ASCII_HEX( in->bv_val[i]) ) {
1980 return LDAP_INVALID_SYNTAX;
1985 return LDAP_SUCCESS;
1994 struct berval *normalized,
1997 unsigned char octet = '\0';
2000 normalized->bv_len = 16;
2001 normalized->bv_val = slap_sl_malloc( normalized->bv_len+1, ctx );
2003 for( i=0, j=0; i<36; i++ ) {
2004 unsigned char nibble;
2005 if( val->bv_val[i] == '-' ) {
2008 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
2009 nibble = val->bv_val[i] - '0';
2011 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
2012 nibble = val->bv_val[i] - ('a'-10);
2014 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
2015 nibble = val->bv_val[i] - ('A'-10);
2018 slap_sl_free( normalized->bv_val, ctx );
2019 return LDAP_INVALID_SYNTAX;
2024 normalized->bv_val[j>>1] = octet;
2026 octet = nibble << 4;
2031 normalized->bv_val[normalized->bv_len] = 0;
2032 return LDAP_SUCCESS;
2038 numericStringValidate(
2044 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2046 for(i=0; i < in->bv_len; i++) {
2047 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2048 return LDAP_INVALID_SYNTAX;
2052 return LDAP_SUCCESS;
2056 numericStringNormalize(
2061 struct berval *normalized,
2064 /* removal all spaces */
2067 assert( val->bv_len );
2069 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2072 q = normalized->bv_val;
2075 if ( ASCII_SPACE( *p ) ) {
2076 /* Ignore whitespace */
2083 /* we should have copied no more then is in val */
2084 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2086 /* null terminate */
2089 normalized->bv_len = q - normalized->bv_val;
2091 if( normalized->bv_len == 0 ) {
2092 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2093 normalized->bv_val[0] = ' ';
2094 normalized->bv_val[1] = '\0';
2095 normalized->bv_len = 1;
2098 return LDAP_SUCCESS;
2102 * Integer conversion macros that will use the largest available
2105 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2106 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2107 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2108 # define SLAP_LONG_MAX LLONG_MAX
2109 # define SLAP_LONG_MIN LLONG_MIN
2110 # define SLAP_LONG long long
2112 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2113 # define SLAP_LONG_MAX LONG_MAX
2114 # define SLAP_LONG_MIN LONG_MIN
2115 # define SLAP_LONG long
2116 #endif /* HAVE_STRTOLL ... */
2124 struct berval *value,
2125 void *assertedValue )
2127 SLAP_LONG lValue, lAssertedValue;
2129 /* safe to assume integers are NUL terminated? */
2130 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2131 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2134 return LDAP_CONSTRAINT_VIOLATION;
2137 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2139 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2142 return LDAP_CONSTRAINT_VIOLATION;
2145 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2146 return LDAP_SUCCESS;
2155 struct berval *value,
2156 void *assertedValue )
2158 SLAP_LONG lValue, lAssertedValue;
2160 /* safe to assume integers are NUL terminated? */
2161 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2162 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2165 return LDAP_CONSTRAINT_VIOLATION;
2168 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2170 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2173 return LDAP_CONSTRAINT_VIOLATION;
2176 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2177 return LDAP_SUCCESS;
2181 serialNumberAndIssuerValidate(
2188 struct berval sn, i;
2189 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2191 i.bv_val = strchr( in->bv_val, '$' );
2192 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2194 sn.bv_val = in->bv_val;
2195 sn.bv_len = i.bv_val - in->bv_val;
2198 i.bv_len = in->bv_len - (sn.bv_len + 1);
2200 /* validate serial number (strict for now) */
2201 for( n=0; n < sn.bv_len; n++ ) {
2202 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2206 rc = dnValidate( NULL, &i );
2207 if( rc ) return LDAP_INVALID_SYNTAX;
2209 return LDAP_SUCCESS;
2213 serialNumberAndIssuerPretty(
2222 struct berval sn, i, newi;
2228 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2229 val->bv_val, 0, 0 );
2231 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2232 val->bv_val, 0, 0 );
2235 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2237 i.bv_val = strchr( val->bv_val, '$' );
2238 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2240 sn.bv_val = val->bv_val;
2241 sn.bv_len = i.bv_val - val->bv_val;
2244 i.bv_len = val->bv_len - (sn.bv_len + 1);
2246 /* eat leading zeros */
2247 for( n=0; n < (sn.bv_len-1); n++ ) {
2248 if( sn.bv_val[n] != '0' ) break;
2253 for( n=0; n < sn.bv_len; n++ ) {
2254 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2258 rc = dnPretty( syntax, &i, &newi, ctx );
2259 if( rc ) return LDAP_INVALID_SYNTAX;
2261 /* make room from sn + "$" */
2262 out->bv_len = sn.bv_len + newi.bv_len + 1;
2263 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2265 if( out->bv_val == NULL ) {
2266 slap_sl_free( newi.bv_val, ctx );
2270 /* push issuer over */
2271 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2272 /* insert sn and "$" */
2273 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2274 out->bv_val[sn.bv_len] = '$';
2276 out->bv_val[out->bv_len] = '\0';
2279 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2280 out->bv_val, 0, 0 );
2282 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2283 out->bv_val, 0, 0 );
2286 return LDAP_SUCCESS;
2290 * This routine is called by certificateExactNormalize when
2291 * certificateExactNormalize receives a search string instead of
2292 * a certificate. This routine checks if the search value is valid
2293 * and then returns the normalized value
2296 serialNumberAndIssuerNormalize(
2307 struct berval sn, i, newi;
2313 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2314 val->bv_val, 0, 0 );
2316 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2317 val->bv_val, 0, 0 );
2320 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2322 i.bv_val = strchr( val->bv_val, '$' );
2323 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2325 sn.bv_val = val->bv_val;
2326 sn.bv_len = i.bv_val - val->bv_val;
2329 i.bv_len = val->bv_len - (sn.bv_len + 1);
2331 /* eat leading zeros */
2332 for( n=0; n < (sn.bv_len-1); n++ ) {
2333 if( sn.bv_val[n] != '0' ) break;
2338 for( n=0; n < sn.bv_len; n++ ) {
2339 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2340 return LDAP_INVALID_SYNTAX;
2345 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2346 if( rc ) return LDAP_INVALID_SYNTAX;
2348 /* make room from sn + "$" */
2349 out->bv_len = sn.bv_len + newi.bv_len + 1;
2350 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2352 if( out->bv_val == NULL ) {
2353 slap_sl_free( newi.bv_val, ctx );
2357 /* push issuer over */
2358 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2359 /* insert sn and "$" */
2360 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2361 out->bv_val[sn.bv_len] = '$';
2363 out->bv_val[out->bv_len] = '\0';
2366 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2367 out->bv_val, 0, 0 );
2369 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2370 out->bv_val, 0, 0 );
2378 certificateExactNormalize(
2383 struct berval *normalized,
2386 int rc = LDAP_INVALID_SYNTAX;
2388 char *serial = NULL;
2389 ber_len_t seriallen;
2390 struct berval issuer_dn = BER_BVNULL;
2391 X509_NAME *name = NULL;
2392 ASN1_INTEGER *sn = NULL;
2395 if( val->bv_len == 0 ) goto done;
2397 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2398 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2401 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2403 p = (unsigned char *)val->bv_val;
2404 xcert = d2i_X509( NULL, &p, val->bv_len);
2405 if( xcert == NULL ) goto done;
2407 sn=X509_get_serialNumber(xcert);
2408 if ( sn == NULL ) goto done;
2409 serial=i2s_ASN1_INTEGER(0, sn );
2410 if( serial == NULL ) goto done;
2411 seriallen=strlen(serial);
2413 name=X509_get_issuer_name(xcert);
2414 if( name == NULL ) goto done;
2415 rc = dnX509normalize( name, &issuer_dn );
2416 if( rc != LDAP_SUCCESS ) goto done;
2418 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2419 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2420 p = (unsigned char *)normalized->bv_val;
2421 AC_MEMCPY(p, serial, seriallen);
2424 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2425 p += issuer_dn.bv_len;
2429 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2430 normalized->bv_val, 0, 0 );
2432 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2433 normalized->bv_val, NULL, NULL );
2437 if (xcert) X509_free(xcert);
2438 if (serial) ch_free(serial);
2439 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2443 #endif /* HAVE_TLS */
2446 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2447 /* slight optimization - does not need the start parameter */
2448 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2453 check_time_syntax (struct berval *val,
2456 struct berval *fraction)
2459 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2460 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2461 * GeneralizedTime supports leap seconds, UTCTime does not.
2463 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2464 static const int mdays[2][12] = {
2465 /* non-leap years */
2466 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2468 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2471 int part, c, c1, c2, tzoffset, leapyear = 0;
2474 e = p + val->bv_len;
2476 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2477 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2479 for (part = start; part < 7 && p < e; part++) {
2481 if (!ASCII_DIGIT(c1)) {
2486 return LDAP_INVALID_SYNTAX;
2489 if (!ASCII_DIGIT(c)) {
2490 return LDAP_INVALID_SYNTAX;
2492 c += c1 * 10 - '0' * 11;
2493 if ((part | 1) == 3) {
2496 return LDAP_INVALID_SYNTAX;
2499 if (c >= ceiling[part]) {
2500 if (! (c == 60 && part == 6 && start == 0))
2501 return LDAP_INVALID_SYNTAX;
2505 if (part < 5 + start) {
2506 return LDAP_INVALID_SYNTAX;
2508 for (; part < 9; part++) {
2512 /* leapyear check for the Gregorian calendar (year>1581) */
2513 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2518 if (parts[3] >= mdays[leapyear][parts[2]]) {
2519 return LDAP_INVALID_SYNTAX;
2523 fraction->bv_val = p;
2524 fraction->bv_len = 0;
2525 if (p < e && (*p == '.' || *p == ',')) {
2527 while (++p < e && ASCII_DIGIT(*p))
2529 if (p - fraction->bv_val == 1) {
2530 return LDAP_INVALID_SYNTAX;
2532 for (end_num = p; end_num[-1] == '0'; --end_num)
2534 c = end_num - fraction->bv_val;
2536 fraction->bv_len = c;
2542 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2548 return LDAP_INVALID_SYNTAX;
2554 for (part = 7; part < 9 && p < e; part++) {
2556 if (!ASCII_DIGIT(c1)) {
2561 return LDAP_INVALID_SYNTAX;
2564 if (!ASCII_DIGIT(c2)) {
2565 return LDAP_INVALID_SYNTAX;
2567 parts[part] = c1 * 10 + c2 - '0' * 11;
2568 if (parts[part] >= ceiling[part]) {
2569 return LDAP_INVALID_SYNTAX;
2572 if (part < 8 + start) {
2573 return LDAP_INVALID_SYNTAX;
2576 if (tzoffset == '-') {
2577 /* negative offset to UTC, ie west of Greenwich */
2578 parts[4] += parts[7];
2579 parts[5] += parts[8];
2580 /* offset is just hhmm, no seconds */
2581 for (part = 6; --part >= 0; ) {
2585 c = mdays[leapyear][parts[2]];
2587 if (parts[part] >= c) {
2589 return LDAP_INVALID_SYNTAX;
2594 } else if (part != 5) {
2599 /* positive offset to UTC, ie east of Greenwich */
2600 parts[4] -= parts[7];
2601 parts[5] -= parts[8];
2602 for (part = 6; --part >= 0; ) {
2603 if (parts[part] < 0) {
2605 return LDAP_INVALID_SYNTAX;
2610 /* make first arg to % non-negative */
2611 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2616 } else if (part != 5) {
2623 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2626 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2633 struct berval *normalized )
2637 rc = check_time_syntax(val, 1, parts, NULL);
2638 if (rc != LDAP_SUCCESS) {
2642 normalized->bv_val = ch_malloc( 14 );
2643 if ( normalized->bv_val == NULL ) {
2644 return LBER_ERROR_MEMORY;
2647 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2648 parts[1], parts[2] + 1, parts[3] + 1,
2649 parts[4], parts[5], parts[6] );
2650 normalized->bv_len = 13;
2652 return LDAP_SUCCESS;
2662 return check_time_syntax(in, 1, parts, NULL);
2665 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2668 generalizedTimeValidate(
2673 struct berval fraction;
2674 return check_time_syntax(in, 0, parts, &fraction);
2678 generalizedTimeNormalize(
2683 struct berval *normalized,
2688 struct berval fraction;
2690 rc = check_time_syntax(val, 0, parts, &fraction);
2691 if (rc != LDAP_SUCCESS) {
2695 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2696 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2697 if ( normalized->bv_val == NULL ) {
2698 return LBER_ERROR_MEMORY;
2701 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2702 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2703 parts[4], parts[5], parts[6] );
2704 if ( fraction.bv_len ) {
2705 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2706 fraction.bv_val, fraction.bv_len );
2707 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2709 strcpy( normalized->bv_val + len-1, "Z" );
2710 normalized->bv_len = len;
2712 return LDAP_SUCCESS;
2716 generalizedTimeOrderingMatch(
2721 struct berval *value,
2722 void *assertedValue )
2724 struct berval *asserted = (struct berval *) assertedValue;
2725 ber_len_t v_len = value->bv_len;
2726 ber_len_t av_len = asserted->bv_len;
2728 /* ignore trailing 'Z' when comparing */
2729 int match = memcmp( value->bv_val, asserted->bv_val,
2730 (v_len < av_len ? v_len : av_len) - 1 );
2731 if ( match == 0 ) match = v_len - av_len;
2734 return LDAP_SUCCESS;
2738 deliveryMethodValidate(
2740 struct berval *val )
2743 #define LENOF(s) (sizeof(s)-1)
2744 struct berval tmp = *val;
2746 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2747 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2748 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2751 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2753 switch( tmp.bv_val[0] ) {
2756 if(( tmp.bv_len >= LENOF("any") ) &&
2757 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2759 tmp.bv_len -= LENOF("any");
2760 tmp.bv_val += LENOF("any");
2763 return LDAP_INVALID_SYNTAX;
2767 if(( tmp.bv_len >= LENOF("mhs") ) &&
2768 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2770 tmp.bv_len -= LENOF("mhs");
2771 tmp.bv_val += LENOF("mhs");
2774 return LDAP_INVALID_SYNTAX;
2778 if(( tmp.bv_len >= LENOF("physical") ) &&
2779 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2781 tmp.bv_len -= LENOF("physical");
2782 tmp.bv_val += LENOF("physical");
2785 return LDAP_INVALID_SYNTAX;
2788 case 'T': /* telex or teletex or telephone */
2789 if(( tmp.bv_len >= LENOF("telex") ) &&
2790 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2792 tmp.bv_len -= LENOF("telex");
2793 tmp.bv_val += LENOF("telex");
2796 if(( tmp.bv_len >= LENOF("teletex") ) &&
2797 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2799 tmp.bv_len -= LENOF("teletex");
2800 tmp.bv_val += LENOF("teletex");
2803 if(( tmp.bv_len >= LENOF("telephone") ) &&
2804 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2806 tmp.bv_len -= LENOF("telephone");
2807 tmp.bv_val += LENOF("telephone");
2810 return LDAP_INVALID_SYNTAX;
2813 case 'G': /* g3fax or g4fax */
2814 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2815 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2816 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2818 tmp.bv_len -= LENOF("g3fax");
2819 tmp.bv_val += LENOF("g3fax");
2822 return LDAP_INVALID_SYNTAX;
2826 if(( tmp.bv_len >= LENOF("ia5") ) &&
2827 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2829 tmp.bv_len -= LENOF("ia5");
2830 tmp.bv_val += LENOF("ia5");
2833 return LDAP_INVALID_SYNTAX;
2837 if(( tmp.bv_len >= LENOF("videotex") ) &&
2838 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2840 tmp.bv_len -= LENOF("videotex");
2841 tmp.bv_val += LENOF("videotex");
2844 return LDAP_INVALID_SYNTAX;
2847 return LDAP_INVALID_SYNTAX;
2850 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2852 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2856 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2860 return LDAP_INVALID_SYNTAX;
2862 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2871 nisNetgroupTripleValidate(
2873 struct berval *val )
2878 if ( val->bv_len == 0 ) {
2879 return LDAP_INVALID_SYNTAX;
2882 p = (char *)val->bv_val;
2883 e = p + val->bv_len;
2885 if ( *p != '(' /*')'*/ ) {
2886 return LDAP_INVALID_SYNTAX;
2889 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2893 return LDAP_INVALID_SYNTAX;
2896 } else if ( !AD_CHAR( *p ) ) {
2897 return LDAP_INVALID_SYNTAX;
2901 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2902 return LDAP_INVALID_SYNTAX;
2908 return LDAP_INVALID_SYNTAX;
2911 return LDAP_SUCCESS;
2915 bootParameterValidate(
2917 struct berval *val )
2921 if ( val->bv_len == 0 ) {
2922 return LDAP_INVALID_SYNTAX;
2925 p = (char *)val->bv_val;
2926 e = p + val->bv_len;
2929 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2930 if ( !AD_CHAR( *p ) ) {
2931 return LDAP_INVALID_SYNTAX;
2936 return LDAP_INVALID_SYNTAX;
2940 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2941 if ( !AD_CHAR( *p ) ) {
2942 return LDAP_INVALID_SYNTAX;
2947 return LDAP_INVALID_SYNTAX;
2951 for ( p++; p < e; p++ ) {
2952 if ( !SLAP_PRINTABLE( *p ) ) {
2953 return LDAP_INVALID_SYNTAX;
2957 return LDAP_SUCCESS;
2961 firstComponentNormalize(
2966 struct berval *normalized,
2973 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2974 ber_dupbv_x( normalized, val, ctx );
2975 return LDAP_SUCCESS;
2978 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2980 if( val->bv_val[0] != '(' /*')'*/ &&
2981 val->bv_val[0] != '{' /*'}'*/ )
2983 return LDAP_INVALID_SYNTAX;
2986 /* trim leading white space */
2988 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2994 /* grab next word */
2995 comp.bv_val = &val->bv_val[len];
2996 len = val->bv_len - len;
2998 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
3004 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
3005 rc = numericoidValidate( NULL, &comp );
3006 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
3007 rc = integerValidate( NULL, &comp );
3009 rc = LDAP_INVALID_SYNTAX;
3013 if( rc == LDAP_SUCCESS ) {
3014 ber_dupbv_x( normalized, &comp, ctx );
3021 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3022 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3024 static slap_syntax_defs_rec syntax_defs[] = {
3025 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
3026 X_BINARY X_NOT_H_R ")",
3027 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
3028 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3030 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3032 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
3034 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3035 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
3037 SLAP_SYNTAX_BER, berValidate, NULL},
3038 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3039 0, bitStringValidate, NULL },
3040 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3041 0, booleanValidate, NULL},
3042 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3043 X_BINARY X_NOT_H_R ")",
3044 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
3045 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3046 X_BINARY X_NOT_H_R ")",
3047 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3048 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3049 X_BINARY X_NOT_H_R ")",
3050 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
3051 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3052 0, countryStringValidate, NULL},
3053 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3054 0, dnValidate, dnPretty},
3055 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3057 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3058 0, deliveryMethodValidate, NULL},
3059 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3060 0, UTF8StringValidate, NULL},
3061 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3063 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3065 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3067 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3069 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3071 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3072 0, printablesStringValidate, NULL},
3073 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3074 SLAP_SYNTAX_BLOB, NULL, NULL},
3075 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3076 0, generalizedTimeValidate, NULL},
3077 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3079 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3080 0, IA5StringValidate, NULL},
3081 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3082 0, integerValidate, NULL},
3083 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3084 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3085 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3087 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3089 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3091 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3093 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3095 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3096 0, nameUIDValidate, nameUIDPretty },
3097 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3099 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3100 0, numericStringValidate, NULL},
3101 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3103 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3104 0, numericoidValidate, NULL},
3105 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3106 0, IA5StringValidate, NULL},
3107 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3108 0, blobValidate, NULL},
3109 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3110 0, UTF8StringValidate, NULL},
3111 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3113 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3115 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3116 0, printableStringValidate, NULL},
3117 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3118 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3119 0, subtreeSpecificationValidate, NULL},
3120 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3121 X_BINARY X_NOT_H_R ")",
3122 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3123 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3124 0, printableStringValidate, NULL},
3125 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3127 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3128 0, printablesStringValidate, NULL},
3129 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3130 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3131 0, utcTimeValidate, NULL},
3133 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3135 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3137 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3139 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3141 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3144 /* RFC 2307 NIS Syntaxes */
3145 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3146 0, nisNetgroupTripleValidate, NULL},
3147 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3148 0, bootParameterValidate, NULL},
3150 /* From PKIX *//* This OID is not published yet. */
3151 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3153 serialNumberAndIssuerValidate,
3154 serialNumberAndIssuerPretty},
3156 #ifdef SLAPD_ACI_ENABLED
3157 /* OpenLDAP Experimental Syntaxes */
3158 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3160 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3164 #ifdef SLAPD_AUTHPASSWD
3165 /* needs updating */
3166 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3167 SLAP_SYNTAX_HIDE, NULL, NULL},
3170 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3171 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3173 /* OpenLDAP Void Syntax */
3174 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3175 SLAP_SYNTAX_HIDE, inValidate, NULL},
3176 {NULL, 0, NULL, NULL}
3179 char *certificateExactMatchSyntaxes[] = {
3180 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3183 char *directoryStringSyntaxes[] = {
3184 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3187 char *integerFirstComponentMatchSyntaxes[] = {
3188 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3189 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3192 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3193 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3194 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3195 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3196 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3197 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3198 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3199 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3200 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3205 * Other matching rules in X.520 that we do not use (yet):
3207 * 2.5.13.25 uTCTimeMatch
3208 * 2.5.13.26 uTCTimeOrderingMatch
3209 * 2.5.13.31* directoryStringFirstComponentMatch
3210 * 2.5.13.32* wordMatch
3211 * 2.5.13.33* keywordMatch
3212 * 2.5.13.36 certificatePairExactMatch
3213 * 2.5.13.37 certificatePairMatch
3214 * 2.5.13.38 certificateListExactMatch
3215 * 2.5.13.39 certificateListMatch
3216 * 2.5.13.40 algorithmIdentifierMatch
3217 * 2.5.13.41* storedPrefixMatch
3218 * 2.5.13.42 attributeCertificateMatch
3219 * 2.5.13.43 readerAndKeyIDMatch
3220 * 2.5.13.44 attributeIntegrityMatch
3222 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3224 static slap_mrule_defs_rec mrule_defs[] = {
3226 * EQUALITY matching rules must be listed after associated APPROX
3227 * matching rules. So, we list all APPROX matching rules first.
3229 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3230 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3231 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3232 NULL, NULL, directoryStringApproxMatch,
3233 directoryStringApproxIndexer, directoryStringApproxFilter,
3236 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3237 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3238 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3239 NULL, NULL, IA5StringApproxMatch,
3240 IA5StringApproxIndexer, IA5StringApproxFilter,
3244 * Other matching rules
3247 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3248 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3249 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3250 NULL, NULL, octetStringMatch,
3251 octetStringIndexer, octetStringFilter,
3254 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3255 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3256 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3257 NULL, dnNormalize, dnMatch,
3258 octetStringIndexer, octetStringFilter,
3261 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3262 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3263 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3264 NULL, UTF8StringNormalize, octetStringMatch,
3265 octetStringIndexer, octetStringFilter,
3266 directoryStringApproxMatchOID },
3268 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3269 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3270 SLAP_MR_ORDERING, directoryStringSyntaxes,
3271 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3273 "caseIgnoreMatch" },
3275 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3276 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3277 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3278 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3279 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3280 "caseIgnoreMatch" },
3282 {"( 2.5.13.5 NAME 'caseExactMatch' "
3283 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3284 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3285 NULL, UTF8StringNormalize, octetStringMatch,
3286 octetStringIndexer, octetStringFilter,
3287 directoryStringApproxMatchOID },
3289 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3290 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3291 SLAP_MR_ORDERING, directoryStringSyntaxes,
3292 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3296 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3297 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3298 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3299 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3300 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3303 {"( 2.5.13.8 NAME 'numericStringMatch' "
3304 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3305 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3306 NULL, numericStringNormalize, octetStringMatch,
3307 octetStringIndexer, octetStringFilter,
3310 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3311 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3312 SLAP_MR_ORDERING, NULL,
3313 NULL, numericStringNormalize, octetStringOrderingMatch,
3315 "numericStringMatch" },
3317 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3318 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3319 SLAP_MR_SUBSTR, NULL,
3320 NULL, numericStringNormalize, octetStringSubstringsMatch,
3321 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3322 "numericStringMatch" },
3324 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3325 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3326 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3327 NULL, NULL, NULL, NULL, NULL, NULL },
3329 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3330 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3331 SLAP_MR_SUBSTR, NULL,
3332 NULL, NULL, NULL, NULL, NULL,
3333 "caseIgnoreListMatch" },
3335 {"( 2.5.13.13 NAME 'booleanMatch' "
3336 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3337 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3338 NULL, NULL, booleanMatch,
3339 octetStringIndexer, octetStringFilter,
3342 {"( 2.5.13.14 NAME 'integerMatch' "
3343 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3344 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3345 NULL, NULL, integerMatch,
3346 octetStringIndexer, octetStringFilter,
3349 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3350 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3351 SLAP_MR_ORDERING, NULL,
3352 NULL, NULL, integerMatch,
3356 {"( 2.5.13.16 NAME 'bitStringMatch' "
3357 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3358 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3359 NULL, NULL, octetStringMatch,
3360 octetStringIndexer, octetStringFilter,
3363 {"( 2.5.13.17 NAME 'octetStringMatch' "
3364 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3365 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3366 NULL, NULL, octetStringMatch,
3367 octetStringIndexer, octetStringFilter,
3370 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3371 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3372 SLAP_MR_ORDERING, NULL,
3373 NULL, NULL, octetStringOrderingMatch,
3375 "octetStringMatch" },
3377 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3378 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3379 SLAP_MR_SUBSTR, NULL,
3380 NULL, NULL, octetStringSubstringsMatch,
3381 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3382 "octetStringMatch" },
3384 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3385 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3386 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3388 telephoneNumberNormalize, octetStringMatch,
3389 octetStringIndexer, octetStringFilter,
3392 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3393 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3394 SLAP_MR_SUBSTR, NULL,
3395 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3396 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3397 "telephoneNumberMatch" },
3399 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3400 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3401 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3402 NULL, NULL, NULL, NULL, NULL, NULL },
3404 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3405 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3406 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3407 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3411 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3412 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3413 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3414 NULL, NULL, NULL, NULL, NULL, NULL },
3416 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3417 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3418 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3419 NULL, generalizedTimeNormalize, octetStringMatch,
3423 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3424 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3425 SLAP_MR_ORDERING, NULL,
3426 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3428 "generalizedTimeMatch" },
3430 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3431 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3432 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3433 integerFirstComponentMatchSyntaxes,
3434 NULL, firstComponentNormalize, integerMatch,
3435 octetStringIndexer, octetStringFilter,
3438 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3439 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3440 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3441 objectIdentifierFirstComponentMatchSyntaxes,
3442 NULL, firstComponentNormalize, octetStringMatch,
3443 octetStringIndexer, octetStringFilter,
3446 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3447 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3448 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3450 NULL, certificateExactNormalize, octetStringMatch,
3451 octetStringIndexer, octetStringFilter,
3453 NULL, NULL, NULL, NULL, NULL,
3457 {"( 2.5.13.35 NAME 'certificateMatch' "
3458 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3459 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3461 NULL, NULL, octetStringMatch,
3462 octetStringIndexer, octetStringFilter,
3464 NULL, NULL, NULL, NULL, NULL,
3468 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3470 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3471 NULL, IA5StringNormalize, octetStringMatch,
3472 octetStringIndexer, octetStringFilter,
3473 IA5StringApproxMatchOID },
3475 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3476 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3477 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3478 NULL, IA5StringNormalize, octetStringMatch,
3479 octetStringIndexer, octetStringFilter,
3480 IA5StringApproxMatchOID },
3482 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3483 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3484 SLAP_MR_SUBSTR, NULL,
3485 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3486 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3487 "caseIgnoreIA5Match" },
3489 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3490 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3491 SLAP_MR_SUBSTR, NULL,
3492 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3493 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3494 "caseExactIA5Match" },
3496 #ifdef SLAPD_AUTHPASSWD
3497 /* needs updating */
3498 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3499 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3500 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3501 NULL, NULL, authPasswordMatch,
3506 #ifdef SLAPD_ACI_ENABLED
3507 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3508 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3509 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3510 NULL, NULL, OpenLDAPaciMatch,
3515 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3518 NULL, NULL, integerBitAndMatch,
3522 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3525 NULL, NULL, integerBitOrMatch,
3529 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3530 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3531 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3532 NULL, UUIDNormalize, octetStringMatch,
3533 octetStringIndexer, octetStringFilter,
3536 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3537 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3538 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3539 NULL, UUIDNormalize, octetStringOrderingMatch,
3540 octetStringIndexer, octetStringFilter,
3543 {NULL, SLAP_MR_NONE, NULL,
3544 NULL, NULL, NULL, NULL, NULL,
3549 slap_schema_init( void )
3554 /* we should only be called once (from main) */
3555 assert( schema_init_done == 0 );
3557 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3558 res = register_syntax( &syntax_defs[i] );
3561 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3562 syntax_defs[i].sd_desc );
3567 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3568 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3569 mrule_defs[i].mrd_compat_syntaxes == NULL )
3572 "slap_schema_init: Ignoring unusable matching rule %s\n",
3573 mrule_defs[i].mrd_desc );
3577 res = register_matching_rule( &mrule_defs[i] );
3581 "slap_schema_init: Error registering matching rule %s\n",
3582 mrule_defs[i].mrd_desc );
3587 res = slap_schema_load();
3588 schema_init_done = 1;
3593 schema_destroy( void )