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 #define MR_ASSOCIATED(mr,amr) (((mr) == (amr)) || \
34 ((mr)->smr_associated == (amr)))
36 /* not yet implemented */
37 #define objectIdentifierNormalize NULL
38 #define integerOrderingMatch NULL
39 #define uniqueMemberMatch NULL
40 #define integerFirstComponentNormalize NULL
41 #define objectIdentifierFirstComponentNormalize NULL
43 #define OpenLDAPaciMatch NULL
45 /* approx matching rules */
47 #define directoryStringApproxMatchOID NULL
48 #define IA5StringApproxMatchOID NULL
50 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
51 #define directoryStringApproxMatch approxMatch
52 #define directoryStringApproxIndexer approxIndexer
53 #define directoryStringApproxFilter approxFilter
54 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
55 #define IA5StringApproxMatch approxMatch
56 #define IA5StringApproxIndexer approxIndexer
57 #define IA5StringApproxFilter approxFilter
65 /* no value allowed */
66 return LDAP_INVALID_SYNTAX;
74 /* any value allowed */
78 #define berValidate blobValidate
89 struct berval *asserted = (struct berval *) assertedValue;
90 int match = value->bv_len - asserted->bv_len;
93 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
101 octetStringOrderingMatch(
106 struct berval *value,
107 void *assertedValue )
109 struct berval *asserted = (struct berval *) assertedValue;
110 ber_len_t v_len = value->bv_len;
111 ber_len_t av_len = asserted->bv_len;
113 int match = memcmp( value->bv_val, asserted->bv_val,
114 (v_len < av_len ? v_len : av_len) );
116 if( match == 0 ) match = v_len - av_len;
122 /* Index generation function */
123 int octetStringIndexer(
128 struct berval *prefix,
136 HASH_CONTEXT HASHcontext;
137 unsigned char HASHdigest[HASH_BYTES];
138 struct berval digest;
139 digest.bv_val = HASHdigest;
140 digest.bv_len = sizeof(HASHdigest);
142 for( i=0; values[i].bv_val != NULL; i++ ) {
143 /* just count them */
146 /* we should have at least one value at this point */
149 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
151 slen = syntax->ssyn_oidlen;
152 mlen = mr->smr_oidlen;
154 for( i=0; values[i].bv_val != NULL; i++ ) {
155 HASH_Init( &HASHcontext );
156 if( prefix != NULL && prefix->bv_len > 0 ) {
157 HASH_Update( &HASHcontext,
158 prefix->bv_val, prefix->bv_len );
160 HASH_Update( &HASHcontext,
161 syntax->ssyn_oid, slen );
162 HASH_Update( &HASHcontext,
164 HASH_Update( &HASHcontext,
165 values[i].bv_val, values[i].bv_len );
166 HASH_Final( HASHdigest, &HASHcontext );
168 ber_dupbv_x( &keys[i], &digest, ctx );
171 keys[i].bv_val = NULL;
179 /* Index generation function */
180 int octetStringFilter(
185 struct berval *prefix,
186 void * assertedValue,
192 HASH_CONTEXT HASHcontext;
193 unsigned char HASHdigest[HASH_BYTES];
194 struct berval *value = (struct berval *) assertedValue;
195 struct berval digest;
196 digest.bv_val = HASHdigest;
197 digest.bv_len = sizeof(HASHdigest);
199 slen = syntax->ssyn_oidlen;
200 mlen = mr->smr_oidlen;
202 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
204 HASH_Init( &HASHcontext );
205 if( prefix != NULL && prefix->bv_len > 0 ) {
206 HASH_Update( &HASHcontext,
207 prefix->bv_val, prefix->bv_len );
209 HASH_Update( &HASHcontext,
210 syntax->ssyn_oid, slen );
211 HASH_Update( &HASHcontext,
213 HASH_Update( &HASHcontext,
214 value->bv_val, value->bv_len );
215 HASH_Final( HASHdigest, &HASHcontext );
217 ber_dupbv_x( keys, &digest, ctx );
218 keys[1].bv_val = NULL;
227 octetStringSubstringsMatch(
232 struct berval *value,
233 void *assertedValue )
236 SubstringsAssertion *sub = assertedValue;
237 struct berval left = *value;
241 /* Add up asserted input length */
242 if( sub->sa_initial.bv_val ) {
243 inlen += sub->sa_initial.bv_len;
246 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
247 inlen += sub->sa_any[i].bv_len;
250 if( sub->sa_final.bv_val ) {
251 inlen += sub->sa_final.bv_len;
254 if( sub->sa_initial.bv_val ) {
255 if( inlen > left.bv_len ) {
260 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
261 sub->sa_initial.bv_len );
267 left.bv_val += sub->sa_initial.bv_len;
268 left.bv_len -= sub->sa_initial.bv_len;
269 inlen -= sub->sa_initial.bv_len;
272 if( sub->sa_final.bv_val ) {
273 if( inlen > left.bv_len ) {
278 match = memcmp( sub->sa_final.bv_val,
279 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
280 sub->sa_final.bv_len );
286 left.bv_len -= sub->sa_final.bv_len;
287 inlen -= sub->sa_final.bv_len;
291 for(i=0; sub->sa_any[i].bv_val; i++) {
296 if( inlen > left.bv_len ) {
297 /* not enough length */
302 if( sub->sa_any[i].bv_len == 0 ) {
306 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
313 idx = p - left.bv_val;
315 if( idx >= left.bv_len ) {
316 /* this shouldn't happen */
323 if( sub->sa_any[i].bv_len > left.bv_len ) {
324 /* not enough left */
329 match = memcmp( left.bv_val,
330 sub->sa_any[i].bv_val,
331 sub->sa_any[i].bv_len );
339 left.bv_val += sub->sa_any[i].bv_len;
340 left.bv_len -= sub->sa_any[i].bv_len;
341 inlen -= sub->sa_any[i].bv_len;
350 /* Substrings Index generation function */
352 octetStringSubstringsIndexer(
357 struct berval *prefix,
362 ber_len_t i, j, nkeys;
366 HASH_CONTEXT HASHcontext;
367 unsigned char HASHdigest[HASH_BYTES];
368 struct berval digest;
369 digest.bv_val = HASHdigest;
370 digest.bv_len = sizeof(HASHdigest);
374 for( i=0; values[i].bv_val != NULL; i++ ) {
375 /* count number of indices to generate */
376 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
380 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
381 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
382 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
383 (SLAP_INDEX_SUBSTR_MINLEN - 1);
385 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
389 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
390 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
391 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
395 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
396 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
397 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
398 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
400 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
406 /* no keys to generate */
411 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
413 slen = syntax->ssyn_oidlen;
414 mlen = mr->smr_oidlen;
417 for( i=0; values[i].bv_val != NULL; i++ ) {
420 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
422 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
423 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
425 char pre = SLAP_INDEX_SUBSTR_PREFIX;
426 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
428 for( j=0; j<max; j++ ) {
429 HASH_Init( &HASHcontext );
430 if( prefix != NULL && prefix->bv_len > 0 ) {
431 HASH_Update( &HASHcontext,
432 prefix->bv_val, prefix->bv_len );
435 HASH_Update( &HASHcontext,
436 &pre, sizeof( pre ) );
437 HASH_Update( &HASHcontext,
438 syntax->ssyn_oid, slen );
439 HASH_Update( &HASHcontext,
441 HASH_Update( &HASHcontext,
442 &values[i].bv_val[j],
443 SLAP_INDEX_SUBSTR_MAXLEN );
444 HASH_Final( HASHdigest, &HASHcontext );
446 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
450 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
451 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
453 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
456 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
457 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
458 HASH_Init( &HASHcontext );
459 if( prefix != NULL && prefix->bv_len > 0 ) {
460 HASH_Update( &HASHcontext,
461 prefix->bv_val, prefix->bv_len );
463 HASH_Update( &HASHcontext,
464 &pre, sizeof( pre ) );
465 HASH_Update( &HASHcontext,
466 syntax->ssyn_oid, slen );
467 HASH_Update( &HASHcontext,
469 HASH_Update( &HASHcontext,
470 values[i].bv_val, j );
471 HASH_Final( HASHdigest, &HASHcontext );
473 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
476 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
477 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
478 HASH_Init( &HASHcontext );
479 if( prefix != NULL && prefix->bv_len > 0 ) {
480 HASH_Update( &HASHcontext,
481 prefix->bv_val, prefix->bv_len );
483 HASH_Update( &HASHcontext,
484 &pre, sizeof( pre ) );
485 HASH_Update( &HASHcontext,
486 syntax->ssyn_oid, slen );
487 HASH_Update( &HASHcontext,
489 HASH_Update( &HASHcontext,
490 &values[i].bv_val[values[i].bv_len-j], j );
491 HASH_Final( HASHdigest, &HASHcontext );
493 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
501 keys[nkeys].bv_val = NULL;
512 octetStringSubstringsFilter (
517 struct berval *prefix,
518 void * assertedValue,
522 SubstringsAssertion *sa;
525 size_t slen, mlen, klen;
527 HASH_CONTEXT HASHcontext;
528 unsigned char HASHdigest[HASH_BYTES];
529 struct berval *value;
530 struct berval digest;
532 sa = (SubstringsAssertion *) assertedValue;
534 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
535 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
540 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
542 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
543 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
544 /* don't bother accounting for stepping */
545 nkeys += sa->sa_any[i].bv_len -
546 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
551 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
552 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
562 digest.bv_val = HASHdigest;
563 digest.bv_len = sizeof(HASHdigest);
565 slen = syntax->ssyn_oidlen;
566 mlen = mr->smr_oidlen;
568 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
571 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
572 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
574 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
575 value = &sa->sa_initial;
577 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
578 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
580 HASH_Init( &HASHcontext );
581 if( prefix != NULL && prefix->bv_len > 0 ) {
582 HASH_Update( &HASHcontext,
583 prefix->bv_val, prefix->bv_len );
585 HASH_Update( &HASHcontext,
586 &pre, sizeof( pre ) );
587 HASH_Update( &HASHcontext,
588 syntax->ssyn_oid, slen );
589 HASH_Update( &HASHcontext,
591 HASH_Update( &HASHcontext,
592 value->bv_val, klen );
593 HASH_Final( HASHdigest, &HASHcontext );
595 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
598 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
600 pre = SLAP_INDEX_SUBSTR_PREFIX;
601 klen = SLAP_INDEX_SUBSTR_MAXLEN;
603 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
604 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
608 value = &sa->sa_any[i];
611 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
612 j += SLAP_INDEX_SUBSTR_STEP )
614 HASH_Init( &HASHcontext );
615 if( prefix != NULL && prefix->bv_len > 0 ) {
616 HASH_Update( &HASHcontext,
617 prefix->bv_val, prefix->bv_len );
619 HASH_Update( &HASHcontext,
620 &pre, sizeof( pre ) );
621 HASH_Update( &HASHcontext,
622 syntax->ssyn_oid, slen );
623 HASH_Update( &HASHcontext,
625 HASH_Update( &HASHcontext,
626 &value->bv_val[j], klen );
627 HASH_Final( HASHdigest, &HASHcontext );
629 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
634 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
635 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
637 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
638 value = &sa->sa_final;
640 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
641 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
643 HASH_Init( &HASHcontext );
644 if( prefix != NULL && prefix->bv_len > 0 ) {
645 HASH_Update( &HASHcontext,
646 prefix->bv_val, prefix->bv_len );
648 HASH_Update( &HASHcontext,
649 &pre, sizeof( pre ) );
650 HASH_Update( &HASHcontext,
651 syntax->ssyn_oid, slen );
652 HASH_Update( &HASHcontext,
654 HASH_Update( &HASHcontext,
655 &value->bv_val[value->bv_len-klen], klen );
656 HASH_Final( HASHdigest, &HASHcontext );
658 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
662 keys[nkeys].bv_val = NULL;
679 /* very unforgiving validation, requires no normalization
680 * before simplistic matching
682 if( in->bv_len < 3 ) {
683 return LDAP_INVALID_SYNTAX;
687 * RFC 2252 section 6.3 Bit String
688 * bitstring = "'" *binary-digit "'B"
689 * binary-digit = "0" / "1"
690 * example: '0101111101'B
693 if( in->bv_val[0] != '\'' ||
694 in->bv_val[in->bv_len-2] != '\'' ||
695 in->bv_val[in->bv_len-1] != 'B' )
697 return LDAP_INVALID_SYNTAX;
700 for( i=in->bv_len-3; i>0; i-- ) {
701 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
702 return LDAP_INVALID_SYNTAX;
717 if( in->bv_len == 0 ) return LDAP_SUCCESS;
719 ber_dupbv( &dn, in );
720 if( !dn.bv_val ) return LDAP_OTHER;
722 if( dn.bv_val[dn.bv_len-1] == 'B'
723 && dn.bv_val[dn.bv_len-2] == '\'' )
725 /* assume presence of optional UID */
728 for(i=dn.bv_len-3; i>1; i--) {
729 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
733 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
734 ber_memfree( dn.bv_val );
735 return LDAP_INVALID_SYNTAX;
738 /* trim the UID to allow use of dnValidate */
739 dn.bv_val[i-1] = '\0';
743 rc = dnValidate( NULL, &dn );
745 ber_memfree( dn.bv_val );
750 uniqueMemberNormalize(
755 struct berval *normalized,
761 ber_dupbv( &out, val );
762 if( out.bv_len != 0 ) {
763 struct berval uid = { 0, NULL };
765 if( out.bv_val[out.bv_len-1] == 'B'
766 && out.bv_val[out.bv_len-2] == '\'' )
768 /* assume presence of optional UID */
769 uid.bv_val = strrchr( out.bv_val, '#' );
771 if( uid.bv_val == NULL ) {
773 return LDAP_INVALID_SYNTAX;
776 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
777 out.bv_len -= uid.bv_len--;
779 /* temporarily trim the UID */
780 *(uid.bv_val++) = '\0';
783 rc = dnNormalize2( NULL, &out, normalized, ctx );
785 if( rc != LDAP_SUCCESS ) {
787 return LDAP_INVALID_SYNTAX;
791 normalized->bv_val = ch_realloc( normalized->bv_val,
792 normalized->bv_len + uid.bv_len + sizeof("#") );
794 /* insert the separator */
795 normalized->bv_val[normalized->bv_len++] = '#';
798 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
799 uid.bv_val, uid.bv_len );
800 normalized->bv_len += uid.bv_len;
803 normalized->bv_val[normalized->bv_len] = '\0';
813 * Handling boolean syntax and matching is quite rigid.
814 * A more flexible approach would be to allow a variety
815 * of strings to be normalized and prettied into TRUE
823 /* very unforgiving validation, requires no normalization
824 * before simplistic matching
827 if( in->bv_len == 4 ) {
828 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
831 } else if( in->bv_len == 5 ) {
832 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
837 return LDAP_INVALID_SYNTAX;
846 struct berval *value,
847 void *assertedValue )
849 /* simplistic matching allowed by rigid validation */
850 struct berval *asserted = (struct berval *) assertedValue;
851 *matchp = value->bv_len != asserted->bv_len;
855 /*-------------------------------------------------------------------
856 LDAP/X.500 string syntax / matching rules have a few oddities. This
857 comment attempts to detail how slapd(8) treats them.
860 StringSyntax X.500 LDAP Matching/Comments
861 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
862 PrintableString subset subset i/e + ignore insignificant spaces
863 PrintableString subset subset i/e + ignore insignificant spaces
864 NumericString subset subset ignore all spaces
865 IA5String ASCII ASCII i/e + ignore insignificant spaces
866 TeletexString T.61 T.61 i/e + ignore insignificant spaces
868 TelephoneNumber subset subset i + ignore all spaces and "-"
870 See draft-ietf-ldapbis-strpro for details (once published).
874 In X.500(93), a directory string can be either a PrintableString,
875 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
876 In later versions, more CHOICEs were added. In all cases the string
879 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
880 A directory string cannot be zero length.
882 For matching, there are both case ignore and exact rules. Both
883 also require that "insignificant" spaces be ignored.
884 spaces before the first non-space are ignored;
885 spaces after the last non-space are ignored;
886 spaces after a space are ignored.
887 Note: by these rules (and as clarified in X.520), a string of only
888 spaces is to be treated as if held one space, not empty (which
889 would be a syntax error).
892 In ASN.1, numeric string is just a string of digits and spaces
893 and could be empty. However, in X.500, all attribute values of
894 numeric string carry a non-empty constraint. For example:
896 internationalISDNNumber ATTRIBUTE ::= {
897 WITH SYNTAX InternationalISDNNumber
898 EQUALITY MATCHING RULE numericStringMatch
899 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
900 ID id-at-internationalISDNNumber }
901 InternationalISDNNumber ::=
902 NumericString (SIZE(1..ub-international-isdn-number))
904 Unforunately, some assertion values are don't carry the same
905 constraint (but its unclear how such an assertion could ever
906 be true). In LDAP, there is one syntax (numericString) not two
907 (numericString with constraint, numericString without constraint).
908 This should be treated as numericString with non-empty constraint.
909 Note that while someone may have no ISDN number, there are no ISDN
910 numbers which are zero length.
912 In matching, spaces are ignored.
915 In ASN.1, Printable string is just a string of printable characters
916 and can be empty. In X.500, semantics much like NumericString (see
917 serialNumber for a like example) excepting uses insignificant space
918 handling instead of ignore all spaces.
921 Basically same as PrintableString. There are no examples in X.500,
922 but same logic applies. So we require them to be non-empty as
925 -------------------------------------------------------------------*/
934 unsigned char *u = in->bv_val;
936 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
937 /* directory strings cannot be empty */
938 return LDAP_INVALID_SYNTAX;
941 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
942 /* get the length indicated by the first byte */
943 len = LDAP_UTF8_CHARLEN2( u, len );
945 /* very basic checks */
948 if( (u[5] & 0xC0) != 0x80 ) {
949 return LDAP_INVALID_SYNTAX;
952 if( (u[4] & 0xC0) != 0x80 ) {
953 return LDAP_INVALID_SYNTAX;
956 if( (u[3] & 0xC0) != 0x80 ) {
957 return LDAP_INVALID_SYNTAX;
960 if( (u[2] & 0xC0 )!= 0x80 ) {
961 return LDAP_INVALID_SYNTAX;
964 if( (u[1] & 0xC0) != 0x80 ) {
965 return LDAP_INVALID_SYNTAX;
968 /* CHARLEN already validated it */
971 return LDAP_INVALID_SYNTAX;
974 /* make sure len corresponds with the offset
975 to the next character */
976 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
980 return LDAP_INVALID_SYNTAX;
992 struct berval *normalized,
995 struct berval tmp, nvalue;
999 if( val->bv_val == NULL ) {
1000 /* assume we're dealing with a syntax (e.g., UTF8String)
1001 * which allows empty strings
1003 normalized->bv_len = 0;
1004 normalized->bv_val = NULL;
1005 return LDAP_SUCCESS;
1008 flags = MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1009 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1010 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1011 ? LDAP_UTF8_APPROX : 0;
1013 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1018 /* collapse spaces (in place) */
1020 nvalue.bv_val = tmp.bv_val;
1022 wasspace=1; /* trim leading spaces */
1023 for( i=0; i<tmp.bv_len; i++) {
1024 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1025 if( wasspace++ == 0 ) {
1026 /* trim repeated spaces */
1027 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1031 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1035 if( nvalue.bv_len ) {
1037 /* last character was a space, trim it */
1040 nvalue.bv_val[nvalue.bv_len] = '\0';
1043 /* string of all spaces is treated as one space */
1044 nvalue.bv_val[0] = ' ';
1045 nvalue.bv_val[1] = '\0';
1049 *normalized = nvalue;
1050 return LDAP_SUCCESS;
1053 #ifndef SLAP_NVALUES
1055 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1056 #if defined(SLAPD_APPROX_INITIALS)
1057 #define SLAPD_APPROX_DELIMITER "._ "
1058 #define SLAPD_APPROX_WORDLEN 2
1060 #define SLAPD_APPROX_DELIMITER " "
1061 #define SLAPD_APPROX_WORDLEN 1
1070 struct berval *value,
1071 void *assertedValue )
1073 struct berval *nval, *assertv;
1074 char *val, **values, **words, *c;
1075 int i, count, len, nextchunk=0, nextavail=0;
1077 /* Yes, this is necessary */
1078 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1079 if( nval == NULL ) {
1081 return LDAP_SUCCESS;
1084 /* Yes, this is necessary */
1085 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1086 NULL, LDAP_UTF8_APPROX );
1087 if( assertv == NULL ) {
1090 return LDAP_SUCCESS;
1093 /* Isolate how many words there are */
1094 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1095 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1096 if ( c == NULL ) break;
1101 /* Get a phonetic copy of each word */
1102 words = (char **)ch_malloc( count * sizeof(char *) );
1103 values = (char **)ch_malloc( count * sizeof(char *) );
1104 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1106 values[i] = phonetic(c);
1109 /* Work through the asserted value's words, to see if at least some
1110 of the words are there, in the same order. */
1112 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1113 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1118 #if defined(SLAPD_APPROX_INITIALS)
1119 else if( len == 1 ) {
1120 /* Single letter words need to at least match one word's initial */
1121 for( i=nextavail; i<count; i++ )
1122 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1129 /* Isolate the next word in the asserted value and phonetic it */
1130 assertv->bv_val[nextchunk+len] = '\0';
1131 val = phonetic( assertv->bv_val + nextchunk );
1133 /* See if this phonetic chunk is in the remaining words of *value */
1134 for( i=nextavail; i<count; i++ ){
1135 if( !strcmp( val, values[i] ) ){
1143 /* This chunk in the asserted value was NOT within the *value. */
1149 /* Go on to the next word in the asserted value */
1153 /* If some of the words were seen, call it a match */
1154 if( nextavail > 0 ) {
1161 /* Cleanup allocs */
1162 ber_bvfree( assertv );
1163 for( i=0; i<count; i++ ) {
1164 ch_free( values[i] );
1170 return LDAP_SUCCESS;
1179 struct berval *prefix,
1184 int i,j, len, wordcount, keycount=0;
1185 struct berval *newkeys;
1186 BerVarray keys=NULL;
1188 for( j=0; values[j].bv_val != NULL; j++ ) {
1189 struct berval val = { 0, NULL };
1190 /* Yes, this is necessary */
1191 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1192 assert( val.bv_val != NULL );
1194 /* Isolate how many words there are. There will be a key for each */
1195 for( wordcount = 0, c = val.bv_val; *c; c++) {
1196 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1197 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1199 if (*c == '\0') break;
1203 /* Allocate/increase storage to account for new keys */
1204 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1205 * sizeof(struct berval) );
1206 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1207 if( keys ) ch_free( keys );
1210 /* Get a phonetic copy of each word */
1211 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1213 if( len < SLAPD_APPROX_WORDLEN ) continue;
1214 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1219 ber_memfree( val.bv_val );
1221 keys[keycount].bv_val = NULL;
1224 return LDAP_SUCCESS;
1233 struct berval *prefix,
1234 void * assertedValue,
1242 /* Yes, this is necessary */
1243 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1244 NULL, LDAP_UTF8_APPROX );
1245 if( val == NULL || val->bv_val == NULL ) {
1246 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1247 keys[0].bv_val = NULL;
1250 return LDAP_SUCCESS;
1253 /* Isolate how many words there are. There will be a key for each */
1254 for( count = 0,c = val->bv_val; *c; c++) {
1255 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1256 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1258 if (*c == '\0') break;
1262 /* Allocate storage for new keys */
1263 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1265 /* Get a phonetic copy of each word */
1266 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1268 if( len < SLAPD_APPROX_WORDLEN ) continue;
1269 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1275 keys[count].bv_val = NULL;
1278 return LDAP_SUCCESS;
1282 /* No other form of Approximate Matching is defined */
1290 struct berval *value,
1291 void *assertedValue )
1293 char *vapprox, *avapprox;
1296 /* Yes, this is necessary */
1297 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1300 return LDAP_SUCCESS;
1303 /* Yes, this is necessary */
1304 t = UTF8normalize( ((struct berval *)assertedValue),
1309 return LDAP_SUCCESS;
1312 vapprox = phonetic( strip8bitChars( s ) );
1313 avapprox = phonetic( strip8bitChars( t ) );
1318 *matchp = strcmp( vapprox, avapprox );
1321 ch_free( avapprox );
1323 return LDAP_SUCCESS;
1332 struct berval *prefix,
1340 for( i=0; values[i].bv_val != NULL; i++ ) {
1341 /* empty - just count them */
1344 /* we should have at least one value at this point */
1347 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1349 /* Copy each value and run it through phonetic() */
1350 for( i=0; values[i].bv_val != NULL; i++ ) {
1351 /* Yes, this is necessary */
1352 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1354 /* strip 8-bit chars and run through phonetic() */
1355 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1358 keys[i].bv_val = NULL;
1361 return LDAP_SUCCESS;
1370 struct berval *prefix,
1371 void * assertedValue,
1377 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1379 /* Yes, this is necessary */
1380 s = UTF8normalize( ((struct berval *)assertedValue),
1385 /* strip 8-bit chars and run through phonetic() */
1386 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1392 return LDAP_SUCCESS;
1395 #endif /* !SLAP_NVALUES */
1397 /* Remove all spaces and '-' characters */
1399 telephoneNumberNormalize(
1404 struct berval *normalized,
1409 /* validator should have refused an empty string */
1410 assert( val->bv_len );
1412 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1414 for( p = val->bv_val; *p; p++ ) {
1415 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1421 normalized->bv_len = q - normalized->bv_val;
1423 if( normalized->bv_len == 0 ) {
1424 sl_free( normalized->bv_val, ctx );
1425 return LDAP_INVALID_SYNTAX;
1428 return LDAP_SUCCESS;
1434 struct berval *val )
1438 if( val->bv_len == 0 ) {
1439 /* disallow empty strings */
1440 return LDAP_INVALID_SYNTAX;
1443 if( OID_LEADCHAR(val->bv_val[0]) ) {
1445 for(i=1; i < val->bv_len; i++) {
1446 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1447 if( dot++ ) return 1;
1448 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1451 return LDAP_INVALID_SYNTAX;
1455 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1457 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1458 for(i=1; i < val->bv_len; i++) {
1459 if( !DESC_CHAR(val->bv_val[i] ) ) {
1460 return LDAP_INVALID_SYNTAX;
1464 return LDAP_SUCCESS;
1467 return LDAP_INVALID_SYNTAX;
1476 struct berval *value,
1477 void *assertedValue )
1480 int vsign = 1, avsign = 1; /* default sign = '+' */
1481 struct berval *asserted;
1482 ber_len_t vlen, avlen;
1485 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1487 vlen = value->bv_len;
1489 #ifndef SLAP_NVALUES
1490 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1491 char *tmp = memchr( v, '$', vlen );
1492 if( tmp ) vlen = tmp - v;
1493 while( vlen && ASCII_SPACE( v[vlen-1] )) vlen--;
1497 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) { /* ANSI 2.2.1 */
1498 if( *v == '-' ) vsign = -1;
1501 if( vlen == 0 ) vsign = 0;
1503 /* Do the same with the *assertedValue number */
1504 asserted = (struct berval *) assertedValue;
1505 av = asserted->bv_val;
1506 avlen = asserted->bv_len;
1507 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1513 match = vsign - avsign;
1515 match = (vlen != avlen
1516 ? ( vlen < avlen ? -1 : 1 )
1517 : memcmp( v, av, vlen ));
1518 if( vsign < 0 ) match = -match;
1522 return LDAP_SUCCESS;
1528 struct berval *val )
1532 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1534 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1535 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1537 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1538 return LDAP_INVALID_SYNTAX;
1541 for( i=1; i < val->bv_len; i++ ) {
1542 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1545 return LDAP_SUCCESS;
1554 struct berval *normalized,
1564 /* Ignore leading spaces */
1565 while ( len && ( *p == ' ' )) {
1572 negative = ( *p == '-' );
1573 if(( *p == '-' ) || ( *p == '+' )) {
1579 /* Ignore leading zeros */
1580 while ( len && ( *p == '0' )) {
1585 /* If there are no non-zero digits left, the number is zero, otherwise
1586 allocate space for the number and copy it into the buffer */
1588 normalized->bv_val = ber_strdup_x("0", ctx);
1589 normalized->bv_len = 1;
1592 normalized->bv_len = len+negative;
1593 normalized->bv_val = sl_malloc( normalized->bv_len + 1, ctx );
1594 if( negative ) normalized->bv_val[0] = '-';
1595 AC_MEMCPY( normalized->bv_val + negative, p, len );
1596 normalized->bv_val[len+negative] = '\0';
1599 return LDAP_SUCCESS;
1603 countryStringValidate(
1605 struct berval *val )
1607 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1609 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1610 return LDAP_INVALID_SYNTAX;
1612 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1613 return LDAP_INVALID_SYNTAX;
1616 return LDAP_SUCCESS;
1620 printableStringValidate(
1622 struct berval *val )
1626 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1628 for(i=0; i < val->bv_len; i++) {
1629 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1630 return LDAP_INVALID_SYNTAX;
1634 return LDAP_SUCCESS;
1638 printablesStringValidate(
1640 struct berval *val )
1644 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1646 for(i=0,len=0; i < val->bv_len; i++) {
1647 int c = val->bv_val[i];
1651 return LDAP_INVALID_SYNTAX;
1655 } else if ( SLAP_PRINTABLE(c) ) {
1658 return LDAP_INVALID_SYNTAX;
1663 return LDAP_INVALID_SYNTAX;
1666 return LDAP_SUCCESS;
1672 struct berval *val )
1676 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1678 for(i=0; i < val->bv_len; i++) {
1679 if( !LDAP_ASCII(val->bv_val[i]) ) {
1680 return LDAP_INVALID_SYNTAX;
1684 return LDAP_SUCCESS;
1693 struct berval *normalized,
1697 int casefold = MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactIA5Match );
1699 assert( val->bv_len );
1703 /* Ignore initial whitespace */
1704 while ( ASCII_SPACE( *p ) ) {
1708 normalized->bv_val = ber_strdup_x( p, ctx );
1709 p = q = normalized->bv_val;
1712 if ( ASCII_SPACE( *p ) ) {
1715 /* Ignore the extra whitespace */
1716 while ( ASCII_SPACE( *p ) ) {
1720 } else if ( casefold ) {
1721 /* Most IA5 rules require casefolding */
1722 *q++ = TOLOWER(*p++);
1729 assert( normalized->bv_val <= p );
1733 * If the string ended in space, backup the pointer one
1734 * position. One is enough because the above loop collapsed
1735 * all whitespace to a single space.
1738 if ( ASCII_SPACE( q[-1] ) ) {
1742 /* null terminate */
1745 normalized->bv_len = q - normalized->bv_val;
1747 if( normalized->bv_len == 0 ) {
1748 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1749 normalized->bv_val[0] = ' ';
1750 normalized->bv_val[1] = '\0';
1751 normalized->bv_len = 1;
1754 return LDAP_SUCCESS;
1758 numericStringValidate(
1764 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1766 for(i=0; i < in->bv_len; i++) {
1767 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1768 return LDAP_INVALID_SYNTAX;
1772 return LDAP_SUCCESS;
1776 numericStringNormalize(
1781 struct berval *normalized,
1784 /* removal all spaces */
1787 assert( val->bv_len );
1789 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1792 q = normalized->bv_val;
1795 if ( ASCII_SPACE( *p ) ) {
1796 /* Ignore whitespace */
1803 /* we should have copied no more then is in val */
1804 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1806 /* null terminate */
1809 normalized->bv_len = q - normalized->bv_val;
1811 if( normalized->bv_len == 0 ) {
1812 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1813 normalized->bv_val[0] = ' ';
1814 normalized->bv_val[1] = '\0';
1815 normalized->bv_len = 1;
1818 return LDAP_SUCCESS;
1821 #ifndef SLAP_NVALUES
1823 objectIdentifierFirstComponentMatch(
1828 struct berval *value,
1829 void *assertedValue )
1831 int rc = LDAP_SUCCESS;
1833 struct berval *asserted = (struct berval *) assertedValue;
1837 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1838 return LDAP_INVALID_SYNTAX;
1841 /* trim leading white space */
1842 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1846 /* grab next word */
1847 oid.bv_val = &value->bv_val[i];
1848 j = value->bv_len - i;
1849 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1854 /* insert attributeTypes, objectclass check here */
1855 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1856 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1859 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1860 MatchingRule *asserted_mr = mr_bvfind( asserted );
1861 MatchingRule *stored_mr = mr_bvfind( &oid );
1863 if( asserted_mr == NULL ) {
1864 rc = SLAPD_COMPARE_UNDEFINED;
1866 match = asserted_mr != stored_mr;
1869 } else if ( !strcmp( syntax->ssyn_oid,
1870 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1872 AttributeType *asserted_at = at_bvfind( asserted );
1873 AttributeType *stored_at = at_bvfind( &oid );
1875 if( asserted_at == NULL ) {
1876 rc = SLAPD_COMPARE_UNDEFINED;
1878 match = asserted_at != stored_at;
1881 } else if ( !strcmp( syntax->ssyn_oid,
1882 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1884 ObjectClass *asserted_oc = oc_bvfind( asserted );
1885 ObjectClass *stored_oc = oc_bvfind( &oid );
1887 if( asserted_oc == NULL ) {
1888 rc = SLAPD_COMPARE_UNDEFINED;
1890 match = asserted_oc != stored_oc;
1896 LDAP_LOG( CONFIG, ENTRY,
1897 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1898 match, value->bv_val, asserted->bv_val );
1900 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1901 "%d\n\t\"%s\"\n\t\"%s\"\n",
1902 match, value->bv_val, asserted->bv_val );
1905 if( rc == LDAP_SUCCESS ) *matchp = match;
1916 struct berval *value,
1917 void *assertedValue )
1919 long lValue, lAssertedValue;
1921 /* safe to assume integers are NUL terminated? */
1922 lValue = strtol(value->bv_val, NULL, 10);
1923 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1924 return LDAP_CONSTRAINT_VIOLATION;
1927 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1928 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1929 && errno == ERANGE )
1931 return LDAP_CONSTRAINT_VIOLATION;
1934 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1935 return LDAP_SUCCESS;
1944 struct berval *value,
1945 void *assertedValue )
1947 long lValue, lAssertedValue;
1949 /* safe to assume integers are NUL terminated? */
1950 lValue = strtol(value->bv_val, NULL, 10);
1951 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1952 return LDAP_CONSTRAINT_VIOLATION;
1955 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1956 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1957 && errno == ERANGE )
1959 return LDAP_CONSTRAINT_VIOLATION;
1962 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1963 return LDAP_SUCCESS;
1966 #ifndef SLAP_NVALUES
1968 #include <openssl/x509.h>
1969 #include <openssl/err.h>
1972 * Next function returns a string representation of a ASN1_INTEGER.
1973 * It works for unlimited lengths.
1976 static struct berval *
1977 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1981 static char digit[] = "0123456789";
1983 /* We work backwards, make it fill from the end of buf */
1984 p = buf + sizeof(buf) - 1;
1987 if ( a == NULL || a->length == 0 ) {
1995 /* We want to preserve the original */
1996 copy = ch_malloc(n*sizeof(unsigned int));
1997 for (i = 0; i<n; i++) {
1998 copy[i] = a->data[i];
2002 * base indicates the index of the most significant
2003 * byte that might be nonzero. When it goes off the
2004 * end, we now there is nothing left to do.
2010 for (i = base; i<n; i++ ) {
2011 copy[i] += carry*256;
2012 carry = copy[i] % 10;
2017 * Way too large, we need to leave
2018 * room for sign if negative
2023 *--p = digit[carry];
2025 if (copy[base] == 0) base++;
2030 if ( a->type == V_ASN1_NEG_INTEGER ) {
2034 return ber_str2bv( p, 0, 1, bv );
2038 * Given a certificate in DER format, extract the corresponding
2039 * assertion value for certificateExactMatch
2042 certificateExactConvert(
2044 struct berval * out )
2047 unsigned char *p = in->bv_val;
2048 struct berval serial;
2049 struct berval issuer_dn;
2051 xcert = d2i_X509(NULL, &p, in->bv_len);
2054 LDAP_LOG( CONFIG, ENTRY,
2055 "certificateExactConvert: error parsing cert: %s\n",
2056 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2058 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2059 "error parsing cert: %s\n",
2060 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2062 return LDAP_INVALID_SYNTAX;
2065 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2067 return LDAP_INVALID_SYNTAX;
2069 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2073 ber_memfree(serial.bv_val);
2074 return LDAP_INVALID_SYNTAX;
2079 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2080 out->bv_val = ch_malloc(out->bv_len);
2082 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2084 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2086 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2087 p += issuer_dn.bv_len;
2091 LDAP_LOG( CONFIG, ARGS,
2092 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2094 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2096 out->bv_val, NULL, NULL );
2099 ber_memfree(serial.bv_val);
2100 ber_memfree(issuer_dn.bv_val);
2102 return LDAP_SUCCESS;
2106 serial_and_issuer_parse(
2107 struct berval *assertion,
2108 struct berval *serial,
2109 struct berval *issuer_dn )
2116 begin = assertion->bv_val;
2117 end = assertion->bv_val+assertion->bv_len-1;
2118 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2119 if ( p > end ) return LDAP_INVALID_SYNTAX;
2121 /* p now points at the $ sign, now use
2122 * begin and end to delimit the serial number
2124 while (ASCII_SPACE(*begin)) begin++;
2126 while (ASCII_SPACE(*end)) end--;
2128 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2130 bv.bv_len = end-begin+1;
2132 ber_dupbv(serial, &bv);
2134 /* now extract the issuer, remember p was at the dollar sign */
2136 end = assertion->bv_val+assertion->bv_len-1;
2137 while (ASCII_SPACE(*begin)) begin++;
2138 /* should we trim spaces at the end too? is it safe always? no, no */
2140 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2143 bv.bv_len = end-begin+1;
2146 dnNormalize2( NULL, &bv, issuer_dn );
2149 return LDAP_SUCCESS;
2153 certificateExactMatch(
2158 struct berval *value,
2159 void *assertedValue )
2162 unsigned char *p = value->bv_val;
2163 struct berval serial;
2164 struct berval issuer_dn;
2165 struct berval asserted_serial;
2166 struct berval asserted_issuer_dn;
2169 xcert = d2i_X509(NULL, &p, value->bv_len);
2172 LDAP_LOG( CONFIG, ENTRY,
2173 "certificateExactMatch: error parsing cert: %s\n",
2174 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2176 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2177 "error parsing cert: %s\n",
2178 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2180 return LDAP_INVALID_SYNTAX;
2183 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2184 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2188 serial_and_issuer_parse(assertedValue,
2189 &asserted_serial, &asserted_issuer_dn);
2194 slap_schema.si_syn_integer,
2195 slap_schema.si_mr_integerMatch,
2198 if ( ret == LDAP_SUCCESS ) {
2199 if ( *matchp == 0 ) {
2200 /* We need to normalize everything for dnMatch */
2204 slap_schema.si_syn_distinguishedName,
2205 slap_schema.si_mr_distinguishedNameMatch,
2207 &asserted_issuer_dn);
2212 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2213 "%d\n\t\"%s $ %s\"\n",
2214 *matchp, serial.bv_val, issuer_dn.bv_val );
2215 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2216 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2219 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2220 "%d\n\t\"%s $ %s\"\n",
2221 *matchp, serial.bv_val, issuer_dn.bv_val );
2222 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2223 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2227 ber_memfree(serial.bv_val);
2228 ber_memfree(issuer_dn.bv_val);
2229 ber_memfree(asserted_serial.bv_val);
2230 ber_memfree(asserted_issuer_dn.bv_val);
2236 * Index generation function
2237 * We just index the serials, in most scenarios the issuer DN is one of
2238 * a very small set of values.
2240 static int certificateExactIndexer(
2245 struct berval *prefix,
2253 struct berval serial;
2255 /* we should have at least one value at this point */
2256 assert( values != NULL && values[0].bv_val != NULL );
2258 for( i=0; values[i].bv_val != NULL; i++ ) {
2259 /* empty -- just count them */
2262 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2264 for( i=0; values[i].bv_val != NULL; i++ ) {
2265 p = values[i].bv_val;
2266 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2269 LDAP_LOG( CONFIG, ENTRY,
2270 "certificateExactIndexer: error parsing cert: %s\n",
2271 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2273 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2274 "error parsing cert: %s\n",
2275 ERR_error_string(ERR_get_error(),NULL),
2278 /* Do we leak keys on error? */
2279 return LDAP_INVALID_SYNTAX;
2282 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2284 xintegerNormalize( slap_schema.si_syn_integer,
2285 &serial, &keys[i] );
2286 ber_memfree(serial.bv_val);
2288 LDAP_LOG( CONFIG, ENTRY,
2289 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2291 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2298 keys[i].bv_val = NULL;
2300 return LDAP_SUCCESS;
2303 /* Index generation function */
2304 /* We think this is always called with a value in matching rule syntax */
2305 static int certificateExactFilter(
2310 struct berval *prefix,
2311 void * assertedValue,
2315 struct berval asserted_serial;
2318 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2319 if( ret != LDAP_SUCCESS ) return ret;
2321 keys = ch_malloc( sizeof( struct berval ) * 2 );
2322 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2323 keys[1].bv_val = NULL;
2326 ber_memfree(asserted_serial.bv_val);
2327 return LDAP_SUCCESS;
2333 check_time_syntax (struct berval *val,
2337 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2338 static int mdays[2][12] = {
2339 /* non-leap years */
2340 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2342 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2345 int part, c, tzoffset, leapyear = 0 ;
2347 if( val->bv_len == 0 ) {
2348 return LDAP_INVALID_SYNTAX;
2351 p = (char *)val->bv_val;
2352 e = p + val->bv_len;
2354 /* Ignore initial whitespace */
2355 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2359 if (e - p < 13 - (2 * start)) {
2360 return LDAP_INVALID_SYNTAX;
2363 for (part = 0; part < 9; part++) {
2367 for (part = start; part < 7; part++) {
2369 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2376 return LDAP_INVALID_SYNTAX;
2378 if (c < 0 || c > 9) {
2379 return LDAP_INVALID_SYNTAX;
2385 return LDAP_INVALID_SYNTAX;
2387 if (c < 0 || c > 9) {
2388 return LDAP_INVALID_SYNTAX;
2393 if (part == 2 || part == 3) {
2396 if (parts[part] < 0) {
2397 return LDAP_INVALID_SYNTAX;
2399 if (parts[part] > ceiling[part]) {
2400 return LDAP_INVALID_SYNTAX;
2404 /* leapyear check for the Gregorian calendar (year>1581) */
2405 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2406 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2411 if (parts[3] > mdays[leapyear][parts[2]]) {
2412 return LDAP_INVALID_SYNTAX;
2417 tzoffset = 0; /* UTC */
2418 } else if (c != '+' && c != '-') {
2419 return LDAP_INVALID_SYNTAX;
2423 } else /* c == '+' */ {
2428 return LDAP_INVALID_SYNTAX;
2431 for (part = 7; part < 9; part++) {
2433 if (c < 0 || c > 9) {
2434 return LDAP_INVALID_SYNTAX;
2439 if (c < 0 || c > 9) {
2440 return LDAP_INVALID_SYNTAX;
2444 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2445 return LDAP_INVALID_SYNTAX;
2450 /* Ignore trailing whitespace */
2451 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2455 return LDAP_INVALID_SYNTAX;
2458 switch ( tzoffset ) {
2459 case -1: /* negativ offset to UTC, ie west of Greenwich */
2460 parts[4] += parts[7];
2461 parts[5] += parts[8];
2462 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2466 c = mdays[leapyear][parts[2]];
2468 if (parts[part] > c) {
2469 parts[part] -= c + 1;
2474 case 1: /* positive offset to UTC, ie east of Greenwich */
2475 parts[4] -= parts[7];
2476 parts[5] -= parts[8];
2477 for (part = 6; --part > 0; ) {
2481 /* first arg to % needs to be non negativ */
2482 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2484 if (parts[part] < 0) {
2485 parts[part] += c + 1;
2490 case 0: /* already UTC */
2494 return LDAP_SUCCESS;
2497 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2502 struct berval *normalized )
2506 rc = check_time_syntax(val, 1, parts);
2507 if (rc != LDAP_SUCCESS) {
2511 normalized->bv_val = ch_malloc( 14 );
2512 if ( normalized->bv_val == NULL ) {
2513 return LBER_ERROR_MEMORY;
2516 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2517 parts[1], parts[2] + 1, parts[3] + 1,
2518 parts[4], parts[5], parts[6] );
2519 normalized->bv_len = 13;
2521 return LDAP_SUCCESS;
2530 return check_time_syntax(in, 1, parts);
2535 generalizedTimeValidate(
2540 return check_time_syntax(in, 0, parts);
2544 generalizedTimeNormalize(
2549 struct berval *normalized,
2554 rc = check_time_syntax(val, 0, parts);
2555 if (rc != LDAP_SUCCESS) {
2559 normalized->bv_val = sl_malloc( 16, ctx );
2560 if ( normalized->bv_val == NULL ) {
2561 return LBER_ERROR_MEMORY;
2564 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2565 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2566 parts[4], parts[5], parts[6] );
2567 normalized->bv_len = 15;
2569 return LDAP_SUCCESS;
2573 nisNetgroupTripleValidate(
2575 struct berval *val )
2580 if ( val->bv_len == 0 ) {
2581 return LDAP_INVALID_SYNTAX;
2584 p = (char *)val->bv_val;
2585 e = p + val->bv_len;
2587 if ( *p != '(' /*')'*/ ) {
2588 return LDAP_INVALID_SYNTAX;
2591 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2595 return LDAP_INVALID_SYNTAX;
2598 } else if ( !AD_CHAR( *p ) ) {
2599 return LDAP_INVALID_SYNTAX;
2603 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2604 return LDAP_INVALID_SYNTAX;
2610 return LDAP_INVALID_SYNTAX;
2613 return LDAP_SUCCESS;
2617 bootParameterValidate(
2619 struct berval *val )
2623 if ( val->bv_len == 0 ) {
2624 return LDAP_INVALID_SYNTAX;
2627 p = (char *)val->bv_val;
2628 e = p + val->bv_len;
2631 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2632 if ( !AD_CHAR( *p ) ) {
2633 return LDAP_INVALID_SYNTAX;
2638 return LDAP_INVALID_SYNTAX;
2642 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2643 if ( !AD_CHAR( *p ) ) {
2644 return LDAP_INVALID_SYNTAX;
2649 return LDAP_INVALID_SYNTAX;
2653 for ( p++; p < e; p++ ) {
2654 if ( !SLAP_PRINTABLE( *p ) ) {
2655 return LDAP_INVALID_SYNTAX;
2659 return LDAP_SUCCESS;
2662 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2663 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2665 static slap_syntax_defs_rec syntax_defs[] = {
2666 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2667 X_BINARY X_NOT_H_R ")",
2668 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2669 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2671 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2673 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2675 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2676 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2678 SLAP_SYNTAX_BER, berValidate, NULL},
2679 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2680 0, bitStringValidate, NULL },
2681 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2682 0, booleanValidate, NULL},
2683 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2684 X_BINARY X_NOT_H_R ")",
2685 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2686 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2687 X_BINARY X_NOT_H_R ")",
2688 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2689 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2690 X_BINARY X_NOT_H_R ")",
2691 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2692 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2693 0, countryStringValidate, NULL},
2694 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2695 0, dnValidate, dnPretty2},
2696 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2698 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2700 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2701 0, UTF8StringValidate, NULL},
2702 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2704 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2706 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2708 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2710 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2712 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2713 0, printablesStringValidate, NULL},
2714 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2715 SLAP_SYNTAX_BLOB, NULL, NULL},
2716 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2717 0, generalizedTimeValidate, NULL},
2718 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2720 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2721 0, IA5StringValidate, NULL},
2722 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2723 0, integerValidate, NULL},
2724 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2725 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2726 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2728 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2730 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2732 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2734 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2736 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2737 0, nameUIDValidate, NULL},
2738 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2740 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2741 0, numericStringValidate, NULL},
2742 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2744 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2745 0, oidValidate, NULL},
2746 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2747 0, IA5StringValidate, NULL},
2748 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2749 0, blobValidate, NULL},
2750 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2751 0, UTF8StringValidate, NULL},
2752 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2754 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2756 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2757 0, printableStringValidate, NULL},
2758 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2759 X_BINARY X_NOT_H_R ")",
2760 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2761 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2762 X_BINARY X_NOT_H_R ")",
2763 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2764 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2765 0, printableStringValidate, NULL},
2766 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2768 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2769 0, printablesStringValidate, NULL},
2770 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2771 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2772 0, utcTimeValidate, NULL},
2774 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2776 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2778 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2780 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2782 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2785 /* RFC 2307 NIS Syntaxes */
2786 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2787 0, nisNetgroupTripleValidate, NULL},
2788 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2789 0, bootParameterValidate, NULL},
2793 /* These OIDs are not published yet, but will be in the next
2794 * I-D for PKIX LDAPv3 schema as have been advanced by David
2795 * Chadwick in private mail.
2797 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2798 0, UTF8StringValidate, NULL},
2801 /* OpenLDAP Experimental Syntaxes */
2802 #ifdef SLAPD_ACI_ENABLED
2803 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2805 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2809 #ifdef SLAPD_AUTHPASSWD
2810 /* needs updating */
2811 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2812 SLAP_SYNTAX_HIDE, NULL, NULL},
2815 /* OpenLDAP Void Syntax */
2816 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2817 SLAP_SYNTAX_HIDE, inValidate, NULL},
2818 {NULL, 0, NULL, NULL}
2822 char *certificateExactMatchSyntaxes[] = {
2823 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2827 char *directoryStringSyntaxes[] = {
2828 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2831 char *integerFirstComponentMatchSyntaxes[] = {
2832 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2833 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2836 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2837 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2838 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2839 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2840 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2841 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2842 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2843 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2844 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2849 * Other matching rules in X.520 that we do not use (yet):
2851 * 2.5.13.9 numericStringOrderingMatch
2852 * 2.5.13.25 uTCTimeMatch
2853 * 2.5.13.26 uTCTimeOrderingMatch
2854 * 2.5.13.31 directoryStringFirstComponentMatch
2855 * 2.5.13.32 wordMatch
2856 * 2.5.13.33 keywordMatch
2857 * 2.5.13.35 certificateMatch
2858 * 2.5.13.36 certificatePairExactMatch
2859 * 2.5.13.37 certificatePairMatch
2860 * 2.5.13.38 certificateListExactMatch
2861 * 2.5.13.39 certificateListMatch
2862 * 2.5.13.40 algorithmIdentifierMatch
2863 * 2.5.13.41 storedPrefixMatch
2864 * 2.5.13.42 attributeCertificateMatch
2865 * 2.5.13.43 readerAndKeyIDMatch
2866 * 2.5.13.44 attributeIntegrityMatch
2868 static slap_mrule_defs_rec mrule_defs[] = {
2870 * EQUALITY matching rules must be listed after associated APPROX
2871 * matching rules. So, we list all APPROX matching rules first.
2873 #ifndef SLAP_NVALUES
2874 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2876 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2877 NULL, NULL, directoryStringApproxMatch,
2878 directoryStringApproxIndexer, directoryStringApproxFilter,
2881 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2882 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2883 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2884 NULL, NULL, IA5StringApproxMatch,
2885 IA5StringApproxIndexer, IA5StringApproxFilter,
2890 * Other matching rules
2893 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2894 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2895 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2896 NULL, objectIdentifierNormalize, octetStringMatch,
2897 octetStringIndexer, octetStringFilter,
2900 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2901 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2902 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2903 NULL, dnNormalize, dnMatch,
2904 octetStringIndexer, octetStringFilter,
2907 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2908 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2909 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2910 NULL, UTF8StringNormalize, octetStringMatch,
2911 octetStringIndexer, octetStringFilter,
2912 directoryStringApproxMatchOID },
2914 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2915 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2916 SLAP_MR_ORDERING, directoryStringSyntaxes,
2917 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2919 "caseIgnoreMatch" },
2921 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2922 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2923 SLAP_MR_SUBSTR, NULL,
2924 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2925 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2926 "caseIgnoreMatch" },
2928 {"( 2.5.13.5 NAME 'caseExactMatch' "
2929 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2930 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2931 NULL, UTF8StringNormalize, octetStringMatch,
2932 octetStringIndexer, octetStringFilter,
2933 directoryStringApproxMatchOID },
2935 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2936 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2937 SLAP_MR_ORDERING, directoryStringSyntaxes,
2938 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2942 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2943 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2944 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2945 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2946 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2949 {"( 2.5.13.8 NAME 'numericStringMatch' "
2950 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2951 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2952 NULL, numericStringNormalize, octetStringSubstringsMatch,
2953 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2956 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2957 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2958 SLAP_MR_SUBSTR, NULL,
2959 NULL, numericStringNormalize, octetStringSubstringsMatch,
2960 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2961 "numericStringMatch" },
2963 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2964 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2965 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2966 NULL, NULL, NULL, NULL, NULL, NULL },
2968 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2969 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2970 SLAP_MR_SUBSTR, NULL,
2971 NULL, NULL, NULL, NULL, NULL,
2972 "caseIgnoreListMatch" },
2974 {"( 2.5.13.13 NAME 'booleanMatch' "
2975 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2976 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2977 NULL, NULL, booleanMatch,
2978 octetStringIndexer, octetStringFilter,
2981 {"( 2.5.13.14 NAME 'integerMatch' "
2982 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2983 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2984 NULL, integerNormalize, integerMatch,
2985 octetStringIndexer, octetStringFilter,
2988 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2989 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2990 SLAP_MR_ORDERING, NULL,
2991 NULL, integerNormalize, integerOrderingMatch,
2995 {"( 2.5.13.16 NAME 'bitStringMatch' "
2996 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2997 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2998 NULL, NULL, octetStringMatch,
2999 octetStringIndexer, octetStringFilter,
3002 {"( 2.5.13.17 NAME 'octetStringMatch' "
3003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3004 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3005 NULL, NULL, octetStringMatch,
3006 octetStringIndexer, octetStringFilter,
3009 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3010 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3011 SLAP_MR_ORDERING, NULL,
3012 NULL, NULL, octetStringOrderingMatch,
3014 "octetStringMatch" },
3016 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3017 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3018 SLAP_MR_SUBSTR, NULL,
3019 NULL, NULL, octetStringSubstringsMatch,
3020 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3021 "octetStringMatch" },
3023 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3024 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3025 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3027 telephoneNumberNormalize, octetStringMatch,
3028 octetStringIndexer, octetStringFilter,
3031 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3032 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3033 SLAP_MR_SUBSTR, NULL,
3034 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3035 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3036 "telephoneNumberMatch" },
3038 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3039 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3040 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3041 NULL, NULL, NULL, NULL, NULL, NULL },
3043 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3044 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3045 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3046 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3050 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3051 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3052 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3053 NULL, NULL, NULL, NULL, NULL, NULL },
3055 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3056 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3057 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3058 NULL, generalizedTimeNormalize, octetStringMatch,
3062 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3063 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3064 SLAP_MR_ORDERING, NULL,
3065 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3067 "generalizedTimeMatch" },
3069 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3070 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3071 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3072 NULL, integerFirstComponentNormalize, integerMatch,
3076 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3077 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3078 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3079 objectIdentifierFirstComponentMatchSyntaxes,
3080 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3081 octetStringIndexer, octetStringFilter,
3084 #ifndef SLAP_NVALUES
3086 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3087 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3088 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3089 certificateExactConvert, NULL, certificateExactMatch,
3090 certificateExactIndexer, certificateExactFilter,
3095 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3096 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3097 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3098 NULL, IA5StringNormalize, octetStringMatch,
3099 octetStringIndexer, octetStringFilter,
3100 IA5StringApproxMatchOID },
3102 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3103 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3104 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3105 NULL, IA5StringNormalize, octetStringMatch,
3106 octetStringIndexer, octetStringFilter,
3107 IA5StringApproxMatchOID },
3109 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3110 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3111 SLAP_MR_SUBSTR, NULL,
3112 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3113 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3114 "caseIgnoreIA5Match" },
3116 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3117 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3118 SLAP_MR_SUBSTR, NULL,
3119 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3120 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3121 "caseExactIA5Match" },
3123 #ifdef SLAPD_AUTHPASSWD
3124 /* needs updating */
3125 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3126 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3127 SLAP_MR_EQUALITY, NULL,
3128 NULL, NULL, authPasswordMatch,
3133 #ifdef SLAPD_ACI_ENABLED
3134 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3135 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3136 SLAP_MR_EQUALITY, NULL,
3137 NULL, NULL, OpenLDAPaciMatch,
3142 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3143 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3145 NULL, integerNormalize, integerBitAndMatch,
3149 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3150 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3152 NULL, integerNormalize, integerBitOrMatch,
3156 {NULL, SLAP_MR_NONE, NULL,
3157 NULL, NULL, NULL, NULL, NULL,
3162 slap_schema_init( void )
3167 /* we should only be called once (from main) */
3168 assert( schema_init_done == 0 );
3170 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3171 res = register_syntax( &syntax_defs[i] );
3174 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3175 syntax_defs[i].sd_desc );
3180 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3181 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3182 mrule_defs[i].mrd_compat_syntaxes == NULL )
3185 "slap_schema_init: Ignoring unusable matching rule %s\n",
3186 mrule_defs[i].mrd_desc );
3190 res = register_matching_rule( &mrule_defs[i] );
3194 "slap_schema_init: Error registering matching rule %s\n",
3195 mrule_defs[i].mrd_desc );
3200 res = slap_schema_load();
3201 schema_init_done = 1;
3206 schema_destroy( void )