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 */
82 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
85 match = memcmp( value->bv_val,
86 ((struct berval *) assertedValue)->bv_val,
95 octetStringOrderingMatch(
100 struct berval *value,
101 void *assertedValue )
103 ber_len_t v_len = value->bv_len;
104 ber_len_t av_len = ((struct berval *) assertedValue)->bv_len;
106 int match = memcmp( value->bv_val,
107 ((struct berval *) assertedValue)->bv_val,
108 (v_len < av_len ? v_len : av_len) );
110 if( match == 0 ) match = v_len - av_len;
116 /* Index generation function */
117 int octetStringIndexer(
122 struct berval *prefix,
129 HASH_CONTEXT HASHcontext;
130 unsigned char HASHdigest[HASH_BYTES];
131 struct berval digest;
132 digest.bv_val = HASHdigest;
133 digest.bv_len = sizeof(HASHdigest);
135 for( i=0; values[i].bv_val != NULL; i++ ) {
136 /* just count them */
139 /* we should have at least one value at this point */
142 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
144 slen = syntax->ssyn_oidlen;
145 mlen = mr->smr_oidlen;
147 for( i=0; values[i].bv_val != NULL; i++ ) {
148 HASH_Init( &HASHcontext );
149 if( prefix != NULL && prefix->bv_len > 0 ) {
150 HASH_Update( &HASHcontext,
151 prefix->bv_val, prefix->bv_len );
153 HASH_Update( &HASHcontext,
154 syntax->ssyn_oid, slen );
155 HASH_Update( &HASHcontext,
157 HASH_Update( &HASHcontext,
158 values[i].bv_val, values[i].bv_len );
159 HASH_Final( HASHdigest, &HASHcontext );
161 ber_dupbv( &keys[i], &digest );
164 keys[i].bv_val = NULL;
172 /* Index generation function */
173 int octetStringFilter(
178 struct berval *prefix,
179 void * assertedValue,
184 HASH_CONTEXT HASHcontext;
185 unsigned char HASHdigest[HASH_BYTES];
186 struct berval *value = (struct berval *) assertedValue;
187 struct berval digest;
188 digest.bv_val = HASHdigest;
189 digest.bv_len = sizeof(HASHdigest);
191 slen = syntax->ssyn_oidlen;
192 mlen = mr->smr_oidlen;
194 keys = ch_malloc( sizeof( struct berval ) * 2 );
196 HASH_Init( &HASHcontext );
197 if( prefix != NULL && prefix->bv_len > 0 ) {
198 HASH_Update( &HASHcontext,
199 prefix->bv_val, prefix->bv_len );
201 HASH_Update( &HASHcontext,
202 syntax->ssyn_oid, slen );
203 HASH_Update( &HASHcontext,
205 HASH_Update( &HASHcontext,
206 value->bv_val, value->bv_len );
207 HASH_Final( HASHdigest, &HASHcontext );
209 ber_dupbv( keys, &digest );
210 keys[1].bv_val = NULL;
219 octetStringSubstringsMatch (
224 struct berval *value,
225 void *assertedValue )
228 SubstringsAssertion *sub = assertedValue;
229 struct berval left = *value;
233 /* Add up asserted input length */
234 if( sub->sa_initial.bv_val ) {
235 inlen += sub->sa_initial.bv_len;
238 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
239 inlen += sub->sa_any[i].bv_len;
242 if( sub->sa_final.bv_val ) {
243 inlen += sub->sa_final.bv_len;
246 if( sub->sa_initial.bv_val ) {
247 if( inlen > left.bv_len ) {
252 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
253 sub->sa_initial.bv_len );
259 left.bv_val += sub->sa_initial.bv_len;
260 left.bv_len -= sub->sa_initial.bv_len;
261 inlen -= sub->sa_initial.bv_len;
264 if( sub->sa_final.bv_val ) {
265 if( inlen > left.bv_len ) {
270 match = memcmp( sub->sa_final.bv_val,
271 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
272 sub->sa_final.bv_len );
278 left.bv_len -= sub->sa_final.bv_len;
279 inlen -= sub->sa_final.bv_len;
283 for(i=0; sub->sa_any[i].bv_val; i++) {
288 if( inlen > left.bv_len ) {
289 /* not enough length */
294 if( sub->sa_any[i].bv_len == 0 ) {
298 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
305 idx = p - left.bv_val;
307 if( idx >= left.bv_len ) {
308 /* this shouldn't happen */
315 if( sub->sa_any[i].bv_len > left.bv_len ) {
316 /* not enough left */
321 match = memcmp( left.bv_val,
322 sub->sa_any[i].bv_val,
323 sub->sa_any[i].bv_len );
331 left.bv_val += sub->sa_any[i].bv_len;
332 left.bv_len -= sub->sa_any[i].bv_len;
333 inlen -= sub->sa_any[i].bv_len;
342 /* Substrings Index generation function */
344 octetStringSubstringsIndexer (
349 struct berval *prefix,
353 ber_len_t i, j, nkeys;
357 HASH_CONTEXT HASHcontext;
358 unsigned char HASHdigest[HASH_BYTES];
359 struct berval digest;
360 digest.bv_val = HASHdigest;
361 digest.bv_len = sizeof(HASHdigest);
365 for( i=0; values[i].bv_val != NULL; i++ ) {
366 /* count number of indices to generate */
367 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
371 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
372 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
373 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
374 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
376 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
380 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
381 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
382 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
386 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
387 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
388 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
389 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
391 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
397 /* no keys to generate */
402 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
404 slen = syntax->ssyn_oidlen;
405 mlen = mr->smr_oidlen;
408 for( i=0; values[i].bv_val != NULL; i++ ) {
411 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
413 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
414 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
416 char pre = SLAP_INDEX_SUBSTR_PREFIX;
417 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
419 for( j=0; j<max; j++ ) {
420 HASH_Init( &HASHcontext );
421 if( prefix != NULL && prefix->bv_len > 0 ) {
422 HASH_Update( &HASHcontext,
423 prefix->bv_val, prefix->bv_len );
426 HASH_Update( &HASHcontext,
427 &pre, sizeof( pre ) );
428 HASH_Update( &HASHcontext,
429 syntax->ssyn_oid, slen );
430 HASH_Update( &HASHcontext,
432 HASH_Update( &HASHcontext,
433 &values[i].bv_val[j],
434 SLAP_INDEX_SUBSTR_MAXLEN );
435 HASH_Final( HASHdigest, &HASHcontext );
437 ber_dupbv( &keys[nkeys++], &digest );
441 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
442 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
444 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
447 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
448 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
449 HASH_Init( &HASHcontext );
450 if( prefix != NULL && prefix->bv_len > 0 ) {
451 HASH_Update( &HASHcontext,
452 prefix->bv_val, prefix->bv_len );
454 HASH_Update( &HASHcontext,
455 &pre, sizeof( pre ) );
456 HASH_Update( &HASHcontext,
457 syntax->ssyn_oid, slen );
458 HASH_Update( &HASHcontext,
460 HASH_Update( &HASHcontext,
461 values[i].bv_val, j );
462 HASH_Final( HASHdigest, &HASHcontext );
464 ber_dupbv( &keys[nkeys++], &digest );
467 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
468 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
469 HASH_Init( &HASHcontext );
470 if( prefix != NULL && prefix->bv_len > 0 ) {
471 HASH_Update( &HASHcontext,
472 prefix->bv_val, prefix->bv_len );
474 HASH_Update( &HASHcontext,
475 &pre, sizeof( pre ) );
476 HASH_Update( &HASHcontext,
477 syntax->ssyn_oid, slen );
478 HASH_Update( &HASHcontext,
480 HASH_Update( &HASHcontext,
481 &values[i].bv_val[values[i].bv_len-j], j );
482 HASH_Final( HASHdigest, &HASHcontext );
484 ber_dupbv( &keys[nkeys++], &digest );
492 keys[nkeys].bv_val = NULL;
503 octetStringSubstringsFilter (
508 struct berval *prefix,
509 void * assertedValue,
512 SubstringsAssertion *sa;
516 size_t slen, mlen, klen;
518 HASH_CONTEXT HASHcontext;
519 unsigned char HASHdigest[HASH_BYTES];
520 struct berval *value;
521 struct berval digest;
523 sa = (SubstringsAssertion *) assertedValue;
525 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
526 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
531 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
533 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
534 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
535 /* don't bother accounting for stepping */
536 nkeys += sa->sa_any[i].bv_len -
537 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
542 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
543 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
553 digest.bv_val = HASHdigest;
554 digest.bv_len = sizeof(HASHdigest);
556 slen = syntax->ssyn_oidlen;
557 mlen = mr->smr_oidlen;
559 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
562 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
563 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
565 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
566 value = &sa->sa_initial;
568 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
569 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
571 HASH_Init( &HASHcontext );
572 if( prefix != NULL && prefix->bv_len > 0 ) {
573 HASH_Update( &HASHcontext,
574 prefix->bv_val, prefix->bv_len );
576 HASH_Update( &HASHcontext,
577 &pre, sizeof( pre ) );
578 HASH_Update( &HASHcontext,
579 syntax->ssyn_oid, slen );
580 HASH_Update( &HASHcontext,
582 HASH_Update( &HASHcontext,
583 value->bv_val, klen );
584 HASH_Final( HASHdigest, &HASHcontext );
586 ber_dupbv( &keys[nkeys++], &digest );
589 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
591 pre = SLAP_INDEX_SUBSTR_PREFIX;
592 klen = SLAP_INDEX_SUBSTR_MAXLEN;
594 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
595 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
599 value = &sa->sa_any[i];
602 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
603 j += SLAP_INDEX_SUBSTR_STEP )
605 HASH_Init( &HASHcontext );
606 if( prefix != NULL && prefix->bv_len > 0 ) {
607 HASH_Update( &HASHcontext,
608 prefix->bv_val, prefix->bv_len );
610 HASH_Update( &HASHcontext,
611 &pre, sizeof( pre ) );
612 HASH_Update( &HASHcontext,
613 syntax->ssyn_oid, slen );
614 HASH_Update( &HASHcontext,
616 HASH_Update( &HASHcontext,
617 &value->bv_val[j], klen );
618 HASH_Final( HASHdigest, &HASHcontext );
620 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 "'"
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 ));
1512 return LDAP_SUCCESS;
1518 struct berval *val )
1522 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1524 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1525 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1527 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1528 return LDAP_INVALID_SYNTAX;
1531 for( i=1; i < val->bv_len; i++ ) {
1532 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1535 return LDAP_SUCCESS;
1544 struct berval *normalized )
1554 /* Ignore leading spaces */
1555 while ( len && ( *p == ' ' )) {
1562 negative = ( *p == '-' );
1563 if(( *p == '-' ) || ( *p == '+' )) {
1569 /* Ignore leading zeros */
1570 while ( len && ( *p == '0' )) {
1575 /* If there are no non-zero digits left, the number is zero, otherwise
1576 allocate space for the number and copy it into the buffer */
1578 normalized->bv_val = ch_strdup("0");
1579 normalized->bv_len = 1;
1582 normalized->bv_len = len+negative;
1583 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1584 if( negative ) normalized->bv_val[0] = '-';
1585 AC_MEMCPY( normalized->bv_val + negative, p, len );
1586 normalized->bv_val[len+negative] = '\0';
1589 return LDAP_SUCCESS;
1593 countryStringValidate(
1595 struct berval *val )
1597 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1599 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1600 return LDAP_INVALID_SYNTAX;
1602 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1603 return LDAP_INVALID_SYNTAX;
1606 return LDAP_SUCCESS;
1610 printableStringValidate(
1612 struct berval *val )
1616 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1618 for(i=0; i < val->bv_len; i++) {
1619 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1620 return LDAP_INVALID_SYNTAX;
1624 return LDAP_SUCCESS;
1628 printablesStringValidate(
1630 struct berval *val )
1634 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1636 for(i=0,len=0; i < val->bv_len; i++) {
1637 int c = val->bv_val[i];
1641 return LDAP_INVALID_SYNTAX;
1645 } else if ( SLAP_PRINTABLE(c) ) {
1648 return LDAP_INVALID_SYNTAX;
1653 return LDAP_INVALID_SYNTAX;
1656 return LDAP_SUCCESS;
1662 struct berval *val )
1666 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1668 for(i=0; i < val->bv_len; i++) {
1669 if( !LDAP_ASCII(val->bv_val[i]) ) {
1670 return LDAP_INVALID_SYNTAX;
1674 return LDAP_SUCCESS;
1683 struct berval *normalized )
1686 int casefold = (mr != slap_schema.si_mr_caseExactIA5Match);
1688 assert( val->bv_len );
1692 /* Ignore initial whitespace */
1693 while ( ASCII_SPACE( *p ) ) {
1697 normalized->bv_val = ch_strdup( p );
1698 p = q = normalized->bv_val;
1701 if ( ASCII_SPACE( *p ) ) {
1704 /* Ignore the extra whitespace */
1705 while ( ASCII_SPACE( *p ) ) {
1709 } else if ( casefold ) {
1710 /* Most IA5 rules require casefolding */
1711 *q++ = TOLOWER(*p++);
1718 assert( normalized->bv_val <= p );
1722 * If the string ended in space, backup the pointer one
1723 * position. One is enough because the above loop collapsed
1724 * all whitespace to a single space.
1727 if ( ASCII_SPACE( q[-1] ) ) {
1731 /* null terminate */
1734 normalized->bv_len = q - normalized->bv_val;
1736 if( normalized->bv_len == 0 ) {
1737 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1738 normalized->bv_val[0] = ' ';
1739 normalized->bv_val[1] = '\0';
1740 normalized->bv_len = 1;
1743 return LDAP_SUCCESS;
1747 numericStringValidate(
1753 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1755 for(i=0; i < in->bv_len; i++) {
1756 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1757 return LDAP_INVALID_SYNTAX;
1761 return LDAP_SUCCESS;
1765 numericStringNormalize(
1770 struct berval *normalized )
1772 /* removal all spaces */
1775 assert( val->bv_len );
1777 normalized->bv_val = ch_malloc( val->bv_len + 1 );
1780 q = normalized->bv_val;
1783 if ( ASCII_SPACE( *p ) ) {
1784 /* Ignore whitespace */
1791 /* we should have copied no more then is in val */
1792 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1794 /* null terminate */
1797 normalized->bv_len = q - normalized->bv_val;
1799 if( normalized->bv_len == 0 ) {
1800 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1801 normalized->bv_val[0] = ' ';
1802 normalized->bv_val[1] = '\0';
1803 normalized->bv_len = 1;
1806 return LDAP_SUCCESS;
1809 #ifndef SLAP_NVALUES
1811 objectIdentifierFirstComponentMatch(
1816 struct berval *value,
1817 void *assertedValue )
1819 int rc = LDAP_SUCCESS;
1821 struct berval *asserted = (struct berval *) assertedValue;
1825 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1826 return LDAP_INVALID_SYNTAX;
1829 /* trim leading white space */
1830 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1834 /* grab next word */
1835 oid.bv_val = &value->bv_val[i];
1836 j = value->bv_len - i;
1837 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1842 /* insert attributeTypes, objectclass check here */
1843 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1844 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1847 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1848 MatchingRule *asserted_mr = mr_bvfind( asserted );
1849 MatchingRule *stored_mr = mr_bvfind( &oid );
1851 if( asserted_mr == NULL ) {
1852 rc = SLAPD_COMPARE_UNDEFINED;
1854 match = asserted_mr != stored_mr;
1857 } else if ( !strcmp( syntax->ssyn_oid,
1858 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1860 AttributeType *asserted_at = at_bvfind( asserted );
1861 AttributeType *stored_at = at_bvfind( &oid );
1863 if( asserted_at == NULL ) {
1864 rc = SLAPD_COMPARE_UNDEFINED;
1866 match = asserted_at != stored_at;
1869 } else if ( !strcmp( syntax->ssyn_oid,
1870 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1872 ObjectClass *asserted_oc = oc_bvfind( asserted );
1873 ObjectClass *stored_oc = oc_bvfind( &oid );
1875 if( asserted_oc == NULL ) {
1876 rc = SLAPD_COMPARE_UNDEFINED;
1878 match = asserted_oc != stored_oc;
1884 LDAP_LOG( CONFIG, ENTRY,
1885 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1886 match, value->bv_val, asserted->bv_val );
1888 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1889 "%d\n\t\"%s\"\n\t\"%s\"\n",
1890 match, value->bv_val, asserted->bv_val );
1893 if( rc == LDAP_SUCCESS ) *matchp = match;
1904 struct berval *value,
1905 void *assertedValue )
1907 long lValue, lAssertedValue;
1909 /* safe to assume integers are NUL terminated? */
1910 lValue = strtol(value->bv_val, NULL, 10);
1911 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1912 return LDAP_CONSTRAINT_VIOLATION;
1915 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1916 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1917 && errno == ERANGE )
1919 return LDAP_CONSTRAINT_VIOLATION;
1922 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1923 return LDAP_SUCCESS;
1932 struct berval *value,
1933 void *assertedValue )
1935 long lValue, lAssertedValue;
1937 /* safe to assume integers are NUL terminated? */
1938 lValue = strtol(value->bv_val, NULL, 10);
1939 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1940 return LDAP_CONSTRAINT_VIOLATION;
1943 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1944 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1945 && errno == ERANGE )
1947 return LDAP_CONSTRAINT_VIOLATION;
1950 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1951 return LDAP_SUCCESS;
1954 #ifndef SLAP_NVALUES
1956 #include <openssl/x509.h>
1957 #include <openssl/err.h>
1960 * Next function returns a string representation of a ASN1_INTEGER.
1961 * It works for unlimited lengths.
1964 static struct berval *
1965 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1969 static char digit[] = "0123456789";
1971 /* We work backwards, make it fill from the end of buf */
1972 p = buf + sizeof(buf) - 1;
1975 if ( a == NULL || a->length == 0 ) {
1983 /* We want to preserve the original */
1984 copy = ch_malloc(n*sizeof(unsigned int));
1985 for (i = 0; i<n; i++) {
1986 copy[i] = a->data[i];
1990 * base indicates the index of the most significant
1991 * byte that might be nonzero. When it goes off the
1992 * end, we now there is nothing left to do.
1998 for (i = base; i<n; i++ ) {
1999 copy[i] += carry*256;
2000 carry = copy[i] % 10;
2005 * Way too large, we need to leave
2006 * room for sign if negative
2011 *--p = digit[carry];
2013 if (copy[base] == 0) base++;
2018 if ( a->type == V_ASN1_NEG_INTEGER ) {
2022 return ber_str2bv( p, 0, 1, bv );
2026 * Given a certificate in DER format, extract the corresponding
2027 * assertion value for certificateExactMatch
2030 certificateExactConvert(
2032 struct berval * out )
2035 unsigned char *p = in->bv_val;
2036 struct berval serial;
2037 struct berval issuer_dn;
2039 xcert = d2i_X509(NULL, &p, in->bv_len);
2042 LDAP_LOG( CONFIG, ENTRY,
2043 "certificateExactConvert: error parsing cert: %s\n",
2044 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2046 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2047 "error parsing cert: %s\n",
2048 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2050 return LDAP_INVALID_SYNTAX;
2053 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2055 return LDAP_INVALID_SYNTAX;
2057 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2061 ber_memfree(serial.bv_val);
2062 return LDAP_INVALID_SYNTAX;
2067 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2068 out->bv_val = ch_malloc(out->bv_len);
2070 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2072 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2074 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2075 p += issuer_dn.bv_len;
2079 LDAP_LOG( CONFIG, ARGS,
2080 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2082 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2084 out->bv_val, NULL, NULL );
2087 ber_memfree(serial.bv_val);
2088 ber_memfree(issuer_dn.bv_val);
2090 return LDAP_SUCCESS;
2094 serial_and_issuer_parse(
2095 struct berval *assertion,
2096 struct berval *serial,
2097 struct berval *issuer_dn
2105 begin = assertion->bv_val;
2106 end = assertion->bv_val+assertion->bv_len-1;
2107 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2108 if ( p > end ) return LDAP_INVALID_SYNTAX;
2110 /* p now points at the $ sign, now use
2111 * begin and end to delimit the serial number
2113 while (ASCII_SPACE(*begin)) begin++;
2115 while (ASCII_SPACE(*end)) end--;
2117 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2119 bv.bv_len = end-begin+1;
2121 ber_dupbv(serial, &bv);
2123 /* now extract the issuer, remember p was at the dollar sign */
2125 end = assertion->bv_val+assertion->bv_len-1;
2126 while (ASCII_SPACE(*begin)) begin++;
2127 /* should we trim spaces at the end too? is it safe always? no, no */
2129 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2132 bv.bv_len = end-begin+1;
2135 dnNormalize2( NULL, &bv, issuer_dn );
2138 return LDAP_SUCCESS;
2142 certificateExactMatch(
2147 struct berval *value,
2148 void *assertedValue )
2151 unsigned char *p = value->bv_val;
2152 struct berval serial;
2153 struct berval issuer_dn;
2154 struct berval asserted_serial;
2155 struct berval asserted_issuer_dn;
2158 xcert = d2i_X509(NULL, &p, value->bv_len);
2161 LDAP_LOG( CONFIG, ENTRY,
2162 "certificateExactMatch: error parsing cert: %s\n",
2163 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2165 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2166 "error parsing cert: %s\n",
2167 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2169 return LDAP_INVALID_SYNTAX;
2172 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2173 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2177 serial_and_issuer_parse(assertedValue,
2178 &asserted_serial, &asserted_issuer_dn);
2183 slap_schema.si_syn_integer,
2184 slap_schema.si_mr_integerMatch,
2187 if ( ret == LDAP_SUCCESS ) {
2188 if ( *matchp == 0 ) {
2189 /* We need to normalize everything for dnMatch */
2193 slap_schema.si_syn_distinguishedName,
2194 slap_schema.si_mr_distinguishedNameMatch,
2196 &asserted_issuer_dn);
2201 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2202 "%d\n\t\"%s $ %s\"\n",
2203 *matchp, serial.bv_val, issuer_dn.bv_val );
2204 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2205 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2208 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2209 "%d\n\t\"%s $ %s\"\n",
2210 *matchp, serial.bv_val, issuer_dn.bv_val );
2211 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2212 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2216 ber_memfree(serial.bv_val);
2217 ber_memfree(issuer_dn.bv_val);
2218 ber_memfree(asserted_serial.bv_val);
2219 ber_memfree(asserted_issuer_dn.bv_val);
2225 * Index generation function
2226 * We just index the serials, in most scenarios the issuer DN is one of
2227 * a very small set of values.
2229 static int certificateExactIndexer(
2234 struct berval *prefix,
2242 struct berval serial;
2244 /* we should have at least one value at this point */
2245 assert( values != NULL && values[0].bv_val != NULL );
2247 for( i=0; values[i].bv_val != NULL; i++ ) {
2248 /* empty -- just count them */
2251 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2253 for( i=0; values[i].bv_val != NULL; i++ ) {
2254 p = values[i].bv_val;
2255 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2258 LDAP_LOG( CONFIG, ENTRY,
2259 "certificateExactIndexer: error parsing cert: %s\n",
2260 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2262 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2263 "error parsing cert: %s\n",
2264 ERR_error_string(ERR_get_error(),NULL),
2267 /* Do we leak keys on error? */
2268 return LDAP_INVALID_SYNTAX;
2271 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2273 xintegerNormalize( slap_schema.si_syn_integer,
2274 &serial, &keys[i] );
2275 ber_memfree(serial.bv_val);
2277 LDAP_LOG( CONFIG, ENTRY,
2278 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2280 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2287 keys[i].bv_val = NULL;
2289 return LDAP_SUCCESS;
2292 /* Index generation function */
2293 /* We think this is always called with a value in matching rule syntax */
2294 static int certificateExactFilter(
2299 struct berval *prefix,
2300 void * assertedValue,
2304 struct berval asserted_serial;
2307 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2308 if( ret != LDAP_SUCCESS ) return ret;
2310 keys = ch_malloc( sizeof( struct berval ) * 2 );
2311 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2312 keys[1].bv_val = NULL;
2315 ber_memfree(asserted_serial.bv_val);
2316 return LDAP_SUCCESS;
2322 check_time_syntax (struct berval *val,
2326 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2327 static int mdays[2][12] = {
2328 /* non-leap years */
2329 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2331 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2334 int part, c, tzoffset, leapyear = 0 ;
2336 if( val->bv_len == 0 ) {
2337 return LDAP_INVALID_SYNTAX;
2340 p = (char *)val->bv_val;
2341 e = p + val->bv_len;
2343 /* Ignore initial whitespace */
2344 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2348 if (e - p < 13 - (2 * start)) {
2349 return LDAP_INVALID_SYNTAX;
2352 for (part = 0; part < 9; part++) {
2356 for (part = start; part < 7; part++) {
2358 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2365 return LDAP_INVALID_SYNTAX;
2367 if (c < 0 || c > 9) {
2368 return LDAP_INVALID_SYNTAX;
2374 return LDAP_INVALID_SYNTAX;
2376 if (c < 0 || c > 9) {
2377 return LDAP_INVALID_SYNTAX;
2382 if (part == 2 || part == 3) {
2385 if (parts[part] < 0) {
2386 return LDAP_INVALID_SYNTAX;
2388 if (parts[part] > ceiling[part]) {
2389 return LDAP_INVALID_SYNTAX;
2393 /* leapyear check for the Gregorian calendar (year>1581) */
2394 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2395 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2400 if (parts[3] > mdays[leapyear][parts[2]]) {
2401 return LDAP_INVALID_SYNTAX;
2406 tzoffset = 0; /* UTC */
2407 } else if (c != '+' && c != '-') {
2408 return LDAP_INVALID_SYNTAX;
2412 } else /* c == '+' */ {
2417 return LDAP_INVALID_SYNTAX;
2420 for (part = 7; part < 9; part++) {
2422 if (c < 0 || c > 9) {
2423 return LDAP_INVALID_SYNTAX;
2428 if (c < 0 || c > 9) {
2429 return LDAP_INVALID_SYNTAX;
2433 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2434 return LDAP_INVALID_SYNTAX;
2439 /* Ignore trailing whitespace */
2440 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2444 return LDAP_INVALID_SYNTAX;
2447 switch ( tzoffset ) {
2448 case -1: /* negativ offset to UTC, ie west of Greenwich */
2449 parts[4] += parts[7];
2450 parts[5] += parts[8];
2451 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2455 c = mdays[leapyear][parts[2]];
2457 if (parts[part] > c) {
2458 parts[part] -= c + 1;
2463 case 1: /* positive offset to UTC, ie east of Greenwich */
2464 parts[4] -= parts[7];
2465 parts[5] -= parts[8];
2466 for (part = 6; --part > 0; ) {
2470 /* first arg to % needs to be non negativ */
2471 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2473 if (parts[part] < 0) {
2474 parts[part] += c + 1;
2479 case 0: /* already UTC */
2483 return LDAP_SUCCESS;
2486 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2491 struct berval *normalized )
2495 rc = check_time_syntax(val, 1, parts);
2496 if (rc != LDAP_SUCCESS) {
2500 normalized->bv_val = ch_malloc( 14 );
2501 if ( normalized->bv_val == NULL ) {
2502 return LBER_ERROR_MEMORY;
2505 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2506 parts[1], parts[2] + 1, parts[3] + 1,
2507 parts[4], parts[5], parts[6] );
2508 normalized->bv_len = 13;
2510 return LDAP_SUCCESS;
2520 return check_time_syntax(in, 1, parts);
2525 generalizedTimeValidate(
2531 return check_time_syntax(in, 0, parts);
2535 generalizedTimeNormalize(
2540 struct berval *normalized )
2544 rc = check_time_syntax(val, 0, parts);
2545 if (rc != LDAP_SUCCESS) {
2549 normalized->bv_val = ch_malloc( 16 );
2550 if ( normalized->bv_val == NULL ) {
2551 return LBER_ERROR_MEMORY;
2554 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2555 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2556 parts[4], parts[5], parts[6] );
2557 normalized->bv_len = 15;
2559 return LDAP_SUCCESS;
2563 nisNetgroupTripleValidate(
2565 struct berval *val )
2570 if ( val->bv_len == 0 ) {
2571 return LDAP_INVALID_SYNTAX;
2574 p = (char *)val->bv_val;
2575 e = p + val->bv_len;
2577 if ( *p != '(' /*')'*/ ) {
2578 return LDAP_INVALID_SYNTAX;
2581 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2585 return LDAP_INVALID_SYNTAX;
2588 } else if ( !AD_CHAR( *p ) ) {
2589 return LDAP_INVALID_SYNTAX;
2593 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2594 return LDAP_INVALID_SYNTAX;
2600 return LDAP_INVALID_SYNTAX;
2603 return LDAP_SUCCESS;
2607 bootParameterValidate(
2609 struct berval *val )
2613 if ( val->bv_len == 0 ) {
2614 return LDAP_INVALID_SYNTAX;
2617 p = (char *)val->bv_val;
2618 e = p + val->bv_len;
2621 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2622 if ( !AD_CHAR( *p ) ) {
2623 return LDAP_INVALID_SYNTAX;
2628 return LDAP_INVALID_SYNTAX;
2632 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2633 if ( !AD_CHAR( *p ) ) {
2634 return LDAP_INVALID_SYNTAX;
2639 return LDAP_INVALID_SYNTAX;
2643 for ( p++; p < e; p++ ) {
2644 if ( !SLAP_PRINTABLE( *p ) ) {
2645 return LDAP_INVALID_SYNTAX;
2649 return LDAP_SUCCESS;
2652 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2653 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2655 static slap_syntax_defs_rec syntax_defs[] = {
2656 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2657 X_BINARY X_NOT_H_R ")",
2658 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2659 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2661 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2663 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2665 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2666 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2668 #define berValidate blobValidate
2669 SLAP_SYNTAX_BER, berValidate, NULL},
2670 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2671 0, bitStringValidate, NULL },
2672 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2673 0, booleanValidate, NULL},
2674 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
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.9 DESC 'Certificate List' "
2678 X_BINARY X_NOT_H_R ")",
2679 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2680 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2681 X_BINARY X_NOT_H_R ")",
2682 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2683 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2684 0, countryStringValidate, NULL},
2685 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2686 0, dnValidate, dnPretty2},
2687 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2689 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2691 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2692 0, UTF8StringValidate, NULL},
2693 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2695 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2697 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2699 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2701 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2703 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2704 0, printablesStringValidate, NULL},
2705 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2706 SLAP_SYNTAX_BLOB, NULL, NULL},
2707 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2708 0, generalizedTimeValidate, NULL},
2709 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2711 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2712 0, IA5StringValidate, NULL},
2713 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2714 0, integerValidate, NULL},
2715 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2716 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2717 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2719 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2721 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2723 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2725 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2727 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2728 0, nameUIDValidate, NULL},
2729 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2731 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2732 0, numericStringValidate, NULL},
2733 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2735 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2736 0, oidValidate, NULL},
2737 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2738 0, IA5StringValidate, NULL},
2739 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2740 0, blobValidate, NULL},
2741 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2742 0, UTF8StringValidate, NULL},
2743 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2745 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2747 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2748 0, printableStringValidate, NULL},
2749 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2750 X_BINARY X_NOT_H_R ")",
2751 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2752 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2753 X_BINARY X_NOT_H_R ")",
2754 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2755 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2756 0, printableStringValidate, NULL},
2757 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2759 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2760 0, printablesStringValidate, NULL},
2761 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2762 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2763 0, utcTimeValidate, NULL},
2765 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2767 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2769 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2771 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2773 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2776 /* RFC 2307 NIS Syntaxes */
2777 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2778 0, nisNetgroupTripleValidate, NULL},
2779 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2780 0, bootParameterValidate, NULL},
2784 /* These OIDs are not published yet, but will be in the next
2785 * I-D for PKIX LDAPv3 schema as have been advanced by David
2786 * Chadwick in private mail.
2788 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2789 0, UTF8StringValidate, NULL},
2792 /* OpenLDAP Experimental Syntaxes */
2793 #ifdef SLAPD_ACI_ENABLED
2794 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2796 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2800 #ifdef SLAPD_AUTHPASSWD
2801 /* needs updating */
2802 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2803 SLAP_SYNTAX_HIDE, NULL, NULL},
2806 /* OpenLDAP Void Syntax */
2807 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2808 SLAP_SYNTAX_HIDE, inValidate, NULL},
2809 {NULL, 0, NULL, NULL}
2813 char *certificateExactMatchSyntaxes[] = {
2814 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2818 char *directoryStringSyntaxes[] = {
2819 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2822 char *integerFirstComponentMatchSyntaxes[] = {
2823 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2824 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2827 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2828 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2829 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2830 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2831 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2832 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2833 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2834 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2835 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2840 * Other matching rules in X.520 that we do not use (yet):
2842 * 2.5.13.9 numericStringOrderingMatch
2843 * 2.5.13.25 uTCTimeMatch
2844 * 2.5.13.26 uTCTimeOrderingMatch
2845 * 2.5.13.31 directoryStringFirstComponentMatch
2846 * 2.5.13.32 wordMatch
2847 * 2.5.13.33 keywordMatch
2848 * 2.5.13.35 certificateMatch
2849 * 2.5.13.36 certificatePairExactMatch
2850 * 2.5.13.37 certificatePairMatch
2851 * 2.5.13.38 certificateListExactMatch
2852 * 2.5.13.39 certificateListMatch
2853 * 2.5.13.40 algorithmIdentifierMatch
2854 * 2.5.13.41 storedPrefixMatch
2855 * 2.5.13.42 attributeCertificateMatch
2856 * 2.5.13.43 readerAndKeyIDMatch
2857 * 2.5.13.44 attributeIntegrityMatch
2859 static slap_mrule_defs_rec mrule_defs[] = {
2861 * EQUALITY matching rules must be listed after associated APPROX
2862 * matching rules. So, we list all APPROX matching rules first.
2864 #ifndef SLAP_NVALUES
2865 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2866 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2867 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2868 NULL, NULL, directoryStringApproxMatch,
2869 directoryStringApproxIndexer, directoryStringApproxFilter,
2872 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2873 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2874 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2875 NULL, NULL, IA5StringApproxMatch,
2876 IA5StringApproxIndexer, IA5StringApproxFilter,
2881 * Other matching rules
2884 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2885 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2886 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2887 NULL, objectIdentifierNormalize, octetStringMatch,
2888 octetStringIndexer, octetStringFilter,
2891 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2893 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2894 NULL, dnNormalize, dnMatch,
2895 octetStringIndexer, octetStringFilter,
2898 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2899 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2900 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2901 NULL, UTF8StringNormalize, octetStringMatch,
2902 octetStringIndexer, octetStringFilter,
2903 directoryStringApproxMatchOID },
2905 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2906 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2907 SLAP_MR_ORDERING, directoryStringSyntaxes,
2908 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2912 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2913 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2914 SLAP_MR_SUBSTR, NULL,
2915 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2916 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2919 {"( 2.5.13.5 NAME 'caseExactMatch' "
2920 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2921 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2922 NULL, UTF8StringNormalize, octetStringMatch,
2923 octetStringIndexer, octetStringFilter,
2924 directoryStringApproxMatchOID },
2926 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2927 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2928 SLAP_MR_ORDERING, directoryStringSyntaxes,
2929 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2933 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2934 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2935 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2936 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2937 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2940 {"( 2.5.13.8 NAME 'numericStringMatch' "
2941 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2942 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2943 NULL, numericStringNormalize, octetStringSubstringsMatch,
2944 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2947 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2948 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2949 SLAP_MR_SUBSTR, NULL,
2950 NULL, numericStringNormalize, octetStringSubstringsMatch,
2951 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2954 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2955 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2956 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2957 NULL, NULL, NULL, NULL, NULL, NULL},
2959 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2960 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2961 SLAP_MR_SUBSTR, NULL,
2962 NULL, NULL, NULL, NULL, NULL, NULL},
2964 {"( 2.5.13.13 NAME 'booleanMatch' "
2965 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2966 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2967 NULL, NULL, booleanMatch,
2968 octetStringIndexer, octetStringFilter,
2971 {"( 2.5.13.14 NAME 'integerMatch' "
2972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2973 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2974 NULL, integerNormalize, integerMatch,
2975 octetStringIndexer, octetStringFilter,
2978 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2980 SLAP_MR_ORDERING, NULL,
2981 NULL, integerNormalize, integerOrderingMatch,
2985 {"( 2.5.13.16 NAME 'bitStringMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2987 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2988 NULL, NULL, octetStringMatch,
2989 octetStringIndexer, octetStringFilter,
2992 {"( 2.5.13.17 NAME 'octetStringMatch' "
2993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2994 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2995 NULL, NULL, octetStringMatch,
2996 octetStringIndexer, octetStringFilter,
2999 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3001 SLAP_MR_ORDERING, NULL,
3002 NULL, NULL, octetStringOrderingMatch,
3006 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3008 SLAP_MR_SUBSTR, NULL,
3009 NULL, NULL, octetStringSubstringsMatch,
3010 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3013 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3015 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3017 telephoneNumberNormalize, octetStringMatch,
3018 octetStringIndexer, octetStringFilter,
3021 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3022 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3023 SLAP_MR_SUBSTR, NULL,
3024 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3025 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3028 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3029 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3030 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3031 NULL, NULL, NULL, NULL, NULL, NULL},
3033 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3034 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3035 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3036 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3040 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3041 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3042 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3043 NULL, NULL, NULL, NULL, NULL, NULL},
3045 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3046 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3047 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3048 NULL, generalizedTimeNormalize, octetStringMatch,
3052 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3054 SLAP_MR_ORDERING, NULL,
3055 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3059 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3061 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3062 NULL, integerFirstComponentNormalize, integerMatch,
3066 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3068 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3069 objectIdentifierFirstComponentMatchSyntaxes,
3070 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3071 octetStringIndexer, octetStringFilter,
3074 #ifndef SLAP_NVALUES
3076 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3077 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3078 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3079 certificateExactConvert, NULL, certificateExactMatch,
3080 certificateExactIndexer, certificateExactFilter,
3085 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3086 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3087 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3088 NULL, IA5StringNormalize, octetStringMatch,
3089 octetStringIndexer, octetStringFilter,
3090 IA5StringApproxMatchOID },
3092 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3094 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3095 NULL, IA5StringNormalize, octetStringMatch,
3096 octetStringIndexer, octetStringFilter,
3097 IA5StringApproxMatchOID },
3099 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3101 SLAP_MR_SUBSTR, NULL,
3102 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3103 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3106 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3108 SLAP_MR_SUBSTR, NULL,
3109 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3110 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3113 #ifdef SLAPD_AUTHPASSWD
3114 /* needs updating */
3115 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3116 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3117 SLAP_MR_EQUALITY, NULL,
3118 NULL, NULL, authPasswordMatch,
3123 #ifdef SLAPD_ACI_ENABLED
3124 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3125 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3126 SLAP_MR_EQUALITY, NULL,
3127 NULL, NULL, OpenLDAPaciMatch,
3132 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3133 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3135 NULL, NULL, integerBitAndMatch,
3139 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3140 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3142 NULL, NULL, integerBitOrMatch,
3146 {NULL, SLAP_MR_NONE, NULL,
3147 NULL, NULL, NULL, NULL, NULL,
3152 slap_schema_init( void )
3157 /* we should only be called once (from main) */
3158 assert( schema_init_done == 0 );
3160 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3161 res = register_syntax( &syntax_defs[i] );
3164 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3165 syntax_defs[i].sd_desc );
3170 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3171 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3172 mrule_defs[i].mrd_compat_syntaxes == NULL )
3175 "slap_schema_init: Ignoring unusable matching rule %s\n",
3176 mrule_defs[i].mrd_desc );
3180 res = register_matching_rule( &mrule_defs[i] );
3184 "slap_schema_init: Error registering matching rule %s\n",
3185 mrule_defs[i].mrd_desc );
3190 res = slap_schema_load();
3191 schema_init_done = 1;
3196 schema_destroy( void )