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 #define OpenLDAPaciMatch NULL
42 /* approx matching rules */
44 #define directoryStringApproxMatchOID NULL
45 #define IA5StringApproxMatchOID NULL
47 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
48 #define directoryStringApproxMatch approxMatch
49 #define directoryStringApproxIndexer approxIndexer
50 #define directoryStringApproxFilter approxFilter
51 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
52 #define IA5StringApproxMatch approxMatch
53 #define IA5StringApproxIndexer approxIndexer
54 #define IA5StringApproxFilter approxFilter
62 /* no value allowed */
63 return LDAP_INVALID_SYNTAX;
71 /* any value allowed */
75 #define berValidate blobValidate
86 struct berval *asserted = (struct berval *) assertedValue;
87 int match = value->bv_len - asserted->bv_len;
90 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
98 octetStringOrderingMatch(
103 struct berval *value,
104 void *assertedValue )
106 struct berval *asserted = (struct berval *) assertedValue;
107 ber_len_t v_len = value->bv_len;
108 ber_len_t av_len = asserted->bv_len;
110 int match = memcmp( value->bv_val, asserted->bv_val,
111 (v_len < av_len ? v_len : av_len) );
113 if( match == 0 ) match = v_len - av_len;
119 /* Index generation function */
120 int octetStringIndexer(
125 struct berval *prefix,
133 HASH_CONTEXT HASHcontext;
134 unsigned char HASHdigest[HASH_BYTES];
135 struct berval digest;
136 digest.bv_val = HASHdigest;
137 digest.bv_len = sizeof(HASHdigest);
139 for( i=0; values[i].bv_val != NULL; i++ ) {
140 /* just count them */
143 /* we should have at least one value at this point */
146 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
148 slen = syntax->ssyn_oidlen;
149 mlen = mr->smr_oidlen;
151 for( i=0; values[i].bv_val != NULL; i++ ) {
152 HASH_Init( &HASHcontext );
153 if( prefix != NULL && prefix->bv_len > 0 ) {
154 HASH_Update( &HASHcontext,
155 prefix->bv_val, prefix->bv_len );
157 HASH_Update( &HASHcontext,
158 syntax->ssyn_oid, slen );
159 HASH_Update( &HASHcontext,
161 HASH_Update( &HASHcontext,
162 values[i].bv_val, values[i].bv_len );
163 HASH_Final( HASHdigest, &HASHcontext );
165 ber_dupbv_x( &keys[i], &digest, ctx );
168 keys[i].bv_val = NULL;
176 /* Index generation function */
177 int octetStringFilter(
182 struct berval *prefix,
183 void * assertedValue,
189 HASH_CONTEXT HASHcontext;
190 unsigned char HASHdigest[HASH_BYTES];
191 struct berval *value = (struct berval *) assertedValue;
192 struct berval digest;
193 digest.bv_val = HASHdigest;
194 digest.bv_len = sizeof(HASHdigest);
196 slen = syntax->ssyn_oidlen;
197 mlen = mr->smr_oidlen;
199 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
201 HASH_Init( &HASHcontext );
202 if( prefix != NULL && prefix->bv_len > 0 ) {
203 HASH_Update( &HASHcontext,
204 prefix->bv_val, prefix->bv_len );
206 HASH_Update( &HASHcontext,
207 syntax->ssyn_oid, slen );
208 HASH_Update( &HASHcontext,
210 HASH_Update( &HASHcontext,
211 value->bv_val, value->bv_len );
212 HASH_Final( HASHdigest, &HASHcontext );
214 ber_dupbv_x( keys, &digest, ctx );
215 keys[1].bv_val = NULL;
224 octetStringSubstringsMatch(
229 struct berval *value,
230 void *assertedValue )
233 SubstringsAssertion *sub = assertedValue;
234 struct berval left = *value;
238 /* Add up asserted input length */
239 if( sub->sa_initial.bv_val ) {
240 inlen += sub->sa_initial.bv_len;
243 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
244 inlen += sub->sa_any[i].bv_len;
247 if( sub->sa_final.bv_val ) {
248 inlen += sub->sa_final.bv_len;
251 if( sub->sa_initial.bv_val ) {
252 if( inlen > left.bv_len ) {
257 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
258 sub->sa_initial.bv_len );
264 left.bv_val += sub->sa_initial.bv_len;
265 left.bv_len -= sub->sa_initial.bv_len;
266 inlen -= sub->sa_initial.bv_len;
269 if( sub->sa_final.bv_val ) {
270 if( inlen > left.bv_len ) {
275 match = memcmp( sub->sa_final.bv_val,
276 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
277 sub->sa_final.bv_len );
283 left.bv_len -= sub->sa_final.bv_len;
284 inlen -= sub->sa_final.bv_len;
288 for(i=0; sub->sa_any[i].bv_val; i++) {
293 if( inlen > left.bv_len ) {
294 /* not enough length */
299 if( sub->sa_any[i].bv_len == 0 ) {
303 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
310 idx = p - left.bv_val;
312 if( idx >= left.bv_len ) {
313 /* this shouldn't happen */
320 if( sub->sa_any[i].bv_len > left.bv_len ) {
321 /* not enough left */
326 match = memcmp( left.bv_val,
327 sub->sa_any[i].bv_val,
328 sub->sa_any[i].bv_len );
336 left.bv_val += sub->sa_any[i].bv_len;
337 left.bv_len -= sub->sa_any[i].bv_len;
338 inlen -= sub->sa_any[i].bv_len;
347 /* Substrings Index generation function */
349 octetStringSubstringsIndexer(
354 struct berval *prefix,
359 ber_len_t i, j, nkeys;
363 HASH_CONTEXT HASHcontext;
364 unsigned char HASHdigest[HASH_BYTES];
365 struct berval digest;
366 digest.bv_val = HASHdigest;
367 digest.bv_len = sizeof(HASHdigest);
371 for( i=0; values[i].bv_val != NULL; i++ ) {
372 /* count number of indices to generate */
373 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
377 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
378 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
379 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
380 (SLAP_INDEX_SUBSTR_MINLEN - 1);
382 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
386 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
387 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
388 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
392 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
393 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
394 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
395 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
397 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
403 /* no keys to generate */
408 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
410 slen = syntax->ssyn_oidlen;
411 mlen = mr->smr_oidlen;
414 for( i=0; values[i].bv_val != NULL; i++ ) {
417 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
419 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
420 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
422 char pre = SLAP_INDEX_SUBSTR_PREFIX;
423 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
425 for( j=0; j<max; j++ ) {
426 HASH_Init( &HASHcontext );
427 if( prefix != NULL && prefix->bv_len > 0 ) {
428 HASH_Update( &HASHcontext,
429 prefix->bv_val, prefix->bv_len );
432 HASH_Update( &HASHcontext,
433 &pre, sizeof( pre ) );
434 HASH_Update( &HASHcontext,
435 syntax->ssyn_oid, slen );
436 HASH_Update( &HASHcontext,
438 HASH_Update( &HASHcontext,
439 &values[i].bv_val[j],
440 SLAP_INDEX_SUBSTR_MAXLEN );
441 HASH_Final( HASHdigest, &HASHcontext );
443 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
447 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
448 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
450 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
453 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
454 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
455 HASH_Init( &HASHcontext );
456 if( prefix != NULL && prefix->bv_len > 0 ) {
457 HASH_Update( &HASHcontext,
458 prefix->bv_val, prefix->bv_len );
460 HASH_Update( &HASHcontext,
461 &pre, sizeof( pre ) );
462 HASH_Update( &HASHcontext,
463 syntax->ssyn_oid, slen );
464 HASH_Update( &HASHcontext,
466 HASH_Update( &HASHcontext,
467 values[i].bv_val, j );
468 HASH_Final( HASHdigest, &HASHcontext );
470 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
473 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
474 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
475 HASH_Init( &HASHcontext );
476 if( prefix != NULL && prefix->bv_len > 0 ) {
477 HASH_Update( &HASHcontext,
478 prefix->bv_val, prefix->bv_len );
480 HASH_Update( &HASHcontext,
481 &pre, sizeof( pre ) );
482 HASH_Update( &HASHcontext,
483 syntax->ssyn_oid, slen );
484 HASH_Update( &HASHcontext,
486 HASH_Update( &HASHcontext,
487 &values[i].bv_val[values[i].bv_len-j], j );
488 HASH_Final( HASHdigest, &HASHcontext );
490 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
498 keys[nkeys].bv_val = NULL;
509 octetStringSubstringsFilter (
514 struct berval *prefix,
515 void * assertedValue,
519 SubstringsAssertion *sa;
523 size_t slen, mlen, klen;
525 HASH_CONTEXT HASHcontext;
526 unsigned char HASHdigest[HASH_BYTES];
527 struct berval *value;
528 struct berval digest;
530 sa = (SubstringsAssertion *) assertedValue;
532 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
533 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
538 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
540 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
541 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
542 /* don't bother accounting for stepping */
543 nkeys += sa->sa_any[i].bv_len -
544 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
549 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
550 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
560 digest.bv_val = HASHdigest;
561 digest.bv_len = sizeof(HASHdigest);
563 slen = syntax->ssyn_oidlen;
564 mlen = mr->smr_oidlen;
566 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
569 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
570 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
572 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
573 value = &sa->sa_initial;
575 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
576 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
578 HASH_Init( &HASHcontext );
579 if( prefix != NULL && prefix->bv_len > 0 ) {
580 HASH_Update( &HASHcontext,
581 prefix->bv_val, prefix->bv_len );
583 HASH_Update( &HASHcontext,
584 &pre, sizeof( pre ) );
585 HASH_Update( &HASHcontext,
586 syntax->ssyn_oid, slen );
587 HASH_Update( &HASHcontext,
589 HASH_Update( &HASHcontext,
590 value->bv_val, klen );
591 HASH_Final( HASHdigest, &HASHcontext );
593 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
596 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
598 pre = SLAP_INDEX_SUBSTR_PREFIX;
599 klen = SLAP_INDEX_SUBSTR_MAXLEN;
601 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
602 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
606 value = &sa->sa_any[i];
609 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
610 j += SLAP_INDEX_SUBSTR_STEP )
612 HASH_Init( &HASHcontext );
613 if( prefix != NULL && prefix->bv_len > 0 ) {
614 HASH_Update( &HASHcontext,
615 prefix->bv_val, prefix->bv_len );
617 HASH_Update( &HASHcontext,
618 &pre, sizeof( pre ) );
619 HASH_Update( &HASHcontext,
620 syntax->ssyn_oid, slen );
621 HASH_Update( &HASHcontext,
623 HASH_Update( &HASHcontext,
624 &value->bv_val[j], klen );
625 HASH_Final( HASHdigest, &HASHcontext );
627 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
632 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
633 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
635 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
636 value = &sa->sa_final;
638 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
639 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
641 HASH_Init( &HASHcontext );
642 if( prefix != NULL && prefix->bv_len > 0 ) {
643 HASH_Update( &HASHcontext,
644 prefix->bv_val, prefix->bv_len );
646 HASH_Update( &HASHcontext,
647 &pre, sizeof( pre ) );
648 HASH_Update( &HASHcontext,
649 syntax->ssyn_oid, slen );
650 HASH_Update( &HASHcontext,
652 HASH_Update( &HASHcontext,
653 &value->bv_val[value->bv_len-klen], klen );
654 HASH_Final( HASHdigest, &HASHcontext );
656 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
660 keys[nkeys].bv_val = NULL;
677 /* very unforgiving validation, requires no normalization
678 * before simplistic matching
680 if( in->bv_len < 3 ) {
681 return LDAP_INVALID_SYNTAX;
685 * RFC 2252 section 6.3 Bit String
686 * bitstring = "'" *binary-digit "'B"
687 * binary-digit = "0" / "1"
688 * example: '0101111101'B
691 if( in->bv_val[0] != '\'' ||
692 in->bv_val[in->bv_len-2] != '\'' ||
693 in->bv_val[in->bv_len-1] != 'B' )
695 return LDAP_INVALID_SYNTAX;
698 for( i=in->bv_len-3; i>0; i-- ) {
699 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
700 return LDAP_INVALID_SYNTAX;
715 if( in->bv_len == 0 ) return LDAP_SUCCESS;
717 ber_dupbv( &dn, in );
718 if( !dn.bv_val ) return LDAP_OTHER;
720 if( dn.bv_val[dn.bv_len-1] == 'B'
721 && dn.bv_val[dn.bv_len-2] == '\'' )
723 /* assume presence of optional UID */
726 for(i=dn.bv_len-3; i>1; i--) {
727 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
731 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
732 ber_memfree( dn.bv_val );
733 return LDAP_INVALID_SYNTAX;
736 /* trim the UID to allow use of dnValidate */
737 dn.bv_val[i-1] = '\0';
741 rc = dnValidate( NULL, &dn );
743 ber_memfree( dn.bv_val );
748 uniqueMemberNormalize(
753 struct berval *normalized,
759 ber_dupbv( &out, val );
760 if( out.bv_len != 0 ) {
761 struct berval uid = { 0, NULL };
763 if( out.bv_val[out.bv_len-1] == 'B'
764 && out.bv_val[out.bv_len-2] == '\'' )
766 /* assume presence of optional UID */
767 uid.bv_val = strrchr( out.bv_val, '#' );
769 if( uid.bv_val == NULL ) {
771 return LDAP_INVALID_SYNTAX;
774 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
775 out.bv_len -= uid.bv_len--;
777 /* temporarily trim the UID */
778 *(uid.bv_val++) = '\0';
781 rc = dnNormalize2( NULL, &out, normalized, ctx );
783 if( rc != LDAP_SUCCESS ) {
785 return LDAP_INVALID_SYNTAX;
789 normalized->bv_val = ch_realloc( normalized->bv_val,
790 normalized->bv_len + uid.bv_len + sizeof("#") );
792 /* insert the separator */
793 normalized->bv_val[normalized->bv_len++] = '#';
796 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
797 uid.bv_val, uid.bv_len );
798 normalized->bv_len += uid.bv_len;
801 normalized->bv_val[normalized->bv_len] = '\0';
811 * Handling boolean syntax and matching is quite rigid.
812 * A more flexible approach would be to allow a variety
813 * of strings to be normalized and prettied into TRUE
821 /* very unforgiving validation, requires no normalization
822 * before simplistic matching
825 if( in->bv_len == 4 ) {
826 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
829 } else if( in->bv_len == 5 ) {
830 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
835 return LDAP_INVALID_SYNTAX;
844 struct berval *value,
845 void *assertedValue )
847 /* simplistic matching allowed by rigid validation */
848 struct berval *asserted = (struct berval *) assertedValue;
849 *matchp = value->bv_len != asserted->bv_len;
853 /*-------------------------------------------------------------------
854 LDAP/X.500 string syntax / matching rules have a few oddities. This
855 comment attempts to detail how slapd(8) treats them.
858 StringSyntax X.500 LDAP Matching/Comments
859 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
860 PrintableString subset subset i/e + ignore insignificant spaces
861 PrintableString subset subset i/e + ignore insignificant spaces
862 NumericString subset subset ignore all spaces
863 IA5String ASCII ASCII i/e + ignore insignificant spaces
864 TeletexString T.61 T.61 i/e + ignore insignificant spaces
866 TelephoneNumber subset subset i + ignore all spaces and "-"
868 See draft-ietf-ldapbis-strpro for details (once published).
872 In X.500(93), a directory string can be either a PrintableString,
873 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
874 In later versions, more CHOICEs were added. In all cases the string
877 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
878 A directory string cannot be zero length.
880 For matching, there are both case ignore and exact rules. Both
881 also require that "insignificant" spaces be ignored.
882 spaces before the first non-space are ignored;
883 spaces after the last non-space are ignored;
884 spaces after a space are ignored.
885 Note: by these rules (and as clarified in X.520), a string of only
886 spaces is to be treated as if held one space, not empty (which
887 would be a syntax error).
890 In ASN.1, numeric string is just a string of digits and spaces
891 and could be empty. However, in X.500, all attribute values of
892 numeric string carry a non-empty constraint. For example:
894 internationalISDNNumber ATTRIBUTE ::= {
895 WITH SYNTAX InternationalISDNNumber
896 EQUALITY MATCHING RULE numericStringMatch
897 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
898 ID id-at-internationalISDNNumber }
899 InternationalISDNNumber ::=
900 NumericString (SIZE(1..ub-international-isdn-number))
902 Unforunately, some assertion values are don't carry the same
903 constraint (but its unclear how such an assertion could ever
904 be true). In LDAP, there is one syntax (numericString) not two
905 (numericString with constraint, numericString without constraint).
906 This should be treated as numericString with non-empty constraint.
907 Note that while someone may have no ISDN number, there are no ISDN
908 numbers which are zero length.
910 In matching, spaces are ignored.
913 In ASN.1, Printable string is just a string of printable characters
914 and can be empty. In X.500, semantics much like NumericString (see
915 serialNumber for a like example) excepting uses insignificant space
916 handling instead of ignore all spaces.
919 Basically same as PrintableString. There are no examples in X.500,
920 but same logic applies. So we require them to be non-empty as
923 -------------------------------------------------------------------*/
932 unsigned char *u = in->bv_val;
934 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
935 /* directory strings cannot be empty */
936 return LDAP_INVALID_SYNTAX;
939 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
940 /* get the length indicated by the first byte */
941 len = LDAP_UTF8_CHARLEN2( u, len );
943 /* very basic checks */
946 if( (u[5] & 0xC0) != 0x80 ) {
947 return LDAP_INVALID_SYNTAX;
950 if( (u[4] & 0xC0) != 0x80 ) {
951 return LDAP_INVALID_SYNTAX;
954 if( (u[3] & 0xC0) != 0x80 ) {
955 return LDAP_INVALID_SYNTAX;
958 if( (u[2] & 0xC0 )!= 0x80 ) {
959 return LDAP_INVALID_SYNTAX;
962 if( (u[1] & 0xC0) != 0x80 ) {
963 return LDAP_INVALID_SYNTAX;
966 /* CHARLEN already validated it */
969 return LDAP_INVALID_SYNTAX;
972 /* make sure len corresponds with the offset
973 to the next character */
974 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
978 return LDAP_INVALID_SYNTAX;
990 struct berval *normalized,
993 struct berval tmp, nvalue;
997 if( val->bv_val == NULL ) {
998 /* assume we're dealing with a syntax (e.g., UTF8String)
999 * which allows empty strings
1001 normalized->bv_len = 0;
1002 normalized->bv_val = NULL;
1003 return LDAP_SUCCESS;
1006 flags = (mr == slap_schema.si_mr_caseExactMatch)
1007 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1008 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1009 ? LDAP_UTF8_APPROX : 0;
1011 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1016 /* collapse spaces (in place) */
1018 nvalue.bv_val = tmp.bv_val;
1020 wasspace=1; /* trim leading spaces */
1021 for( i=0; i<tmp.bv_len; i++) {
1022 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1023 if( wasspace++ == 0 ) {
1024 /* trim repeated spaces */
1025 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1029 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1033 if( nvalue.bv_len ) {
1035 /* last character was a space, trim it */
1038 nvalue.bv_val[nvalue.bv_len] = '\0';
1041 /* string of all spaces is treated as one space */
1042 nvalue.bv_val[0] = ' ';
1043 nvalue.bv_val[1] = '\0';
1047 *normalized = nvalue;
1048 return LDAP_SUCCESS;
1051 #ifndef SLAP_NVALUES
1053 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1054 #if defined(SLAPD_APPROX_INITIALS)
1055 #define SLAPD_APPROX_DELIMITER "._ "
1056 #define SLAPD_APPROX_WORDLEN 2
1058 #define SLAPD_APPROX_DELIMITER " "
1059 #define SLAPD_APPROX_WORDLEN 1
1068 struct berval *value,
1069 void *assertedValue )
1071 struct berval *nval, *assertv;
1072 char *val, **values, **words, *c;
1073 int i, count, len, nextchunk=0, nextavail=0;
1075 /* Yes, this is necessary */
1076 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1077 if( nval == NULL ) {
1079 return LDAP_SUCCESS;
1082 /* Yes, this is necessary */
1083 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1084 NULL, LDAP_UTF8_APPROX );
1085 if( assertv == NULL ) {
1088 return LDAP_SUCCESS;
1091 /* Isolate how many words there are */
1092 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1093 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1094 if ( c == NULL ) break;
1099 /* Get a phonetic copy of each word */
1100 words = (char **)ch_malloc( count * sizeof(char *) );
1101 values = (char **)ch_malloc( count * sizeof(char *) );
1102 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1104 values[i] = phonetic(c);
1107 /* Work through the asserted value's words, to see if at least some
1108 of the words are there, in the same order. */
1110 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1111 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1116 #if defined(SLAPD_APPROX_INITIALS)
1117 else if( len == 1 ) {
1118 /* Single letter words need to at least match one word's initial */
1119 for( i=nextavail; i<count; i++ )
1120 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1127 /* Isolate the next word in the asserted value and phonetic it */
1128 assertv->bv_val[nextchunk+len] = '\0';
1129 val = phonetic( assertv->bv_val + nextchunk );
1131 /* See if this phonetic chunk is in the remaining words of *value */
1132 for( i=nextavail; i<count; i++ ){
1133 if( !strcmp( val, values[i] ) ){
1141 /* This chunk in the asserted value was NOT within the *value. */
1147 /* Go on to the next word in the asserted value */
1151 /* If some of the words were seen, call it a match */
1152 if( nextavail > 0 ) {
1159 /* Cleanup allocs */
1160 ber_bvfree( assertv );
1161 for( i=0; i<count; i++ ) {
1162 ch_free( values[i] );
1168 return LDAP_SUCCESS;
1177 struct berval *prefix,
1182 int i,j, len, wordcount, keycount=0;
1183 struct berval *newkeys;
1184 BerVarray keys=NULL;
1186 for( j=0; values[j].bv_val != NULL; j++ ) {
1187 struct berval val = { 0, NULL };
1188 /* Yes, this is necessary */
1189 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1190 assert( val.bv_val != NULL );
1192 /* Isolate how many words there are. There will be a key for each */
1193 for( wordcount = 0, c = val.bv_val; *c; c++) {
1194 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1195 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1197 if (*c == '\0') break;
1201 /* Allocate/increase storage to account for new keys */
1202 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1203 * sizeof(struct berval) );
1204 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1205 if( keys ) ch_free( keys );
1208 /* Get a phonetic copy of each word */
1209 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1211 if( len < SLAPD_APPROX_WORDLEN ) continue;
1212 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1217 ber_memfree( val.bv_val );
1219 keys[keycount].bv_val = NULL;
1222 return LDAP_SUCCESS;
1231 struct berval *prefix,
1232 void * assertedValue,
1240 /* Yes, this is necessary */
1241 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1242 NULL, LDAP_UTF8_APPROX );
1243 if( val == NULL || val->bv_val == NULL ) {
1244 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1245 keys[0].bv_val = NULL;
1248 return LDAP_SUCCESS;
1251 /* Isolate how many words there are. There will be a key for each */
1252 for( count = 0,c = val->bv_val; *c; c++) {
1253 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1254 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1256 if (*c == '\0') break;
1260 /* Allocate storage for new keys */
1261 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1263 /* Get a phonetic copy of each word */
1264 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1266 if( len < SLAPD_APPROX_WORDLEN ) continue;
1267 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1273 keys[count].bv_val = NULL;
1276 return LDAP_SUCCESS;
1280 /* No other form of Approximate Matching is defined */
1288 struct berval *value,
1289 void *assertedValue )
1291 char *vapprox, *avapprox;
1294 /* Yes, this is necessary */
1295 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1298 return LDAP_SUCCESS;
1301 /* Yes, this is necessary */
1302 t = UTF8normalize( ((struct berval *)assertedValue),
1307 return LDAP_SUCCESS;
1310 vapprox = phonetic( strip8bitChars( s ) );
1311 avapprox = phonetic( strip8bitChars( t ) );
1316 *matchp = strcmp( vapprox, avapprox );
1319 ch_free( avapprox );
1321 return LDAP_SUCCESS;
1330 struct berval *prefix,
1338 for( i=0; values[i].bv_val != NULL; i++ ) {
1339 /* empty - just count them */
1342 /* we should have at least one value at this point */
1345 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1347 /* Copy each value and run it through phonetic() */
1348 for( i=0; values[i].bv_val != NULL; i++ ) {
1349 /* Yes, this is necessary */
1350 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1352 /* strip 8-bit chars and run through phonetic() */
1353 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1356 keys[i].bv_val = NULL;
1359 return LDAP_SUCCESS;
1368 struct berval *prefix,
1369 void * assertedValue,
1375 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1377 /* Yes, this is necessary */
1378 s = UTF8normalize( ((struct berval *)assertedValue),
1383 /* strip 8-bit chars and run through phonetic() */
1384 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1390 return LDAP_SUCCESS;
1393 #endif /* !SLAP_NVALUES */
1395 /* Remove all spaces and '-' characters */
1397 telephoneNumberNormalize(
1402 struct berval *normalized,
1407 /* validator should have refused an empty string */
1408 assert( val->bv_len );
1410 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1412 for( p = val->bv_val; *p; p++ ) {
1413 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1419 normalized->bv_len = q - normalized->bv_val;
1421 if( normalized->bv_len == 0 ) {
1422 sl_free( normalized->bv_val, ctx );
1423 return LDAP_INVALID_SYNTAX;
1426 return LDAP_SUCCESS;
1432 struct berval *val )
1436 if( val->bv_len == 0 ) {
1437 /* disallow empty strings */
1438 return LDAP_INVALID_SYNTAX;
1441 if( OID_LEADCHAR(val->bv_val[0]) ) {
1443 for(i=1; i < val->bv_len; i++) {
1444 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1445 if( dot++ ) return 1;
1446 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1449 return LDAP_INVALID_SYNTAX;
1453 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1455 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1456 for(i=1; i < val->bv_len; i++) {
1457 if( !DESC_CHAR(val->bv_val[i] ) ) {
1458 return LDAP_INVALID_SYNTAX;
1462 return LDAP_SUCCESS;
1465 return LDAP_INVALID_SYNTAX;
1474 struct berval *value,
1475 void *assertedValue )
1478 int vsign = 1, avsign = 1; /* default sign = '+' */
1479 struct berval *asserted;
1480 ber_len_t vlen, avlen;
1483 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1485 vlen = value->bv_len;
1487 #ifndef SLAP_NVALUES
1488 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1489 char *tmp = memchr( v, '$', vlen );
1490 if( tmp ) vlen = tmp - v;
1491 while( vlen && ASCII_SPACE( v[vlen-1] )) vlen--;
1495 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) { /* ANSI 2.2.1 */
1496 if( *v == '-' ) vsign = -1;
1499 if( vlen == 0 ) vsign = 0;
1501 /* Do the same with the *assertedValue number */
1502 asserted = (struct berval *) assertedValue;
1503 av = asserted->bv_val;
1504 avlen = asserted->bv_len;
1505 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1511 match = vsign - avsign;
1513 match = (vlen != avlen
1514 ? ( vlen < avlen ? -1 : 1 )
1515 : memcmp( v, av, vlen ));
1516 if( vsign < 0 ) match = -match;
1520 return LDAP_SUCCESS;
1526 struct berval *val )
1530 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1532 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1533 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1535 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1536 return LDAP_INVALID_SYNTAX;
1539 for( i=1; i < val->bv_len; i++ ) {
1540 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1543 return LDAP_SUCCESS;
1552 struct berval *normalized,
1562 /* Ignore leading spaces */
1563 while ( len && ( *p == ' ' )) {
1570 negative = ( *p == '-' );
1571 if(( *p == '-' ) || ( *p == '+' )) {
1577 /* Ignore leading zeros */
1578 while ( len && ( *p == '0' )) {
1583 /* If there are no non-zero digits left, the number is zero, otherwise
1584 allocate space for the number and copy it into the buffer */
1586 normalized->bv_val = ber_strdup_x("0", ctx);
1587 normalized->bv_len = 1;
1590 normalized->bv_len = len+negative;
1591 normalized->bv_val = sl_malloc( normalized->bv_len + 1, ctx );
1592 if( negative ) normalized->bv_val[0] = '-';
1593 AC_MEMCPY( normalized->bv_val + negative, p, len );
1594 normalized->bv_val[len+negative] = '\0';
1597 return LDAP_SUCCESS;
1601 countryStringValidate(
1603 struct berval *val )
1605 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1607 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1608 return LDAP_INVALID_SYNTAX;
1610 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1611 return LDAP_INVALID_SYNTAX;
1614 return LDAP_SUCCESS;
1618 printableStringValidate(
1620 struct berval *val )
1624 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1626 for(i=0; i < val->bv_len; i++) {
1627 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1628 return LDAP_INVALID_SYNTAX;
1632 return LDAP_SUCCESS;
1636 printablesStringValidate(
1638 struct berval *val )
1642 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1644 for(i=0,len=0; i < val->bv_len; i++) {
1645 int c = val->bv_val[i];
1649 return LDAP_INVALID_SYNTAX;
1653 } else if ( SLAP_PRINTABLE(c) ) {
1656 return LDAP_INVALID_SYNTAX;
1661 return LDAP_INVALID_SYNTAX;
1664 return LDAP_SUCCESS;
1670 struct berval *val )
1674 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1676 for(i=0; i < val->bv_len; i++) {
1677 if( !LDAP_ASCII(val->bv_val[i]) ) {
1678 return LDAP_INVALID_SYNTAX;
1682 return LDAP_SUCCESS;
1691 struct berval *normalized,
1695 int casefold = (mr != slap_schema.si_mr_caseExactIA5Match);
1697 assert( val->bv_len );
1701 /* Ignore initial whitespace */
1702 while ( ASCII_SPACE( *p ) ) {
1706 normalized->bv_val = ber_strdup_x( p, ctx );
1707 p = q = normalized->bv_val;
1710 if ( ASCII_SPACE( *p ) ) {
1713 /* Ignore the extra whitespace */
1714 while ( ASCII_SPACE( *p ) ) {
1718 } else if ( casefold ) {
1719 /* Most IA5 rules require casefolding */
1720 *q++ = TOLOWER(*p++);
1727 assert( normalized->bv_val <= p );
1731 * If the string ended in space, backup the pointer one
1732 * position. One is enough because the above loop collapsed
1733 * all whitespace to a single space.
1736 if ( ASCII_SPACE( q[-1] ) ) {
1740 /* null terminate */
1743 normalized->bv_len = q - normalized->bv_val;
1745 if( normalized->bv_len == 0 ) {
1746 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1747 normalized->bv_val[0] = ' ';
1748 normalized->bv_val[1] = '\0';
1749 normalized->bv_len = 1;
1752 return LDAP_SUCCESS;
1756 numericStringValidate(
1762 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1764 for(i=0; i < in->bv_len; i++) {
1765 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1766 return LDAP_INVALID_SYNTAX;
1770 return LDAP_SUCCESS;
1774 numericStringNormalize(
1779 struct berval *normalized,
1782 /* removal all spaces */
1785 assert( val->bv_len );
1787 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1790 q = normalized->bv_val;
1793 if ( ASCII_SPACE( *p ) ) {
1794 /* Ignore whitespace */
1801 /* we should have copied no more then is in val */
1802 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1804 /* null terminate */
1807 normalized->bv_len = q - normalized->bv_val;
1809 if( normalized->bv_len == 0 ) {
1810 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1811 normalized->bv_val[0] = ' ';
1812 normalized->bv_val[1] = '\0';
1813 normalized->bv_len = 1;
1816 return LDAP_SUCCESS;
1819 #ifndef SLAP_NVALUES
1821 objectIdentifierFirstComponentMatch(
1826 struct berval *value,
1827 void *assertedValue )
1829 int rc = LDAP_SUCCESS;
1831 struct berval *asserted = (struct berval *) assertedValue;
1835 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1836 return LDAP_INVALID_SYNTAX;
1839 /* trim leading white space */
1840 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1844 /* grab next word */
1845 oid.bv_val = &value->bv_val[i];
1846 j = value->bv_len - i;
1847 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1852 /* insert attributeTypes, objectclass check here */
1853 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1854 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1857 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1858 MatchingRule *asserted_mr = mr_bvfind( asserted );
1859 MatchingRule *stored_mr = mr_bvfind( &oid );
1861 if( asserted_mr == NULL ) {
1862 rc = SLAPD_COMPARE_UNDEFINED;
1864 match = asserted_mr != stored_mr;
1867 } else if ( !strcmp( syntax->ssyn_oid,
1868 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1870 AttributeType *asserted_at = at_bvfind( asserted );
1871 AttributeType *stored_at = at_bvfind( &oid );
1873 if( asserted_at == NULL ) {
1874 rc = SLAPD_COMPARE_UNDEFINED;
1876 match = asserted_at != stored_at;
1879 } else if ( !strcmp( syntax->ssyn_oid,
1880 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1882 ObjectClass *asserted_oc = oc_bvfind( asserted );
1883 ObjectClass *stored_oc = oc_bvfind( &oid );
1885 if( asserted_oc == NULL ) {
1886 rc = SLAPD_COMPARE_UNDEFINED;
1888 match = asserted_oc != stored_oc;
1894 LDAP_LOG( CONFIG, ENTRY,
1895 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1896 match, value->bv_val, asserted->bv_val );
1898 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1899 "%d\n\t\"%s\"\n\t\"%s\"\n",
1900 match, value->bv_val, asserted->bv_val );
1903 if( rc == LDAP_SUCCESS ) *matchp = match;
1914 struct berval *value,
1915 void *assertedValue )
1917 long lValue, lAssertedValue;
1919 /* safe to assume integers are NUL terminated? */
1920 lValue = strtol(value->bv_val, NULL, 10);
1921 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1922 return LDAP_CONSTRAINT_VIOLATION;
1925 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1926 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1927 && errno == ERANGE )
1929 return LDAP_CONSTRAINT_VIOLATION;
1932 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1933 return LDAP_SUCCESS;
1942 struct berval *value,
1943 void *assertedValue )
1945 long lValue, lAssertedValue;
1947 /* safe to assume integers are NUL terminated? */
1948 lValue = strtol(value->bv_val, NULL, 10);
1949 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1950 return LDAP_CONSTRAINT_VIOLATION;
1953 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1954 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1955 && errno == ERANGE )
1957 return LDAP_CONSTRAINT_VIOLATION;
1960 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1961 return LDAP_SUCCESS;
1964 #ifndef SLAP_NVALUES
1966 #include <openssl/x509.h>
1967 #include <openssl/err.h>
1970 * Next function returns a string representation of a ASN1_INTEGER.
1971 * It works for unlimited lengths.
1974 static struct berval *
1975 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1979 static char digit[] = "0123456789";
1981 /* We work backwards, make it fill from the end of buf */
1982 p = buf + sizeof(buf) - 1;
1985 if ( a == NULL || a->length == 0 ) {
1993 /* We want to preserve the original */
1994 copy = ch_malloc(n*sizeof(unsigned int));
1995 for (i = 0; i<n; i++) {
1996 copy[i] = a->data[i];
2000 * base indicates the index of the most significant
2001 * byte that might be nonzero. When it goes off the
2002 * end, we now there is nothing left to do.
2008 for (i = base; i<n; i++ ) {
2009 copy[i] += carry*256;
2010 carry = copy[i] % 10;
2015 * Way too large, we need to leave
2016 * room for sign if negative
2021 *--p = digit[carry];
2023 if (copy[base] == 0) base++;
2028 if ( a->type == V_ASN1_NEG_INTEGER ) {
2032 return ber_str2bv( p, 0, 1, bv );
2036 * Given a certificate in DER format, extract the corresponding
2037 * assertion value for certificateExactMatch
2040 certificateExactConvert(
2042 struct berval * out )
2045 unsigned char *p = in->bv_val;
2046 struct berval serial;
2047 struct berval issuer_dn;
2049 xcert = d2i_X509(NULL, &p, in->bv_len);
2052 LDAP_LOG( CONFIG, ENTRY,
2053 "certificateExactConvert: error parsing cert: %s\n",
2054 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2056 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2057 "error parsing cert: %s\n",
2058 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2060 return LDAP_INVALID_SYNTAX;
2063 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2065 return LDAP_INVALID_SYNTAX;
2067 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2071 ber_memfree(serial.bv_val);
2072 return LDAP_INVALID_SYNTAX;
2077 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2078 out->bv_val = ch_malloc(out->bv_len);
2080 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2082 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2084 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2085 p += issuer_dn.bv_len;
2089 LDAP_LOG( CONFIG, ARGS,
2090 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2092 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2094 out->bv_val, NULL, NULL );
2097 ber_memfree(serial.bv_val);
2098 ber_memfree(issuer_dn.bv_val);
2100 return LDAP_SUCCESS;
2104 serial_and_issuer_parse(
2105 struct berval *assertion,
2106 struct berval *serial,
2107 struct berval *issuer_dn )
2114 begin = assertion->bv_val;
2115 end = assertion->bv_val+assertion->bv_len-1;
2116 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2117 if ( p > end ) return LDAP_INVALID_SYNTAX;
2119 /* p now points at the $ sign, now use
2120 * begin and end to delimit the serial number
2122 while (ASCII_SPACE(*begin)) begin++;
2124 while (ASCII_SPACE(*end)) end--;
2126 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2128 bv.bv_len = end-begin+1;
2130 ber_dupbv(serial, &bv);
2132 /* now extract the issuer, remember p was at the dollar sign */
2134 end = assertion->bv_val+assertion->bv_len-1;
2135 while (ASCII_SPACE(*begin)) begin++;
2136 /* should we trim spaces at the end too? is it safe always? no, no */
2138 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2141 bv.bv_len = end-begin+1;
2144 dnNormalize2( NULL, &bv, issuer_dn );
2147 return LDAP_SUCCESS;
2151 certificateExactMatch(
2156 struct berval *value,
2157 void *assertedValue )
2160 unsigned char *p = value->bv_val;
2161 struct berval serial;
2162 struct berval issuer_dn;
2163 struct berval asserted_serial;
2164 struct berval asserted_issuer_dn;
2167 xcert = d2i_X509(NULL, &p, value->bv_len);
2170 LDAP_LOG( CONFIG, ENTRY,
2171 "certificateExactMatch: error parsing cert: %s\n",
2172 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2174 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2175 "error parsing cert: %s\n",
2176 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2178 return LDAP_INVALID_SYNTAX;
2181 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2182 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2186 serial_and_issuer_parse(assertedValue,
2187 &asserted_serial, &asserted_issuer_dn);
2192 slap_schema.si_syn_integer,
2193 slap_schema.si_mr_integerMatch,
2196 if ( ret == LDAP_SUCCESS ) {
2197 if ( *matchp == 0 ) {
2198 /* We need to normalize everything for dnMatch */
2202 slap_schema.si_syn_distinguishedName,
2203 slap_schema.si_mr_distinguishedNameMatch,
2205 &asserted_issuer_dn);
2210 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2211 "%d\n\t\"%s $ %s\"\n",
2212 *matchp, serial.bv_val, issuer_dn.bv_val );
2213 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2214 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2217 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2218 "%d\n\t\"%s $ %s\"\n",
2219 *matchp, serial.bv_val, issuer_dn.bv_val );
2220 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2221 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2225 ber_memfree(serial.bv_val);
2226 ber_memfree(issuer_dn.bv_val);
2227 ber_memfree(asserted_serial.bv_val);
2228 ber_memfree(asserted_issuer_dn.bv_val);
2234 * Index generation function
2235 * We just index the serials, in most scenarios the issuer DN is one of
2236 * a very small set of values.
2238 static int certificateExactIndexer(
2243 struct berval *prefix,
2251 struct berval serial;
2253 /* we should have at least one value at this point */
2254 assert( values != NULL && values[0].bv_val != NULL );
2256 for( i=0; values[i].bv_val != NULL; i++ ) {
2257 /* empty -- just count them */
2260 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2262 for( i=0; values[i].bv_val != NULL; i++ ) {
2263 p = values[i].bv_val;
2264 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2267 LDAP_LOG( CONFIG, ENTRY,
2268 "certificateExactIndexer: error parsing cert: %s\n",
2269 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2271 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2272 "error parsing cert: %s\n",
2273 ERR_error_string(ERR_get_error(),NULL),
2276 /* Do we leak keys on error? */
2277 return LDAP_INVALID_SYNTAX;
2280 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2282 xintegerNormalize( slap_schema.si_syn_integer,
2283 &serial, &keys[i] );
2284 ber_memfree(serial.bv_val);
2286 LDAP_LOG( CONFIG, ENTRY,
2287 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2289 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2296 keys[i].bv_val = NULL;
2298 return LDAP_SUCCESS;
2301 /* Index generation function */
2302 /* We think this is always called with a value in matching rule syntax */
2303 static int certificateExactFilter(
2308 struct berval *prefix,
2309 void * assertedValue,
2313 struct berval asserted_serial;
2316 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2317 if( ret != LDAP_SUCCESS ) return ret;
2319 keys = ch_malloc( sizeof( struct berval ) * 2 );
2320 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2321 keys[1].bv_val = NULL;
2324 ber_memfree(asserted_serial.bv_val);
2325 return LDAP_SUCCESS;
2331 check_time_syntax (struct berval *val,
2335 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2336 static int mdays[2][12] = {
2337 /* non-leap years */
2338 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2340 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2343 int part, c, tzoffset, leapyear = 0 ;
2345 if( val->bv_len == 0 ) {
2346 return LDAP_INVALID_SYNTAX;
2349 p = (char *)val->bv_val;
2350 e = p + val->bv_len;
2352 /* Ignore initial whitespace */
2353 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2357 if (e - p < 13 - (2 * start)) {
2358 return LDAP_INVALID_SYNTAX;
2361 for (part = 0; part < 9; part++) {
2365 for (part = start; part < 7; part++) {
2367 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2374 return LDAP_INVALID_SYNTAX;
2376 if (c < 0 || c > 9) {
2377 return LDAP_INVALID_SYNTAX;
2383 return LDAP_INVALID_SYNTAX;
2385 if (c < 0 || c > 9) {
2386 return LDAP_INVALID_SYNTAX;
2391 if (part == 2 || part == 3) {
2394 if (parts[part] < 0) {
2395 return LDAP_INVALID_SYNTAX;
2397 if (parts[part] > ceiling[part]) {
2398 return LDAP_INVALID_SYNTAX;
2402 /* leapyear check for the Gregorian calendar (year>1581) */
2403 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2404 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2409 if (parts[3] > mdays[leapyear][parts[2]]) {
2410 return LDAP_INVALID_SYNTAX;
2415 tzoffset = 0; /* UTC */
2416 } else if (c != '+' && c != '-') {
2417 return LDAP_INVALID_SYNTAX;
2421 } else /* c == '+' */ {
2426 return LDAP_INVALID_SYNTAX;
2429 for (part = 7; part < 9; part++) {
2431 if (c < 0 || c > 9) {
2432 return LDAP_INVALID_SYNTAX;
2437 if (c < 0 || c > 9) {
2438 return LDAP_INVALID_SYNTAX;
2442 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2443 return LDAP_INVALID_SYNTAX;
2448 /* Ignore trailing whitespace */
2449 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2453 return LDAP_INVALID_SYNTAX;
2456 switch ( tzoffset ) {
2457 case -1: /* negativ offset to UTC, ie west of Greenwich */
2458 parts[4] += parts[7];
2459 parts[5] += parts[8];
2460 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2464 c = mdays[leapyear][parts[2]];
2466 if (parts[part] > c) {
2467 parts[part] -= c + 1;
2472 case 1: /* positive offset to UTC, ie east of Greenwich */
2473 parts[4] -= parts[7];
2474 parts[5] -= parts[8];
2475 for (part = 6; --part > 0; ) {
2479 /* first arg to % needs to be non negativ */
2480 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2482 if (parts[part] < 0) {
2483 parts[part] += c + 1;
2488 case 0: /* already UTC */
2492 return LDAP_SUCCESS;
2495 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2500 struct berval *normalized )
2504 rc = check_time_syntax(val, 1, parts);
2505 if (rc != LDAP_SUCCESS) {
2509 normalized->bv_val = ch_malloc( 14 );
2510 if ( normalized->bv_val == NULL ) {
2511 return LBER_ERROR_MEMORY;
2514 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2515 parts[1], parts[2] + 1, parts[3] + 1,
2516 parts[4], parts[5], parts[6] );
2517 normalized->bv_len = 13;
2519 return LDAP_SUCCESS;
2528 return check_time_syntax(in, 1, parts);
2533 generalizedTimeValidate(
2538 return check_time_syntax(in, 0, parts);
2542 generalizedTimeNormalize(
2547 struct berval *normalized,
2552 rc = check_time_syntax(val, 0, parts);
2553 if (rc != LDAP_SUCCESS) {
2557 normalized->bv_val = sl_malloc( 16, ctx );
2558 if ( normalized->bv_val == NULL ) {
2559 return LBER_ERROR_MEMORY;
2562 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2563 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2564 parts[4], parts[5], parts[6] );
2565 normalized->bv_len = 15;
2567 return LDAP_SUCCESS;
2571 nisNetgroupTripleValidate(
2573 struct berval *val )
2578 if ( val->bv_len == 0 ) {
2579 return LDAP_INVALID_SYNTAX;
2582 p = (char *)val->bv_val;
2583 e = p + val->bv_len;
2585 if ( *p != '(' /*')'*/ ) {
2586 return LDAP_INVALID_SYNTAX;
2589 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2593 return LDAP_INVALID_SYNTAX;
2596 } else if ( !AD_CHAR( *p ) ) {
2597 return LDAP_INVALID_SYNTAX;
2601 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2602 return LDAP_INVALID_SYNTAX;
2608 return LDAP_INVALID_SYNTAX;
2611 return LDAP_SUCCESS;
2615 bootParameterValidate(
2617 struct berval *val )
2621 if ( val->bv_len == 0 ) {
2622 return LDAP_INVALID_SYNTAX;
2625 p = (char *)val->bv_val;
2626 e = p + val->bv_len;
2629 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2630 if ( !AD_CHAR( *p ) ) {
2631 return LDAP_INVALID_SYNTAX;
2636 return LDAP_INVALID_SYNTAX;
2640 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2641 if ( !AD_CHAR( *p ) ) {
2642 return LDAP_INVALID_SYNTAX;
2647 return LDAP_INVALID_SYNTAX;
2651 for ( p++; p < e; p++ ) {
2652 if ( !SLAP_PRINTABLE( *p ) ) {
2653 return LDAP_INVALID_SYNTAX;
2657 return LDAP_SUCCESS;
2660 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2661 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2663 static slap_syntax_defs_rec syntax_defs[] = {
2664 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2665 X_BINARY X_NOT_H_R ")",
2666 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2667 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2669 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2671 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2673 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2674 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2676 SLAP_SYNTAX_BER, berValidate, NULL},
2677 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2678 0, bitStringValidate, NULL },
2679 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2680 0, booleanValidate, NULL},
2681 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2682 X_BINARY X_NOT_H_R ")",
2683 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2684 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2685 X_BINARY X_NOT_H_R ")",
2686 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2687 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2688 X_BINARY X_NOT_H_R ")",
2689 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2690 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2691 0, countryStringValidate, NULL},
2692 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2693 0, dnValidate, dnPretty2},
2694 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2696 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2698 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2699 0, UTF8StringValidate, NULL},
2700 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2702 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2704 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2706 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2708 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2710 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2711 0, printablesStringValidate, NULL},
2712 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2713 SLAP_SYNTAX_BLOB, NULL, NULL},
2714 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2715 0, generalizedTimeValidate, NULL},
2716 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2718 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2719 0, IA5StringValidate, NULL},
2720 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2721 0, integerValidate, NULL},
2722 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2723 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2724 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2726 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2728 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2730 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2732 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2734 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2735 0, nameUIDValidate, NULL},
2736 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2738 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2739 0, numericStringValidate, NULL},
2740 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2742 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2743 0, oidValidate, NULL},
2744 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2745 0, IA5StringValidate, NULL},
2746 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2747 0, blobValidate, NULL},
2748 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2749 0, UTF8StringValidate, NULL},
2750 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2752 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2754 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2755 0, printableStringValidate, NULL},
2756 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2757 X_BINARY X_NOT_H_R ")",
2758 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2759 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2760 X_BINARY X_NOT_H_R ")",
2761 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2762 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2763 0, printableStringValidate, NULL},
2764 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2766 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2767 0, printablesStringValidate, NULL},
2768 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2769 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2770 0, utcTimeValidate, NULL},
2772 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2774 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2776 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2778 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2780 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2783 /* RFC 2307 NIS Syntaxes */
2784 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2785 0, nisNetgroupTripleValidate, NULL},
2786 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2787 0, bootParameterValidate, NULL},
2791 /* These OIDs are not published yet, but will be in the next
2792 * I-D for PKIX LDAPv3 schema as have been advanced by David
2793 * Chadwick in private mail.
2795 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2796 0, UTF8StringValidate, NULL},
2799 /* OpenLDAP Experimental Syntaxes */
2800 #ifdef SLAPD_ACI_ENABLED
2801 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2803 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2807 #ifdef SLAPD_AUTHPASSWD
2808 /* needs updating */
2809 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2810 SLAP_SYNTAX_HIDE, NULL, NULL},
2813 /* OpenLDAP Void Syntax */
2814 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2815 SLAP_SYNTAX_HIDE, inValidate, NULL},
2816 {NULL, 0, NULL, NULL}
2820 char *certificateExactMatchSyntaxes[] = {
2821 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2825 char *directoryStringSyntaxes[] = {
2826 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2829 char *integerFirstComponentMatchSyntaxes[] = {
2830 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2831 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2834 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2835 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2836 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2837 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2838 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2839 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2840 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2841 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2842 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2847 * Other matching rules in X.520 that we do not use (yet):
2849 * 2.5.13.9 numericStringOrderingMatch
2850 * 2.5.13.25 uTCTimeMatch
2851 * 2.5.13.26 uTCTimeOrderingMatch
2852 * 2.5.13.31 directoryStringFirstComponentMatch
2853 * 2.5.13.32 wordMatch
2854 * 2.5.13.33 keywordMatch
2855 * 2.5.13.35 certificateMatch
2856 * 2.5.13.36 certificatePairExactMatch
2857 * 2.5.13.37 certificatePairMatch
2858 * 2.5.13.38 certificateListExactMatch
2859 * 2.5.13.39 certificateListMatch
2860 * 2.5.13.40 algorithmIdentifierMatch
2861 * 2.5.13.41 storedPrefixMatch
2862 * 2.5.13.42 attributeCertificateMatch
2863 * 2.5.13.43 readerAndKeyIDMatch
2864 * 2.5.13.44 attributeIntegrityMatch
2866 static slap_mrule_defs_rec mrule_defs[] = {
2868 * EQUALITY matching rules must be listed after associated APPROX
2869 * matching rules. So, we list all APPROX matching rules first.
2871 #ifndef SLAP_NVALUES
2872 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2873 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2874 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2875 NULL, NULL, directoryStringApproxMatch,
2876 directoryStringApproxIndexer, directoryStringApproxFilter,
2879 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2880 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2881 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2882 NULL, NULL, IA5StringApproxMatch,
2883 IA5StringApproxIndexer, IA5StringApproxFilter,
2888 * Other matching rules
2891 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2893 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2894 NULL, objectIdentifierNormalize, octetStringMatch,
2895 octetStringIndexer, octetStringFilter,
2898 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2899 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2900 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2901 NULL, dnNormalize, dnMatch,
2902 octetStringIndexer, octetStringFilter,
2905 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2906 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2907 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2908 NULL, UTF8StringNormalize, octetStringMatch,
2909 octetStringIndexer, octetStringFilter,
2910 directoryStringApproxMatchOID },
2912 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2913 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2914 SLAP_MR_ORDERING, directoryStringSyntaxes,
2915 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2919 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2920 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2921 SLAP_MR_SUBSTR, NULL,
2922 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2923 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2926 {"( 2.5.13.5 NAME 'caseExactMatch' "
2927 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2928 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2929 NULL, UTF8StringNormalize, octetStringMatch,
2930 octetStringIndexer, octetStringFilter,
2931 directoryStringApproxMatchOID },
2933 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2934 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2935 SLAP_MR_ORDERING, directoryStringSyntaxes,
2936 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2940 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2941 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2942 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2943 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2944 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2947 {"( 2.5.13.8 NAME 'numericStringMatch' "
2948 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2949 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2950 NULL, numericStringNormalize, octetStringSubstringsMatch,
2951 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2954 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2955 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2956 SLAP_MR_SUBSTR, NULL,
2957 NULL, numericStringNormalize, octetStringSubstringsMatch,
2958 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2961 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2962 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2963 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2964 NULL, NULL, NULL, NULL, NULL, NULL},
2966 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2968 SLAP_MR_SUBSTR, NULL,
2969 NULL, NULL, NULL, NULL, NULL, NULL},
2971 {"( 2.5.13.13 NAME 'booleanMatch' "
2972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2973 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2974 NULL, NULL, booleanMatch,
2975 octetStringIndexer, octetStringFilter,
2978 {"( 2.5.13.14 NAME 'integerMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2980 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2981 NULL, integerNormalize, integerMatch,
2982 octetStringIndexer, octetStringFilter,
2985 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2987 SLAP_MR_ORDERING, NULL,
2988 NULL, integerNormalize, integerOrderingMatch,
2992 {"( 2.5.13.16 NAME 'bitStringMatch' "
2993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2994 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2995 NULL, NULL, octetStringMatch,
2996 octetStringIndexer, octetStringFilter,
2999 {"( 2.5.13.17 NAME 'octetStringMatch' "
3000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3001 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3002 NULL, NULL, octetStringMatch,
3003 octetStringIndexer, octetStringFilter,
3006 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3008 SLAP_MR_ORDERING, NULL,
3009 NULL, NULL, octetStringOrderingMatch,
3013 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3015 SLAP_MR_SUBSTR, NULL,
3016 NULL, NULL, octetStringSubstringsMatch,
3017 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3020 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3021 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3022 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3024 telephoneNumberNormalize, octetStringMatch,
3025 octetStringIndexer, octetStringFilter,
3028 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3029 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3030 SLAP_MR_SUBSTR, NULL,
3031 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3032 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3035 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3036 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3037 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3038 NULL, NULL, NULL, NULL, NULL, NULL},
3040 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3041 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3042 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3043 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3047 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3049 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3050 NULL, NULL, NULL, NULL, NULL, NULL},
3052 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3054 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3055 NULL, generalizedTimeNormalize, octetStringMatch,
3059 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3061 SLAP_MR_ORDERING, NULL,
3062 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3066 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3068 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3069 NULL, integerFirstComponentNormalize, integerMatch,
3073 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3074 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3075 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3076 objectIdentifierFirstComponentMatchSyntaxes,
3077 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3078 octetStringIndexer, octetStringFilter,
3081 #ifndef SLAP_NVALUES
3083 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3084 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3085 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3086 certificateExactConvert, NULL, certificateExactMatch,
3087 certificateExactIndexer, certificateExactFilter,
3092 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
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.2 NAME 'caseIgnoreIA5Match' "
3100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3101 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3102 NULL, IA5StringNormalize, octetStringMatch,
3103 octetStringIndexer, octetStringFilter,
3104 IA5StringApproxMatchOID },
3106 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
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 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3115 SLAP_MR_SUBSTR, NULL,
3116 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3117 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3120 #ifdef SLAPD_AUTHPASSWD
3121 /* needs updating */
3122 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3123 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3124 SLAP_MR_EQUALITY, NULL,
3125 NULL, NULL, authPasswordMatch,
3130 #ifdef SLAPD_ACI_ENABLED
3131 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3132 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3133 SLAP_MR_EQUALITY, NULL,
3134 NULL, NULL, OpenLDAPaciMatch,
3139 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3140 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3142 NULL, NULL, integerBitAndMatch,
3146 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3147 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3149 NULL, NULL, integerBitOrMatch,
3153 {NULL, SLAP_MR_NONE, NULL,
3154 NULL, NULL, NULL, NULL, NULL,
3159 slap_schema_init( void )
3164 /* we should only be called once (from main) */
3165 assert( schema_init_done == 0 );
3167 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3168 res = register_syntax( &syntax_defs[i] );
3171 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3172 syntax_defs[i].sd_desc );
3177 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3178 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3179 mrule_defs[i].mrd_compat_syntaxes == NULL )
3182 "slap_schema_init: Ignoring unusable matching rule %s\n",
3183 mrule_defs[i].mrd_desc );
3187 res = register_matching_rule( &mrule_defs[i] );
3191 "slap_schema_init: Error registering matching rule %s\n",
3192 mrule_defs[i].mrd_desc );
3197 res = slap_schema_load();
3198 schema_init_done = 1;
3203 schema_destroy( void )