1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
15 #include <ac/string.h>
16 #include <ac/socket.h>
22 #include "ldap_utf8.h"
24 #include "lutil_hash.h"
25 #define HASH_BYTES LUTIL_HASH_BYTES
26 #define HASH_CONTEXT lutil_HASH_CTX
27 #define HASH_Init(c) lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
31 #define SLAP_NVALUES 1
33 /* not yet implemented */
34 #define integerFirstComponentNormalize NULL
35 #define objectIdentifierNormalize NULL
36 #define objectIdentifierFirstComponentNormalize NULL
37 #define uniqueMemberMatch NULL
39 #define OpenLDAPaciMatch NULL
41 /* approx matching rules */
43 #define directoryStringApproxMatchOID NULL
44 #define IA5StringApproxMatchOID NULL
46 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
47 #define directoryStringApproxMatch approxMatch
48 #define directoryStringApproxIndexer approxIndexer
49 #define directoryStringApproxFilter approxFilter
50 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
51 #define IA5StringApproxMatch approxMatch
52 #define IA5StringApproxIndexer approxIndexer
53 #define IA5StringApproxFilter approxFilter
61 /* no value allowed */
62 return LDAP_INVALID_SYNTAX;
70 /* any value allowed */
74 #define berValidate blobValidate
85 struct berval *asserted = (struct berval *) assertedValue;
86 int match = value->bv_len - asserted->bv_len;
89 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
97 octetStringOrderingMatch(
102 struct berval *value,
103 void *assertedValue )
105 struct berval *asserted = (struct berval *) assertedValue;
106 ber_len_t v_len = value->bv_len;
107 ber_len_t av_len = asserted->bv_len;
109 int match = memcmp( value->bv_val, asserted->bv_val,
110 (v_len < av_len ? v_len : av_len) );
112 if( match == 0 ) match = v_len - av_len;
118 /* Index generation function */
119 int octetStringIndexer(
124 struct berval *prefix,
132 HASH_CONTEXT HASHcontext;
133 unsigned char HASHdigest[HASH_BYTES];
134 struct berval digest;
135 digest.bv_val = HASHdigest;
136 digest.bv_len = sizeof(HASHdigest);
138 for( i=0; values[i].bv_val != NULL; i++ ) {
139 /* just count them */
142 /* we should have at least one value at this point */
145 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
147 slen = syntax->ssyn_oidlen;
148 mlen = mr->smr_oidlen;
150 for( i=0; values[i].bv_val != NULL; i++ ) {
151 HASH_Init( &HASHcontext );
152 if( prefix != NULL && prefix->bv_len > 0 ) {
153 HASH_Update( &HASHcontext,
154 prefix->bv_val, prefix->bv_len );
156 HASH_Update( &HASHcontext,
157 syntax->ssyn_oid, slen );
158 HASH_Update( &HASHcontext,
160 HASH_Update( &HASHcontext,
161 values[i].bv_val, values[i].bv_len );
162 HASH_Final( HASHdigest, &HASHcontext );
164 ber_dupbv_x( &keys[i], &digest, ctx );
167 keys[i].bv_val = NULL;
175 /* Index generation function */
176 int octetStringFilter(
181 struct berval *prefix,
182 void * assertedValue,
188 HASH_CONTEXT HASHcontext;
189 unsigned char HASHdigest[HASH_BYTES];
190 struct berval *value = (struct berval *) assertedValue;
191 struct berval digest;
192 digest.bv_val = HASHdigest;
193 digest.bv_len = sizeof(HASHdigest);
195 slen = syntax->ssyn_oidlen;
196 mlen = mr->smr_oidlen;
198 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
200 HASH_Init( &HASHcontext );
201 if( prefix != NULL && prefix->bv_len > 0 ) {
202 HASH_Update( &HASHcontext,
203 prefix->bv_val, prefix->bv_len );
205 HASH_Update( &HASHcontext,
206 syntax->ssyn_oid, slen );
207 HASH_Update( &HASHcontext,
209 HASH_Update( &HASHcontext,
210 value->bv_val, value->bv_len );
211 HASH_Final( HASHdigest, &HASHcontext );
213 ber_dupbv_x( keys, &digest, ctx );
214 keys[1].bv_val = NULL;
223 octetStringSubstringsMatch(
228 struct berval *value,
229 void *assertedValue )
232 SubstringsAssertion *sub = assertedValue;
233 struct berval left = *value;
237 /* Add up asserted input length */
238 if( sub->sa_initial.bv_val ) {
239 inlen += sub->sa_initial.bv_len;
242 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
243 inlen += sub->sa_any[i].bv_len;
246 if( sub->sa_final.bv_val ) {
247 inlen += sub->sa_final.bv_len;
250 if( sub->sa_initial.bv_val ) {
251 if( inlen > left.bv_len ) {
256 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
257 sub->sa_initial.bv_len );
263 left.bv_val += sub->sa_initial.bv_len;
264 left.bv_len -= sub->sa_initial.bv_len;
265 inlen -= sub->sa_initial.bv_len;
268 if( sub->sa_final.bv_val ) {
269 if( inlen > left.bv_len ) {
274 match = memcmp( sub->sa_final.bv_val,
275 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
276 sub->sa_final.bv_len );
282 left.bv_len -= sub->sa_final.bv_len;
283 inlen -= sub->sa_final.bv_len;
287 for(i=0; sub->sa_any[i].bv_val; i++) {
292 if( inlen > left.bv_len ) {
293 /* not enough length */
298 if( sub->sa_any[i].bv_len == 0 ) {
302 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
309 idx = p - left.bv_val;
311 if( idx >= left.bv_len ) {
312 /* this shouldn't happen */
319 if( sub->sa_any[i].bv_len > left.bv_len ) {
320 /* not enough left */
325 match = memcmp( left.bv_val,
326 sub->sa_any[i].bv_val,
327 sub->sa_any[i].bv_len );
335 left.bv_val += sub->sa_any[i].bv_len;
336 left.bv_len -= sub->sa_any[i].bv_len;
337 inlen -= sub->sa_any[i].bv_len;
346 /* Substrings Index generation function */
348 octetStringSubstringsIndexer(
353 struct berval *prefix,
358 ber_len_t i, j, nkeys;
362 HASH_CONTEXT HASHcontext;
363 unsigned char HASHdigest[HASH_BYTES];
364 struct berval digest;
365 digest.bv_val = HASHdigest;
366 digest.bv_len = sizeof(HASHdigest);
370 for( i=0; values[i].bv_val != NULL; i++ ) {
371 /* count number of indices to generate */
372 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
376 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
377 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
378 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
379 (SLAP_INDEX_SUBSTR_MINLEN - 1);
381 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
385 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
386 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
387 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
391 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
392 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
393 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
394 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
396 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
402 /* no keys to generate */
407 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
409 slen = syntax->ssyn_oidlen;
410 mlen = mr->smr_oidlen;
413 for( i=0; values[i].bv_val != NULL; i++ ) {
416 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
418 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
419 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
421 char pre = SLAP_INDEX_SUBSTR_PREFIX;
422 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
424 for( j=0; j<max; j++ ) {
425 HASH_Init( &HASHcontext );
426 if( prefix != NULL && prefix->bv_len > 0 ) {
427 HASH_Update( &HASHcontext,
428 prefix->bv_val, prefix->bv_len );
431 HASH_Update( &HASHcontext,
432 &pre, sizeof( pre ) );
433 HASH_Update( &HASHcontext,
434 syntax->ssyn_oid, slen );
435 HASH_Update( &HASHcontext,
437 HASH_Update( &HASHcontext,
438 &values[i].bv_val[j],
439 SLAP_INDEX_SUBSTR_MAXLEN );
440 HASH_Final( HASHdigest, &HASHcontext );
442 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
446 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
447 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
449 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
452 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
453 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
454 HASH_Init( &HASHcontext );
455 if( prefix != NULL && prefix->bv_len > 0 ) {
456 HASH_Update( &HASHcontext,
457 prefix->bv_val, prefix->bv_len );
459 HASH_Update( &HASHcontext,
460 &pre, sizeof( pre ) );
461 HASH_Update( &HASHcontext,
462 syntax->ssyn_oid, slen );
463 HASH_Update( &HASHcontext,
465 HASH_Update( &HASHcontext,
466 values[i].bv_val, j );
467 HASH_Final( HASHdigest, &HASHcontext );
469 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
472 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
473 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
474 HASH_Init( &HASHcontext );
475 if( prefix != NULL && prefix->bv_len > 0 ) {
476 HASH_Update( &HASHcontext,
477 prefix->bv_val, prefix->bv_len );
479 HASH_Update( &HASHcontext,
480 &pre, sizeof( pre ) );
481 HASH_Update( &HASHcontext,
482 syntax->ssyn_oid, slen );
483 HASH_Update( &HASHcontext,
485 HASH_Update( &HASHcontext,
486 &values[i].bv_val[values[i].bv_len-j], j );
487 HASH_Final( HASHdigest, &HASHcontext );
489 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
497 keys[nkeys].bv_val = NULL;
508 octetStringSubstringsFilter (
513 struct berval *prefix,
514 void * assertedValue,
518 SubstringsAssertion *sa;
521 size_t slen, mlen, klen;
523 HASH_CONTEXT HASHcontext;
524 unsigned char HASHdigest[HASH_BYTES];
525 struct berval *value;
526 struct berval digest;
528 sa = (SubstringsAssertion *) assertedValue;
530 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
531 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
536 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
538 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
539 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
540 /* don't bother accounting for stepping */
541 nkeys += sa->sa_any[i].bv_len -
542 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
547 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
548 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
558 digest.bv_val = HASHdigest;
559 digest.bv_len = sizeof(HASHdigest);
561 slen = syntax->ssyn_oidlen;
562 mlen = mr->smr_oidlen;
564 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
567 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
568 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
570 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
571 value = &sa->sa_initial;
573 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
574 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
576 HASH_Init( &HASHcontext );
577 if( prefix != NULL && prefix->bv_len > 0 ) {
578 HASH_Update( &HASHcontext,
579 prefix->bv_val, prefix->bv_len );
581 HASH_Update( &HASHcontext,
582 &pre, sizeof( pre ) );
583 HASH_Update( &HASHcontext,
584 syntax->ssyn_oid, slen );
585 HASH_Update( &HASHcontext,
587 HASH_Update( &HASHcontext,
588 value->bv_val, klen );
589 HASH_Final( HASHdigest, &HASHcontext );
591 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
594 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
596 pre = SLAP_INDEX_SUBSTR_PREFIX;
597 klen = SLAP_INDEX_SUBSTR_MAXLEN;
599 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
600 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
604 value = &sa->sa_any[i];
607 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
608 j += SLAP_INDEX_SUBSTR_STEP )
610 HASH_Init( &HASHcontext );
611 if( prefix != NULL && prefix->bv_len > 0 ) {
612 HASH_Update( &HASHcontext,
613 prefix->bv_val, prefix->bv_len );
615 HASH_Update( &HASHcontext,
616 &pre, sizeof( pre ) );
617 HASH_Update( &HASHcontext,
618 syntax->ssyn_oid, slen );
619 HASH_Update( &HASHcontext,
621 HASH_Update( &HASHcontext,
622 &value->bv_val[j], klen );
623 HASH_Final( HASHdigest, &HASHcontext );
625 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
630 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
631 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
633 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
634 value = &sa->sa_final;
636 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
637 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
639 HASH_Init( &HASHcontext );
640 if( prefix != NULL && prefix->bv_len > 0 ) {
641 HASH_Update( &HASHcontext,
642 prefix->bv_val, prefix->bv_len );
644 HASH_Update( &HASHcontext,
645 &pre, sizeof( pre ) );
646 HASH_Update( &HASHcontext,
647 syntax->ssyn_oid, slen );
648 HASH_Update( &HASHcontext,
650 HASH_Update( &HASHcontext,
651 &value->bv_val[value->bv_len-klen], klen );
652 HASH_Final( HASHdigest, &HASHcontext );
654 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
658 keys[nkeys].bv_val = NULL;
675 /* very unforgiving validation, requires no normalization
676 * before simplistic matching
678 if( in->bv_len < 3 ) {
679 return LDAP_INVALID_SYNTAX;
683 * RFC 2252 section 6.3 Bit String
684 * bitstring = "'" *binary-digit "'B"
685 * binary-digit = "0" / "1"
686 * example: '0101111101'B
689 if( in->bv_val[0] != '\'' ||
690 in->bv_val[in->bv_len-2] != '\'' ||
691 in->bv_val[in->bv_len-1] != 'B' )
693 return LDAP_INVALID_SYNTAX;
696 for( i=in->bv_len-3; i>0; i-- ) {
697 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
698 return LDAP_INVALID_SYNTAX;
713 if( in->bv_len == 0 ) return LDAP_SUCCESS;
715 ber_dupbv( &dn, in );
716 if( !dn.bv_val ) return LDAP_OTHER;
718 if( dn.bv_val[dn.bv_len-1] == 'B'
719 && dn.bv_val[dn.bv_len-2] == '\'' )
721 /* assume presence of optional UID */
724 for(i=dn.bv_len-3; i>1; i--) {
725 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
729 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
730 ber_memfree( dn.bv_val );
731 return LDAP_INVALID_SYNTAX;
734 /* trim the UID to allow use of dnValidate */
735 dn.bv_val[i-1] = '\0';
739 rc = dnValidate( NULL, &dn );
741 ber_memfree( dn.bv_val );
746 uniqueMemberNormalize(
751 struct berval *normalized,
757 ber_dupbv( &out, val );
758 if( out.bv_len != 0 ) {
759 struct berval uid = { 0, NULL };
761 if( out.bv_val[out.bv_len-1] == 'B'
762 && out.bv_val[out.bv_len-2] == '\'' )
764 /* assume presence of optional UID */
765 uid.bv_val = strrchr( out.bv_val, '#' );
767 if( uid.bv_val == NULL ) {
769 return LDAP_INVALID_SYNTAX;
772 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
773 out.bv_len -= uid.bv_len--;
775 /* temporarily trim the UID */
776 *(uid.bv_val++) = '\0';
779 rc = dnNormalize2( NULL, &out, normalized, ctx );
781 if( rc != LDAP_SUCCESS ) {
783 return LDAP_INVALID_SYNTAX;
787 normalized->bv_val = ch_realloc( normalized->bv_val,
788 normalized->bv_len + uid.bv_len + sizeof("#") );
790 /* insert the separator */
791 normalized->bv_val[normalized->bv_len++] = '#';
794 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
795 uid.bv_val, uid.bv_len );
796 normalized->bv_len += uid.bv_len;
799 normalized->bv_val[normalized->bv_len] = '\0';
809 * Handling boolean syntax and matching is quite rigid.
810 * A more flexible approach would be to allow a variety
811 * of strings to be normalized and prettied into TRUE
819 /* very unforgiving validation, requires no normalization
820 * before simplistic matching
823 if( in->bv_len == 4 ) {
824 if( bvmatch( in, &slap_true_bv ) ) {
827 } else if( in->bv_len == 5 ) {
828 if( bvmatch( in, &slap_false_bv ) ) {
833 return LDAP_INVALID_SYNTAX;
842 struct berval *value,
843 void *assertedValue )
845 /* simplistic matching allowed by rigid validation */
846 struct berval *asserted = (struct berval *) assertedValue;
847 *matchp = value->bv_len != asserted->bv_len;
851 /*-------------------------------------------------------------------
852 LDAP/X.500 string syntax / matching rules have a few oddities. This
853 comment attempts to detail how slapd(8) treats them.
856 StringSyntax X.500 LDAP Matching/Comments
857 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
858 PrintableString subset subset i/e + ignore insignificant spaces
859 PrintableString subset subset i/e + ignore insignificant spaces
860 NumericString subset subset ignore all spaces
861 IA5String ASCII ASCII i/e + ignore insignificant spaces
862 TeletexString T.61 T.61 i/e + ignore insignificant spaces
864 TelephoneNumber subset subset i + ignore all spaces and "-"
866 See draft-ietf-ldapbis-strpro for details (once published).
870 In X.500(93), a directory string can be either a PrintableString,
871 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
872 In later versions, more CHOICEs were added. In all cases the string
875 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
876 A directory string cannot be zero length.
878 For matching, there are both case ignore and exact rules. Both
879 also require that "insignificant" spaces be ignored.
880 spaces before the first non-space are ignored;
881 spaces after the last non-space are ignored;
882 spaces after a space are ignored.
883 Note: by these rules (and as clarified in X.520), a string of only
884 spaces is to be treated as if held one space, not empty (which
885 would be a syntax error).
888 In ASN.1, numeric string is just a string of digits and spaces
889 and could be empty. However, in X.500, all attribute values of
890 numeric string carry a non-empty constraint. For example:
892 internationalISDNNumber ATTRIBUTE ::= {
893 WITH SYNTAX InternationalISDNNumber
894 EQUALITY MATCHING RULE numericStringMatch
895 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
896 ID id-at-internationalISDNNumber }
897 InternationalISDNNumber ::=
898 NumericString (SIZE(1..ub-international-isdn-number))
900 Unforunately, some assertion values are don't carry the same
901 constraint (but its unclear how such an assertion could ever
902 be true). In LDAP, there is one syntax (numericString) not two
903 (numericString with constraint, numericString without constraint).
904 This should be treated as numericString with non-empty constraint.
905 Note that while someone may have no ISDN number, there are no ISDN
906 numbers which are zero length.
908 In matching, spaces are ignored.
911 In ASN.1, Printable string is just a string of printable characters
912 and can be empty. In X.500, semantics much like NumericString (see
913 serialNumber for a like example) excepting uses insignificant space
914 handling instead of ignore all spaces.
917 Basically same as PrintableString. There are no examples in X.500,
918 but same logic applies. So we require them to be non-empty as
921 -------------------------------------------------------------------*/
930 unsigned char *u = in->bv_val;
932 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
933 /* directory strings cannot be empty */
934 return LDAP_INVALID_SYNTAX;
937 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
938 /* get the length indicated by the first byte */
939 len = LDAP_UTF8_CHARLEN2( u, len );
941 /* very basic checks */
944 if( (u[5] & 0xC0) != 0x80 ) {
945 return LDAP_INVALID_SYNTAX;
948 if( (u[4] & 0xC0) != 0x80 ) {
949 return LDAP_INVALID_SYNTAX;
952 if( (u[3] & 0xC0) != 0x80 ) {
953 return LDAP_INVALID_SYNTAX;
956 if( (u[2] & 0xC0 )!= 0x80 ) {
957 return LDAP_INVALID_SYNTAX;
960 if( (u[1] & 0xC0) != 0x80 ) {
961 return LDAP_INVALID_SYNTAX;
964 /* CHARLEN already validated it */
967 return LDAP_INVALID_SYNTAX;
970 /* make sure len corresponds with the offset
971 to the next character */
972 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
976 return LDAP_INVALID_SYNTAX;
988 struct berval *normalized,
991 struct berval tmp, nvalue;
995 if( val->bv_val == NULL ) {
996 /* assume we're dealing with a syntax (e.g., UTF8String)
997 * which allows empty strings
999 normalized->bv_len = 0;
1000 normalized->bv_val = NULL;
1001 return LDAP_SUCCESS;
1004 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1005 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1006 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1007 ? LDAP_UTF8_APPROX : 0;
1009 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1014 /* collapse spaces (in place) */
1016 nvalue.bv_val = tmp.bv_val;
1018 wasspace=1; /* trim leading spaces */
1019 for( i=0; i<tmp.bv_len; i++) {
1020 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1021 if( wasspace++ == 0 ) {
1022 /* trim repeated spaces */
1023 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1027 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1031 if( nvalue.bv_len ) {
1033 /* last character was a space, trim it */
1036 nvalue.bv_val[nvalue.bv_len] = '\0';
1039 /* string of all spaces is treated as one space */
1040 nvalue.bv_val[0] = ' ';
1041 nvalue.bv_val[1] = '\0';
1045 *normalized = nvalue;
1046 return LDAP_SUCCESS;
1049 #ifndef SLAP_NVALUES
1051 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1052 #if defined(SLAPD_APPROX_INITIALS)
1053 #define SLAPD_APPROX_DELIMITER "._ "
1054 #define SLAPD_APPROX_WORDLEN 2
1056 #define SLAPD_APPROX_DELIMITER " "
1057 #define SLAPD_APPROX_WORDLEN 1
1066 struct berval *value,
1067 void *assertedValue )
1069 struct berval *nval, *assertv;
1070 char *val, **values, **words, *c;
1071 int i, count, len, nextchunk=0, nextavail=0;
1073 /* Yes, this is necessary */
1074 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1075 if( nval == NULL ) {
1077 return LDAP_SUCCESS;
1080 /* Yes, this is necessary */
1081 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1082 NULL, LDAP_UTF8_APPROX );
1083 if( assertv == NULL ) {
1086 return LDAP_SUCCESS;
1089 /* Isolate how many words there are */
1090 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1091 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1092 if ( c == NULL ) break;
1097 /* Get a phonetic copy of each word */
1098 words = (char **)ch_malloc( count * sizeof(char *) );
1099 values = (char **)ch_malloc( count * sizeof(char *) );
1100 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1102 values[i] = phonetic(c);
1105 /* Work through the asserted value's words, to see if at least some
1106 of the words are there, in the same order. */
1108 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1109 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1114 #if defined(SLAPD_APPROX_INITIALS)
1115 else if( len == 1 ) {
1116 /* Single letter words need to at least match one word's initial */
1117 for( i=nextavail; i<count; i++ )
1118 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1125 /* Isolate the next word in the asserted value and phonetic it */
1126 assertv->bv_val[nextchunk+len] = '\0';
1127 val = phonetic( assertv->bv_val + nextchunk );
1129 /* See if this phonetic chunk is in the remaining words of *value */
1130 for( i=nextavail; i<count; i++ ){
1131 if( !strcmp( val, values[i] ) ){
1139 /* This chunk in the asserted value was NOT within the *value. */
1145 /* Go on to the next word in the asserted value */
1149 /* If some of the words were seen, call it a match */
1150 if( nextavail > 0 ) {
1157 /* Cleanup allocs */
1158 ber_bvfree( assertv );
1159 for( i=0; i<count; i++ ) {
1160 ch_free( values[i] );
1166 return LDAP_SUCCESS;
1175 struct berval *prefix,
1180 int i,j, len, wordcount, keycount=0;
1181 struct berval *newkeys;
1182 BerVarray keys=NULL;
1184 for( j=0; values[j].bv_val != NULL; j++ ) {
1185 struct berval val = { 0, NULL };
1186 /* Yes, this is necessary */
1187 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1188 assert( val.bv_val != NULL );
1190 /* Isolate how many words there are. There will be a key for each */
1191 for( wordcount = 0, c = val.bv_val; *c; c++) {
1192 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1193 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1195 if (*c == '\0') break;
1199 /* Allocate/increase storage to account for new keys */
1200 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1201 * sizeof(struct berval) );
1202 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1203 if( keys ) ch_free( keys );
1206 /* Get a phonetic copy of each word */
1207 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1209 if( len < SLAPD_APPROX_WORDLEN ) continue;
1210 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1215 ber_memfree( val.bv_val );
1217 keys[keycount].bv_val = NULL;
1220 return LDAP_SUCCESS;
1229 struct berval *prefix,
1230 void * assertedValue,
1238 /* Yes, this is necessary */
1239 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1240 NULL, LDAP_UTF8_APPROX );
1241 if( val == NULL || val->bv_val == NULL ) {
1242 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1243 keys[0].bv_val = NULL;
1246 return LDAP_SUCCESS;
1249 /* Isolate how many words there are. There will be a key for each */
1250 for( count = 0,c = val->bv_val; *c; c++) {
1251 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1252 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1254 if (*c == '\0') break;
1258 /* Allocate storage for new keys */
1259 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1261 /* Get a phonetic copy of each word */
1262 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1264 if( len < SLAPD_APPROX_WORDLEN ) continue;
1265 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1271 keys[count].bv_val = NULL;
1274 return LDAP_SUCCESS;
1278 /* No other form of Approximate Matching is defined */
1286 struct berval *value,
1287 void *assertedValue )
1289 char *vapprox, *avapprox;
1292 /* Yes, this is necessary */
1293 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1296 return LDAP_SUCCESS;
1299 /* Yes, this is necessary */
1300 t = UTF8normalize( ((struct berval *)assertedValue),
1305 return LDAP_SUCCESS;
1308 vapprox = phonetic( strip8bitChars( s ) );
1309 avapprox = phonetic( strip8bitChars( t ) );
1314 *matchp = strcmp( vapprox, avapprox );
1317 ch_free( avapprox );
1319 return LDAP_SUCCESS;
1328 struct berval *prefix,
1336 for( i=0; values[i].bv_val != NULL; i++ ) {
1337 /* empty - just count them */
1340 /* we should have at least one value at this point */
1343 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1345 /* Copy each value and run it through phonetic() */
1346 for( i=0; values[i].bv_val != NULL; i++ ) {
1347 /* Yes, this is necessary */
1348 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1350 /* strip 8-bit chars and run through phonetic() */
1351 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1354 keys[i].bv_val = NULL;
1357 return LDAP_SUCCESS;
1366 struct berval *prefix,
1367 void * assertedValue,
1373 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1375 /* Yes, this is necessary */
1376 s = UTF8normalize( ((struct berval *)assertedValue),
1381 /* strip 8-bit chars and run through phonetic() */
1382 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1388 return LDAP_SUCCESS;
1391 #endif /* !SLAP_NVALUES */
1393 /* Remove all spaces and '-' characters */
1395 telephoneNumberNormalize(
1400 struct berval *normalized,
1405 /* validator should have refused an empty string */
1406 assert( val->bv_len );
1408 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1410 for( p = val->bv_val; *p; p++ ) {
1411 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1417 normalized->bv_len = q - normalized->bv_val;
1419 if( normalized->bv_len == 0 ) {
1420 sl_free( normalized->bv_val, ctx );
1421 return LDAP_INVALID_SYNTAX;
1424 return LDAP_SUCCESS;
1430 struct berval *val )
1434 if( val->bv_len == 0 ) {
1435 /* disallow empty strings */
1436 return LDAP_INVALID_SYNTAX;
1439 if( OID_LEADCHAR(val->bv_val[0]) ) {
1441 for(i=1; i < val->bv_len; i++) {
1442 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1443 if( dot++ ) return 1;
1444 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1447 return LDAP_INVALID_SYNTAX;
1451 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1453 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1454 for(i=1; i < val->bv_len; i++) {
1455 if( !DESC_CHAR(val->bv_val[i] ) ) {
1456 return LDAP_INVALID_SYNTAX;
1460 return LDAP_SUCCESS;
1463 return LDAP_INVALID_SYNTAX;
1472 struct berval val = *in;
1474 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1476 if ( val.bv_val[0] == '-' ) {
1480 if( val.bv_len == 0 ) { /* bare "-" */
1481 return LDAP_INVALID_SYNTAX;
1484 if( val.bv_val[0] == '0' ) { /* "-0" */
1485 return LDAP_INVALID_SYNTAX;
1488 } else if ( val.bv_val[0] == '0' ) {
1489 if( val.bv_len > 1 ) { /* "0<more>" */
1490 return LDAP_INVALID_SYNTAX;
1493 return LDAP_SUCCESS;
1496 for( i=0; i < val.bv_len; i++ ) {
1497 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1498 return LDAP_INVALID_SYNTAX;
1502 return LDAP_SUCCESS;
1511 struct berval *value,
1512 void *assertedValue )
1514 struct berval *asserted = (struct berval *) assertedValue;
1515 int vsign = 1, asign = 1; /* default sign = '+' */
1520 if( v.bv_val[0] == '-' ) {
1526 if( v.bv_len == 0 ) vsign = 0;
1529 if( a.bv_val[0] == '-' ) {
1535 if( a.bv_len == 0 ) vsign = 0;
1537 match = vsign - asign;
1539 match = ( v.bv_len != a.bv_len
1540 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1541 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1542 if( vsign < 0 ) match = -match;
1546 return LDAP_SUCCESS;
1550 countryStringValidate(
1552 struct berval *val )
1554 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1556 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1557 return LDAP_INVALID_SYNTAX;
1559 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1560 return LDAP_INVALID_SYNTAX;
1563 return LDAP_SUCCESS;
1567 printableStringValidate(
1569 struct berval *val )
1573 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1575 for(i=0; i < val->bv_len; i++) {
1576 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1577 return LDAP_INVALID_SYNTAX;
1581 return LDAP_SUCCESS;
1585 printablesStringValidate(
1587 struct berval *val )
1591 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1593 for(i=0,len=0; i < val->bv_len; i++) {
1594 int c = val->bv_val[i];
1598 return LDAP_INVALID_SYNTAX;
1602 } else if ( SLAP_PRINTABLE(c) ) {
1605 return LDAP_INVALID_SYNTAX;
1610 return LDAP_INVALID_SYNTAX;
1613 return LDAP_SUCCESS;
1619 struct berval *val )
1623 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1625 for(i=0; i < val->bv_len; i++) {
1626 if( !LDAP_ASCII(val->bv_val[i]) ) {
1627 return LDAP_INVALID_SYNTAX;
1631 return LDAP_SUCCESS;
1640 struct berval *normalized,
1644 int casefold = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactIA5Match );
1646 assert( val->bv_len );
1650 /* Ignore initial whitespace */
1651 while ( ASCII_SPACE( *p ) ) {
1655 normalized->bv_val = ber_strdup_x( p, ctx );
1656 p = q = normalized->bv_val;
1659 if ( ASCII_SPACE( *p ) ) {
1662 /* Ignore the extra whitespace */
1663 while ( ASCII_SPACE( *p ) ) {
1667 } else if ( casefold ) {
1668 /* Most IA5 rules require casefolding */
1669 *q++ = TOLOWER(*p++);
1676 assert( normalized->bv_val <= p );
1680 * If the string ended in space, backup the pointer one
1681 * position. One is enough because the above loop collapsed
1682 * all whitespace to a single space.
1685 if ( ASCII_SPACE( q[-1] ) ) {
1689 /* null terminate */
1692 normalized->bv_len = q - normalized->bv_val;
1694 if( normalized->bv_len == 0 ) {
1695 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1696 normalized->bv_val[0] = ' ';
1697 normalized->bv_val[1] = '\0';
1698 normalized->bv_len = 1;
1701 return LDAP_SUCCESS;
1705 numericStringValidate(
1711 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1713 for(i=0; i < in->bv_len; i++) {
1714 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1715 return LDAP_INVALID_SYNTAX;
1719 return LDAP_SUCCESS;
1723 numericStringNormalize(
1728 struct berval *normalized,
1731 /* removal all spaces */
1734 assert( val->bv_len );
1736 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1739 q = normalized->bv_val;
1742 if ( ASCII_SPACE( *p ) ) {
1743 /* Ignore whitespace */
1750 /* we should have copied no more then is in val */
1751 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1753 /* null terminate */
1756 normalized->bv_len = q - normalized->bv_val;
1758 if( normalized->bv_len == 0 ) {
1759 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1760 normalized->bv_val[0] = ' ';
1761 normalized->bv_val[1] = '\0';
1762 normalized->bv_len = 1;
1765 return LDAP_SUCCESS;
1768 #ifndef SLAP_NVALUES
1770 objectIdentifierFirstComponentMatch(
1775 struct berval *value,
1776 void *assertedValue )
1778 int rc = LDAP_SUCCESS;
1780 struct berval *asserted = (struct berval *) assertedValue;
1784 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1785 return LDAP_INVALID_SYNTAX;
1788 /* trim leading white space */
1789 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1793 /* grab next word */
1794 oid.bv_val = &value->bv_val[i];
1795 j = value->bv_len - i;
1796 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1801 /* insert attributeTypes, objectclass check here */
1802 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1803 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1806 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1807 MatchingRule *asserted_mr = mr_bvfind( asserted );
1808 MatchingRule *stored_mr = mr_bvfind( &oid );
1810 if( asserted_mr == NULL ) {
1811 rc = SLAPD_COMPARE_UNDEFINED;
1813 match = asserted_mr != stored_mr;
1816 } else if ( !strcmp( syntax->ssyn_oid,
1817 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1819 AttributeType *asserted_at = at_bvfind( asserted );
1820 AttributeType *stored_at = at_bvfind( &oid );
1822 if( asserted_at == NULL ) {
1823 rc = SLAPD_COMPARE_UNDEFINED;
1825 match = asserted_at != stored_at;
1828 } else if ( !strcmp( syntax->ssyn_oid,
1829 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1831 ObjectClass *asserted_oc = oc_bvfind( asserted );
1832 ObjectClass *stored_oc = oc_bvfind( &oid );
1834 if( asserted_oc == NULL ) {
1835 rc = SLAPD_COMPARE_UNDEFINED;
1837 match = asserted_oc != stored_oc;
1843 LDAP_LOG( CONFIG, ENTRY,
1844 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1845 match, value->bv_val, asserted->bv_val );
1847 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1848 "%d\n\t\"%s\"\n\t\"%s\"\n",
1849 match, value->bv_val, asserted->bv_val );
1852 if( rc == LDAP_SUCCESS ) *matchp = match;
1863 struct berval *value,
1864 void *assertedValue )
1866 long lValue, lAssertedValue;
1868 /* safe to assume integers are NUL terminated? */
1869 lValue = strtol(value->bv_val, NULL, 10);
1870 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1871 return LDAP_CONSTRAINT_VIOLATION;
1874 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1875 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1876 && errno == ERANGE )
1878 return LDAP_CONSTRAINT_VIOLATION;
1881 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1882 return LDAP_SUCCESS;
1891 struct berval *value,
1892 void *assertedValue )
1894 long lValue, lAssertedValue;
1896 /* safe to assume integers are NUL terminated? */
1897 lValue = strtol(value->bv_val, NULL, 10);
1898 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1899 return LDAP_CONSTRAINT_VIOLATION;
1902 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1903 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1904 && errno == ERANGE )
1906 return LDAP_CONSTRAINT_VIOLATION;
1909 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1910 return LDAP_SUCCESS;
1913 #ifndef SLAP_NVALUES
1915 #include <openssl/x509.h>
1916 #include <openssl/err.h>
1919 * Next function returns a string representation of a ASN1_INTEGER.
1920 * It works for unlimited lengths.
1923 static struct berval *
1924 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1928 static char digit[] = "0123456789";
1930 /* We work backwards, make it fill from the end of buf */
1931 p = buf + sizeof(buf) - 1;
1934 if ( a == NULL || a->length == 0 ) {
1942 /* We want to preserve the original */
1943 copy = ch_malloc(n*sizeof(unsigned int));
1944 for (i = 0; i<n; i++) {
1945 copy[i] = a->data[i];
1949 * base indicates the index of the most significant
1950 * byte that might be nonzero. When it goes off the
1951 * end, we now there is nothing left to do.
1957 for (i = base; i<n; i++ ) {
1958 copy[i] += carry*256;
1959 carry = copy[i] % 10;
1964 * Way too large, we need to leave
1965 * room for sign if negative
1970 *--p = digit[carry];
1972 if (copy[base] == 0) base++;
1977 if ( a->type == V_ASN1_NEG_INTEGER ) {
1981 return ber_str2bv( p, 0, 1, bv );
1985 * Given a certificate in DER format, extract the corresponding
1986 * assertion value for certificateExactMatch
1989 certificateExactConvert(
1991 struct berval * out )
1994 unsigned char *p = in->bv_val;
1995 struct berval serial;
1996 struct berval issuer_dn;
1998 xcert = d2i_X509(NULL, &p, in->bv_len);
2001 LDAP_LOG( CONFIG, ENTRY,
2002 "certificateExactConvert: error parsing cert: %s\n",
2003 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2005 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2006 "error parsing cert: %s\n",
2007 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2009 return LDAP_INVALID_SYNTAX;
2012 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2014 return LDAP_INVALID_SYNTAX;
2016 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2020 ber_memfree(serial.bv_val);
2021 return LDAP_INVALID_SYNTAX;
2026 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2027 out->bv_val = ch_malloc(out->bv_len);
2029 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2031 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2033 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2034 p += issuer_dn.bv_len;
2038 LDAP_LOG( CONFIG, ARGS,
2039 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2041 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2043 out->bv_val, NULL, NULL );
2046 ber_memfree(serial.bv_val);
2047 ber_memfree(issuer_dn.bv_val);
2049 return LDAP_SUCCESS;
2053 serial_and_issuer_parse(
2054 struct berval *assertion,
2055 struct berval *serial,
2056 struct berval *issuer_dn )
2063 begin = assertion->bv_val;
2064 end = assertion->bv_val+assertion->bv_len-1;
2065 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2066 if ( p > end ) return LDAP_INVALID_SYNTAX;
2068 /* p now points at the $ sign, now use
2069 * begin and end to delimit the serial number
2071 while (ASCII_SPACE(*begin)) begin++;
2073 while (ASCII_SPACE(*end)) end--;
2075 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2077 bv.bv_len = end-begin+1;
2079 ber_dupbv(serial, &bv);
2081 /* now extract the issuer, remember p was at the dollar sign */
2083 end = assertion->bv_val+assertion->bv_len-1;
2084 while (ASCII_SPACE(*begin)) begin++;
2085 /* should we trim spaces at the end too? is it safe always? no, no */
2087 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2090 bv.bv_len = end-begin+1;
2093 dnNormalize2( NULL, &bv, issuer_dn );
2096 return LDAP_SUCCESS;
2100 certificateExactMatch(
2105 struct berval *value,
2106 void *assertedValue )
2109 unsigned char *p = value->bv_val;
2110 struct berval serial;
2111 struct berval issuer_dn;
2112 struct berval asserted_serial;
2113 struct berval asserted_issuer_dn;
2116 xcert = d2i_X509(NULL, &p, value->bv_len);
2119 LDAP_LOG( CONFIG, ENTRY,
2120 "certificateExactMatch: error parsing cert: %s\n",
2121 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2123 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2124 "error parsing cert: %s\n",
2125 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2127 return LDAP_INVALID_SYNTAX;
2130 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2131 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2135 serial_and_issuer_parse(assertedValue,
2136 &asserted_serial, &asserted_issuer_dn);
2141 slap_schema.si_syn_integer,
2142 slap_schema.si_mr_integerMatch,
2145 if ( ret == LDAP_SUCCESS ) {
2146 if ( *matchp == 0 ) {
2147 /* We need to normalize everything for dnMatch */
2151 slap_schema.si_syn_distinguishedName,
2152 slap_schema.si_mr_distinguishedNameMatch,
2154 &asserted_issuer_dn);
2159 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2160 "%d\n\t\"%s $ %s\"\n",
2161 *matchp, serial.bv_val, issuer_dn.bv_val );
2162 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2163 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2166 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2167 "%d\n\t\"%s $ %s\"\n",
2168 *matchp, serial.bv_val, issuer_dn.bv_val );
2169 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2170 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2174 ber_memfree(serial.bv_val);
2175 ber_memfree(issuer_dn.bv_val);
2176 ber_memfree(asserted_serial.bv_val);
2177 ber_memfree(asserted_issuer_dn.bv_val);
2183 * Index generation function
2184 * We just index the serials, in most scenarios the issuer DN is one of
2185 * a very small set of values.
2187 static int certificateExactIndexer(
2192 struct berval *prefix,
2200 struct berval serial;
2202 /* we should have at least one value at this point */
2203 assert( values != NULL && values[0].bv_val != NULL );
2205 for( i=0; values[i].bv_val != NULL; i++ ) {
2206 /* empty -- just count them */
2209 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2211 for( i=0; values[i].bv_val != NULL; i++ ) {
2212 p = values[i].bv_val;
2213 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2216 LDAP_LOG( CONFIG, ENTRY,
2217 "certificateExactIndexer: error parsing cert: %s\n",
2218 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2220 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2221 "error parsing cert: %s\n",
2222 ERR_error_string(ERR_get_error(),NULL),
2225 /* Do we leak keys on error? */
2226 return LDAP_INVALID_SYNTAX;
2229 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2231 xintegerNormalize( slap_schema.si_syn_integer,
2232 &serial, &keys[i] );
2233 ber_memfree(serial.bv_val);
2235 LDAP_LOG( CONFIG, ENTRY,
2236 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2238 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2245 keys[i].bv_val = NULL;
2247 return LDAP_SUCCESS;
2250 /* Index generation function */
2251 /* We think this is always called with a value in matching rule syntax */
2252 static int certificateExactFilter(
2257 struct berval *prefix,
2258 void * assertedValue,
2262 struct berval asserted_serial;
2265 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2266 if( ret != LDAP_SUCCESS ) return ret;
2268 keys = ch_malloc( sizeof( struct berval ) * 2 );
2269 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2270 keys[1].bv_val = NULL;
2273 ber_memfree(asserted_serial.bv_val);
2274 return LDAP_SUCCESS;
2280 check_time_syntax (struct berval *val,
2284 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2285 static int mdays[2][12] = {
2286 /* non-leap years */
2287 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2289 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2292 int part, c, tzoffset, leapyear = 0 ;
2294 if( val->bv_len == 0 ) {
2295 return LDAP_INVALID_SYNTAX;
2298 p = (char *)val->bv_val;
2299 e = p + val->bv_len;
2301 /* Ignore initial whitespace */
2302 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2306 if (e - p < 13 - (2 * start)) {
2307 return LDAP_INVALID_SYNTAX;
2310 for (part = 0; part < 9; part++) {
2314 for (part = start; part < 7; part++) {
2316 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2323 return LDAP_INVALID_SYNTAX;
2325 if (c < 0 || c > 9) {
2326 return LDAP_INVALID_SYNTAX;
2332 return LDAP_INVALID_SYNTAX;
2334 if (c < 0 || c > 9) {
2335 return LDAP_INVALID_SYNTAX;
2340 if (part == 2 || part == 3) {
2343 if (parts[part] < 0) {
2344 return LDAP_INVALID_SYNTAX;
2346 if (parts[part] > ceiling[part]) {
2347 return LDAP_INVALID_SYNTAX;
2351 /* leapyear check for the Gregorian calendar (year>1581) */
2352 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2353 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2358 if (parts[3] > mdays[leapyear][parts[2]]) {
2359 return LDAP_INVALID_SYNTAX;
2364 tzoffset = 0; /* UTC */
2365 } else if (c != '+' && c != '-') {
2366 return LDAP_INVALID_SYNTAX;
2370 } else /* c == '+' */ {
2375 return LDAP_INVALID_SYNTAX;
2378 for (part = 7; part < 9; part++) {
2380 if (c < 0 || c > 9) {
2381 return LDAP_INVALID_SYNTAX;
2386 if (c < 0 || c > 9) {
2387 return LDAP_INVALID_SYNTAX;
2391 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2392 return LDAP_INVALID_SYNTAX;
2397 /* Ignore trailing whitespace */
2398 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2402 return LDAP_INVALID_SYNTAX;
2405 switch ( tzoffset ) {
2406 case -1: /* negativ offset to UTC, ie west of Greenwich */
2407 parts[4] += parts[7];
2408 parts[5] += parts[8];
2409 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2413 c = mdays[leapyear][parts[2]];
2415 if (parts[part] > c) {
2416 parts[part] -= c + 1;
2421 case 1: /* positive offset to UTC, ie east of Greenwich */
2422 parts[4] -= parts[7];
2423 parts[5] -= parts[8];
2424 for (part = 6; --part > 0; ) {
2428 /* first arg to % needs to be non negativ */
2429 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2431 if (parts[part] < 0) {
2432 parts[part] += c + 1;
2437 case 0: /* already UTC */
2441 return LDAP_SUCCESS;
2444 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2449 struct berval *normalized )
2453 rc = check_time_syntax(val, 1, parts);
2454 if (rc != LDAP_SUCCESS) {
2458 normalized->bv_val = ch_malloc( 14 );
2459 if ( normalized->bv_val == NULL ) {
2460 return LBER_ERROR_MEMORY;
2463 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2464 parts[1], parts[2] + 1, parts[3] + 1,
2465 parts[4], parts[5], parts[6] );
2466 normalized->bv_len = 13;
2468 return LDAP_SUCCESS;
2477 return check_time_syntax(in, 1, parts);
2482 generalizedTimeValidate(
2487 return check_time_syntax(in, 0, parts);
2491 generalizedTimeNormalize(
2496 struct berval *normalized,
2501 rc = check_time_syntax(val, 0, parts);
2502 if (rc != LDAP_SUCCESS) {
2506 normalized->bv_val = sl_malloc( 16, ctx );
2507 if ( normalized->bv_val == NULL ) {
2508 return LBER_ERROR_MEMORY;
2511 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2512 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2513 parts[4], parts[5], parts[6] );
2514 normalized->bv_len = 15;
2516 return LDAP_SUCCESS;
2520 nisNetgroupTripleValidate(
2522 struct berval *val )
2527 if ( val->bv_len == 0 ) {
2528 return LDAP_INVALID_SYNTAX;
2531 p = (char *)val->bv_val;
2532 e = p + val->bv_len;
2534 if ( *p != '(' /*')'*/ ) {
2535 return LDAP_INVALID_SYNTAX;
2538 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2542 return LDAP_INVALID_SYNTAX;
2545 } else if ( !AD_CHAR( *p ) ) {
2546 return LDAP_INVALID_SYNTAX;
2550 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2551 return LDAP_INVALID_SYNTAX;
2557 return LDAP_INVALID_SYNTAX;
2560 return LDAP_SUCCESS;
2564 bootParameterValidate(
2566 struct berval *val )
2570 if ( val->bv_len == 0 ) {
2571 return LDAP_INVALID_SYNTAX;
2574 p = (char *)val->bv_val;
2575 e = p + val->bv_len;
2578 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2579 if ( !AD_CHAR( *p ) ) {
2580 return LDAP_INVALID_SYNTAX;
2585 return LDAP_INVALID_SYNTAX;
2589 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2590 if ( !AD_CHAR( *p ) ) {
2591 return LDAP_INVALID_SYNTAX;
2596 return LDAP_INVALID_SYNTAX;
2600 for ( p++; p < e; p++ ) {
2601 if ( !SLAP_PRINTABLE( *p ) ) {
2602 return LDAP_INVALID_SYNTAX;
2606 return LDAP_SUCCESS;
2609 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2610 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2612 static slap_syntax_defs_rec syntax_defs[] = {
2613 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2614 X_BINARY X_NOT_H_R ")",
2615 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2616 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2618 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2620 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2622 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2623 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2625 SLAP_SYNTAX_BER, berValidate, NULL},
2626 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2627 0, bitStringValidate, NULL },
2628 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2629 0, booleanValidate, NULL},
2630 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2631 X_BINARY X_NOT_H_R ")",
2632 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2633 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2634 X_BINARY X_NOT_H_R ")",
2635 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2636 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2637 X_BINARY X_NOT_H_R ")",
2638 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2639 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2640 0, countryStringValidate, NULL},
2641 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2642 0, dnValidate, dnPretty2},
2643 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2645 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2647 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2648 0, UTF8StringValidate, NULL},
2649 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2651 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2653 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2655 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2657 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2659 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2660 0, printablesStringValidate, NULL},
2661 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2662 SLAP_SYNTAX_BLOB, NULL, NULL},
2663 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2664 0, generalizedTimeValidate, NULL},
2665 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2667 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2668 0, IA5StringValidate, NULL},
2669 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2670 0, integerValidate, NULL},
2671 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2672 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2673 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2675 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2677 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2679 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2681 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2683 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2684 0, nameUIDValidate, NULL},
2685 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2687 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2688 0, numericStringValidate, NULL},
2689 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2691 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2692 0, oidValidate, NULL},
2693 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2694 0, IA5StringValidate, NULL},
2695 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2696 0, blobValidate, NULL},
2697 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2698 0, UTF8StringValidate, NULL},
2699 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2701 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2703 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2704 0, printableStringValidate, NULL},
2705 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2706 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2707 0, subtreeSpecificationValidate, NULL},
2708 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2709 X_BINARY X_NOT_H_R ")",
2710 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2711 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2712 0, printableStringValidate, NULL},
2713 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2715 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2716 0, printablesStringValidate, NULL},
2717 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2718 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2719 0, utcTimeValidate, NULL},
2721 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2723 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2725 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2727 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2729 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2732 /* RFC 2307 NIS Syntaxes */
2733 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2734 0, nisNetgroupTripleValidate, NULL},
2735 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2736 0, bootParameterValidate, NULL},
2740 /* These OIDs are not published yet, but will be in the next
2741 * I-D for PKIX LDAPv3 schema as have been advanced by David
2742 * Chadwick in private mail.
2744 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2745 0, UTF8StringValidate, NULL},
2748 /* OpenLDAP Experimental Syntaxes */
2749 #ifdef SLAPD_ACI_ENABLED
2750 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2752 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2756 #ifdef SLAPD_AUTHPASSWD
2757 /* needs updating */
2758 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2759 SLAP_SYNTAX_HIDE, NULL, NULL},
2762 /* OpenLDAP Void Syntax */
2763 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2764 SLAP_SYNTAX_HIDE, inValidate, NULL},
2765 {NULL, 0, NULL, NULL}
2769 char *certificateExactMatchSyntaxes[] = {
2770 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2774 char *directoryStringSyntaxes[] = {
2775 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2778 char *integerFirstComponentMatchSyntaxes[] = {
2779 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2780 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2783 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2784 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2785 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2786 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2787 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2788 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2789 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2790 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2791 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2796 * Other matching rules in X.520 that we do not use (yet):
2798 * 2.5.13.9 numericStringOrderingMatch
2799 * 2.5.13.25 uTCTimeMatch
2800 * 2.5.13.26 uTCTimeOrderingMatch
2801 * 2.5.13.31 directoryStringFirstComponentMatch
2802 * 2.5.13.32 wordMatch
2803 * 2.5.13.33 keywordMatch
2804 * 2.5.13.35 certificateMatch
2805 * 2.5.13.36 certificatePairExactMatch
2806 * 2.5.13.37 certificatePairMatch
2807 * 2.5.13.38 certificateListExactMatch
2808 * 2.5.13.39 certificateListMatch
2809 * 2.5.13.40 algorithmIdentifierMatch
2810 * 2.5.13.41 storedPrefixMatch
2811 * 2.5.13.42 attributeCertificateMatch
2812 * 2.5.13.43 readerAndKeyIDMatch
2813 * 2.5.13.44 attributeIntegrityMatch
2815 static slap_mrule_defs_rec mrule_defs[] = {
2817 * EQUALITY matching rules must be listed after associated APPROX
2818 * matching rules. So, we list all APPROX matching rules first.
2820 #ifndef SLAP_NVALUES
2821 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2822 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2823 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2824 NULL, NULL, directoryStringApproxMatch,
2825 directoryStringApproxIndexer, directoryStringApproxFilter,
2828 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2829 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2830 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2831 NULL, NULL, IA5StringApproxMatch,
2832 IA5StringApproxIndexer, IA5StringApproxFilter,
2837 * Other matching rules
2840 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2841 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2842 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2843 NULL, objectIdentifierNormalize, octetStringMatch,
2844 octetStringIndexer, octetStringFilter,
2847 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2848 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2849 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2850 NULL, dnNormalize, dnMatch,
2851 octetStringIndexer, octetStringFilter,
2854 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2855 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2856 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2857 NULL, UTF8StringNormalize, octetStringMatch,
2858 octetStringIndexer, octetStringFilter,
2859 directoryStringApproxMatchOID },
2861 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2862 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2863 SLAP_MR_ORDERING, directoryStringSyntaxes,
2864 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2866 "caseIgnoreMatch" },
2868 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2869 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2870 SLAP_MR_SUBSTR, NULL,
2871 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2872 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2873 "caseIgnoreMatch" },
2875 {"( 2.5.13.5 NAME 'caseExactMatch' "
2876 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2877 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2878 NULL, UTF8StringNormalize, octetStringMatch,
2879 octetStringIndexer, octetStringFilter,
2880 directoryStringApproxMatchOID },
2882 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2883 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2884 SLAP_MR_ORDERING, directoryStringSyntaxes,
2885 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2889 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2890 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2891 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2892 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2893 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2896 {"( 2.5.13.8 NAME 'numericStringMatch' "
2897 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2898 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2899 NULL, numericStringNormalize, octetStringSubstringsMatch,
2900 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2903 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2904 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2905 SLAP_MR_SUBSTR, NULL,
2906 NULL, numericStringNormalize, octetStringSubstringsMatch,
2907 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2908 "numericStringMatch" },
2910 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2911 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2912 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2913 NULL, NULL, NULL, NULL, NULL, NULL },
2915 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2916 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2917 SLAP_MR_SUBSTR, NULL,
2918 NULL, NULL, NULL, NULL, NULL,
2919 "caseIgnoreListMatch" },
2921 {"( 2.5.13.13 NAME 'booleanMatch' "
2922 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2923 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2924 NULL, NULL, booleanMatch,
2925 octetStringIndexer, octetStringFilter,
2928 {"( 2.5.13.14 NAME 'integerMatch' "
2929 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2930 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2931 NULL, NULL, integerMatch,
2932 octetStringIndexer, octetStringFilter,
2935 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2936 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2937 SLAP_MR_ORDERING, NULL,
2938 NULL, NULL, integerMatch,
2942 {"( 2.5.13.16 NAME 'bitStringMatch' "
2943 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2944 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2945 NULL, NULL, octetStringMatch,
2946 octetStringIndexer, octetStringFilter,
2949 {"( 2.5.13.17 NAME 'octetStringMatch' "
2950 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2951 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2952 NULL, NULL, octetStringMatch,
2953 octetStringIndexer, octetStringFilter,
2956 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2957 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2958 SLAP_MR_ORDERING, NULL,
2959 NULL, NULL, octetStringOrderingMatch,
2961 "octetStringMatch" },
2963 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2964 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2965 SLAP_MR_SUBSTR, NULL,
2966 NULL, NULL, octetStringSubstringsMatch,
2967 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2968 "octetStringMatch" },
2970 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2971 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2972 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2974 telephoneNumberNormalize, octetStringMatch,
2975 octetStringIndexer, octetStringFilter,
2978 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2980 SLAP_MR_SUBSTR, NULL,
2981 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2982 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2983 "telephoneNumberMatch" },
2985 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2987 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2988 NULL, NULL, NULL, NULL, NULL, NULL },
2990 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2991 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2992 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2993 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2997 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2998 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2999 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3000 NULL, NULL, NULL, NULL, NULL, NULL },
3002 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3004 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3005 NULL, generalizedTimeNormalize, octetStringMatch,
3009 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3010 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3011 SLAP_MR_ORDERING, NULL,
3012 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3014 "generalizedTimeMatch" },
3016 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3017 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3018 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3019 integerFirstComponentMatchSyntaxes,
3020 NULL, integerFirstComponentNormalize, integerMatch,
3021 octetStringIndexer, octetStringFilter,
3024 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3025 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3026 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3027 objectIdentifierFirstComponentMatchSyntaxes,
3028 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3029 octetStringIndexer, octetStringFilter,
3032 #ifndef SLAP_NVALUES
3034 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3035 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3036 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3037 certificateExactConvert, NULL, certificateExactMatch,
3038 certificateExactIndexer, certificateExactFilter,
3043 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3044 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3045 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3046 NULL, IA5StringNormalize, octetStringMatch,
3047 octetStringIndexer, octetStringFilter,
3048 IA5StringApproxMatchOID },
3050 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3051 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3052 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3053 NULL, IA5StringNormalize, octetStringMatch,
3054 octetStringIndexer, octetStringFilter,
3055 IA5StringApproxMatchOID },
3057 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3058 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3059 SLAP_MR_SUBSTR, NULL,
3060 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3061 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3062 "caseIgnoreIA5Match" },
3064 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3065 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3066 SLAP_MR_SUBSTR, NULL,
3067 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3068 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3069 "caseExactIA5Match" },
3071 #ifdef SLAPD_AUTHPASSWD
3072 /* needs updating */
3073 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3074 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3075 SLAP_MR_EQUALITY, NULL,
3076 NULL, NULL, authPasswordMatch,
3081 #ifdef SLAPD_ACI_ENABLED
3082 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3083 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3084 SLAP_MR_EQUALITY, NULL,
3085 NULL, NULL, OpenLDAPaciMatch,
3090 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3091 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3093 NULL, NULL, integerBitAndMatch,
3097 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3098 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3100 NULL, NULL, integerBitOrMatch,
3104 {NULL, SLAP_MR_NONE, NULL,
3105 NULL, NULL, NULL, NULL, NULL,
3110 slap_schema_init( void )
3115 /* we should only be called once (from main) */
3116 assert( schema_init_done == 0 );
3118 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3119 res = register_syntax( &syntax_defs[i] );
3122 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3123 syntax_defs[i].sd_desc );
3128 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3129 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3130 mrule_defs[i].mrd_compat_syntaxes == NULL )
3133 "slap_schema_init: Ignoring unusable matching rule %s\n",
3134 mrule_defs[i].mrd_desc );
3138 res = register_matching_rule( &mrule_defs[i] );
3142 "slap_schema_init: Error registering matching rule %s\n",
3143 mrule_defs[i].mrd_desc );
3148 res = slap_schema_load();
3149 schema_init_done = 1;
3154 schema_destroy( void )