1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
15 #include <ac/string.h>
16 #include <ac/socket.h>
22 #include "ldap_utf8.h"
24 #include "lutil_hash.h"
25 #define HASH_BYTES LUTIL_HASH_BYTES
26 #define HASH_CONTEXT lutil_HASH_CTX
27 #define HASH_Init(c) lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
31 #define SLAP_NVALUES 1
33 /* not yet implemented */
34 #define integerFirstComponentNormalize NULL
35 #define objectIdentifierFirstComponentNormalize NULL
36 #define uniqueMemberMatch NULL
38 #define OpenLDAPaciMatch NULL
40 /* approx matching rules */
42 #define directoryStringApproxMatchOID NULL
43 #define IA5StringApproxMatchOID NULL
45 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
46 #define directoryStringApproxMatch approxMatch
47 #define directoryStringApproxIndexer approxIndexer
48 #define directoryStringApproxFilter approxFilter
49 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
50 #define IA5StringApproxMatch approxMatch
51 #define IA5StringApproxIndexer approxIndexer
52 #define IA5StringApproxFilter approxFilter
60 /* no value allowed */
61 return LDAP_INVALID_SYNTAX;
69 /* any value allowed */
73 #define berValidate blobValidate
84 struct berval *asserted = (struct berval *) assertedValue;
85 int match = value->bv_len - asserted->bv_len;
88 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
96 octetStringOrderingMatch(
101 struct berval *value,
102 void *assertedValue )
104 struct berval *asserted = (struct berval *) assertedValue;
105 ber_len_t v_len = value->bv_len;
106 ber_len_t av_len = asserted->bv_len;
108 int match = memcmp( value->bv_val, asserted->bv_val,
109 (v_len < av_len ? v_len : av_len) );
111 if( match == 0 ) match = v_len - av_len;
117 /* Index generation function */
118 int octetStringIndexer(
123 struct berval *prefix,
131 HASH_CONTEXT HASHcontext;
132 unsigned char HASHdigest[HASH_BYTES];
133 struct berval digest;
134 digest.bv_val = HASHdigest;
135 digest.bv_len = sizeof(HASHdigest);
137 for( i=0; values[i].bv_val != NULL; i++ ) {
138 /* just count them */
141 /* we should have at least one value at this point */
144 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
146 slen = syntax->ssyn_oidlen;
147 mlen = mr->smr_oidlen;
149 for( i=0; values[i].bv_val != NULL; i++ ) {
150 HASH_Init( &HASHcontext );
151 if( prefix != NULL && prefix->bv_len > 0 ) {
152 HASH_Update( &HASHcontext,
153 prefix->bv_val, prefix->bv_len );
155 HASH_Update( &HASHcontext,
156 syntax->ssyn_oid, slen );
157 HASH_Update( &HASHcontext,
159 HASH_Update( &HASHcontext,
160 values[i].bv_val, values[i].bv_len );
161 HASH_Final( HASHdigest, &HASHcontext );
163 ber_dupbv_x( &keys[i], &digest, ctx );
166 keys[i].bv_val = NULL;
174 /* Index generation function */
175 int octetStringFilter(
180 struct berval *prefix,
181 void * assertedValue,
187 HASH_CONTEXT HASHcontext;
188 unsigned char HASHdigest[HASH_BYTES];
189 struct berval *value = (struct berval *) assertedValue;
190 struct berval digest;
191 digest.bv_val = HASHdigest;
192 digest.bv_len = sizeof(HASHdigest);
194 slen = syntax->ssyn_oidlen;
195 mlen = mr->smr_oidlen;
197 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
199 HASH_Init( &HASHcontext );
200 if( prefix != NULL && prefix->bv_len > 0 ) {
201 HASH_Update( &HASHcontext,
202 prefix->bv_val, prefix->bv_len );
204 HASH_Update( &HASHcontext,
205 syntax->ssyn_oid, slen );
206 HASH_Update( &HASHcontext,
208 HASH_Update( &HASHcontext,
209 value->bv_val, value->bv_len );
210 HASH_Final( HASHdigest, &HASHcontext );
212 ber_dupbv_x( keys, &digest, ctx );
213 keys[1].bv_val = NULL;
222 octetStringSubstringsMatch(
227 struct berval *value,
228 void *assertedValue )
231 SubstringsAssertion *sub = assertedValue;
232 struct berval left = *value;
236 /* Add up asserted input length */
237 if( sub->sa_initial.bv_val ) {
238 inlen += sub->sa_initial.bv_len;
241 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
242 inlen += sub->sa_any[i].bv_len;
245 if( sub->sa_final.bv_val ) {
246 inlen += sub->sa_final.bv_len;
249 if( sub->sa_initial.bv_val ) {
250 if( inlen > left.bv_len ) {
255 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
256 sub->sa_initial.bv_len );
262 left.bv_val += sub->sa_initial.bv_len;
263 left.bv_len -= sub->sa_initial.bv_len;
264 inlen -= sub->sa_initial.bv_len;
267 if( sub->sa_final.bv_val ) {
268 if( inlen > left.bv_len ) {
273 match = memcmp( sub->sa_final.bv_val,
274 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
275 sub->sa_final.bv_len );
281 left.bv_len -= sub->sa_final.bv_len;
282 inlen -= sub->sa_final.bv_len;
286 for(i=0; sub->sa_any[i].bv_val; i++) {
291 if( inlen > left.bv_len ) {
292 /* not enough length */
297 if( sub->sa_any[i].bv_len == 0 ) {
301 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
308 idx = p - left.bv_val;
310 if( idx >= left.bv_len ) {
311 /* this shouldn't happen */
318 if( sub->sa_any[i].bv_len > left.bv_len ) {
319 /* not enough left */
324 match = memcmp( left.bv_val,
325 sub->sa_any[i].bv_val,
326 sub->sa_any[i].bv_len );
334 left.bv_val += sub->sa_any[i].bv_len;
335 left.bv_len -= sub->sa_any[i].bv_len;
336 inlen -= sub->sa_any[i].bv_len;
345 /* Substrings Index generation function */
347 octetStringSubstringsIndexer(
352 struct berval *prefix,
357 ber_len_t i, j, nkeys;
361 HASH_CONTEXT HASHcontext;
362 unsigned char HASHdigest[HASH_BYTES];
363 struct berval digest;
364 digest.bv_val = HASHdigest;
365 digest.bv_len = sizeof(HASHdigest);
369 for( i=0; values[i].bv_val != NULL; i++ ) {
370 /* count number of indices to generate */
371 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
375 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
376 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
377 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
378 (SLAP_INDEX_SUBSTR_MINLEN - 1);
380 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
384 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
385 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
386 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
390 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
391 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
392 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
393 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
395 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
401 /* no keys to generate */
406 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
408 slen = syntax->ssyn_oidlen;
409 mlen = mr->smr_oidlen;
412 for( i=0; values[i].bv_val != NULL; i++ ) {
415 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
417 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
418 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
420 char pre = SLAP_INDEX_SUBSTR_PREFIX;
421 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
423 for( j=0; j<max; j++ ) {
424 HASH_Init( &HASHcontext );
425 if( prefix != NULL && prefix->bv_len > 0 ) {
426 HASH_Update( &HASHcontext,
427 prefix->bv_val, prefix->bv_len );
430 HASH_Update( &HASHcontext,
431 &pre, sizeof( pre ) );
432 HASH_Update( &HASHcontext,
433 syntax->ssyn_oid, slen );
434 HASH_Update( &HASHcontext,
436 HASH_Update( &HASHcontext,
437 &values[i].bv_val[j],
438 SLAP_INDEX_SUBSTR_MAXLEN );
439 HASH_Final( HASHdigest, &HASHcontext );
441 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
445 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
446 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
448 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
451 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
452 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
453 HASH_Init( &HASHcontext );
454 if( prefix != NULL && prefix->bv_len > 0 ) {
455 HASH_Update( &HASHcontext,
456 prefix->bv_val, prefix->bv_len );
458 HASH_Update( &HASHcontext,
459 &pre, sizeof( pre ) );
460 HASH_Update( &HASHcontext,
461 syntax->ssyn_oid, slen );
462 HASH_Update( &HASHcontext,
464 HASH_Update( &HASHcontext,
465 values[i].bv_val, j );
466 HASH_Final( HASHdigest, &HASHcontext );
468 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
471 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
472 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
473 HASH_Init( &HASHcontext );
474 if( prefix != NULL && prefix->bv_len > 0 ) {
475 HASH_Update( &HASHcontext,
476 prefix->bv_val, prefix->bv_len );
478 HASH_Update( &HASHcontext,
479 &pre, sizeof( pre ) );
480 HASH_Update( &HASHcontext,
481 syntax->ssyn_oid, slen );
482 HASH_Update( &HASHcontext,
484 HASH_Update( &HASHcontext,
485 &values[i].bv_val[values[i].bv_len-j], j );
486 HASH_Final( HASHdigest, &HASHcontext );
488 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
496 keys[nkeys].bv_val = NULL;
507 octetStringSubstringsFilter (
512 struct berval *prefix,
513 void * assertedValue,
517 SubstringsAssertion *sa;
520 size_t slen, mlen, klen;
522 HASH_CONTEXT HASHcontext;
523 unsigned char HASHdigest[HASH_BYTES];
524 struct berval *value;
525 struct berval digest;
527 sa = (SubstringsAssertion *) assertedValue;
529 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
530 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
535 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
537 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
538 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
539 /* don't bother accounting for stepping */
540 nkeys += sa->sa_any[i].bv_len -
541 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
546 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
547 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
557 digest.bv_val = HASHdigest;
558 digest.bv_len = sizeof(HASHdigest);
560 slen = syntax->ssyn_oidlen;
561 mlen = mr->smr_oidlen;
563 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
566 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
567 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
569 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
570 value = &sa->sa_initial;
572 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
573 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
575 HASH_Init( &HASHcontext );
576 if( prefix != NULL && prefix->bv_len > 0 ) {
577 HASH_Update( &HASHcontext,
578 prefix->bv_val, prefix->bv_len );
580 HASH_Update( &HASHcontext,
581 &pre, sizeof( pre ) );
582 HASH_Update( &HASHcontext,
583 syntax->ssyn_oid, slen );
584 HASH_Update( &HASHcontext,
586 HASH_Update( &HASHcontext,
587 value->bv_val, klen );
588 HASH_Final( HASHdigest, &HASHcontext );
590 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
593 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
595 pre = SLAP_INDEX_SUBSTR_PREFIX;
596 klen = SLAP_INDEX_SUBSTR_MAXLEN;
598 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
599 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
603 value = &sa->sa_any[i];
606 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
607 j += SLAP_INDEX_SUBSTR_STEP )
609 HASH_Init( &HASHcontext );
610 if( prefix != NULL && prefix->bv_len > 0 ) {
611 HASH_Update( &HASHcontext,
612 prefix->bv_val, prefix->bv_len );
614 HASH_Update( &HASHcontext,
615 &pre, sizeof( pre ) );
616 HASH_Update( &HASHcontext,
617 syntax->ssyn_oid, slen );
618 HASH_Update( &HASHcontext,
620 HASH_Update( &HASHcontext,
621 &value->bv_val[j], klen );
622 HASH_Final( HASHdigest, &HASHcontext );
624 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
629 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
630 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
632 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
633 value = &sa->sa_final;
635 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
636 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
638 HASH_Init( &HASHcontext );
639 if( prefix != NULL && prefix->bv_len > 0 ) {
640 HASH_Update( &HASHcontext,
641 prefix->bv_val, prefix->bv_len );
643 HASH_Update( &HASHcontext,
644 &pre, sizeof( pre ) );
645 HASH_Update( &HASHcontext,
646 syntax->ssyn_oid, slen );
647 HASH_Update( &HASHcontext,
649 HASH_Update( &HASHcontext,
650 &value->bv_val[value->bv_len-klen], klen );
651 HASH_Final( HASHdigest, &HASHcontext );
653 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
657 keys[nkeys].bv_val = NULL;
674 /* very unforgiving validation, requires no normalization
675 * before simplistic matching
677 if( in->bv_len < 3 ) {
678 return LDAP_INVALID_SYNTAX;
682 * RFC 2252 section 6.3 Bit String
683 * bitstring = "'" *binary-digit "'B"
684 * binary-digit = "0" / "1"
685 * example: '0101111101'B
688 if( in->bv_val[0] != '\'' ||
689 in->bv_val[in->bv_len-2] != '\'' ||
690 in->bv_val[in->bv_len-1] != 'B' )
692 return LDAP_INVALID_SYNTAX;
695 for( i=in->bv_len-3; i>0; i-- ) {
696 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
697 return LDAP_INVALID_SYNTAX;
712 if( in->bv_len == 0 ) return LDAP_SUCCESS;
714 ber_dupbv( &dn, in );
715 if( !dn.bv_val ) return LDAP_OTHER;
717 if( dn.bv_val[dn.bv_len-1] == 'B'
718 && dn.bv_val[dn.bv_len-2] == '\'' )
720 /* assume presence of optional UID */
723 for(i=dn.bv_len-3; i>1; i--) {
724 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
728 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
729 ber_memfree( dn.bv_val );
730 return LDAP_INVALID_SYNTAX;
733 /* trim the UID to allow use of dnValidate */
734 dn.bv_val[i-1] = '\0';
738 rc = dnValidate( NULL, &dn );
740 ber_memfree( dn.bv_val );
745 uniqueMemberNormalize(
750 struct berval *normalized,
756 ber_dupbv( &out, val );
757 if( out.bv_len != 0 ) {
758 struct berval uid = { 0, NULL };
760 if( out.bv_val[out.bv_len-1] == 'B'
761 && out.bv_val[out.bv_len-2] == '\'' )
763 /* assume presence of optional UID */
764 uid.bv_val = strrchr( out.bv_val, '#' );
766 if( uid.bv_val == NULL ) {
768 return LDAP_INVALID_SYNTAX;
771 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
772 out.bv_len -= uid.bv_len--;
774 /* temporarily trim the UID */
775 *(uid.bv_val++) = '\0';
778 rc = dnNormalize2( NULL, &out, normalized, ctx );
780 if( rc != LDAP_SUCCESS ) {
782 return LDAP_INVALID_SYNTAX;
786 normalized->bv_val = ch_realloc( normalized->bv_val,
787 normalized->bv_len + uid.bv_len + sizeof("#") );
789 /* insert the separator */
790 normalized->bv_val[normalized->bv_len++] = '#';
793 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
794 uid.bv_val, uid.bv_len );
795 normalized->bv_len += uid.bv_len;
798 normalized->bv_val[normalized->bv_len] = '\0';
808 * Handling boolean syntax and matching is quite rigid.
809 * A more flexible approach would be to allow a variety
810 * of strings to be normalized and prettied into TRUE
818 /* very unforgiving validation, requires no normalization
819 * before simplistic matching
822 if( in->bv_len == 4 ) {
823 if( bvmatch( in, &slap_true_bv ) ) {
826 } else if( in->bv_len == 5 ) {
827 if( bvmatch( in, &slap_false_bv ) ) {
832 return LDAP_INVALID_SYNTAX;
841 struct berval *value,
842 void *assertedValue )
844 /* simplistic matching allowed by rigid validation */
845 struct berval *asserted = (struct berval *) assertedValue;
846 *matchp = value->bv_len != asserted->bv_len;
850 /*-------------------------------------------------------------------
851 LDAP/X.500 string syntax / matching rules have a few oddities. This
852 comment attempts to detail how slapd(8) treats them.
855 StringSyntax X.500 LDAP Matching/Comments
856 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
857 PrintableString subset subset i/e + ignore insignificant spaces
858 PrintableString subset subset i/e + ignore insignificant spaces
859 NumericString subset subset ignore all spaces
860 IA5String ASCII ASCII i/e + ignore insignificant spaces
861 TeletexString T.61 T.61 i/e + ignore insignificant spaces
863 TelephoneNumber subset subset i + ignore all spaces and "-"
865 See draft-ietf-ldapbis-strpro for details (once published).
869 In X.500(93), a directory string can be either a PrintableString,
870 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
871 In later versions, more CHOICEs were added. In all cases the string
874 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
875 A directory string cannot be zero length.
877 For matching, there are both case ignore and exact rules. Both
878 also require that "insignificant" spaces be ignored.
879 spaces before the first non-space are ignored;
880 spaces after the last non-space are ignored;
881 spaces after a space are ignored.
882 Note: by these rules (and as clarified in X.520), a string of only
883 spaces is to be treated as if held one space, not empty (which
884 would be a syntax error).
887 In ASN.1, numeric string is just a string of digits and spaces
888 and could be empty. However, in X.500, all attribute values of
889 numeric string carry a non-empty constraint. For example:
891 internationalISDNNumber ATTRIBUTE ::= {
892 WITH SYNTAX InternationalISDNNumber
893 EQUALITY MATCHING RULE numericStringMatch
894 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
895 ID id-at-internationalISDNNumber }
896 InternationalISDNNumber ::=
897 NumericString (SIZE(1..ub-international-isdn-number))
899 Unforunately, some assertion values are don't carry the same
900 constraint (but its unclear how such an assertion could ever
901 be true). In LDAP, there is one syntax (numericString) not two
902 (numericString with constraint, numericString without constraint).
903 This should be treated as numericString with non-empty constraint.
904 Note that while someone may have no ISDN number, there are no ISDN
905 numbers which are zero length.
907 In matching, spaces are ignored.
910 In ASN.1, Printable string is just a string of printable characters
911 and can be empty. In X.500, semantics much like NumericString (see
912 serialNumber for a like example) excepting uses insignificant space
913 handling instead of ignore all spaces.
916 Basically same as PrintableString. There are no examples in X.500,
917 but same logic applies. So we require them to be non-empty as
920 -------------------------------------------------------------------*/
929 unsigned char *u = in->bv_val;
931 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
932 /* directory strings cannot be empty */
933 return LDAP_INVALID_SYNTAX;
936 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
937 /* get the length indicated by the first byte */
938 len = LDAP_UTF8_CHARLEN2( u, len );
940 /* very basic checks */
943 if( (u[5] & 0xC0) != 0x80 ) {
944 return LDAP_INVALID_SYNTAX;
947 if( (u[4] & 0xC0) != 0x80 ) {
948 return LDAP_INVALID_SYNTAX;
951 if( (u[3] & 0xC0) != 0x80 ) {
952 return LDAP_INVALID_SYNTAX;
955 if( (u[2] & 0xC0 )!= 0x80 ) {
956 return LDAP_INVALID_SYNTAX;
959 if( (u[1] & 0xC0) != 0x80 ) {
960 return LDAP_INVALID_SYNTAX;
963 /* CHARLEN already validated it */
966 return LDAP_INVALID_SYNTAX;
969 /* make sure len corresponds with the offset
970 to the next character */
971 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
975 return LDAP_INVALID_SYNTAX;
987 struct berval *normalized,
990 struct berval tmp, nvalue;
994 if( val->bv_val == NULL ) {
995 /* assume we're dealing with a syntax (e.g., UTF8String)
996 * which allows empty strings
998 normalized->bv_len = 0;
999 normalized->bv_val = NULL;
1000 return LDAP_SUCCESS;
1003 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1004 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1005 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1006 ? LDAP_UTF8_APPROX : 0;
1008 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1013 /* collapse spaces (in place) */
1015 nvalue.bv_val = tmp.bv_val;
1017 wasspace=1; /* trim leading spaces */
1018 for( i=0; i<tmp.bv_len; i++) {
1019 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1020 if( wasspace++ == 0 ) {
1021 /* trim repeated spaces */
1022 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1026 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1030 if( nvalue.bv_len ) {
1032 /* last character was a space, trim it */
1035 nvalue.bv_val[nvalue.bv_len] = '\0';
1038 /* string of all spaces is treated as one space */
1039 nvalue.bv_val[0] = ' ';
1040 nvalue.bv_val[1] = '\0';
1044 *normalized = nvalue;
1045 return LDAP_SUCCESS;
1048 #ifndef SLAP_NVALUES
1050 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1051 #if defined(SLAPD_APPROX_INITIALS)
1052 #define SLAPD_APPROX_DELIMITER "._ "
1053 #define SLAPD_APPROX_WORDLEN 2
1055 #define SLAPD_APPROX_DELIMITER " "
1056 #define SLAPD_APPROX_WORDLEN 1
1065 struct berval *value,
1066 void *assertedValue )
1068 struct berval *nval, *assertv;
1069 char *val, **values, **words, *c;
1070 int i, count, len, nextchunk=0, nextavail=0;
1072 /* Yes, this is necessary */
1073 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1074 if( nval == NULL ) {
1076 return LDAP_SUCCESS;
1079 /* Yes, this is necessary */
1080 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1081 NULL, LDAP_UTF8_APPROX );
1082 if( assertv == NULL ) {
1085 return LDAP_SUCCESS;
1088 /* Isolate how many words there are */
1089 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1090 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1091 if ( c == NULL ) break;
1096 /* Get a phonetic copy of each word */
1097 words = (char **)ch_malloc( count * sizeof(char *) );
1098 values = (char **)ch_malloc( count * sizeof(char *) );
1099 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1101 values[i] = phonetic(c);
1104 /* Work through the asserted value's words, to see if at least some
1105 of the words are there, in the same order. */
1107 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1108 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1113 #if defined(SLAPD_APPROX_INITIALS)
1114 else if( len == 1 ) {
1115 /* Single letter words need to at least match one word's initial */
1116 for( i=nextavail; i<count; i++ )
1117 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1124 /* Isolate the next word in the asserted value and phonetic it */
1125 assertv->bv_val[nextchunk+len] = '\0';
1126 val = phonetic( assertv->bv_val + nextchunk );
1128 /* See if this phonetic chunk is in the remaining words of *value */
1129 for( i=nextavail; i<count; i++ ){
1130 if( !strcmp( val, values[i] ) ){
1138 /* This chunk in the asserted value was NOT within the *value. */
1144 /* Go on to the next word in the asserted value */
1148 /* If some of the words were seen, call it a match */
1149 if( nextavail > 0 ) {
1156 /* Cleanup allocs */
1157 ber_bvfree( assertv );
1158 for( i=0; i<count; i++ ) {
1159 ch_free( values[i] );
1165 return LDAP_SUCCESS;
1174 struct berval *prefix,
1179 int i,j, len, wordcount, keycount=0;
1180 struct berval *newkeys;
1181 BerVarray keys=NULL;
1183 for( j=0; values[j].bv_val != NULL; j++ ) {
1184 struct berval val = { 0, NULL };
1185 /* Yes, this is necessary */
1186 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1187 assert( val.bv_val != NULL );
1189 /* Isolate how many words there are. There will be a key for each */
1190 for( wordcount = 0, c = val.bv_val; *c; c++) {
1191 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1192 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1194 if (*c == '\0') break;
1198 /* Allocate/increase storage to account for new keys */
1199 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1200 * sizeof(struct berval) );
1201 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1202 if( keys ) ch_free( keys );
1205 /* Get a phonetic copy of each word */
1206 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1208 if( len < SLAPD_APPROX_WORDLEN ) continue;
1209 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1214 ber_memfree( val.bv_val );
1216 keys[keycount].bv_val = NULL;
1219 return LDAP_SUCCESS;
1228 struct berval *prefix,
1229 void * assertedValue,
1237 /* Yes, this is necessary */
1238 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1239 NULL, LDAP_UTF8_APPROX );
1240 if( val == NULL || val->bv_val == NULL ) {
1241 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1242 keys[0].bv_val = NULL;
1245 return LDAP_SUCCESS;
1248 /* Isolate how many words there are. There will be a key for each */
1249 for( count = 0,c = val->bv_val; *c; c++) {
1250 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1251 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1253 if (*c == '\0') break;
1257 /* Allocate storage for new keys */
1258 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1260 /* Get a phonetic copy of each word */
1261 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1263 if( len < SLAPD_APPROX_WORDLEN ) continue;
1264 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1270 keys[count].bv_val = NULL;
1273 return LDAP_SUCCESS;
1277 /* No other form of Approximate Matching is defined */
1285 struct berval *value,
1286 void *assertedValue )
1288 char *vapprox, *avapprox;
1291 /* Yes, this is necessary */
1292 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1295 return LDAP_SUCCESS;
1298 /* Yes, this is necessary */
1299 t = UTF8normalize( ((struct berval *)assertedValue),
1304 return LDAP_SUCCESS;
1307 vapprox = phonetic( strip8bitChars( s ) );
1308 avapprox = phonetic( strip8bitChars( t ) );
1313 *matchp = strcmp( vapprox, avapprox );
1316 ch_free( avapprox );
1318 return LDAP_SUCCESS;
1327 struct berval *prefix,
1335 for( i=0; values[i].bv_val != NULL; i++ ) {
1336 /* empty - just count them */
1339 /* we should have at least one value at this point */
1342 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1344 /* Copy each value and run it through phonetic() */
1345 for( i=0; values[i].bv_val != NULL; i++ ) {
1346 /* Yes, this is necessary */
1347 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1349 /* strip 8-bit chars and run through phonetic() */
1350 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1353 keys[i].bv_val = NULL;
1356 return LDAP_SUCCESS;
1365 struct berval *prefix,
1366 void * assertedValue,
1372 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1374 /* Yes, this is necessary */
1375 s = UTF8normalize( ((struct berval *)assertedValue),
1380 /* strip 8-bit chars and run through phonetic() */
1381 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1387 return LDAP_SUCCESS;
1390 #endif /* !SLAP_NVALUES */
1392 /* Remove all spaces and '-' characters */
1394 telephoneNumberNormalize(
1399 struct berval *normalized,
1404 /* validator should have refused an empty string */
1405 assert( val->bv_len );
1407 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1409 for( p = val->bv_val; *p; p++ ) {
1410 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1416 normalized->bv_len = q - normalized->bv_val;
1418 if( normalized->bv_len == 0 ) {
1419 sl_free( normalized->bv_val, ctx );
1420 return LDAP_INVALID_SYNTAX;
1423 return LDAP_SUCCESS;
1431 struct berval val = *in;
1433 if( val.bv_len == 0 ) {
1434 /* disallow empty strings */
1435 return LDAP_INVALID_SYNTAX;
1438 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1439 if ( val.bv_len == 1 ) {
1440 return LDAP_SUCCESS;
1443 if ( val.bv_val[0] == '0' ) {
1450 while ( OID_LEADCHAR( val.bv_val[0] )) {
1454 if ( val.bv_len == 0 ) {
1455 return LDAP_SUCCESS;
1459 if( !OID_SEPARATOR( val.bv_val[0] )) {
1467 return LDAP_INVALID_SYNTAX;
1476 struct berval val = *in;
1478 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1480 if ( val.bv_val[0] == '-' ) {
1484 if( val.bv_len == 0 ) { /* bare "-" */
1485 return LDAP_INVALID_SYNTAX;
1488 if( val.bv_val[0] == '0' ) { /* "-0" */
1489 return LDAP_INVALID_SYNTAX;
1492 } else if ( val.bv_val[0] == '0' ) {
1493 if( val.bv_len > 1 ) { /* "0<more>" */
1494 return LDAP_INVALID_SYNTAX;
1497 return LDAP_SUCCESS;
1500 for( i=0; i < val.bv_len; i++ ) {
1501 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1502 return LDAP_INVALID_SYNTAX;
1506 return LDAP_SUCCESS;
1515 struct berval *value,
1516 void *assertedValue )
1518 struct berval *asserted = (struct berval *) assertedValue;
1519 int vsign = 1, asign = 1; /* default sign = '+' */
1524 if( v.bv_val[0] == '-' ) {
1530 if( v.bv_len == 0 ) vsign = 0;
1533 if( a.bv_val[0] == '-' ) {
1539 if( a.bv_len == 0 ) vsign = 0;
1541 match = vsign - asign;
1543 match = ( v.bv_len != a.bv_len
1544 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1545 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1546 if( vsign < 0 ) match = -match;
1550 return LDAP_SUCCESS;
1554 countryStringValidate(
1556 struct berval *val )
1558 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1560 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1561 return LDAP_INVALID_SYNTAX;
1563 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1564 return LDAP_INVALID_SYNTAX;
1567 return LDAP_SUCCESS;
1571 printableStringValidate(
1573 struct berval *val )
1577 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1579 for(i=0; i < val->bv_len; i++) {
1580 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1581 return LDAP_INVALID_SYNTAX;
1585 return LDAP_SUCCESS;
1589 printablesStringValidate(
1591 struct berval *val )
1595 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1597 for(i=0,len=0; i < val->bv_len; i++) {
1598 int c = val->bv_val[i];
1602 return LDAP_INVALID_SYNTAX;
1606 } else if ( SLAP_PRINTABLE(c) ) {
1609 return LDAP_INVALID_SYNTAX;
1614 return LDAP_INVALID_SYNTAX;
1617 return LDAP_SUCCESS;
1623 struct berval *val )
1627 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1629 for(i=0; i < val->bv_len; i++) {
1630 if( !LDAP_ASCII(val->bv_val[i]) ) {
1631 return LDAP_INVALID_SYNTAX;
1635 return LDAP_SUCCESS;
1644 struct berval *normalized,
1648 int casefold = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactIA5Match );
1650 assert( val->bv_len );
1654 /* Ignore initial whitespace */
1655 while ( ASCII_SPACE( *p ) ) {
1659 normalized->bv_val = ber_strdup_x( p, ctx );
1660 p = q = normalized->bv_val;
1663 if ( ASCII_SPACE( *p ) ) {
1666 /* Ignore the extra whitespace */
1667 while ( ASCII_SPACE( *p ) ) {
1671 } else if ( casefold ) {
1672 /* Most IA5 rules require casefolding */
1673 *q++ = TOLOWER(*p++);
1680 assert( normalized->bv_val <= p );
1684 * If the string ended in space, backup the pointer one
1685 * position. One is enough because the above loop collapsed
1686 * all whitespace to a single space.
1689 if ( ASCII_SPACE( q[-1] ) ) {
1693 /* null terminate */
1696 normalized->bv_len = q - normalized->bv_val;
1698 if( normalized->bv_len == 0 ) {
1699 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1700 normalized->bv_val[0] = ' ';
1701 normalized->bv_val[1] = '\0';
1702 normalized->bv_len = 1;
1705 return LDAP_SUCCESS;
1709 numericStringValidate(
1715 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1717 for(i=0; i < in->bv_len; i++) {
1718 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1719 return LDAP_INVALID_SYNTAX;
1723 return LDAP_SUCCESS;
1727 numericStringNormalize(
1732 struct berval *normalized,
1735 /* removal all spaces */
1738 assert( val->bv_len );
1740 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1743 q = normalized->bv_val;
1746 if ( ASCII_SPACE( *p ) ) {
1747 /* Ignore whitespace */
1754 /* we should have copied no more then is in val */
1755 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1757 /* null terminate */
1760 normalized->bv_len = q - normalized->bv_val;
1762 if( normalized->bv_len == 0 ) {
1763 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1764 normalized->bv_val[0] = ' ';
1765 normalized->bv_val[1] = '\0';
1766 normalized->bv_len = 1;
1769 return LDAP_SUCCESS;
1772 #ifndef SLAP_NVALUES
1774 objectIdentifierFirstComponentMatch(
1779 struct berval *value,
1780 void *assertedValue )
1782 int rc = LDAP_SUCCESS;
1784 struct berval *asserted = (struct berval *) assertedValue;
1788 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1789 return LDAP_INVALID_SYNTAX;
1792 /* trim leading white space */
1793 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1797 /* grab next word */
1798 oid.bv_val = &value->bv_val[i];
1799 j = value->bv_len - i;
1800 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1805 /* insert attributeTypes, objectclass check here */
1806 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1807 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1810 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1811 MatchingRule *asserted_mr = mr_bvfind( asserted );
1812 MatchingRule *stored_mr = mr_bvfind( &oid );
1814 if( asserted_mr == NULL ) {
1815 rc = SLAPD_COMPARE_UNDEFINED;
1817 match = asserted_mr != stored_mr;
1820 } else if ( !strcmp( syntax->ssyn_oid,
1821 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1823 AttributeType *asserted_at = at_bvfind( asserted );
1824 AttributeType *stored_at = at_bvfind( &oid );
1826 if( asserted_at == NULL ) {
1827 rc = SLAPD_COMPARE_UNDEFINED;
1829 match = asserted_at != stored_at;
1832 } else if ( !strcmp( syntax->ssyn_oid,
1833 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1835 ObjectClass *asserted_oc = oc_bvfind( asserted );
1836 ObjectClass *stored_oc = oc_bvfind( &oid );
1838 if( asserted_oc == NULL ) {
1839 rc = SLAPD_COMPARE_UNDEFINED;
1841 match = asserted_oc != stored_oc;
1847 LDAP_LOG( CONFIG, ENTRY,
1848 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1849 match, value->bv_val, asserted->bv_val );
1851 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1852 "%d\n\t\"%s\"\n\t\"%s\"\n",
1853 match, value->bv_val, asserted->bv_val );
1856 if( rc == LDAP_SUCCESS ) *matchp = match;
1867 struct berval *value,
1868 void *assertedValue )
1870 long lValue, lAssertedValue;
1872 /* safe to assume integers are NUL terminated? */
1873 lValue = strtol(value->bv_val, NULL, 10);
1874 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1875 return LDAP_CONSTRAINT_VIOLATION;
1878 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1879 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1880 && errno == ERANGE )
1882 return LDAP_CONSTRAINT_VIOLATION;
1885 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1886 return LDAP_SUCCESS;
1895 struct berval *value,
1896 void *assertedValue )
1898 long lValue, lAssertedValue;
1900 /* safe to assume integers are NUL terminated? */
1901 lValue = strtol(value->bv_val, NULL, 10);
1902 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1903 return LDAP_CONSTRAINT_VIOLATION;
1906 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1907 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1908 && errno == ERANGE )
1910 return LDAP_CONSTRAINT_VIOLATION;
1913 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1914 return LDAP_SUCCESS;
1917 #ifndef SLAP_NVALUES
1919 #include <openssl/x509.h>
1920 #include <openssl/err.h>
1923 * Next function returns a string representation of a ASN1_INTEGER.
1924 * It works for unlimited lengths.
1927 static struct berval *
1928 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1932 static char digit[] = "0123456789";
1934 /* We work backwards, make it fill from the end of buf */
1935 p = buf + sizeof(buf) - 1;
1938 if ( a == NULL || a->length == 0 ) {
1946 /* We want to preserve the original */
1947 copy = ch_malloc(n*sizeof(unsigned int));
1948 for (i = 0; i<n; i++) {
1949 copy[i] = a->data[i];
1953 * base indicates the index of the most significant
1954 * byte that might be nonzero. When it goes off the
1955 * end, we now there is nothing left to do.
1961 for (i = base; i<n; i++ ) {
1962 copy[i] += carry*256;
1963 carry = copy[i] % 10;
1968 * Way too large, we need to leave
1969 * room for sign if negative
1974 *--p = digit[carry];
1976 if (copy[base] == 0) base++;
1981 if ( a->type == V_ASN1_NEG_INTEGER ) {
1985 return ber_str2bv( p, 0, 1, bv );
1989 * Given a certificate in DER format, extract the corresponding
1990 * assertion value for certificateExactMatch
1993 certificateExactConvert(
1995 struct berval * out )
1998 unsigned char *p = in->bv_val;
1999 struct berval serial;
2000 struct berval issuer_dn;
2002 xcert = d2i_X509(NULL, &p, in->bv_len);
2005 LDAP_LOG( CONFIG, ENTRY,
2006 "certificateExactConvert: error parsing cert: %s\n",
2007 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2009 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2010 "error parsing cert: %s\n",
2011 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2013 return LDAP_INVALID_SYNTAX;
2016 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2018 return LDAP_INVALID_SYNTAX;
2020 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2024 ber_memfree(serial.bv_val);
2025 return LDAP_INVALID_SYNTAX;
2030 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2031 out->bv_val = ch_malloc(out->bv_len);
2033 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2035 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2037 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2038 p += issuer_dn.bv_len;
2042 LDAP_LOG( CONFIG, ARGS,
2043 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2045 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2047 out->bv_val, NULL, NULL );
2050 ber_memfree(serial.bv_val);
2051 ber_memfree(issuer_dn.bv_val);
2053 return LDAP_SUCCESS;
2057 serial_and_issuer_parse(
2058 struct berval *assertion,
2059 struct berval *serial,
2060 struct berval *issuer_dn )
2067 begin = assertion->bv_val;
2068 end = assertion->bv_val+assertion->bv_len-1;
2069 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2070 if ( p > end ) return LDAP_INVALID_SYNTAX;
2072 /* p now points at the $ sign, now use
2073 * begin and end to delimit the serial number
2075 while (ASCII_SPACE(*begin)) begin++;
2077 while (ASCII_SPACE(*end)) end--;
2079 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2081 bv.bv_len = end-begin+1;
2083 ber_dupbv(serial, &bv);
2085 /* now extract the issuer, remember p was at the dollar sign */
2087 end = assertion->bv_val+assertion->bv_len-1;
2088 while (ASCII_SPACE(*begin)) begin++;
2089 /* should we trim spaces at the end too? is it safe always? no, no */
2091 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2094 bv.bv_len = end-begin+1;
2097 dnNormalize2( NULL, &bv, issuer_dn );
2100 return LDAP_SUCCESS;
2104 certificateExactMatch(
2109 struct berval *value,
2110 void *assertedValue )
2113 unsigned char *p = value->bv_val;
2114 struct berval serial;
2115 struct berval issuer_dn;
2116 struct berval asserted_serial;
2117 struct berval asserted_issuer_dn;
2120 xcert = d2i_X509(NULL, &p, value->bv_len);
2123 LDAP_LOG( CONFIG, ENTRY,
2124 "certificateExactMatch: error parsing cert: %s\n",
2125 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2127 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2128 "error parsing cert: %s\n",
2129 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2131 return LDAP_INVALID_SYNTAX;
2134 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2135 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2139 serial_and_issuer_parse(assertedValue,
2140 &asserted_serial, &asserted_issuer_dn);
2145 slap_schema.si_syn_integer,
2146 slap_schema.si_mr_integerMatch,
2149 if ( ret == LDAP_SUCCESS ) {
2150 if ( *matchp == 0 ) {
2151 /* We need to normalize everything for dnMatch */
2155 slap_schema.si_syn_distinguishedName,
2156 slap_schema.si_mr_distinguishedNameMatch,
2158 &asserted_issuer_dn);
2163 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2164 "%d\n\t\"%s $ %s\"\n",
2165 *matchp, serial.bv_val, issuer_dn.bv_val );
2166 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2167 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2170 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2171 "%d\n\t\"%s $ %s\"\n",
2172 *matchp, serial.bv_val, issuer_dn.bv_val );
2173 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2174 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2178 ber_memfree(serial.bv_val);
2179 ber_memfree(issuer_dn.bv_val);
2180 ber_memfree(asserted_serial.bv_val);
2181 ber_memfree(asserted_issuer_dn.bv_val);
2187 * Index generation function
2188 * We just index the serials, in most scenarios the issuer DN is one of
2189 * a very small set of values.
2191 static int certificateExactIndexer(
2196 struct berval *prefix,
2204 struct berval serial;
2206 /* we should have at least one value at this point */
2207 assert( values != NULL && values[0].bv_val != NULL );
2209 for( i=0; values[i].bv_val != NULL; i++ ) {
2210 /* empty -- just count them */
2213 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2215 for( i=0; values[i].bv_val != NULL; i++ ) {
2216 p = values[i].bv_val;
2217 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2220 LDAP_LOG( CONFIG, ENTRY,
2221 "certificateExactIndexer: error parsing cert: %s\n",
2222 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2224 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2225 "error parsing cert: %s\n",
2226 ERR_error_string(ERR_get_error(),NULL),
2229 /* Do we leak keys on error? */
2230 return LDAP_INVALID_SYNTAX;
2233 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2235 xintegerNormalize( slap_schema.si_syn_integer,
2236 &serial, &keys[i] );
2237 ber_memfree(serial.bv_val);
2239 LDAP_LOG( CONFIG, ENTRY,
2240 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2242 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2249 keys[i].bv_val = NULL;
2251 return LDAP_SUCCESS;
2254 /* Index generation function */
2255 /* We think this is always called with a value in matching rule syntax */
2256 static int certificateExactFilter(
2261 struct berval *prefix,
2262 void * assertedValue,
2266 struct berval asserted_serial;
2269 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2270 if( ret != LDAP_SUCCESS ) return ret;
2272 keys = ch_malloc( sizeof( struct berval ) * 2 );
2273 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2274 keys[1].bv_val = NULL;
2277 ber_memfree(asserted_serial.bv_val);
2278 return LDAP_SUCCESS;
2284 check_time_syntax (struct berval *val,
2288 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2289 static int mdays[2][12] = {
2290 /* non-leap years */
2291 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2293 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2296 int part, c, tzoffset, leapyear = 0 ;
2298 if( val->bv_len == 0 ) {
2299 return LDAP_INVALID_SYNTAX;
2302 p = (char *)val->bv_val;
2303 e = p + val->bv_len;
2305 /* Ignore initial whitespace */
2306 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2310 if (e - p < 13 - (2 * start)) {
2311 return LDAP_INVALID_SYNTAX;
2314 for (part = 0; part < 9; part++) {
2318 for (part = start; part < 7; part++) {
2320 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2327 return LDAP_INVALID_SYNTAX;
2329 if (c < 0 || c > 9) {
2330 return LDAP_INVALID_SYNTAX;
2336 return LDAP_INVALID_SYNTAX;
2338 if (c < 0 || c > 9) {
2339 return LDAP_INVALID_SYNTAX;
2344 if (part == 2 || part == 3) {
2347 if (parts[part] < 0) {
2348 return LDAP_INVALID_SYNTAX;
2350 if (parts[part] > ceiling[part]) {
2351 return LDAP_INVALID_SYNTAX;
2355 /* leapyear check for the Gregorian calendar (year>1581) */
2356 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2357 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2362 if (parts[3] > mdays[leapyear][parts[2]]) {
2363 return LDAP_INVALID_SYNTAX;
2368 tzoffset = 0; /* UTC */
2369 } else if (c != '+' && c != '-') {
2370 return LDAP_INVALID_SYNTAX;
2374 } else /* c == '+' */ {
2379 return LDAP_INVALID_SYNTAX;
2382 for (part = 7; part < 9; part++) {
2384 if (c < 0 || c > 9) {
2385 return LDAP_INVALID_SYNTAX;
2390 if (c < 0 || c > 9) {
2391 return LDAP_INVALID_SYNTAX;
2395 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2396 return LDAP_INVALID_SYNTAX;
2401 /* Ignore trailing whitespace */
2402 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2406 return LDAP_INVALID_SYNTAX;
2409 switch ( tzoffset ) {
2410 case -1: /* negativ offset to UTC, ie west of Greenwich */
2411 parts[4] += parts[7];
2412 parts[5] += parts[8];
2413 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2417 c = mdays[leapyear][parts[2]];
2419 if (parts[part] > c) {
2420 parts[part] -= c + 1;
2425 case 1: /* positive offset to UTC, ie east of Greenwich */
2426 parts[4] -= parts[7];
2427 parts[5] -= parts[8];
2428 for (part = 6; --part > 0; ) {
2432 /* first arg to % needs to be non negativ */
2433 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2435 if (parts[part] < 0) {
2436 parts[part] += c + 1;
2441 case 0: /* already UTC */
2445 return LDAP_SUCCESS;
2448 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2453 struct berval *normalized )
2457 rc = check_time_syntax(val, 1, parts);
2458 if (rc != LDAP_SUCCESS) {
2462 normalized->bv_val = ch_malloc( 14 );
2463 if ( normalized->bv_val == NULL ) {
2464 return LBER_ERROR_MEMORY;
2467 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2468 parts[1], parts[2] + 1, parts[3] + 1,
2469 parts[4], parts[5], parts[6] );
2470 normalized->bv_len = 13;
2472 return LDAP_SUCCESS;
2481 return check_time_syntax(in, 1, parts);
2486 generalizedTimeValidate(
2491 return check_time_syntax(in, 0, parts);
2495 generalizedTimeNormalize(
2500 struct berval *normalized,
2505 rc = check_time_syntax(val, 0, parts);
2506 if (rc != LDAP_SUCCESS) {
2510 normalized->bv_val = sl_malloc( 16, ctx );
2511 if ( normalized->bv_val == NULL ) {
2512 return LBER_ERROR_MEMORY;
2515 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2516 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2517 parts[4], parts[5], parts[6] );
2518 normalized->bv_len = 15;
2520 return LDAP_SUCCESS;
2524 nisNetgroupTripleValidate(
2526 struct berval *val )
2531 if ( val->bv_len == 0 ) {
2532 return LDAP_INVALID_SYNTAX;
2535 p = (char *)val->bv_val;
2536 e = p + val->bv_len;
2538 if ( *p != '(' /*')'*/ ) {
2539 return LDAP_INVALID_SYNTAX;
2542 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2546 return LDAP_INVALID_SYNTAX;
2549 } else if ( !AD_CHAR( *p ) ) {
2550 return LDAP_INVALID_SYNTAX;
2554 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2555 return LDAP_INVALID_SYNTAX;
2561 return LDAP_INVALID_SYNTAX;
2564 return LDAP_SUCCESS;
2568 bootParameterValidate(
2570 struct berval *val )
2574 if ( val->bv_len == 0 ) {
2575 return LDAP_INVALID_SYNTAX;
2578 p = (char *)val->bv_val;
2579 e = p + val->bv_len;
2582 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2583 if ( !AD_CHAR( *p ) ) {
2584 return LDAP_INVALID_SYNTAX;
2589 return LDAP_INVALID_SYNTAX;
2593 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2594 if ( !AD_CHAR( *p ) ) {
2595 return LDAP_INVALID_SYNTAX;
2600 return LDAP_INVALID_SYNTAX;
2604 for ( p++; p < e; p++ ) {
2605 if ( !SLAP_PRINTABLE( *p ) ) {
2606 return LDAP_INVALID_SYNTAX;
2610 return LDAP_SUCCESS;
2613 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2614 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2616 static slap_syntax_defs_rec syntax_defs[] = {
2617 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2618 X_BINARY X_NOT_H_R ")",
2619 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2620 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2622 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2624 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2626 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2627 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2629 SLAP_SYNTAX_BER, berValidate, NULL},
2630 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2631 0, bitStringValidate, NULL },
2632 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2633 0, booleanValidate, NULL},
2634 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2635 X_BINARY X_NOT_H_R ")",
2636 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2637 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2638 X_BINARY X_NOT_H_R ")",
2639 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2640 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2641 X_BINARY X_NOT_H_R ")",
2642 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2643 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2644 0, countryStringValidate, NULL},
2645 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2646 0, dnValidate, dnPretty2},
2647 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2649 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2651 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2652 0, UTF8StringValidate, NULL},
2653 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2655 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2657 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2659 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2661 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2663 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2664 0, printablesStringValidate, NULL},
2665 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2666 SLAP_SYNTAX_BLOB, NULL, NULL},
2667 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2668 0, generalizedTimeValidate, NULL},
2669 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2671 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2672 0, IA5StringValidate, NULL},
2673 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2674 0, integerValidate, NULL},
2675 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2676 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2677 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2679 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2681 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2683 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2685 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2687 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2688 0, nameUIDValidate, NULL},
2689 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2691 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2692 0, numericStringValidate, NULL},
2693 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2695 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2696 0, numericoidValidate, NULL},
2697 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2698 0, IA5StringValidate, NULL},
2699 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2700 0, blobValidate, NULL},
2701 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2702 0, UTF8StringValidate, NULL},
2703 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2705 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2707 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2708 0, printableStringValidate, NULL},
2709 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2710 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2711 0, subtreeSpecificationValidate, NULL},
2712 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2713 X_BINARY X_NOT_H_R ")",
2714 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2715 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2716 0, printableStringValidate, NULL},
2717 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2719 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2720 0, printablesStringValidate, NULL},
2721 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2722 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2723 0, utcTimeValidate, NULL},
2725 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2727 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2729 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2731 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2733 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2736 /* RFC 2307 NIS Syntaxes */
2737 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2738 0, nisNetgroupTripleValidate, NULL},
2739 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2740 0, bootParameterValidate, NULL},
2744 /* These OIDs are not published yet, but will be in the next
2745 * I-D for PKIX LDAPv3 schema as have been advanced by David
2746 * Chadwick in private mail.
2748 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2749 0, UTF8StringValidate, NULL},
2752 /* OpenLDAP Experimental Syntaxes */
2753 #ifdef SLAPD_ACI_ENABLED
2754 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2756 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2760 #ifdef SLAPD_AUTHPASSWD
2761 /* needs updating */
2762 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2763 SLAP_SYNTAX_HIDE, NULL, NULL},
2766 /* OpenLDAP Void Syntax */
2767 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2768 SLAP_SYNTAX_HIDE, inValidate, NULL},
2769 {NULL, 0, NULL, NULL}
2773 char *certificateExactMatchSyntaxes[] = {
2774 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2778 char *directoryStringSyntaxes[] = {
2779 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2782 char *integerFirstComponentMatchSyntaxes[] = {
2783 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2784 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2787 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2788 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2789 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2790 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2791 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2792 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2793 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2794 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2795 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2800 * Other matching rules in X.520 that we do not use (yet):
2802 * 2.5.13.9 numericStringOrderingMatch
2803 * 2.5.13.25 uTCTimeMatch
2804 * 2.5.13.26 uTCTimeOrderingMatch
2805 * 2.5.13.31 directoryStringFirstComponentMatch
2806 * 2.5.13.32 wordMatch
2807 * 2.5.13.33 keywordMatch
2808 * 2.5.13.35 certificateMatch
2809 * 2.5.13.36 certificatePairExactMatch
2810 * 2.5.13.37 certificatePairMatch
2811 * 2.5.13.38 certificateListExactMatch
2812 * 2.5.13.39 certificateListMatch
2813 * 2.5.13.40 algorithmIdentifierMatch
2814 * 2.5.13.41 storedPrefixMatch
2815 * 2.5.13.42 attributeCertificateMatch
2816 * 2.5.13.43 readerAndKeyIDMatch
2817 * 2.5.13.44 attributeIntegrityMatch
2819 static slap_mrule_defs_rec mrule_defs[] = {
2821 * EQUALITY matching rules must be listed after associated APPROX
2822 * matching rules. So, we list all APPROX matching rules first.
2824 #ifndef SLAP_NVALUES
2825 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2826 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2827 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2828 NULL, NULL, directoryStringApproxMatch,
2829 directoryStringApproxIndexer, directoryStringApproxFilter,
2832 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2833 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2834 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2835 NULL, NULL, IA5StringApproxMatch,
2836 IA5StringApproxIndexer, IA5StringApproxFilter,
2841 * Other matching rules
2844 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2845 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2846 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2847 NULL, NULL, octetStringMatch,
2848 octetStringIndexer, octetStringFilter,
2851 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2852 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2853 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2854 NULL, dnNormalize, dnMatch,
2855 octetStringIndexer, octetStringFilter,
2858 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2859 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2860 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2861 NULL, UTF8StringNormalize, octetStringMatch,
2862 octetStringIndexer, octetStringFilter,
2863 directoryStringApproxMatchOID },
2865 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2866 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2867 SLAP_MR_ORDERING, directoryStringSyntaxes,
2868 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2870 "caseIgnoreMatch" },
2872 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2873 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2874 SLAP_MR_SUBSTR, NULL,
2875 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2876 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2877 "caseIgnoreMatch" },
2879 {"( 2.5.13.5 NAME 'caseExactMatch' "
2880 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2881 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2882 NULL, UTF8StringNormalize, octetStringMatch,
2883 octetStringIndexer, octetStringFilter,
2884 directoryStringApproxMatchOID },
2886 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2887 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2888 SLAP_MR_ORDERING, directoryStringSyntaxes,
2889 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2893 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2894 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2895 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2896 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2897 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2900 {"( 2.5.13.8 NAME 'numericStringMatch' "
2901 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2902 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2903 NULL, numericStringNormalize, octetStringSubstringsMatch,
2904 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2907 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2908 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2909 SLAP_MR_SUBSTR, NULL,
2910 NULL, numericStringNormalize, octetStringSubstringsMatch,
2911 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2912 "numericStringMatch" },
2914 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2915 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2916 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2917 NULL, NULL, NULL, NULL, NULL, NULL },
2919 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2920 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2921 SLAP_MR_SUBSTR, NULL,
2922 NULL, NULL, NULL, NULL, NULL,
2923 "caseIgnoreListMatch" },
2925 {"( 2.5.13.13 NAME 'booleanMatch' "
2926 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2927 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2928 NULL, NULL, booleanMatch,
2929 octetStringIndexer, octetStringFilter,
2932 {"( 2.5.13.14 NAME 'integerMatch' "
2933 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2934 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2935 NULL, NULL, integerMatch,
2936 octetStringIndexer, octetStringFilter,
2939 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2940 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2941 SLAP_MR_ORDERING, NULL,
2942 NULL, NULL, integerMatch,
2946 {"( 2.5.13.16 NAME 'bitStringMatch' "
2947 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2948 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2949 NULL, NULL, octetStringMatch,
2950 octetStringIndexer, octetStringFilter,
2953 {"( 2.5.13.17 NAME 'octetStringMatch' "
2954 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2955 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2956 NULL, NULL, octetStringMatch,
2957 octetStringIndexer, octetStringFilter,
2960 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2962 SLAP_MR_ORDERING, NULL,
2963 NULL, NULL, octetStringOrderingMatch,
2965 "octetStringMatch" },
2967 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2968 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2969 SLAP_MR_SUBSTR, NULL,
2970 NULL, NULL, octetStringSubstringsMatch,
2971 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2972 "octetStringMatch" },
2974 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2975 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2976 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2978 telephoneNumberNormalize, octetStringMatch,
2979 octetStringIndexer, octetStringFilter,
2982 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2983 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2984 SLAP_MR_SUBSTR, NULL,
2985 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2986 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2987 "telephoneNumberMatch" },
2989 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2990 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2991 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2992 NULL, NULL, NULL, NULL, NULL, NULL },
2994 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2995 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2996 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2997 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3001 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3002 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3003 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3004 NULL, NULL, NULL, NULL, NULL, NULL },
3006 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3008 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3009 NULL, generalizedTimeNormalize, octetStringMatch,
3013 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3015 SLAP_MR_ORDERING, NULL,
3016 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3018 "generalizedTimeMatch" },
3020 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3021 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3022 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3023 integerFirstComponentMatchSyntaxes,
3024 NULL, integerFirstComponentNormalize, integerMatch,
3025 octetStringIndexer, octetStringFilter,
3028 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3029 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3030 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3031 objectIdentifierFirstComponentMatchSyntaxes,
3032 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3033 octetStringIndexer, octetStringFilter,
3036 #ifndef SLAP_NVALUES
3038 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3039 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3040 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3041 certificateExactConvert, NULL, certificateExactMatch,
3042 certificateExactIndexer, certificateExactFilter,
3047 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3049 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3050 NULL, IA5StringNormalize, octetStringMatch,
3051 octetStringIndexer, octetStringFilter,
3052 IA5StringApproxMatchOID },
3054 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3055 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3056 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3057 NULL, IA5StringNormalize, octetStringMatch,
3058 octetStringIndexer, octetStringFilter,
3059 IA5StringApproxMatchOID },
3061 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3062 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3063 SLAP_MR_SUBSTR, NULL,
3064 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3065 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3066 "caseIgnoreIA5Match" },
3068 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3069 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3070 SLAP_MR_SUBSTR, NULL,
3071 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3072 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3073 "caseExactIA5Match" },
3075 #ifdef SLAPD_AUTHPASSWD
3076 /* needs updating */
3077 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3078 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3079 SLAP_MR_EQUALITY, NULL,
3080 NULL, NULL, authPasswordMatch,
3085 #ifdef SLAPD_ACI_ENABLED
3086 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3087 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3088 SLAP_MR_EQUALITY, NULL,
3089 NULL, NULL, OpenLDAPaciMatch,
3094 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3095 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3097 NULL, NULL, integerBitAndMatch,
3101 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3102 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3104 NULL, NULL, integerBitOrMatch,
3108 {NULL, SLAP_MR_NONE, NULL,
3109 NULL, NULL, NULL, NULL, NULL,
3114 slap_schema_init( void )
3119 /* we should only be called once (from main) */
3120 assert( schema_init_done == 0 );
3122 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3123 res = register_syntax( &syntax_defs[i] );
3126 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3127 syntax_defs[i].sd_desc );
3132 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3133 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3134 mrule_defs[i].mrd_compat_syntaxes == NULL )
3137 "slap_schema_init: Ignoring unusable matching rule %s\n",
3138 mrule_defs[i].mrd_desc );
3142 res = register_matching_rule( &mrule_defs[i] );
3146 "slap_schema_init: Error registering matching rule %s\n",
3147 mrule_defs[i].mrd_desc );
3152 res = slap_schema_load();
3153 schema_init_done = 1;
3158 schema_destroy( void )