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 );
926 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
928 if( val->bv_len == 0 ) {
929 ber_dupbv_x( out, val, ctx );
931 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
932 return LDAP_INVALID_SYNTAX;
936 struct berval dnval = *val;
937 struct berval uidval = BER_BVNULL;
939 uidval.bv_val = strrchr( val->bv_val, '#' );
940 if ( uidval.bv_val ) {
942 uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
944 rc = bitStringValidate( NULL, &uidval );
946 if ( rc == LDAP_SUCCESS ) {
947 ber_dupbv_x( &dnval, val, ctx );
948 dnval.bv_len -= uidval.bv_len + 1;
949 dnval.bv_val[dnval.bv_len] = '\0';
952 uidval.bv_val = NULL;
956 rc = dnPretty( syntax, &dnval, out, ctx );
957 if ( dnval.bv_val != val->bv_val ) {
958 slap_sl_free( dnval.bv_val, ctx );
960 if( rc != LDAP_SUCCESS ) {
964 if( uidval.bv_val ) {
968 tmp = slap_sl_realloc( out->bv_val, out->bv_len
969 + STRLENOF( "#" ) + uidval.bv_len + 1,
972 ber_memfree_x( out->bv_val, ctx );
976 out->bv_val[out->bv_len++] = '#';
977 out->bv_val[out->bv_len++] = '\'';
979 got1 = uidval.bv_len < sizeof("'0'B");
980 for( i = 1; i < uidval.bv_len - 2; i++ ) {
981 c = uidval.bv_val[i];
984 if( got1 ) out->bv_val[out->bv_len++] = c;
988 out->bv_val[out->bv_len++] = c;
993 out->bv_val[out->bv_len++] = '\'';
994 out->bv_val[out->bv_len++] = 'B';
995 out->bv_val[out->bv_len] = '\0';
999 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
1001 return LDAP_SUCCESS;
1005 uniqueMemberNormalize(
1010 struct berval *normalized,
1016 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1018 ber_dupbv_x( &out, val, ctx );
1019 if ( BER_BVISEMPTY( &out ) ) {
1023 struct berval uid = BER_BVNULL;
1025 uid.bv_val = strrchr( out.bv_val, '#' );
1028 uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
1030 rc = bitStringValidate( NULL, &uid );
1031 if ( rc == LDAP_SUCCESS ) {
1032 uid.bv_val[-1] = '\0';
1033 out.bv_len -= uid.bv_len + 1;
1039 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
1041 if( rc != LDAP_SUCCESS ) {
1042 slap_sl_free( out.bv_val, ctx );
1043 return LDAP_INVALID_SYNTAX;
1049 tmp = ch_realloc( normalized->bv_val,
1050 normalized->bv_len + uid.bv_len
1051 + STRLENOF("#") + 1 );
1052 if ( tmp == NULL ) {
1053 ber_memfree_x( normalized->bv_val, ctx );
1057 normalized->bv_val = tmp;
1059 /* insert the separator */
1060 normalized->bv_val[normalized->bv_len++] = '#';
1062 /* append the UID */
1063 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
1064 uid.bv_val, uid.bv_len );
1065 normalized->bv_len += uid.bv_len;
1068 normalized->bv_val[normalized->bv_len] = '\0';
1071 slap_sl_free( out.bv_val, ctx );
1074 return LDAP_SUCCESS;
1083 struct berval *value,
1084 void *assertedValue )
1087 struct berval *asserted = (struct berval *) assertedValue;
1088 struct berval assertedDN = *asserted;
1089 struct berval assertedUID = BER_BVNULL;
1090 struct berval valueDN = BER_BVNULL;
1091 struct berval valueUID = BER_BVNULL;
1093 if ( !BER_BVISEMPTY( asserted ) ) {
1094 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
1095 if ( !BER_BVISNULL( &assertedUID ) ) {
1096 assertedUID.bv_val++;
1097 assertedUID.bv_len = assertedDN.bv_len
1098 - ( assertedUID.bv_val - assertedDN.bv_val );
1100 if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
1101 assertedDN.bv_len -= assertedUID.bv_len + 1;
1104 BER_BVZERO( &assertedUID );
1109 if ( !BER_BVISEMPTY( value ) ) {
1112 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1113 if ( !BER_BVISNULL( &valueUID ) ) {
1115 valueUID.bv_len = valueDN.bv_len
1116 - ( valueUID.bv_val - valueDN.bv_val );
1118 if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
1119 valueDN.bv_len -= valueUID.bv_len + 1;
1122 BER_BVZERO( &valueUID );
1127 if( valueUID.bv_len && assertedUID.bv_len ) {
1128 match = valueUID.bv_len - assertedUID.bv_len;
1131 return LDAP_SUCCESS;
1134 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1137 return LDAP_SUCCESS;
1141 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1145 * Handling boolean syntax and matching is quite rigid.
1146 * A more flexible approach would be to allow a variety
1147 * of strings to be normalized and prettied into TRUE
1155 /* very unforgiving validation, requires no normalization
1156 * before simplistic matching
1159 if( in->bv_len == 4 ) {
1160 if( bvmatch( in, &slap_true_bv ) ) {
1161 return LDAP_SUCCESS;
1163 } else if( in->bv_len == 5 ) {
1164 if( bvmatch( in, &slap_false_bv ) ) {
1165 return LDAP_SUCCESS;
1169 return LDAP_INVALID_SYNTAX;
1178 struct berval *value,
1179 void *assertedValue )
1181 /* simplistic matching allowed by rigid validation */
1182 struct berval *asserted = (struct berval *) assertedValue;
1183 *matchp = value->bv_len != asserted->bv_len;
1184 return LDAP_SUCCESS;
1187 /*-------------------------------------------------------------------
1188 LDAP/X.500 string syntax / matching rules have a few oddities. This
1189 comment attempts to detail how slapd(8) treats them.
1192 StringSyntax X.500 LDAP Matching/Comments
1193 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1194 PrintableString subset subset i/e + ignore insignificant spaces
1195 PrintableString subset subset i/e + ignore insignificant spaces
1196 NumericString subset subset ignore all spaces
1197 IA5String ASCII ASCII i/e + ignore insignificant spaces
1198 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1200 TelephoneNumber subset subset i + ignore all spaces and "-"
1202 See draft-ietf-ldapbis-strpro for details (once published).
1206 In X.500(93), a directory string can be either a PrintableString,
1207 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1208 In later versions, more CHOICEs were added. In all cases the string
1211 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1212 A directory string cannot be zero length.
1214 For matching, there are both case ignore and exact rules. Both
1215 also require that "insignificant" spaces be ignored.
1216 spaces before the first non-space are ignored;
1217 spaces after the last non-space are ignored;
1218 spaces after a space are ignored.
1219 Note: by these rules (and as clarified in X.520), a string of only
1220 spaces is to be treated as if held one space, not empty (which
1221 would be a syntax error).
1224 In ASN.1, numeric string is just a string of digits and spaces
1225 and could be empty. However, in X.500, all attribute values of
1226 numeric string carry a non-empty constraint. For example:
1228 internationalISDNNumber ATTRIBUTE ::= {
1229 WITH SYNTAX InternationalISDNNumber
1230 EQUALITY MATCHING RULE numericStringMatch
1231 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1232 ID id-at-internationalISDNNumber }
1233 InternationalISDNNumber ::=
1234 NumericString (SIZE(1..ub-international-isdn-number))
1236 Unforunately, some assertion values are don't carry the same
1237 constraint (but its unclear how such an assertion could ever
1238 be true). In LDAP, there is one syntax (numericString) not two
1239 (numericString with constraint, numericString without constraint).
1240 This should be treated as numericString with non-empty constraint.
1241 Note that while someone may have no ISDN number, there are no ISDN
1242 numbers which are zero length.
1244 In matching, spaces are ignored.
1247 In ASN.1, Printable string is just a string of printable characters
1248 and can be empty. In X.500, semantics much like NumericString (see
1249 serialNumber for a like example) excepting uses insignificant space
1250 handling instead of ignore all spaces.
1253 Basically same as PrintableString. There are no examples in X.500,
1254 but same logic applies. So we require them to be non-empty as
1257 -------------------------------------------------------------------*/
1266 unsigned char *u = (unsigned char *)in->bv_val;
1268 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1269 /* directory strings cannot be empty */
1270 return LDAP_INVALID_SYNTAX;
1273 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1274 /* get the length indicated by the first byte */
1275 len = LDAP_UTF8_CHARLEN2( u, len );
1277 /* very basic checks */
1280 if( (u[5] & 0xC0) != 0x80 ) {
1281 return LDAP_INVALID_SYNTAX;
1284 if( (u[4] & 0xC0) != 0x80 ) {
1285 return LDAP_INVALID_SYNTAX;
1288 if( (u[3] & 0xC0) != 0x80 ) {
1289 return LDAP_INVALID_SYNTAX;
1292 if( (u[2] & 0xC0 )!= 0x80 ) {
1293 return LDAP_INVALID_SYNTAX;
1296 if( (u[1] & 0xC0) != 0x80 ) {
1297 return LDAP_INVALID_SYNTAX;
1300 /* CHARLEN already validated it */
1303 return LDAP_INVALID_SYNTAX;
1306 /* make sure len corresponds with the offset
1307 to the next character */
1308 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1312 return LDAP_INVALID_SYNTAX;
1315 return LDAP_SUCCESS;
1319 UTF8StringNormalize(
1324 struct berval *normalized,
1327 struct berval tmp, nvalue;
1331 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1333 if( val->bv_val == NULL ) {
1334 /* assume we're dealing with a syntax (e.g., UTF8String)
1335 * which allows empty strings
1337 normalized->bv_len = 0;
1338 normalized->bv_val = NULL;
1339 return LDAP_SUCCESS;
1342 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1343 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1344 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1345 ? LDAP_UTF8_APPROX : 0;
1347 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1352 /* collapse spaces (in place) */
1354 nvalue.bv_val = tmp.bv_val;
1356 wasspace=1; /* trim leading spaces */
1357 for( i=0; i<tmp.bv_len; i++) {
1358 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1359 if( wasspace++ == 0 ) {
1360 /* trim repeated spaces */
1361 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1365 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1369 if( nvalue.bv_len ) {
1371 /* last character was a space, trim it */
1374 nvalue.bv_val[nvalue.bv_len] = '\0';
1377 /* string of all spaces is treated as one space */
1378 nvalue.bv_val[0] = ' ';
1379 nvalue.bv_val[1] = '\0';
1383 *normalized = nvalue;
1384 return LDAP_SUCCESS;
1387 #if defined(SLAPD_APPROX_INITIALS)
1388 # define SLAPD_APPROX_DELIMITER "._ "
1389 # define SLAPD_APPROX_WORDLEN 2
1391 # define SLAPD_APPROX_DELIMITER " "
1392 # define SLAPD_APPROX_WORDLEN 1
1401 struct berval *value,
1402 void *assertedValue )
1404 struct berval *nval, *assertv;
1405 char *val, **values, **words, *c;
1406 int i, count, len, nextchunk=0, nextavail=0;
1408 /* Yes, this is necessary */
1409 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1410 if( nval == NULL ) {
1412 return LDAP_SUCCESS;
1415 /* Yes, this is necessary */
1416 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1417 NULL, LDAP_UTF8_APPROX, NULL );
1418 if( assertv == NULL ) {
1421 return LDAP_SUCCESS;
1424 /* Isolate how many words there are */
1425 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1426 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1427 if ( c == NULL ) break;
1432 /* Get a phonetic copy of each word */
1433 words = (char **)ch_malloc( count * sizeof(char *) );
1434 values = (char **)ch_malloc( count * sizeof(char *) );
1435 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1437 values[i] = phonetic(c);
1440 /* Work through the asserted value's words, to see if at least some
1441 of the words are there, in the same order. */
1443 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1444 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1449 #if defined(SLAPD_APPROX_INITIALS)
1450 else if( len == 1 ) {
1451 /* Single letter words need to at least match one word's initial */
1452 for( i=nextavail; i<count; i++ )
1453 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1460 /* Isolate the next word in the asserted value and phonetic it */
1461 assertv->bv_val[nextchunk+len] = '\0';
1462 val = phonetic( assertv->bv_val + nextchunk );
1464 /* See if this phonetic chunk is in the remaining words of *value */
1465 for( i=nextavail; i<count; i++ ){
1466 if( !strcmp( val, values[i] ) ){
1474 /* This chunk in the asserted value was NOT within the *value. */
1480 /* Go on to the next word in the asserted value */
1484 /* If some of the words were seen, call it a match */
1485 if( nextavail > 0 ) {
1492 /* Cleanup allocs */
1493 ber_bvfree( assertv );
1494 for( i=0; i<count; i++ ) {
1495 ch_free( values[i] );
1501 return LDAP_SUCCESS;
1510 struct berval *prefix,
1516 int i,j, len, wordcount, keycount=0;
1517 struct berval *newkeys;
1518 BerVarray keys=NULL;
1520 for( j=0; values[j].bv_val != NULL; j++ ) {
1521 struct berval val = BER_BVNULL;
1522 /* Yes, this is necessary */
1523 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1524 assert( val.bv_val != NULL );
1526 /* Isolate how many words there are. There will be a key for each */
1527 for( wordcount = 0, c = val.bv_val; *c; c++) {
1528 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1529 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1531 if (*c == '\0') break;
1535 /* Allocate/increase storage to account for new keys */
1536 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1537 * sizeof(struct berval) );
1538 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1539 if( keys ) ch_free( keys );
1542 /* Get a phonetic copy of each word */
1543 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1545 if( len < SLAPD_APPROX_WORDLEN ) continue;
1546 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1551 ber_memfree( val.bv_val );
1553 keys[keycount].bv_val = NULL;
1556 return LDAP_SUCCESS;
1565 struct berval *prefix,
1566 void * assertedValue,
1575 /* Yes, this is necessary */
1576 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1577 NULL, LDAP_UTF8_APPROX, NULL );
1578 if( val == NULL || val->bv_val == NULL ) {
1579 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1580 keys[0].bv_val = NULL;
1583 return LDAP_SUCCESS;
1586 /* Isolate how many words there are. There will be a key for each */
1587 for( count = 0,c = val->bv_val; *c; c++) {
1588 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1589 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1591 if (*c == '\0') break;
1595 /* Allocate storage for new keys */
1596 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1598 /* Get a phonetic copy of each word */
1599 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1601 if( len < SLAPD_APPROX_WORDLEN ) continue;
1602 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1608 keys[count].bv_val = NULL;
1611 return LDAP_SUCCESS;
1614 /* Remove all spaces and '-' characters */
1616 telephoneNumberNormalize(
1621 struct berval *normalized,
1626 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1628 /* validator should have refused an empty string */
1629 assert( val->bv_len );
1631 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1633 for( p = val->bv_val; *p; p++ ) {
1634 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1640 normalized->bv_len = q - normalized->bv_val;
1642 if( normalized->bv_len == 0 ) {
1643 slap_sl_free( normalized->bv_val, ctx );
1644 normalized->bv_val = NULL;
1645 return LDAP_INVALID_SYNTAX;
1648 return LDAP_SUCCESS;
1656 struct berval val = *in;
1658 if( val.bv_len == 0 ) {
1659 /* disallow empty strings */
1660 return LDAP_INVALID_SYNTAX;
1663 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1664 if ( val.bv_len == 1 ) {
1665 return LDAP_SUCCESS;
1668 if ( val.bv_val[0] == '0' ) {
1675 while ( OID_LEADCHAR( val.bv_val[0] )) {
1679 if ( val.bv_len == 0 ) {
1680 return LDAP_SUCCESS;
1684 if( !OID_SEPARATOR( val.bv_val[0] )) {
1692 return LDAP_INVALID_SYNTAX;
1701 struct berval val = *in;
1703 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1705 if ( val.bv_val[0] == '-' ) {
1709 if( val.bv_len == 0 ) { /* bare "-" */
1710 return LDAP_INVALID_SYNTAX;
1713 if( val.bv_val[0] == '0' ) { /* "-0" */
1714 return LDAP_INVALID_SYNTAX;
1717 } else if ( val.bv_val[0] == '0' ) {
1718 if( val.bv_len > 1 ) { /* "0<more>" */
1719 return LDAP_INVALID_SYNTAX;
1722 return LDAP_SUCCESS;
1725 for( i=0; i < val.bv_len; i++ ) {
1726 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1727 return LDAP_INVALID_SYNTAX;
1731 return LDAP_SUCCESS;
1740 struct berval *value,
1741 void *assertedValue )
1743 struct berval *asserted = (struct berval *) assertedValue;
1744 int vsign = 1, asign = 1; /* default sign = '+' */
1749 if( v.bv_val[0] == '-' ) {
1755 if( v.bv_len == 0 ) vsign = 0;
1758 if( a.bv_val[0] == '-' ) {
1764 if( a.bv_len == 0 ) vsign = 0;
1766 match = vsign - asign;
1768 match = ( v.bv_len != a.bv_len
1769 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1770 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1771 if( vsign < 0 ) match = -match;
1775 return LDAP_SUCCESS;
1779 countryStringValidate(
1781 struct berval *val )
1783 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1785 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1786 return LDAP_INVALID_SYNTAX;
1788 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1789 return LDAP_INVALID_SYNTAX;
1792 return LDAP_SUCCESS;
1796 printableStringValidate(
1798 struct berval *val )
1802 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1804 for(i=0; i < val->bv_len; i++) {
1805 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1806 return LDAP_INVALID_SYNTAX;
1810 return LDAP_SUCCESS;
1814 printablesStringValidate(
1816 struct berval *val )
1820 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1822 for(i=0,len=0; i < val->bv_len; i++) {
1823 int c = val->bv_val[i];
1827 return LDAP_INVALID_SYNTAX;
1831 } else if ( SLAP_PRINTABLE(c) ) {
1834 return LDAP_INVALID_SYNTAX;
1839 return LDAP_INVALID_SYNTAX;
1842 return LDAP_SUCCESS;
1848 struct berval *val )
1852 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1854 for(i=0; i < val->bv_len; i++) {
1855 if( !LDAP_ASCII(val->bv_val[i]) ) {
1856 return LDAP_INVALID_SYNTAX;
1860 return LDAP_SUCCESS;
1869 struct berval *normalized,
1873 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1875 assert( val->bv_len );
1877 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1881 /* Ignore initial whitespace */
1882 while ( ASCII_SPACE( *p ) ) p++;
1884 normalized->bv_val = ber_strdup_x( p, ctx );
1885 p = q = normalized->bv_val;
1888 if ( ASCII_SPACE( *p ) ) {
1891 /* Ignore the extra whitespace */
1892 while ( ASCII_SPACE( *p ) ) {
1896 } else if ( casefold ) {
1897 /* Most IA5 rules require casefolding */
1898 *q++ = TOLOWER(*p); p++;
1905 assert( normalized->bv_val <= p );
1909 * If the string ended in space, backup the pointer one
1910 * position. One is enough because the above loop collapsed
1911 * all whitespace to a single space.
1913 if ( ASCII_SPACE( q[-1] ) ) --q;
1915 /* null terminate */
1918 normalized->bv_len = q - normalized->bv_val;
1919 if( normalized->bv_len == 0 ) {
1920 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1921 normalized->bv_val[0] = ' ';
1922 normalized->bv_val[1] = '\0';
1923 normalized->bv_len = 1;
1926 return LDAP_SUCCESS;
1935 if( in->bv_len != 36 ) {
1936 return LDAP_INVALID_SYNTAX;
1939 for( i=0; i<36; i++ ) {
1945 if( in->bv_val[i] != '-' ) {
1946 return LDAP_INVALID_SYNTAX;
1950 if( !ASCII_HEX( in->bv_val[i]) ) {
1951 return LDAP_INVALID_SYNTAX;
1956 return LDAP_SUCCESS;
1965 struct berval *normalized,
1968 unsigned char octet = '\0';
1971 normalized->bv_len = 16;
1972 normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
1974 for( i=0, j=0; i<36; i++ ) {
1975 unsigned char nibble;
1976 if( val->bv_val[i] == '-' ) {
1979 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1980 nibble = val->bv_val[i] - '0';
1982 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1983 nibble = val->bv_val[i] - ('a'-10);
1985 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1986 nibble = val->bv_val[i] - ('A'-10);
1989 slap_sl_free( normalized->bv_val, ctx );
1990 return LDAP_INVALID_SYNTAX;
1995 normalized->bv_val[j>>1] = octet;
1997 octet = nibble << 4;
2002 normalized->bv_val[normalized->bv_len] = 0;
2003 return LDAP_SUCCESS;
2009 numericStringValidate(
2015 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2017 for(i=0; i < in->bv_len; i++) {
2018 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
2019 return LDAP_INVALID_SYNTAX;
2023 return LDAP_SUCCESS;
2027 numericStringNormalize(
2032 struct berval *normalized,
2035 /* removal all spaces */
2038 assert( val->bv_len );
2040 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
2043 q = normalized->bv_val;
2046 if ( ASCII_SPACE( *p ) ) {
2047 /* Ignore whitespace */
2054 /* we should have copied no more then is in val */
2055 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
2057 /* null terminate */
2060 normalized->bv_len = q - normalized->bv_val;
2062 if( normalized->bv_len == 0 ) {
2063 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
2064 normalized->bv_val[0] = ' ';
2065 normalized->bv_val[1] = '\0';
2066 normalized->bv_len = 1;
2069 return LDAP_SUCCESS;
2073 * Integer conversion macros that will use the largest available
2076 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
2077 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
2078 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
2079 # define SLAP_LONG_MAX LLONG_MAX
2080 # define SLAP_LONG_MIN LLONG_MIN
2081 # define SLAP_LONG long long
2083 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
2084 # define SLAP_LONG_MAX LONG_MAX
2085 # define SLAP_LONG_MIN LONG_MIN
2086 # define SLAP_LONG long
2087 #endif /* HAVE_STRTOLL ... */
2095 struct berval *value,
2096 void *assertedValue )
2098 SLAP_LONG lValue, lAssertedValue;
2100 /* safe to assume integers are NUL terminated? */
2101 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2102 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2105 return LDAP_CONSTRAINT_VIOLATION;
2108 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2110 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2113 return LDAP_CONSTRAINT_VIOLATION;
2116 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2117 return LDAP_SUCCESS;
2126 struct berval *value,
2127 void *assertedValue )
2129 SLAP_LONG lValue, lAssertedValue;
2131 /* safe to assume integers are NUL terminated? */
2132 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2133 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2136 return LDAP_CONSTRAINT_VIOLATION;
2139 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2141 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2144 return LDAP_CONSTRAINT_VIOLATION;
2147 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2148 return LDAP_SUCCESS;
2152 serialNumberAndIssuerValidate(
2159 struct berval sn, i;
2160 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2162 i.bv_val = strchr( in->bv_val, '$' );
2163 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2165 sn.bv_val = in->bv_val;
2166 sn.bv_len = i.bv_val - in->bv_val;
2169 i.bv_len = in->bv_len - (sn.bv_len + 1);
2171 /* validate serial number (strict for now) */
2172 for( n=0; n < sn.bv_len; n++ ) {
2173 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2177 rc = dnValidate( NULL, &i );
2178 if( rc ) return LDAP_INVALID_SYNTAX;
2180 return LDAP_SUCCESS;
2184 serialNumberAndIssuerPretty(
2193 struct berval sn, i, newi;
2198 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2199 val->bv_val, 0, 0 );
2201 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2203 i.bv_val = strchr( val->bv_val, '$' );
2204 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2206 sn.bv_val = val->bv_val;
2207 sn.bv_len = i.bv_val - val->bv_val;
2210 i.bv_len = val->bv_len - (sn.bv_len + 1);
2212 /* eat leading zeros */
2213 for( n=0; n < (sn.bv_len-1); n++ ) {
2214 if( sn.bv_val[n] != '0' ) break;
2219 for( n=0; n < sn.bv_len; n++ ) {
2220 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2224 rc = dnPretty( syntax, &i, &newi, ctx );
2225 if( rc ) return LDAP_INVALID_SYNTAX;
2227 /* make room from sn + "$" */
2228 out->bv_len = sn.bv_len + newi.bv_len + 1;
2229 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2231 if( out->bv_val == NULL ) {
2232 slap_sl_free( newi.bv_val, ctx );
2236 /* push issuer over */
2237 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2238 /* insert sn and "$" */
2239 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2240 out->bv_val[sn.bv_len] = '$';
2242 out->bv_val[out->bv_len] = '\0';
2244 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2245 out->bv_val, 0, 0 );
2247 return LDAP_SUCCESS;
2251 * This routine is called by certificateExactNormalize when
2252 * certificateExactNormalize receives a search string instead of
2253 * a certificate. This routine checks if the search value is valid
2254 * and then returns the normalized value
2257 serialNumberAndIssuerNormalize(
2268 struct berval sn, i, newi;
2273 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2274 val->bv_val, 0, 0 );
2276 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2278 i.bv_val = strchr( val->bv_val, '$' );
2279 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2281 sn.bv_val = val->bv_val;
2282 sn.bv_len = i.bv_val - val->bv_val;
2285 i.bv_len = val->bv_len - (sn.bv_len + 1);
2287 /* eat leading zeros */
2288 for( n=0; n < (sn.bv_len-1); n++ ) {
2289 if( sn.bv_val[n] != '0' ) break;
2294 for( n=0; n < sn.bv_len; n++ ) {
2295 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2296 return LDAP_INVALID_SYNTAX;
2301 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2302 if( rc ) return LDAP_INVALID_SYNTAX;
2304 /* make room from sn + "$" */
2305 out->bv_len = sn.bv_len + newi.bv_len + 1;
2306 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2308 if( out->bv_val == NULL ) {
2309 slap_sl_free( newi.bv_val, ctx );
2313 /* push issuer over */
2314 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2315 /* insert sn and "$" */
2316 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2317 out->bv_val[sn.bv_len] = '$';
2319 out->bv_val[out->bv_len] = '\0';
2321 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2322 out->bv_val, 0, 0 );
2329 certificateExactNormalize(
2334 struct berval *normalized,
2337 int rc = LDAP_INVALID_SYNTAX;
2339 char *serial = NULL;
2340 ber_len_t seriallen;
2341 struct berval issuer_dn = BER_BVNULL;
2342 X509_NAME *name = NULL;
2343 ASN1_INTEGER *sn = NULL;
2346 if( val->bv_len == 0 ) goto done;
2348 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2349 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2352 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2354 p = (unsigned char *)val->bv_val;
2355 xcert = d2i_X509( NULL, &p, val->bv_len);
2356 if( xcert == NULL ) goto done;
2358 sn=X509_get_serialNumber(xcert);
2359 if ( sn == NULL ) goto done;
2360 serial=i2s_ASN1_INTEGER(0, sn );
2361 if( serial == NULL ) goto done;
2362 seriallen=strlen(serial);
2364 name=X509_get_issuer_name(xcert);
2365 if( name == NULL ) goto done;
2366 rc = dnX509normalize( name, &issuer_dn );
2367 if( rc != LDAP_SUCCESS ) goto done;
2369 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2370 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2371 p = (unsigned char *)normalized->bv_val;
2372 AC_MEMCPY(p, serial, seriallen);
2375 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2376 p += issuer_dn.bv_len;
2379 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2380 normalized->bv_val, NULL, NULL );
2383 if (xcert) X509_free(xcert);
2384 if (serial) ch_free(serial);
2385 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2389 #endif /* HAVE_TLS */
2392 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2393 /* slight optimization - does not need the start parameter */
2394 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2399 check_time_syntax (struct berval *val,
2402 struct berval *fraction)
2405 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2406 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2407 * GeneralizedTime supports leap seconds, UTCTime does not.
2409 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2410 static const int mdays[2][12] = {
2411 /* non-leap years */
2412 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2414 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2417 int part, c, c1, c2, tzoffset, leapyear = 0;
2420 e = p + val->bv_len;
2422 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2423 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2425 for (part = start; part < 7 && p < e; part++) {
2427 if (!ASCII_DIGIT(c1)) {
2432 return LDAP_INVALID_SYNTAX;
2435 if (!ASCII_DIGIT(c)) {
2436 return LDAP_INVALID_SYNTAX;
2438 c += c1 * 10 - '0' * 11;
2439 if ((part | 1) == 3) {
2442 return LDAP_INVALID_SYNTAX;
2445 if (c >= ceiling[part]) {
2446 if (! (c == 60 && part == 6 && start == 0))
2447 return LDAP_INVALID_SYNTAX;
2451 if (part < 5 + start) {
2452 return LDAP_INVALID_SYNTAX;
2454 for (; part < 9; part++) {
2458 /* leapyear check for the Gregorian calendar (year>1581) */
2459 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
2463 if (parts[3] >= mdays[leapyear][parts[2]]) {
2464 return LDAP_INVALID_SYNTAX;
2468 fraction->bv_val = p;
2469 fraction->bv_len = 0;
2470 if (p < e && (*p == '.' || *p == ',')) {
2472 while (++p < e && ASCII_DIGIT(*p)) {
2475 if (p - fraction->bv_val == 1) {
2476 return LDAP_INVALID_SYNTAX;
2478 for (end_num = p; end_num[-1] == '0'; --end_num) {
2481 c = end_num - fraction->bv_val;
2482 if (c != 1) fraction->bv_len = c;
2488 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2494 return LDAP_INVALID_SYNTAX;
2500 for (part = 7; part < 9 && p < e; part++) {
2502 if (!ASCII_DIGIT(c1)) {
2507 return LDAP_INVALID_SYNTAX;
2510 if (!ASCII_DIGIT(c2)) {
2511 return LDAP_INVALID_SYNTAX;
2513 parts[part] = c1 * 10 + c2 - '0' * 11;
2514 if (parts[part] >= ceiling[part]) {
2515 return LDAP_INVALID_SYNTAX;
2518 if (part < 8 + start) {
2519 return LDAP_INVALID_SYNTAX;
2522 if (tzoffset == '-') {
2523 /* negative offset to UTC, ie west of Greenwich */
2524 parts[4] += parts[7];
2525 parts[5] += parts[8];
2526 /* offset is just hhmm, no seconds */
2527 for (part = 6; --part >= 0; ) {
2531 c = mdays[leapyear][parts[2]];
2533 if (parts[part] >= c) {
2535 return LDAP_INVALID_SYNTAX;
2540 } else if (part != 5) {
2545 /* positive offset to UTC, ie east of Greenwich */
2546 parts[4] -= parts[7];
2547 parts[5] -= parts[8];
2548 for (part = 6; --part >= 0; ) {
2549 if (parts[part] < 0) {
2551 return LDAP_INVALID_SYNTAX;
2556 /* make first arg to % non-negative */
2557 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2562 } else if (part != 5) {
2569 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2572 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2579 struct berval *normalized )
2583 rc = check_time_syntax(val, 1, parts, NULL);
2584 if (rc != LDAP_SUCCESS) {
2588 normalized->bv_val = ch_malloc( 14 );
2589 if ( normalized->bv_val == NULL ) {
2590 return LBER_ERROR_MEMORY;
2593 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2594 parts[1], parts[2] + 1, parts[3] + 1,
2595 parts[4], parts[5], parts[6] );
2596 normalized->bv_len = 13;
2598 return LDAP_SUCCESS;
2608 return check_time_syntax(in, 1, parts, NULL);
2611 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2614 generalizedTimeValidate(
2619 struct berval fraction;
2620 return check_time_syntax(in, 0, parts, &fraction);
2624 generalizedTimeNormalize(
2629 struct berval *normalized,
2634 struct berval fraction;
2636 rc = check_time_syntax(val, 0, parts, &fraction);
2637 if (rc != LDAP_SUCCESS) {
2641 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2642 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2643 if ( normalized->bv_val == NULL ) {
2644 return LBER_ERROR_MEMORY;
2647 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2648 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2649 parts[4], parts[5], parts[6] );
2650 if ( fraction.bv_len ) {
2651 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2652 fraction.bv_val, fraction.bv_len );
2653 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2655 strcpy( normalized->bv_val + len-1, "Z" );
2656 normalized->bv_len = len;
2658 return LDAP_SUCCESS;
2662 generalizedTimeOrderingMatch(
2667 struct berval *value,
2668 void *assertedValue )
2670 struct berval *asserted = (struct berval *) assertedValue;
2671 ber_len_t v_len = value->bv_len;
2672 ber_len_t av_len = asserted->bv_len;
2674 /* ignore trailing 'Z' when comparing */
2675 int match = memcmp( value->bv_val, asserted->bv_val,
2676 (v_len < av_len ? v_len : av_len) - 1 );
2677 if ( match == 0 ) match = v_len - av_len;
2680 return LDAP_SUCCESS;
2684 deliveryMethodValidate(
2686 struct berval *val )
2689 #define LENOF(s) (sizeof(s)-1)
2690 struct berval tmp = *val;
2692 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2693 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2694 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2697 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2699 switch( tmp.bv_val[0] ) {
2702 if(( tmp.bv_len >= LENOF("any") ) &&
2703 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2705 tmp.bv_len -= LENOF("any");
2706 tmp.bv_val += LENOF("any");
2709 return LDAP_INVALID_SYNTAX;
2713 if(( tmp.bv_len >= LENOF("mhs") ) &&
2714 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2716 tmp.bv_len -= LENOF("mhs");
2717 tmp.bv_val += LENOF("mhs");
2720 return LDAP_INVALID_SYNTAX;
2724 if(( tmp.bv_len >= LENOF("physical") ) &&
2725 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2727 tmp.bv_len -= LENOF("physical");
2728 tmp.bv_val += LENOF("physical");
2731 return LDAP_INVALID_SYNTAX;
2734 case 'T': /* telex or teletex or telephone */
2735 if(( tmp.bv_len >= LENOF("telex") ) &&
2736 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2738 tmp.bv_len -= LENOF("telex");
2739 tmp.bv_val += LENOF("telex");
2742 if(( tmp.bv_len >= LENOF("teletex") ) &&
2743 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2745 tmp.bv_len -= LENOF("teletex");
2746 tmp.bv_val += LENOF("teletex");
2749 if(( tmp.bv_len >= LENOF("telephone") ) &&
2750 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2752 tmp.bv_len -= LENOF("telephone");
2753 tmp.bv_val += LENOF("telephone");
2756 return LDAP_INVALID_SYNTAX;
2759 case 'G': /* g3fax or g4fax */
2760 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2761 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2762 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2764 tmp.bv_len -= LENOF("g3fax");
2765 tmp.bv_val += LENOF("g3fax");
2768 return LDAP_INVALID_SYNTAX;
2772 if(( tmp.bv_len >= LENOF("ia5") ) &&
2773 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2775 tmp.bv_len -= LENOF("ia5");
2776 tmp.bv_val += LENOF("ia5");
2779 return LDAP_INVALID_SYNTAX;
2783 if(( tmp.bv_len >= LENOF("videotex") ) &&
2784 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2786 tmp.bv_len -= LENOF("videotex");
2787 tmp.bv_val += LENOF("videotex");
2790 return LDAP_INVALID_SYNTAX;
2793 return LDAP_INVALID_SYNTAX;
2796 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2798 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2802 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2806 return LDAP_INVALID_SYNTAX;
2808 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2817 nisNetgroupTripleValidate(
2819 struct berval *val )
2824 if ( val->bv_len == 0 ) {
2825 return LDAP_INVALID_SYNTAX;
2828 p = (char *)val->bv_val;
2829 e = p + val->bv_len;
2831 if ( *p != '(' /*')'*/ ) {
2832 return LDAP_INVALID_SYNTAX;
2835 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2839 return LDAP_INVALID_SYNTAX;
2842 } else if ( !AD_CHAR( *p ) ) {
2843 return LDAP_INVALID_SYNTAX;
2847 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2848 return LDAP_INVALID_SYNTAX;
2854 return LDAP_INVALID_SYNTAX;
2857 return LDAP_SUCCESS;
2861 bootParameterValidate(
2863 struct berval *val )
2867 if ( val->bv_len == 0 ) {
2868 return LDAP_INVALID_SYNTAX;
2871 p = (char *)val->bv_val;
2872 e = p + val->bv_len;
2875 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2876 if ( !AD_CHAR( *p ) ) {
2877 return LDAP_INVALID_SYNTAX;
2882 return LDAP_INVALID_SYNTAX;
2886 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2887 if ( !AD_CHAR( *p ) ) {
2888 return LDAP_INVALID_SYNTAX;
2893 return LDAP_INVALID_SYNTAX;
2897 for ( p++; p < e; p++ ) {
2898 if ( !SLAP_PRINTABLE( *p ) ) {
2899 return LDAP_INVALID_SYNTAX;
2903 return LDAP_SUCCESS;
2907 firstComponentNormalize(
2912 struct berval *normalized,
2919 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2920 ber_dupbv_x( normalized, val, ctx );
2921 return LDAP_SUCCESS;
2924 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2926 if( val->bv_val[0] != '(' /*')'*/ &&
2927 val->bv_val[0] != '{' /*'}'*/ )
2929 return LDAP_INVALID_SYNTAX;
2932 /* trim leading white space */
2934 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2940 /* grab next word */
2941 comp.bv_val = &val->bv_val[len];
2942 len = val->bv_len - len;
2944 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2950 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2951 rc = numericoidValidate( NULL, &comp );
2952 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2953 rc = integerValidate( NULL, &comp );
2955 rc = LDAP_INVALID_SYNTAX;
2959 if( rc == LDAP_SUCCESS ) {
2960 ber_dupbv_x( normalized, &comp, ctx );
2967 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2968 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2970 static slap_syntax_defs_rec syntax_defs[] = {
2971 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2972 X_BINARY X_NOT_H_R ")",
2973 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2974 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2976 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2978 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2980 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2981 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2983 SLAP_SYNTAX_BER, berValidate, NULL},
2984 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2985 0, bitStringValidate, NULL },
2986 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2987 0, booleanValidate, NULL},
2988 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2989 X_BINARY X_NOT_H_R ")",
2990 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2991 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2992 X_BINARY X_NOT_H_R ")",
2993 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2994 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2995 X_BINARY X_NOT_H_R ")",
2996 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2997 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2998 0, countryStringValidate, NULL},
2999 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3000 0, dnValidate, dnPretty},
3001 {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
3002 0, rdnValidate, rdnPretty},
3003 #ifdef LDAP_COMP_MATCH
3004 {"( 1.2.36.79672281.1.5.2 DESC 'ComponentFilter' )",
3005 0, componentFilterValidate, NULL},
3007 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3009 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3010 0, deliveryMethodValidate, NULL},
3011 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3012 0, UTF8StringValidate, NULL},
3013 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3015 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3017 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3019 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3021 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3023 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3024 0, printablesStringValidate, NULL},
3025 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3026 SLAP_SYNTAX_BLOB, NULL, NULL},
3027 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3028 0, generalizedTimeValidate, NULL},
3029 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3031 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3032 0, IA5StringValidate, NULL},
3033 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3034 0, integerValidate, NULL},
3035 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3036 SLAP_SYNTAX_BLOB, blobValidate, NULL},
3037 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3039 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3041 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3043 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3045 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3047 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3048 0, nameUIDValidate, nameUIDPretty },
3049 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3051 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3052 0, numericStringValidate, NULL},
3053 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3055 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3056 0, numericoidValidate, NULL},
3057 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3058 0, IA5StringValidate, NULL},
3059 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3060 0, blobValidate, NULL},
3061 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3062 0, UTF8StringValidate, NULL},
3063 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3065 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3067 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3068 0, printableStringValidate, NULL},
3069 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
3070 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
3071 0, subtreeSpecificationValidate, NULL},
3072 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3073 X_BINARY X_NOT_H_R ")",
3074 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
3075 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3076 0, printableStringValidate, NULL},
3077 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3079 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3080 0, printablesStringValidate, NULL},
3081 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3082 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3083 0, utcTimeValidate, NULL},
3085 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3087 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3089 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3091 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3093 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3096 /* RFC 2307 NIS Syntaxes */
3097 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3098 0, nisNetgroupTripleValidate, NULL},
3099 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3100 0, bootParameterValidate, NULL},
3102 /* From PKIX *//* This OID is not published yet. */
3103 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3105 serialNumberAndIssuerValidate,
3106 serialNumberAndIssuerPretty},
3108 #ifdef SLAPD_ACI_ENABLED
3109 /* OpenLDAP Experimental Syntaxes */
3110 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3112 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3116 #ifdef SLAPD_AUTHPASSWD
3117 /* needs updating */
3118 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3119 SLAP_SYNTAX_HIDE, NULL, NULL},
3122 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3123 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3125 /* OpenLDAP Void Syntax */
3126 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3127 SLAP_SYNTAX_HIDE, inValidate, NULL},
3128 {NULL, 0, NULL, NULL}
3131 char *certificateExactMatchSyntaxes[] = {
3132 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3135 char *directoryStringSyntaxes[] = {
3136 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3139 char *integerFirstComponentMatchSyntaxes[] = {
3140 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3141 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3144 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3145 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3146 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3147 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3148 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3149 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3150 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3151 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3152 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3157 * Other matching rules in X.520 that we do not use (yet):
3159 * 2.5.13.25 uTCTimeMatch
3160 * 2.5.13.26 uTCTimeOrderingMatch
3161 * 2.5.13.31* directoryStringFirstComponentMatch
3162 * 2.5.13.32* wordMatch
3163 * 2.5.13.33* keywordMatch
3164 * 2.5.13.36 certificatePairExactMatch
3165 * 2.5.13.37 certificatePairMatch
3166 * 2.5.13.38 certificateListExactMatch
3167 * 2.5.13.39 certificateListMatch
3168 * 2.5.13.40 algorithmIdentifierMatch
3169 * 2.5.13.41* storedPrefixMatch
3170 * 2.5.13.42 attributeCertificateMatch
3171 * 2.5.13.43 readerAndKeyIDMatch
3172 * 2.5.13.44 attributeIntegrityMatch
3174 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3176 static slap_mrule_defs_rec mrule_defs[] = {
3178 * EQUALITY matching rules must be listed after associated APPROX
3179 * matching rules. So, we list all APPROX matching rules first.
3181 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3182 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3183 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3184 NULL, NULL, directoryStringApproxMatch,
3185 directoryStringApproxIndexer, directoryStringApproxFilter,
3188 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3189 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3190 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3191 NULL, NULL, IA5StringApproxMatch,
3192 IA5StringApproxIndexer, IA5StringApproxFilter,
3196 * Other matching rules
3199 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3200 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3201 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3202 NULL, NULL, octetStringMatch,
3203 octetStringIndexer, octetStringFilter,
3206 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3207 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3208 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3209 NULL, dnNormalize, dnMatch,
3210 octetStringIndexer, octetStringFilter,
3213 {"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
3214 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3215 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3216 NULL, dnNormalize, dnRelativeMatch,
3220 {"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
3221 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3222 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3223 NULL, dnNormalize, dnRelativeMatch,
3227 {"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
3228 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3229 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3230 NULL, dnNormalize, dnRelativeMatch,
3234 {"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
3235 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3236 SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
3237 NULL, dnNormalize, dnRelativeMatch,
3241 {"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
3242 "SYNTAX 1.2.36.79672281.1.5.0 )",
3243 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3244 NULL, rdnNormalize, rdnMatch,
3245 octetStringIndexer, octetStringFilter,
3248 #ifdef LDAP_COMP_MATCH
3249 {"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
3250 "SYNTAX 1.2.36.79672281.1.5.2 )",
3251 SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
3252 NULL, NULL , componentFilterMatch,
3253 octetStringIndexer, octetStringFilter,
3257 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3258 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3259 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3260 NULL, UTF8StringNormalize, octetStringMatch,
3261 octetStringIndexer, octetStringFilter,
3262 directoryStringApproxMatchOID },
3264 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3265 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3266 SLAP_MR_ORDERING, directoryStringSyntaxes,
3267 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3269 "caseIgnoreMatch" },
3271 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3272 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3273 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3274 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3275 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3276 "caseIgnoreMatch" },
3278 {"( 2.5.13.5 NAME 'caseExactMatch' "
3279 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3280 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3281 NULL, UTF8StringNormalize, octetStringMatch,
3282 octetStringIndexer, octetStringFilter,
3283 directoryStringApproxMatchOID },
3285 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3286 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3287 SLAP_MR_ORDERING, directoryStringSyntaxes,
3288 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3292 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3294 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3295 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3296 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3299 {"( 2.5.13.8 NAME 'numericStringMatch' "
3300 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3301 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3302 NULL, numericStringNormalize, octetStringMatch,
3303 octetStringIndexer, octetStringFilter,
3306 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3307 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3308 SLAP_MR_ORDERING, NULL,
3309 NULL, numericStringNormalize, octetStringOrderingMatch,
3311 "numericStringMatch" },
3313 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3314 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3315 SLAP_MR_SUBSTR, NULL,
3316 NULL, numericStringNormalize, octetStringSubstringsMatch,
3317 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3318 "numericStringMatch" },
3320 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3321 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3322 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3323 NULL, NULL, NULL, NULL, NULL, NULL },
3325 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3326 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3327 SLAP_MR_SUBSTR, NULL,
3328 NULL, NULL, NULL, NULL, NULL,
3329 "caseIgnoreListMatch" },
3331 {"( 2.5.13.13 NAME 'booleanMatch' "
3332 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3333 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3334 NULL, NULL, booleanMatch,
3335 octetStringIndexer, octetStringFilter,
3338 {"( 2.5.13.14 NAME 'integerMatch' "
3339 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3340 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3341 NULL, NULL, integerMatch,
3342 octetStringIndexer, octetStringFilter,
3345 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3346 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3347 SLAP_MR_ORDERING, NULL,
3348 NULL, NULL, integerMatch,
3352 {"( 2.5.13.16 NAME 'bitStringMatch' "
3353 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3354 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3355 NULL, NULL, octetStringMatch,
3356 octetStringIndexer, octetStringFilter,
3359 {"( 2.5.13.17 NAME 'octetStringMatch' "
3360 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3361 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3362 NULL, NULL, octetStringMatch,
3363 octetStringIndexer, octetStringFilter,
3366 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3367 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3368 SLAP_MR_ORDERING, NULL,
3369 NULL, NULL, octetStringOrderingMatch,
3371 "octetStringMatch" },
3373 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3374 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3375 SLAP_MR_SUBSTR, NULL,
3376 NULL, NULL, octetStringSubstringsMatch,
3377 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3378 "octetStringMatch" },
3380 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3381 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3382 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3384 telephoneNumberNormalize, octetStringMatch,
3385 octetStringIndexer, octetStringFilter,
3388 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3389 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3390 SLAP_MR_SUBSTR, NULL,
3391 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3392 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3393 "telephoneNumberMatch" },
3395 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3396 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3397 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3398 NULL, NULL, NULL, NULL, NULL, NULL },
3400 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3401 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3402 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3403 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3407 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3408 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3409 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3410 NULL, NULL, NULL, NULL, NULL, NULL },
3412 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3413 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3414 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3415 NULL, generalizedTimeNormalize, octetStringMatch,
3419 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3420 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3421 SLAP_MR_ORDERING, NULL,
3422 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3424 "generalizedTimeMatch" },
3426 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3427 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3428 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3429 integerFirstComponentMatchSyntaxes,
3430 NULL, firstComponentNormalize, integerMatch,
3431 octetStringIndexer, octetStringFilter,
3434 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3435 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3436 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3437 objectIdentifierFirstComponentMatchSyntaxes,
3438 NULL, firstComponentNormalize, octetStringMatch,
3439 octetStringIndexer, octetStringFilter,
3442 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3443 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3444 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3446 NULL, certificateExactNormalize, octetStringMatch,
3447 octetStringIndexer, octetStringFilter,
3449 NULL, NULL, NULL, NULL, NULL,
3453 {"( 2.5.13.35 NAME 'certificateMatch' "
3454 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3455 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3457 NULL, NULL, octetStringMatch,
3458 octetStringIndexer, octetStringFilter,
3460 NULL, NULL, NULL, NULL, NULL,
3464 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3465 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3466 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3467 NULL, IA5StringNormalize, octetStringMatch,
3468 octetStringIndexer, octetStringFilter,
3469 IA5StringApproxMatchOID },
3471 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3472 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3473 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3474 NULL, IA5StringNormalize, octetStringMatch,
3475 octetStringIndexer, octetStringFilter,
3476 IA5StringApproxMatchOID },
3478 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3480 SLAP_MR_SUBSTR, NULL,
3481 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3482 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3483 "caseIgnoreIA5Match" },
3485 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3486 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3487 SLAP_MR_SUBSTR, NULL,
3488 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3489 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3490 "caseExactIA5Match" },
3492 #ifdef SLAPD_AUTHPASSWD
3493 /* needs updating */
3494 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3495 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3496 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3497 NULL, NULL, authPasswordMatch,
3502 #ifdef SLAPD_ACI_ENABLED
3503 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3504 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3505 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3506 NULL, NULL, OpenLDAPaciMatch,
3511 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3512 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3514 NULL, NULL, integerBitAndMatch,
3518 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3519 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3521 NULL, NULL, integerBitOrMatch,
3525 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3526 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3527 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3528 NULL, UUIDNormalize, octetStringMatch,
3529 octetStringIndexer, octetStringFilter,
3532 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3533 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3534 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3535 NULL, UUIDNormalize, octetStringOrderingMatch,
3536 octetStringIndexer, octetStringFilter,
3539 {NULL, SLAP_MR_NONE, NULL,
3540 NULL, NULL, NULL, NULL, NULL,
3545 slap_schema_init( void )
3550 /* we should only be called once (from main) */
3551 assert( schema_init_done == 0 );
3553 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3554 res = register_syntax( &syntax_defs[i] );
3557 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3558 syntax_defs[i].sd_desc );
3563 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3564 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3565 mrule_defs[i].mrd_compat_syntaxes == NULL )
3568 "slap_schema_init: Ignoring unusable matching rule %s\n",
3569 mrule_defs[i].mrd_desc );
3573 res = register_matching_rule( &mrule_defs[i] );
3577 "slap_schema_init: Error registering matching rule %s\n",
3578 mrule_defs[i].mrd_desc );
3583 res = slap_schema_load();
3584 schema_init_done = 1;
3589 schema_destroy( void )