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 objectIdentifierNormalize NULL
35 #define integerOrderingMatch NULL
36 #define uniqueMemberMatch NULL
37 #define integerFirstComponentNormalize NULL
38 #define objectIdentifierFirstComponentNormalize 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,
130 HASH_CONTEXT HASHcontext;
131 unsigned char HASHdigest[HASH_BYTES];
132 struct berval digest;
133 digest.bv_val = HASHdigest;
134 digest.bv_len = sizeof(HASHdigest);
136 for( i=0; values[i].bv_val != NULL; i++ ) {
137 /* just count them */
140 /* we should have at least one value at this point */
143 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
145 slen = syntax->ssyn_oidlen;
146 mlen = mr->smr_oidlen;
148 for( i=0; values[i].bv_val != NULL; i++ ) {
149 HASH_Init( &HASHcontext );
150 if( prefix != NULL && prefix->bv_len > 0 ) {
151 HASH_Update( &HASHcontext,
152 prefix->bv_val, prefix->bv_len );
154 HASH_Update( &HASHcontext,
155 syntax->ssyn_oid, slen );
156 HASH_Update( &HASHcontext,
158 HASH_Update( &HASHcontext,
159 values[i].bv_val, values[i].bv_len );
160 HASH_Final( HASHdigest, &HASHcontext );
162 ber_dupbv( &keys[i], &digest );
165 keys[i].bv_val = NULL;
173 /* Index generation function */
174 int octetStringFilter(
179 struct berval *prefix,
180 void * assertedValue,
185 HASH_CONTEXT HASHcontext;
186 unsigned char HASHdigest[HASH_BYTES];
187 struct berval *value = (struct berval *) assertedValue;
188 struct berval digest;
189 digest.bv_val = HASHdigest;
190 digest.bv_len = sizeof(HASHdigest);
192 slen = syntax->ssyn_oidlen;
193 mlen = mr->smr_oidlen;
195 keys = ch_malloc( sizeof( struct berval ) * 2 );
197 HASH_Init( &HASHcontext );
198 if( prefix != NULL && prefix->bv_len > 0 ) {
199 HASH_Update( &HASHcontext,
200 prefix->bv_val, prefix->bv_len );
202 HASH_Update( &HASHcontext,
203 syntax->ssyn_oid, slen );
204 HASH_Update( &HASHcontext,
206 HASH_Update( &HASHcontext,
207 value->bv_val, value->bv_len );
208 HASH_Final( HASHdigest, &HASHcontext );
210 ber_dupbv( keys, &digest );
211 keys[1].bv_val = NULL;
220 octetStringSubstringsMatch(
225 struct berval *value,
226 void *assertedValue )
229 SubstringsAssertion *sub = assertedValue;
230 struct berval left = *value;
234 /* Add up asserted input length */
235 if( sub->sa_initial.bv_val ) {
236 inlen += sub->sa_initial.bv_len;
239 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
240 inlen += sub->sa_any[i].bv_len;
243 if( sub->sa_final.bv_val ) {
244 inlen += sub->sa_final.bv_len;
247 if( sub->sa_initial.bv_val ) {
248 if( inlen > left.bv_len ) {
253 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
254 sub->sa_initial.bv_len );
260 left.bv_val += sub->sa_initial.bv_len;
261 left.bv_len -= sub->sa_initial.bv_len;
262 inlen -= sub->sa_initial.bv_len;
265 if( sub->sa_final.bv_val ) {
266 if( inlen > left.bv_len ) {
271 match = memcmp( sub->sa_final.bv_val,
272 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
273 sub->sa_final.bv_len );
279 left.bv_len -= sub->sa_final.bv_len;
280 inlen -= sub->sa_final.bv_len;
284 for(i=0; sub->sa_any[i].bv_val; i++) {
289 if( inlen > left.bv_len ) {
290 /* not enough length */
295 if( sub->sa_any[i].bv_len == 0 ) {
299 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
306 idx = p - left.bv_val;
308 if( idx >= left.bv_len ) {
309 /* this shouldn't happen */
316 if( sub->sa_any[i].bv_len > left.bv_len ) {
317 /* not enough left */
322 match = memcmp( left.bv_val,
323 sub->sa_any[i].bv_val,
324 sub->sa_any[i].bv_len );
332 left.bv_val += sub->sa_any[i].bv_len;
333 left.bv_len -= sub->sa_any[i].bv_len;
334 inlen -= sub->sa_any[i].bv_len;
343 /* Substrings Index generation function */
345 octetStringSubstringsIndexer(
350 struct berval *prefix,
354 ber_len_t i, j, nkeys;
358 HASH_CONTEXT HASHcontext;
359 unsigned char HASHdigest[HASH_BYTES];
360 struct berval digest;
361 digest.bv_val = HASHdigest;
362 digest.bv_len = sizeof(HASHdigest);
366 for( i=0; values[i].bv_val != NULL; i++ ) {
367 /* count number of indices to generate */
368 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
372 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
373 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
374 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
375 (SLAP_INDEX_SUBSTR_MINLEN - 1);
377 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
381 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
382 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
383 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
387 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
388 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
389 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
390 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
392 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
398 /* no keys to generate */
403 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
405 slen = syntax->ssyn_oidlen;
406 mlen = mr->smr_oidlen;
409 for( i=0; values[i].bv_val != NULL; i++ ) {
412 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
414 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
415 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
417 char pre = SLAP_INDEX_SUBSTR_PREFIX;
418 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
420 for( j=0; j<max; j++ ) {
421 HASH_Init( &HASHcontext );
422 if( prefix != NULL && prefix->bv_len > 0 ) {
423 HASH_Update( &HASHcontext,
424 prefix->bv_val, prefix->bv_len );
427 HASH_Update( &HASHcontext,
428 &pre, sizeof( pre ) );
429 HASH_Update( &HASHcontext,
430 syntax->ssyn_oid, slen );
431 HASH_Update( &HASHcontext,
433 HASH_Update( &HASHcontext,
434 &values[i].bv_val[j],
435 SLAP_INDEX_SUBSTR_MAXLEN );
436 HASH_Final( HASHdigest, &HASHcontext );
438 ber_dupbv( &keys[nkeys++], &digest );
442 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
443 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
445 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
448 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
449 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
450 HASH_Init( &HASHcontext );
451 if( prefix != NULL && prefix->bv_len > 0 ) {
452 HASH_Update( &HASHcontext,
453 prefix->bv_val, prefix->bv_len );
455 HASH_Update( &HASHcontext,
456 &pre, sizeof( pre ) );
457 HASH_Update( &HASHcontext,
458 syntax->ssyn_oid, slen );
459 HASH_Update( &HASHcontext,
461 HASH_Update( &HASHcontext,
462 values[i].bv_val, j );
463 HASH_Final( HASHdigest, &HASHcontext );
465 ber_dupbv( &keys[nkeys++], &digest );
468 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
469 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
470 HASH_Init( &HASHcontext );
471 if( prefix != NULL && prefix->bv_len > 0 ) {
472 HASH_Update( &HASHcontext,
473 prefix->bv_val, prefix->bv_len );
475 HASH_Update( &HASHcontext,
476 &pre, sizeof( pre ) );
477 HASH_Update( &HASHcontext,
478 syntax->ssyn_oid, slen );
479 HASH_Update( &HASHcontext,
481 HASH_Update( &HASHcontext,
482 &values[i].bv_val[values[i].bv_len-j], j );
483 HASH_Final( HASHdigest, &HASHcontext );
485 ber_dupbv( &keys[nkeys++], &digest );
493 keys[nkeys].bv_val = NULL;
504 octetStringSubstringsFilter (
509 struct berval *prefix,
510 void * assertedValue,
513 SubstringsAssertion *sa;
517 size_t slen, mlen, klen;
519 HASH_CONTEXT HASHcontext;
520 unsigned char HASHdigest[HASH_BYTES];
521 struct berval *value;
522 struct berval digest;
524 sa = (SubstringsAssertion *) assertedValue;
526 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
527 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
532 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
534 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
535 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
536 /* don't bother accounting for stepping */
537 nkeys += sa->sa_any[i].bv_len -
538 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
543 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
544 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
554 digest.bv_val = HASHdigest;
555 digest.bv_len = sizeof(HASHdigest);
557 slen = syntax->ssyn_oidlen;
558 mlen = mr->smr_oidlen;
560 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
563 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
564 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
566 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
567 value = &sa->sa_initial;
569 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
570 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
572 HASH_Init( &HASHcontext );
573 if( prefix != NULL && prefix->bv_len > 0 ) {
574 HASH_Update( &HASHcontext,
575 prefix->bv_val, prefix->bv_len );
577 HASH_Update( &HASHcontext,
578 &pre, sizeof( pre ) );
579 HASH_Update( &HASHcontext,
580 syntax->ssyn_oid, slen );
581 HASH_Update( &HASHcontext,
583 HASH_Update( &HASHcontext,
584 value->bv_val, klen );
585 HASH_Final( HASHdigest, &HASHcontext );
587 ber_dupbv( &keys[nkeys++], &digest );
590 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
592 pre = SLAP_INDEX_SUBSTR_PREFIX;
593 klen = SLAP_INDEX_SUBSTR_MAXLEN;
595 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
596 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
600 value = &sa->sa_any[i];
603 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
604 j += SLAP_INDEX_SUBSTR_STEP )
606 HASH_Init( &HASHcontext );
607 if( prefix != NULL && prefix->bv_len > 0 ) {
608 HASH_Update( &HASHcontext,
609 prefix->bv_val, prefix->bv_len );
611 HASH_Update( &HASHcontext,
612 &pre, sizeof( pre ) );
613 HASH_Update( &HASHcontext,
614 syntax->ssyn_oid, slen );
615 HASH_Update( &HASHcontext,
617 HASH_Update( &HASHcontext,
618 &value->bv_val[j], klen );
619 HASH_Final( HASHdigest, &HASHcontext );
621 ber_dupbv( &keys[nkeys++], &digest );
626 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
627 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
629 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
630 value = &sa->sa_final;
632 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
633 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
635 HASH_Init( &HASHcontext );
636 if( prefix != NULL && prefix->bv_len > 0 ) {
637 HASH_Update( &HASHcontext,
638 prefix->bv_val, prefix->bv_len );
640 HASH_Update( &HASHcontext,
641 &pre, sizeof( pre ) );
642 HASH_Update( &HASHcontext,
643 syntax->ssyn_oid, slen );
644 HASH_Update( &HASHcontext,
646 HASH_Update( &HASHcontext,
647 &value->bv_val[value->bv_len-klen], klen );
648 HASH_Final( HASHdigest, &HASHcontext );
650 ber_dupbv( &keys[nkeys++], &digest );
654 keys[nkeys].bv_val = NULL;
671 /* very unforgiving validation, requires no normalization
672 * before simplistic matching
674 if( in->bv_len < 3 ) {
675 return LDAP_INVALID_SYNTAX;
679 * RFC 2252 section 6.3 Bit String
680 * bitstring = "'" *binary-digit "'B"
681 * binary-digit = "0" / "1"
682 * example: '0101111101'B
685 if( in->bv_val[0] != '\'' ||
686 in->bv_val[in->bv_len-2] != '\'' ||
687 in->bv_val[in->bv_len-1] != 'B' )
689 return LDAP_INVALID_SYNTAX;
692 for( i=in->bv_len-3; i>0; i-- ) {
693 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
694 return LDAP_INVALID_SYNTAX;
709 if( in->bv_len == 0 ) return LDAP_SUCCESS;
711 ber_dupbv( &dn, in );
712 if( !dn.bv_val ) return LDAP_OTHER;
714 if( dn.bv_val[dn.bv_len-1] == 'B'
715 && dn.bv_val[dn.bv_len-2] == '\'' )
717 /* assume presence of optional UID */
720 for(i=dn.bv_len-3; i>1; i--) {
721 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
725 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
726 ber_memfree( dn.bv_val );
727 return LDAP_INVALID_SYNTAX;
730 /* trim the UID to allow use of dnValidate */
731 dn.bv_val[i-1] = '\0';
735 rc = dnValidate( NULL, &dn );
737 ber_memfree( dn.bv_val );
742 uniqueMemberNormalize(
747 struct berval *normalized )
752 ber_dupbv( &out, val );
753 if( out.bv_len != 0 ) {
754 struct berval uid = { 0, NULL };
756 if( out.bv_val[out.bv_len-1] == 'B'
757 && out.bv_val[out.bv_len-2] == '\'' )
759 /* assume presence of optional UID */
760 uid.bv_val = strrchr( out.bv_val, '#' );
762 if( uid.bv_val == NULL ) {
764 return LDAP_INVALID_SYNTAX;
767 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
768 out.bv_len -= uid.bv_len--;
770 /* temporarily trim the UID */
771 *(uid.bv_val++) = '\0';
774 rc = dnNormalize2( NULL, &out, normalized );
776 if( rc != LDAP_SUCCESS ) {
778 return LDAP_INVALID_SYNTAX;
782 normalized->bv_val = ch_realloc( normalized->bv_val,
783 normalized->bv_len + uid.bv_len + sizeof("#") );
785 /* insert the separator */
786 normalized->bv_val[normalized->bv_len++] = '#';
789 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
790 uid.bv_val, uid.bv_len );
791 normalized->bv_len += uid.bv_len;
794 normalized->bv_val[normalized->bv_len] = '\0';
804 * Handling boolean syntax and matching is quite rigid.
805 * A more flexible approach would be to allow a variety
806 * of strings to be normalized and prettied into TRUE
814 /* very unforgiving validation, requires no normalization
815 * before simplistic matching
818 if( in->bv_len == 4 ) {
819 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
822 } else if( in->bv_len == 5 ) {
823 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
828 return LDAP_INVALID_SYNTAX;
837 struct berval *value,
838 void *assertedValue )
840 /* simplistic matching allowed by rigid validation */
841 struct berval *asserted = (struct berval *) assertedValue;
842 *matchp = value->bv_len != asserted->bv_len;
846 /*-------------------------------------------------------------------
847 LDAP/X.500 string syntax / matching rules have a few oddities. This
848 comment attempts to detail how slapd(8) treats them.
851 StringSyntax X.500 LDAP Matching/Comments
852 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
853 PrintableString subset subset i/e + ignore insignificant spaces
854 PrintableString subset subset i/e + ignore insignificant spaces
855 NumericString subset subset ignore all spaces
856 IA5String ASCII ASCII i/e + ignore insignificant spaces
857 TeletexString T.61 T.61 i/e + ignore insignificant spaces
859 TelephoneNumber subset subset i + ignore all spaces and "-"
861 See draft-ietf-ldapbis-strpro for details (once published).
865 In X.500(93), a directory string can be either a PrintableString,
866 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
867 In later versions, more CHOICEs were added. In all cases the string
870 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
871 A directory string cannot be zero length.
873 For matching, there are both case ignore and exact rules. Both
874 also require that "insignificant" spaces be ignored.
875 spaces before the first non-space are ignored;
876 spaces after the last non-space are ignored;
877 spaces after a space are ignored.
878 Note: by these rules (and as clarified in X.520), a string of only
879 spaces is to be treated as if held one space, not empty (which
880 would be a syntax error).
883 In ASN.1, numeric string is just a string of digits and spaces
884 and could be empty. However, in X.500, all attribute values of
885 numeric string carry a non-empty constraint. For example:
887 internationalISDNNumber ATTRIBUTE ::= {
888 WITH SYNTAX InternationalISDNNumber
889 EQUALITY MATCHING RULE numericStringMatch
890 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
891 ID id-at-internationalISDNNumber }
892 InternationalISDNNumber ::=
893 NumericString (SIZE(1..ub-international-isdn-number))
895 Unforunately, some assertion values are don't carry the same
896 constraint (but its unclear how such an assertion could ever
897 be true). In LDAP, there is one syntax (numericString) not two
898 (numericString with constraint, numericString without constraint).
899 This should be treated as numericString with non-empty constraint.
900 Note that while someone may have no ISDN number, there are no ISDN
901 numbers which are zero length.
903 In matching, spaces are ignored.
906 In ASN.1, Printable string is just a string of printable characters
907 and can be empty. In X.500, semantics much like NumericString (see
908 serialNumber for a like example) excepting uses insignificant space
909 handling instead of ignore all spaces.
912 Basically same as PrintableString. There are no examples in X.500,
913 but same logic applies. So we require them to be non-empty as
916 -------------------------------------------------------------------*/
925 unsigned char *u = in->bv_val;
927 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
928 /* directory strings cannot be empty */
929 return LDAP_INVALID_SYNTAX;
932 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
933 /* get the length indicated by the first byte */
934 len = LDAP_UTF8_CHARLEN2( u, len );
936 /* very basic checks */
939 if( (u[5] & 0xC0) != 0x80 ) {
940 return LDAP_INVALID_SYNTAX;
943 if( (u[4] & 0xC0) != 0x80 ) {
944 return LDAP_INVALID_SYNTAX;
947 if( (u[3] & 0xC0) != 0x80 ) {
948 return LDAP_INVALID_SYNTAX;
951 if( (u[2] & 0xC0 )!= 0x80 ) {
952 return LDAP_INVALID_SYNTAX;
955 if( (u[1] & 0xC0) != 0x80 ) {
956 return LDAP_INVALID_SYNTAX;
959 /* CHARLEN already validated it */
962 return LDAP_INVALID_SYNTAX;
965 /* make sure len corresponds with the offset
966 to the next character */
967 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
971 return LDAP_INVALID_SYNTAX;
983 struct berval *normalized )
985 struct berval tmp, nvalue;
989 if( val->bv_val == NULL ) {
990 /* assume we're dealing with a syntax (e.g., UTF8String)
991 * which allows empty strings
993 normalized->bv_len = 0;
994 normalized->bv_val = NULL;
998 flags = (mr == slap_schema.si_mr_caseExactMatch)
999 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1000 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1001 ? LDAP_UTF8_APPROX : 0;
1003 val = UTF8bvnormalize( val, &tmp, flags );
1008 /* collapse spaces (in place) */
1010 nvalue.bv_val = tmp.bv_val;
1012 wasspace=1; /* trim leading spaces */
1013 for( i=0; i<tmp.bv_len; i++) {
1014 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1015 if( wasspace++ == 0 ) {
1016 /* trim repeated spaces */
1017 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1021 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1025 if( nvalue.bv_len ) {
1027 /* last character was a space, trim it */
1030 nvalue.bv_val[nvalue.bv_len] = '\0';
1033 /* string of all spaces is treated as one space */
1034 nvalue.bv_val[0] = ' ';
1035 nvalue.bv_val[1] = '\0';
1039 *normalized = nvalue;
1040 return LDAP_SUCCESS;
1043 #ifndef SLAP_NVALUES
1045 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1046 #if defined(SLAPD_APPROX_INITIALS)
1047 #define SLAPD_APPROX_DELIMITER "._ "
1048 #define SLAPD_APPROX_WORDLEN 2
1050 #define SLAPD_APPROX_DELIMITER " "
1051 #define SLAPD_APPROX_WORDLEN 1
1060 struct berval *value,
1061 void *assertedValue )
1063 struct berval *nval, *assertv;
1064 char *val, **values, **words, *c;
1065 int i, count, len, nextchunk=0, nextavail=0;
1067 /* Yes, this is necessary */
1068 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1069 if( nval == NULL ) {
1071 return LDAP_SUCCESS;
1074 /* Yes, this is necessary */
1075 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1076 NULL, LDAP_UTF8_APPROX );
1077 if( assertv == NULL ) {
1080 return LDAP_SUCCESS;
1083 /* Isolate how many words there are */
1084 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1085 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1086 if ( c == NULL ) break;
1091 /* Get a phonetic copy of each word */
1092 words = (char **)ch_malloc( count * sizeof(char *) );
1093 values = (char **)ch_malloc( count * sizeof(char *) );
1094 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1096 values[i] = phonetic(c);
1099 /* Work through the asserted value's words, to see if at least some
1100 of the words are there, in the same order. */
1102 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1103 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1108 #if defined(SLAPD_APPROX_INITIALS)
1109 else if( len == 1 ) {
1110 /* Single letter words need to at least match one word's initial */
1111 for( i=nextavail; i<count; i++ )
1112 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1119 /* Isolate the next word in the asserted value and phonetic it */
1120 assertv->bv_val[nextchunk+len] = '\0';
1121 val = phonetic( assertv->bv_val + nextchunk );
1123 /* See if this phonetic chunk is in the remaining words of *value */
1124 for( i=nextavail; i<count; i++ ){
1125 if( !strcmp( val, values[i] ) ){
1133 /* This chunk in the asserted value was NOT within the *value. */
1139 /* Go on to the next word in the asserted value */
1143 /* If some of the words were seen, call it a match */
1144 if( nextavail > 0 ) {
1151 /* Cleanup allocs */
1152 ber_bvfree( assertv );
1153 for( i=0; i<count; i++ ) {
1154 ch_free( values[i] );
1160 return LDAP_SUCCESS;
1169 struct berval *prefix,
1174 int i,j, len, wordcount, keycount=0;
1175 struct berval *newkeys;
1176 BerVarray keys=NULL;
1178 for( j=0; values[j].bv_val != NULL; j++ ) {
1179 struct berval val = { 0, NULL };
1180 /* Yes, this is necessary */
1181 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1182 assert( val.bv_val != NULL );
1184 /* Isolate how many words there are. There will be a key for each */
1185 for( wordcount = 0, c = val.bv_val; *c; c++) {
1186 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1187 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1189 if (*c == '\0') break;
1193 /* Allocate/increase storage to account for new keys */
1194 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1195 * sizeof(struct berval) );
1196 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1197 if( keys ) ch_free( keys );
1200 /* Get a phonetic copy of each word */
1201 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1203 if( len < SLAPD_APPROX_WORDLEN ) continue;
1204 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1209 ber_memfree( val.bv_val );
1211 keys[keycount].bv_val = NULL;
1214 return LDAP_SUCCESS;
1223 struct berval *prefix,
1224 void * assertedValue,
1232 /* Yes, this is necessary */
1233 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1234 NULL, LDAP_UTF8_APPROX );
1235 if( val == NULL || val->bv_val == NULL ) {
1236 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1237 keys[0].bv_val = NULL;
1240 return LDAP_SUCCESS;
1243 /* Isolate how many words there are. There will be a key for each */
1244 for( count = 0,c = val->bv_val; *c; c++) {
1245 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1246 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1248 if (*c == '\0') break;
1252 /* Allocate storage for new keys */
1253 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1255 /* Get a phonetic copy of each word */
1256 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1258 if( len < SLAPD_APPROX_WORDLEN ) continue;
1259 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1265 keys[count].bv_val = NULL;
1268 return LDAP_SUCCESS;
1272 /* No other form of Approximate Matching is defined */
1280 struct berval *value,
1281 void *assertedValue )
1283 char *vapprox, *avapprox;
1286 /* Yes, this is necessary */
1287 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1290 return LDAP_SUCCESS;
1293 /* Yes, this is necessary */
1294 t = UTF8normalize( ((struct berval *)assertedValue),
1299 return LDAP_SUCCESS;
1302 vapprox = phonetic( strip8bitChars( s ) );
1303 avapprox = phonetic( strip8bitChars( t ) );
1308 *matchp = strcmp( vapprox, avapprox );
1311 ch_free( avapprox );
1313 return LDAP_SUCCESS;
1322 struct berval *prefix,
1330 for( i=0; values[i].bv_val != NULL; i++ ) {
1331 /* empty - just count them */
1334 /* we should have at least one value at this point */
1337 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1339 /* Copy each value and run it through phonetic() */
1340 for( i=0; values[i].bv_val != NULL; i++ ) {
1341 /* Yes, this is necessary */
1342 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1344 /* strip 8-bit chars and run through phonetic() */
1345 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1348 keys[i].bv_val = NULL;
1351 return LDAP_SUCCESS;
1360 struct berval *prefix,
1361 void * assertedValue,
1367 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1369 /* Yes, this is necessary */
1370 s = UTF8normalize( ((struct berval *)assertedValue),
1375 /* strip 8-bit chars and run through phonetic() */
1376 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1382 return LDAP_SUCCESS;
1385 #endif /* !SLAP_NVALUES */
1387 /* Remove all spaces and '-' characters */
1389 telephoneNumberNormalize(
1394 struct berval *normalized )
1398 /* validator should have refused an empty string */
1399 assert( val->bv_len );
1401 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1403 for( p = val->bv_val; *p; p++ ) {
1404 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1410 normalized->bv_len = q - normalized->bv_val;
1412 if( normalized->bv_len == 0 ) {
1413 free( normalized->bv_val );
1414 return LDAP_INVALID_SYNTAX;
1417 return LDAP_SUCCESS;
1423 struct berval *val )
1427 if( val->bv_len == 0 ) {
1428 /* disallow empty strings */
1429 return LDAP_INVALID_SYNTAX;
1432 if( OID_LEADCHAR(val->bv_val[0]) ) {
1434 for(i=1; i < val->bv_len; i++) {
1435 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1436 if( dot++ ) return 1;
1437 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1440 return LDAP_INVALID_SYNTAX;
1444 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1446 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1447 for(i=1; i < val->bv_len; i++) {
1448 if( !DESC_CHAR(val->bv_val[i] ) ) {
1449 return LDAP_INVALID_SYNTAX;
1453 return LDAP_SUCCESS;
1456 return LDAP_INVALID_SYNTAX;
1465 struct berval *value,
1466 void *assertedValue )
1469 int vsign = 1, avsign = 1; /* default sign = '+' */
1470 struct berval *asserted;
1471 ber_len_t vlen, avlen;
1474 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1476 vlen = value->bv_len;
1478 #ifndef SLAP_NVALUES
1479 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1480 char *tmp = memchr( v, '$', vlen );
1481 if( tmp ) vlen = tmp - v;
1482 while( vlen && ASCII_SPACE( v[vlen-1] )) vlen--;
1486 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) { /* ANSI 2.2.1 */
1487 if( *v == '-' ) vsign = -1;
1490 if( vlen == 0 ) vsign = 0;
1492 /* Do the same with the *assertedValue number */
1493 asserted = (struct berval *) assertedValue;
1494 av = asserted->bv_val;
1495 avlen = asserted->bv_len;
1496 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1502 match = vsign - avsign;
1504 match = (vlen != avlen
1505 ? ( vlen < avlen ? -1 : 1 )
1506 : memcmp( v, av, vlen ));
1507 if( vsign < 0 ) match = -match;
1511 return LDAP_SUCCESS;
1517 struct berval *val )
1521 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1523 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1524 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1526 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1527 return LDAP_INVALID_SYNTAX;
1530 for( i=1; i < val->bv_len; i++ ) {
1531 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1534 return LDAP_SUCCESS;
1543 struct berval *normalized )
1552 /* Ignore leading spaces */
1553 while ( len && ( *p == ' ' )) {
1560 negative = ( *p == '-' );
1561 if(( *p == '-' ) || ( *p == '+' )) {
1567 /* Ignore leading zeros */
1568 while ( len && ( *p == '0' )) {
1573 /* If there are no non-zero digits left, the number is zero, otherwise
1574 allocate space for the number and copy it into the buffer */
1576 normalized->bv_val = ch_strdup("0");
1577 normalized->bv_len = 1;
1580 normalized->bv_len = len+negative;
1581 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1582 if( negative ) normalized->bv_val[0] = '-';
1583 AC_MEMCPY( normalized->bv_val + negative, p, len );
1584 normalized->bv_val[len+negative] = '\0';
1587 return LDAP_SUCCESS;
1591 countryStringValidate(
1593 struct berval *val )
1595 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1597 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1598 return LDAP_INVALID_SYNTAX;
1600 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1601 return LDAP_INVALID_SYNTAX;
1604 return LDAP_SUCCESS;
1608 printableStringValidate(
1610 struct berval *val )
1614 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1616 for(i=0; i < val->bv_len; i++) {
1617 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1618 return LDAP_INVALID_SYNTAX;
1622 return LDAP_SUCCESS;
1626 printablesStringValidate(
1628 struct berval *val )
1632 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1634 for(i=0,len=0; i < val->bv_len; i++) {
1635 int c = val->bv_val[i];
1639 return LDAP_INVALID_SYNTAX;
1643 } else if ( SLAP_PRINTABLE(c) ) {
1646 return LDAP_INVALID_SYNTAX;
1651 return LDAP_INVALID_SYNTAX;
1654 return LDAP_SUCCESS;
1660 struct berval *val )
1664 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1666 for(i=0; i < val->bv_len; i++) {
1667 if( !LDAP_ASCII(val->bv_val[i]) ) {
1668 return LDAP_INVALID_SYNTAX;
1672 return LDAP_SUCCESS;
1681 struct berval *normalized )
1684 int casefold = (mr != slap_schema.si_mr_caseExactIA5Match);
1686 assert( val->bv_len );
1690 /* Ignore initial whitespace */
1691 while ( ASCII_SPACE( *p ) ) {
1695 normalized->bv_val = ch_strdup( p );
1696 p = q = normalized->bv_val;
1699 if ( ASCII_SPACE( *p ) ) {
1702 /* Ignore the extra whitespace */
1703 while ( ASCII_SPACE( *p ) ) {
1707 } else if ( casefold ) {
1708 /* Most IA5 rules require casefolding */
1709 *q++ = TOLOWER(*p++);
1716 assert( normalized->bv_val <= p );
1720 * If the string ended in space, backup the pointer one
1721 * position. One is enough because the above loop collapsed
1722 * all whitespace to a single space.
1725 if ( ASCII_SPACE( q[-1] ) ) {
1729 /* null terminate */
1732 normalized->bv_len = q - normalized->bv_val;
1734 if( normalized->bv_len == 0 ) {
1735 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1736 normalized->bv_val[0] = ' ';
1737 normalized->bv_val[1] = '\0';
1738 normalized->bv_len = 1;
1741 return LDAP_SUCCESS;
1745 numericStringValidate(
1751 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1753 for(i=0; i < in->bv_len; i++) {
1754 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1755 return LDAP_INVALID_SYNTAX;
1759 return LDAP_SUCCESS;
1763 numericStringNormalize(
1768 struct berval *normalized )
1770 /* removal all spaces */
1773 assert( val->bv_len );
1775 normalized->bv_val = ch_malloc( val->bv_len + 1 );
1778 q = normalized->bv_val;
1781 if ( ASCII_SPACE( *p ) ) {
1782 /* Ignore whitespace */
1789 /* we should have copied no more then is in val */
1790 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1792 /* null terminate */
1795 normalized->bv_len = q - normalized->bv_val;
1797 if( normalized->bv_len == 0 ) {
1798 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1799 normalized->bv_val[0] = ' ';
1800 normalized->bv_val[1] = '\0';
1801 normalized->bv_len = 1;
1804 return LDAP_SUCCESS;
1807 #ifndef SLAP_NVALUES
1809 objectIdentifierFirstComponentMatch(
1814 struct berval *value,
1815 void *assertedValue )
1817 int rc = LDAP_SUCCESS;
1819 struct berval *asserted = (struct berval *) assertedValue;
1823 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1824 return LDAP_INVALID_SYNTAX;
1827 /* trim leading white space */
1828 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1832 /* grab next word */
1833 oid.bv_val = &value->bv_val[i];
1834 j = value->bv_len - i;
1835 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1840 /* insert attributeTypes, objectclass check here */
1841 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1842 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1845 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1846 MatchingRule *asserted_mr = mr_bvfind( asserted );
1847 MatchingRule *stored_mr = mr_bvfind( &oid );
1849 if( asserted_mr == NULL ) {
1850 rc = SLAPD_COMPARE_UNDEFINED;
1852 match = asserted_mr != stored_mr;
1855 } else if ( !strcmp( syntax->ssyn_oid,
1856 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1858 AttributeType *asserted_at = at_bvfind( asserted );
1859 AttributeType *stored_at = at_bvfind( &oid );
1861 if( asserted_at == NULL ) {
1862 rc = SLAPD_COMPARE_UNDEFINED;
1864 match = asserted_at != stored_at;
1867 } else if ( !strcmp( syntax->ssyn_oid,
1868 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1870 ObjectClass *asserted_oc = oc_bvfind( asserted );
1871 ObjectClass *stored_oc = oc_bvfind( &oid );
1873 if( asserted_oc == NULL ) {
1874 rc = SLAPD_COMPARE_UNDEFINED;
1876 match = asserted_oc != stored_oc;
1882 LDAP_LOG( CONFIG, ENTRY,
1883 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1884 match, value->bv_val, asserted->bv_val );
1886 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1887 "%d\n\t\"%s\"\n\t\"%s\"\n",
1888 match, value->bv_val, asserted->bv_val );
1891 if( rc == LDAP_SUCCESS ) *matchp = match;
1902 struct berval *value,
1903 void *assertedValue )
1905 long lValue, lAssertedValue;
1907 /* safe to assume integers are NUL terminated? */
1908 lValue = strtol(value->bv_val, NULL, 10);
1909 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1910 return LDAP_CONSTRAINT_VIOLATION;
1913 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1914 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1915 && errno == ERANGE )
1917 return LDAP_CONSTRAINT_VIOLATION;
1920 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1921 return LDAP_SUCCESS;
1930 struct berval *value,
1931 void *assertedValue )
1933 long lValue, lAssertedValue;
1935 /* safe to assume integers are NUL terminated? */
1936 lValue = strtol(value->bv_val, NULL, 10);
1937 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1938 return LDAP_CONSTRAINT_VIOLATION;
1941 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1942 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1943 && errno == ERANGE )
1945 return LDAP_CONSTRAINT_VIOLATION;
1948 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1949 return LDAP_SUCCESS;
1952 #ifndef SLAP_NVALUES
1954 #include <openssl/x509.h>
1955 #include <openssl/err.h>
1958 * Next function returns a string representation of a ASN1_INTEGER.
1959 * It works for unlimited lengths.
1962 static struct berval *
1963 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1967 static char digit[] = "0123456789";
1969 /* We work backwards, make it fill from the end of buf */
1970 p = buf + sizeof(buf) - 1;
1973 if ( a == NULL || a->length == 0 ) {
1981 /* We want to preserve the original */
1982 copy = ch_malloc(n*sizeof(unsigned int));
1983 for (i = 0; i<n; i++) {
1984 copy[i] = a->data[i];
1988 * base indicates the index of the most significant
1989 * byte that might be nonzero. When it goes off the
1990 * end, we now there is nothing left to do.
1996 for (i = base; i<n; i++ ) {
1997 copy[i] += carry*256;
1998 carry = copy[i] % 10;
2003 * Way too large, we need to leave
2004 * room for sign if negative
2009 *--p = digit[carry];
2011 if (copy[base] == 0) base++;
2016 if ( a->type == V_ASN1_NEG_INTEGER ) {
2020 return ber_str2bv( p, 0, 1, bv );
2024 * Given a certificate in DER format, extract the corresponding
2025 * assertion value for certificateExactMatch
2028 certificateExactConvert(
2030 struct berval * out )
2033 unsigned char *p = in->bv_val;
2034 struct berval serial;
2035 struct berval issuer_dn;
2037 xcert = d2i_X509(NULL, &p, in->bv_len);
2040 LDAP_LOG( CONFIG, ENTRY,
2041 "certificateExactConvert: error parsing cert: %s\n",
2042 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2044 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2045 "error parsing cert: %s\n",
2046 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2048 return LDAP_INVALID_SYNTAX;
2051 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2053 return LDAP_INVALID_SYNTAX;
2055 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2059 ber_memfree(serial.bv_val);
2060 return LDAP_INVALID_SYNTAX;
2065 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2066 out->bv_val = ch_malloc(out->bv_len);
2068 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2070 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2072 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2073 p += issuer_dn.bv_len;
2077 LDAP_LOG( CONFIG, ARGS,
2078 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2080 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2082 out->bv_val, NULL, NULL );
2085 ber_memfree(serial.bv_val);
2086 ber_memfree(issuer_dn.bv_val);
2088 return LDAP_SUCCESS;
2092 serial_and_issuer_parse(
2093 struct berval *assertion,
2094 struct berval *serial,
2095 struct berval *issuer_dn )
2102 begin = assertion->bv_val;
2103 end = assertion->bv_val+assertion->bv_len-1;
2104 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2105 if ( p > end ) return LDAP_INVALID_SYNTAX;
2107 /* p now points at the $ sign, now use
2108 * begin and end to delimit the serial number
2110 while (ASCII_SPACE(*begin)) begin++;
2112 while (ASCII_SPACE(*end)) end--;
2114 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2116 bv.bv_len = end-begin+1;
2118 ber_dupbv(serial, &bv);
2120 /* now extract the issuer, remember p was at the dollar sign */
2122 end = assertion->bv_val+assertion->bv_len-1;
2123 while (ASCII_SPACE(*begin)) begin++;
2124 /* should we trim spaces at the end too? is it safe always? no, no */
2126 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2129 bv.bv_len = end-begin+1;
2132 dnNormalize2( NULL, &bv, issuer_dn );
2135 return LDAP_SUCCESS;
2139 certificateExactMatch(
2144 struct berval *value,
2145 void *assertedValue )
2148 unsigned char *p = value->bv_val;
2149 struct berval serial;
2150 struct berval issuer_dn;
2151 struct berval asserted_serial;
2152 struct berval asserted_issuer_dn;
2155 xcert = d2i_X509(NULL, &p, value->bv_len);
2158 LDAP_LOG( CONFIG, ENTRY,
2159 "certificateExactMatch: error parsing cert: %s\n",
2160 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2162 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2163 "error parsing cert: %s\n",
2164 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2166 return LDAP_INVALID_SYNTAX;
2169 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2170 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2174 serial_and_issuer_parse(assertedValue,
2175 &asserted_serial, &asserted_issuer_dn);
2180 slap_schema.si_syn_integer,
2181 slap_schema.si_mr_integerMatch,
2184 if ( ret == LDAP_SUCCESS ) {
2185 if ( *matchp == 0 ) {
2186 /* We need to normalize everything for dnMatch */
2190 slap_schema.si_syn_distinguishedName,
2191 slap_schema.si_mr_distinguishedNameMatch,
2193 &asserted_issuer_dn);
2198 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2199 "%d\n\t\"%s $ %s\"\n",
2200 *matchp, serial.bv_val, issuer_dn.bv_val );
2201 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2202 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2205 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2206 "%d\n\t\"%s $ %s\"\n",
2207 *matchp, serial.bv_val, issuer_dn.bv_val );
2208 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2209 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2213 ber_memfree(serial.bv_val);
2214 ber_memfree(issuer_dn.bv_val);
2215 ber_memfree(asserted_serial.bv_val);
2216 ber_memfree(asserted_issuer_dn.bv_val);
2222 * Index generation function
2223 * We just index the serials, in most scenarios the issuer DN is one of
2224 * a very small set of values.
2226 static int certificateExactIndexer(
2231 struct berval *prefix,
2239 struct berval serial;
2241 /* we should have at least one value at this point */
2242 assert( values != NULL && values[0].bv_val != NULL );
2244 for( i=0; values[i].bv_val != NULL; i++ ) {
2245 /* empty -- just count them */
2248 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2250 for( i=0; values[i].bv_val != NULL; i++ ) {
2251 p = values[i].bv_val;
2252 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2255 LDAP_LOG( CONFIG, ENTRY,
2256 "certificateExactIndexer: error parsing cert: %s\n",
2257 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2259 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2260 "error parsing cert: %s\n",
2261 ERR_error_string(ERR_get_error(),NULL),
2264 /* Do we leak keys on error? */
2265 return LDAP_INVALID_SYNTAX;
2268 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2270 xintegerNormalize( slap_schema.si_syn_integer,
2271 &serial, &keys[i] );
2272 ber_memfree(serial.bv_val);
2274 LDAP_LOG( CONFIG, ENTRY,
2275 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2277 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2284 keys[i].bv_val = NULL;
2286 return LDAP_SUCCESS;
2289 /* Index generation function */
2290 /* We think this is always called with a value in matching rule syntax */
2291 static int certificateExactFilter(
2296 struct berval *prefix,
2297 void * assertedValue,
2301 struct berval asserted_serial;
2304 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2305 if( ret != LDAP_SUCCESS ) return ret;
2307 keys = ch_malloc( sizeof( struct berval ) * 2 );
2308 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2309 keys[1].bv_val = NULL;
2312 ber_memfree(asserted_serial.bv_val);
2313 return LDAP_SUCCESS;
2319 check_time_syntax (struct berval *val,
2323 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2324 static int mdays[2][12] = {
2325 /* non-leap years */
2326 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2328 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2331 int part, c, tzoffset, leapyear = 0 ;
2333 if( val->bv_len == 0 ) {
2334 return LDAP_INVALID_SYNTAX;
2337 p = (char *)val->bv_val;
2338 e = p + val->bv_len;
2340 /* Ignore initial whitespace */
2341 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2345 if (e - p < 13 - (2 * start)) {
2346 return LDAP_INVALID_SYNTAX;
2349 for (part = 0; part < 9; part++) {
2353 for (part = start; part < 7; part++) {
2355 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2362 return LDAP_INVALID_SYNTAX;
2364 if (c < 0 || c > 9) {
2365 return LDAP_INVALID_SYNTAX;
2371 return LDAP_INVALID_SYNTAX;
2373 if (c < 0 || c > 9) {
2374 return LDAP_INVALID_SYNTAX;
2379 if (part == 2 || part == 3) {
2382 if (parts[part] < 0) {
2383 return LDAP_INVALID_SYNTAX;
2385 if (parts[part] > ceiling[part]) {
2386 return LDAP_INVALID_SYNTAX;
2390 /* leapyear check for the Gregorian calendar (year>1581) */
2391 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2392 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2397 if (parts[3] > mdays[leapyear][parts[2]]) {
2398 return LDAP_INVALID_SYNTAX;
2403 tzoffset = 0; /* UTC */
2404 } else if (c != '+' && c != '-') {
2405 return LDAP_INVALID_SYNTAX;
2409 } else /* c == '+' */ {
2414 return LDAP_INVALID_SYNTAX;
2417 for (part = 7; part < 9; part++) {
2419 if (c < 0 || c > 9) {
2420 return LDAP_INVALID_SYNTAX;
2425 if (c < 0 || c > 9) {
2426 return LDAP_INVALID_SYNTAX;
2430 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2431 return LDAP_INVALID_SYNTAX;
2436 /* Ignore trailing whitespace */
2437 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2441 return LDAP_INVALID_SYNTAX;
2444 switch ( tzoffset ) {
2445 case -1: /* negativ offset to UTC, ie west of Greenwich */
2446 parts[4] += parts[7];
2447 parts[5] += parts[8];
2448 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2452 c = mdays[leapyear][parts[2]];
2454 if (parts[part] > c) {
2455 parts[part] -= c + 1;
2460 case 1: /* positive offset to UTC, ie east of Greenwich */
2461 parts[4] -= parts[7];
2462 parts[5] -= parts[8];
2463 for (part = 6; --part > 0; ) {
2467 /* first arg to % needs to be non negativ */
2468 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2470 if (parts[part] < 0) {
2471 parts[part] += c + 1;
2476 case 0: /* already UTC */
2480 return LDAP_SUCCESS;
2483 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2488 struct berval *normalized )
2492 rc = check_time_syntax(val, 1, parts);
2493 if (rc != LDAP_SUCCESS) {
2497 normalized->bv_val = ch_malloc( 14 );
2498 if ( normalized->bv_val == NULL ) {
2499 return LBER_ERROR_MEMORY;
2502 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2503 parts[1], parts[2] + 1, parts[3] + 1,
2504 parts[4], parts[5], parts[6] );
2505 normalized->bv_len = 13;
2507 return LDAP_SUCCESS;
2516 return check_time_syntax(in, 1, parts);
2521 generalizedTimeValidate(
2526 return check_time_syntax(in, 0, parts);
2530 generalizedTimeNormalize(
2535 struct berval *normalized )
2539 rc = check_time_syntax(val, 0, parts);
2540 if (rc != LDAP_SUCCESS) {
2544 normalized->bv_val = ch_malloc( 16 );
2545 if ( normalized->bv_val == NULL ) {
2546 return LBER_ERROR_MEMORY;
2549 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2550 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2551 parts[4], parts[5], parts[6] );
2552 normalized->bv_len = 15;
2554 return LDAP_SUCCESS;
2558 nisNetgroupTripleValidate(
2560 struct berval *val )
2565 if ( val->bv_len == 0 ) {
2566 return LDAP_INVALID_SYNTAX;
2569 p = (char *)val->bv_val;
2570 e = p + val->bv_len;
2572 if ( *p != '(' /*')'*/ ) {
2573 return LDAP_INVALID_SYNTAX;
2576 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2580 return LDAP_INVALID_SYNTAX;
2583 } else if ( !AD_CHAR( *p ) ) {
2584 return LDAP_INVALID_SYNTAX;
2588 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2589 return LDAP_INVALID_SYNTAX;
2595 return LDAP_INVALID_SYNTAX;
2598 return LDAP_SUCCESS;
2602 bootParameterValidate(
2604 struct berval *val )
2608 if ( val->bv_len == 0 ) {
2609 return LDAP_INVALID_SYNTAX;
2612 p = (char *)val->bv_val;
2613 e = p + val->bv_len;
2616 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2617 if ( !AD_CHAR( *p ) ) {
2618 return LDAP_INVALID_SYNTAX;
2623 return LDAP_INVALID_SYNTAX;
2627 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2628 if ( !AD_CHAR( *p ) ) {
2629 return LDAP_INVALID_SYNTAX;
2634 return LDAP_INVALID_SYNTAX;
2638 for ( p++; p < e; p++ ) {
2639 if ( !SLAP_PRINTABLE( *p ) ) {
2640 return LDAP_INVALID_SYNTAX;
2644 return LDAP_SUCCESS;
2647 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2648 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2650 static slap_syntax_defs_rec syntax_defs[] = {
2651 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2652 X_BINARY X_NOT_H_R ")",
2653 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2654 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2656 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2658 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2660 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2661 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2663 SLAP_SYNTAX_BER, berValidate, NULL},
2664 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2665 0, bitStringValidate, NULL },
2666 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2667 0, booleanValidate, NULL},
2668 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2669 X_BINARY X_NOT_H_R ")",
2670 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2671 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2672 X_BINARY X_NOT_H_R ")",
2673 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2674 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2675 X_BINARY X_NOT_H_R ")",
2676 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2677 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2678 0, countryStringValidate, NULL},
2679 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2680 0, dnValidate, dnPretty2},
2681 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2683 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2685 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2686 0, UTF8StringValidate, NULL},
2687 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2689 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2691 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2693 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2695 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2697 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2698 0, printablesStringValidate, NULL},
2699 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2700 SLAP_SYNTAX_BLOB, NULL, NULL},
2701 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2702 0, generalizedTimeValidate, NULL},
2703 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2705 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2706 0, IA5StringValidate, NULL},
2707 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2708 0, integerValidate, NULL},
2709 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2710 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2711 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2713 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2715 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2717 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2719 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2721 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2722 0, nameUIDValidate, NULL},
2723 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2725 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2726 0, numericStringValidate, NULL},
2727 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2729 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2730 0, oidValidate, NULL},
2731 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2732 0, IA5StringValidate, NULL},
2733 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2734 0, blobValidate, NULL},
2735 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2736 0, UTF8StringValidate, NULL},
2737 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2739 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2741 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2742 0, printableStringValidate, NULL},
2743 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2744 X_BINARY X_NOT_H_R ")",
2745 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2746 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2747 X_BINARY X_NOT_H_R ")",
2748 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2749 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2750 0, printableStringValidate, NULL},
2751 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2753 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2754 0, printablesStringValidate, NULL},
2755 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2756 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2757 0, utcTimeValidate, NULL},
2759 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2761 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2763 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2765 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2767 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2770 /* RFC 2307 NIS Syntaxes */
2771 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2772 0, nisNetgroupTripleValidate, NULL},
2773 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2774 0, bootParameterValidate, NULL},
2778 /* These OIDs are not published yet, but will be in the next
2779 * I-D for PKIX LDAPv3 schema as have been advanced by David
2780 * Chadwick in private mail.
2782 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2783 0, UTF8StringValidate, NULL},
2786 /* OpenLDAP Experimental Syntaxes */
2787 #ifdef SLAPD_ACI_ENABLED
2788 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2790 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2794 #ifdef SLAPD_AUTHPASSWD
2795 /* needs updating */
2796 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2797 SLAP_SYNTAX_HIDE, NULL, NULL},
2800 /* OpenLDAP Void Syntax */
2801 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2802 SLAP_SYNTAX_HIDE, inValidate, NULL},
2803 {NULL, 0, NULL, NULL}
2807 char *certificateExactMatchSyntaxes[] = {
2808 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2812 char *directoryStringSyntaxes[] = {
2813 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2816 char *integerFirstComponentMatchSyntaxes[] = {
2817 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2818 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2821 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2822 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2823 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2824 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2825 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2826 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2827 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2828 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2829 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2834 * Other matching rules in X.520 that we do not use (yet):
2836 * 2.5.13.9 numericStringOrderingMatch
2837 * 2.5.13.25 uTCTimeMatch
2838 * 2.5.13.26 uTCTimeOrderingMatch
2839 * 2.5.13.31 directoryStringFirstComponentMatch
2840 * 2.5.13.32 wordMatch
2841 * 2.5.13.33 keywordMatch
2842 * 2.5.13.35 certificateMatch
2843 * 2.5.13.36 certificatePairExactMatch
2844 * 2.5.13.37 certificatePairMatch
2845 * 2.5.13.38 certificateListExactMatch
2846 * 2.5.13.39 certificateListMatch
2847 * 2.5.13.40 algorithmIdentifierMatch
2848 * 2.5.13.41 storedPrefixMatch
2849 * 2.5.13.42 attributeCertificateMatch
2850 * 2.5.13.43 readerAndKeyIDMatch
2851 * 2.5.13.44 attributeIntegrityMatch
2853 static slap_mrule_defs_rec mrule_defs[] = {
2855 * EQUALITY matching rules must be listed after associated APPROX
2856 * matching rules. So, we list all APPROX matching rules first.
2858 #ifndef SLAP_NVALUES
2859 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2860 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2861 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2862 NULL, NULL, directoryStringApproxMatch,
2863 directoryStringApproxIndexer, directoryStringApproxFilter,
2866 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2867 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2868 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2869 NULL, NULL, IA5StringApproxMatch,
2870 IA5StringApproxIndexer, IA5StringApproxFilter,
2875 * Other matching rules
2878 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2879 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2880 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2881 NULL, objectIdentifierNormalize, octetStringMatch,
2882 octetStringIndexer, octetStringFilter,
2885 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2886 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2887 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2888 NULL, dnNormalize, dnMatch,
2889 octetStringIndexer, octetStringFilter,
2892 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2893 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2894 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2895 NULL, UTF8StringNormalize, octetStringMatch,
2896 octetStringIndexer, octetStringFilter,
2897 directoryStringApproxMatchOID },
2899 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2900 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2901 SLAP_MR_ORDERING, directoryStringSyntaxes,
2902 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2906 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2907 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2908 SLAP_MR_SUBSTR, NULL,
2909 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2910 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2913 {"( 2.5.13.5 NAME 'caseExactMatch' "
2914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2915 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2916 NULL, UTF8StringNormalize, octetStringMatch,
2917 octetStringIndexer, octetStringFilter,
2918 directoryStringApproxMatchOID },
2920 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2922 SLAP_MR_ORDERING, directoryStringSyntaxes,
2923 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2927 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2928 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2929 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2930 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2931 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2934 {"( 2.5.13.8 NAME 'numericStringMatch' "
2935 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2936 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2937 NULL, numericStringNormalize, octetStringSubstringsMatch,
2938 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2941 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2942 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2943 SLAP_MR_SUBSTR, NULL,
2944 NULL, numericStringNormalize, octetStringSubstringsMatch,
2945 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2948 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2949 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2950 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2951 NULL, NULL, NULL, NULL, NULL, NULL},
2953 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2954 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2955 SLAP_MR_SUBSTR, NULL,
2956 NULL, NULL, NULL, NULL, NULL, NULL},
2958 {"( 2.5.13.13 NAME 'booleanMatch' "
2959 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2960 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2961 NULL, NULL, booleanMatch,
2962 octetStringIndexer, octetStringFilter,
2965 {"( 2.5.13.14 NAME 'integerMatch' "
2966 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2967 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2968 NULL, integerNormalize, integerMatch,
2969 octetStringIndexer, octetStringFilter,
2972 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2973 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2974 SLAP_MR_ORDERING, NULL,
2975 NULL, integerNormalize, integerOrderingMatch,
2979 {"( 2.5.13.16 NAME 'bitStringMatch' "
2980 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2981 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2982 NULL, NULL, octetStringMatch,
2983 octetStringIndexer, octetStringFilter,
2986 {"( 2.5.13.17 NAME 'octetStringMatch' "
2987 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2988 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2989 NULL, NULL, octetStringMatch,
2990 octetStringIndexer, octetStringFilter,
2993 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2994 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2995 SLAP_MR_ORDERING, NULL,
2996 NULL, NULL, octetStringOrderingMatch,
3000 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3001 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3002 SLAP_MR_SUBSTR, NULL,
3003 NULL, NULL, octetStringSubstringsMatch,
3004 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3007 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3008 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3009 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3011 telephoneNumberNormalize, octetStringMatch,
3012 octetStringIndexer, octetStringFilter,
3015 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3016 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3017 SLAP_MR_SUBSTR, NULL,
3018 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3019 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3022 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3023 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3024 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3025 NULL, NULL, NULL, NULL, NULL, NULL},
3027 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3028 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3029 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3030 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3034 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3035 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3036 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3037 NULL, NULL, NULL, NULL, NULL, NULL},
3039 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3040 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3041 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3042 NULL, generalizedTimeNormalize, octetStringMatch,
3046 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3047 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3048 SLAP_MR_ORDERING, NULL,
3049 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3053 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3054 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3055 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3056 NULL, integerFirstComponentNormalize, integerMatch,
3060 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3061 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3062 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3063 objectIdentifierFirstComponentMatchSyntaxes,
3064 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3065 octetStringIndexer, octetStringFilter,
3068 #ifndef SLAP_NVALUES
3070 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3071 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3072 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3073 certificateExactConvert, NULL, certificateExactMatch,
3074 certificateExactIndexer, certificateExactFilter,
3079 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3080 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3081 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3082 NULL, IA5StringNormalize, octetStringMatch,
3083 octetStringIndexer, octetStringFilter,
3084 IA5StringApproxMatchOID },
3086 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3087 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3088 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3089 NULL, IA5StringNormalize, octetStringMatch,
3090 octetStringIndexer, octetStringFilter,
3091 IA5StringApproxMatchOID },
3093 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3094 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3095 SLAP_MR_SUBSTR, NULL,
3096 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3097 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3100 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3101 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3102 SLAP_MR_SUBSTR, NULL,
3103 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3104 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3107 #ifdef SLAPD_AUTHPASSWD
3108 /* needs updating */
3109 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3110 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3111 SLAP_MR_EQUALITY, NULL,
3112 NULL, NULL, authPasswordMatch,
3117 #ifdef SLAPD_ACI_ENABLED
3118 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3119 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3120 SLAP_MR_EQUALITY, NULL,
3121 NULL, NULL, OpenLDAPaciMatch,
3126 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3127 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3129 NULL, NULL, integerBitAndMatch,
3133 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3134 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3136 NULL, NULL, integerBitOrMatch,
3140 {NULL, SLAP_MR_NONE, NULL,
3141 NULL, NULL, NULL, NULL, NULL,
3146 slap_schema_init( void )
3151 /* we should only be called once (from main) */
3152 assert( schema_init_done == 0 );
3154 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3155 res = register_syntax( &syntax_defs[i] );
3158 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3159 syntax_defs[i].sd_desc );
3164 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3165 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3166 mrule_defs[i].mrd_compat_syntaxes == NULL )
3169 "slap_schema_init: Ignoring unusable matching rule %s\n",
3170 mrule_defs[i].mrd_desc );
3174 res = register_matching_rule( &mrule_defs[i] );
3178 "slap_schema_init: Error registering matching rule %s\n",
3179 mrule_defs[i].mrd_desc );
3184 res = slap_schema_load();
3185 schema_init_done = 1;
3190 schema_destroy( void )