1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
15 #include <ac/string.h>
16 #include <ac/socket.h>
22 #include "ldap_utf8.h"
24 #include "lutil_hash.h"
25 #define HASH_BYTES LUTIL_HASH_BYTES
26 #define HASH_CONTEXT lutil_HASH_CTX
27 #define HASH_Init(c) lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
31 #define SLAP_NVALUES 1
33 /* not yet implemented */
34 #define objectIdentifierNormalize NULL
35 #define integerOrderingMatch NULL
36 #define uniqueMemberMatch NULL
37 #define integerFirstComponentNormalize NULL
38 #define objectIdentifierFirstComponentNormalize NULL
40 #define OpenLDAPaciMatch NULL
42 /* approx matching rules */
44 #define directoryStringApproxMatchOID NULL
45 #define IA5StringApproxMatchOID NULL
47 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
48 #define directoryStringApproxMatch approxMatch
49 #define directoryStringApproxIndexer approxIndexer
50 #define directoryStringApproxFilter approxFilter
51 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
52 #define IA5StringApproxMatch approxMatch
53 #define IA5StringApproxIndexer approxIndexer
54 #define IA5StringApproxFilter approxFilter
62 /* no value allowed */
63 return LDAP_INVALID_SYNTAX;
71 /* any value allowed */
75 #define berValidate blobValidate
86 struct berval *asserted = (struct berval *) assertedValue;
87 int match = value->bv_len - asserted->bv_len;
90 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
98 octetStringOrderingMatch(
103 struct berval *value,
104 void *assertedValue )
106 struct berval *asserted = (struct berval *) assertedValue;
107 ber_len_t v_len = value->bv_len;
108 ber_len_t av_len = asserted->bv_len;
110 int match = memcmp( value->bv_val, asserted->bv_val,
111 (v_len < av_len ? v_len : av_len) );
113 if( match == 0 ) match = v_len - av_len;
119 /* Index generation function */
120 int octetStringIndexer(
125 struct berval *prefix,
133 HASH_CONTEXT HASHcontext;
134 unsigned char HASHdigest[HASH_BYTES];
135 struct berval digest;
136 digest.bv_val = HASHdigest;
137 digest.bv_len = sizeof(HASHdigest);
139 for( i=0; values[i].bv_val != NULL; i++ ) {
140 /* just count them */
143 /* we should have at least one value at this point */
146 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
148 slen = syntax->ssyn_oidlen;
149 mlen = mr->smr_oidlen;
151 for( i=0; values[i].bv_val != NULL; i++ ) {
152 HASH_Init( &HASHcontext );
153 if( prefix != NULL && prefix->bv_len > 0 ) {
154 HASH_Update( &HASHcontext,
155 prefix->bv_val, prefix->bv_len );
157 HASH_Update( &HASHcontext,
158 syntax->ssyn_oid, slen );
159 HASH_Update( &HASHcontext,
161 HASH_Update( &HASHcontext,
162 values[i].bv_val, values[i].bv_len );
163 HASH_Final( HASHdigest, &HASHcontext );
165 ber_dupbv_x( &keys[i], &digest, ctx );
168 keys[i].bv_val = NULL;
176 /* Index generation function */
177 int octetStringFilter(
182 struct berval *prefix,
183 void * assertedValue,
189 HASH_CONTEXT HASHcontext;
190 unsigned char HASHdigest[HASH_BYTES];
191 struct berval *value = (struct berval *) assertedValue;
192 struct berval digest;
193 digest.bv_val = HASHdigest;
194 digest.bv_len = sizeof(HASHdigest);
196 slen = syntax->ssyn_oidlen;
197 mlen = mr->smr_oidlen;
199 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
201 HASH_Init( &HASHcontext );
202 if( prefix != NULL && prefix->bv_len > 0 ) {
203 HASH_Update( &HASHcontext,
204 prefix->bv_val, prefix->bv_len );
206 HASH_Update( &HASHcontext,
207 syntax->ssyn_oid, slen );
208 HASH_Update( &HASHcontext,
210 HASH_Update( &HASHcontext,
211 value->bv_val, value->bv_len );
212 HASH_Final( HASHdigest, &HASHcontext );
214 ber_dupbv_x( keys, &digest, ctx );
215 keys[1].bv_val = NULL;
224 octetStringSubstringsMatch(
229 struct berval *value,
230 void *assertedValue )
233 SubstringsAssertion *sub = assertedValue;
234 struct berval left = *value;
238 /* Add up asserted input length */
239 if( sub->sa_initial.bv_val ) {
240 inlen += sub->sa_initial.bv_len;
243 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
244 inlen += sub->sa_any[i].bv_len;
247 if( sub->sa_final.bv_val ) {
248 inlen += sub->sa_final.bv_len;
251 if( sub->sa_initial.bv_val ) {
252 if( inlen > left.bv_len ) {
257 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
258 sub->sa_initial.bv_len );
264 left.bv_val += sub->sa_initial.bv_len;
265 left.bv_len -= sub->sa_initial.bv_len;
266 inlen -= sub->sa_initial.bv_len;
269 if( sub->sa_final.bv_val ) {
270 if( inlen > left.bv_len ) {
275 match = memcmp( sub->sa_final.bv_val,
276 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
277 sub->sa_final.bv_len );
283 left.bv_len -= sub->sa_final.bv_len;
284 inlen -= sub->sa_final.bv_len;
288 for(i=0; sub->sa_any[i].bv_val; i++) {
293 if( inlen > left.bv_len ) {
294 /* not enough length */
299 if( sub->sa_any[i].bv_len == 0 ) {
303 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
310 idx = p - left.bv_val;
312 if( idx >= left.bv_len ) {
313 /* this shouldn't happen */
320 if( sub->sa_any[i].bv_len > left.bv_len ) {
321 /* not enough left */
326 match = memcmp( left.bv_val,
327 sub->sa_any[i].bv_val,
328 sub->sa_any[i].bv_len );
336 left.bv_val += sub->sa_any[i].bv_len;
337 left.bv_len -= sub->sa_any[i].bv_len;
338 inlen -= sub->sa_any[i].bv_len;
347 /* Substrings Index generation function */
349 octetStringSubstringsIndexer(
354 struct berval *prefix,
359 ber_len_t i, j, nkeys;
363 HASH_CONTEXT HASHcontext;
364 unsigned char HASHdigest[HASH_BYTES];
365 struct berval digest;
366 digest.bv_val = HASHdigest;
367 digest.bv_len = sizeof(HASHdigest);
371 for( i=0; values[i].bv_val != NULL; i++ ) {
372 /* count number of indices to generate */
373 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
377 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
378 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
379 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
380 (SLAP_INDEX_SUBSTR_MINLEN - 1);
382 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
386 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
387 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
388 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
392 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
393 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
394 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
395 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
397 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
403 /* no keys to generate */
408 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
410 slen = syntax->ssyn_oidlen;
411 mlen = mr->smr_oidlen;
414 for( i=0; values[i].bv_val != NULL; i++ ) {
417 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
419 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
420 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
422 char pre = SLAP_INDEX_SUBSTR_PREFIX;
423 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
425 for( j=0; j<max; j++ ) {
426 HASH_Init( &HASHcontext );
427 if( prefix != NULL && prefix->bv_len > 0 ) {
428 HASH_Update( &HASHcontext,
429 prefix->bv_val, prefix->bv_len );
432 HASH_Update( &HASHcontext,
433 &pre, sizeof( pre ) );
434 HASH_Update( &HASHcontext,
435 syntax->ssyn_oid, slen );
436 HASH_Update( &HASHcontext,
438 HASH_Update( &HASHcontext,
439 &values[i].bv_val[j],
440 SLAP_INDEX_SUBSTR_MAXLEN );
441 HASH_Final( HASHdigest, &HASHcontext );
443 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
447 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
448 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
450 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
453 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
454 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
455 HASH_Init( &HASHcontext );
456 if( prefix != NULL && prefix->bv_len > 0 ) {
457 HASH_Update( &HASHcontext,
458 prefix->bv_val, prefix->bv_len );
460 HASH_Update( &HASHcontext,
461 &pre, sizeof( pre ) );
462 HASH_Update( &HASHcontext,
463 syntax->ssyn_oid, slen );
464 HASH_Update( &HASHcontext,
466 HASH_Update( &HASHcontext,
467 values[i].bv_val, j );
468 HASH_Final( HASHdigest, &HASHcontext );
470 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
473 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
474 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
475 HASH_Init( &HASHcontext );
476 if( prefix != NULL && prefix->bv_len > 0 ) {
477 HASH_Update( &HASHcontext,
478 prefix->bv_val, prefix->bv_len );
480 HASH_Update( &HASHcontext,
481 &pre, sizeof( pre ) );
482 HASH_Update( &HASHcontext,
483 syntax->ssyn_oid, slen );
484 HASH_Update( &HASHcontext,
486 HASH_Update( &HASHcontext,
487 &values[i].bv_val[values[i].bv_len-j], j );
488 HASH_Final( HASHdigest, &HASHcontext );
490 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
498 keys[nkeys].bv_val = NULL;
509 octetStringSubstringsFilter (
514 struct berval *prefix,
515 void * assertedValue,
519 SubstringsAssertion *sa;
522 size_t slen, mlen, klen;
524 HASH_CONTEXT HASHcontext;
525 unsigned char HASHdigest[HASH_BYTES];
526 struct berval *value;
527 struct berval digest;
529 sa = (SubstringsAssertion *) assertedValue;
531 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
532 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
537 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
539 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
540 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
541 /* don't bother accounting for stepping */
542 nkeys += sa->sa_any[i].bv_len -
543 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
548 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
549 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
559 digest.bv_val = HASHdigest;
560 digest.bv_len = sizeof(HASHdigest);
562 slen = syntax->ssyn_oidlen;
563 mlen = mr->smr_oidlen;
565 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
568 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
569 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
571 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
572 value = &sa->sa_initial;
574 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
575 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
577 HASH_Init( &HASHcontext );
578 if( prefix != NULL && prefix->bv_len > 0 ) {
579 HASH_Update( &HASHcontext,
580 prefix->bv_val, prefix->bv_len );
582 HASH_Update( &HASHcontext,
583 &pre, sizeof( pre ) );
584 HASH_Update( &HASHcontext,
585 syntax->ssyn_oid, slen );
586 HASH_Update( &HASHcontext,
588 HASH_Update( &HASHcontext,
589 value->bv_val, klen );
590 HASH_Final( HASHdigest, &HASHcontext );
592 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
595 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
597 pre = SLAP_INDEX_SUBSTR_PREFIX;
598 klen = SLAP_INDEX_SUBSTR_MAXLEN;
600 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
601 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
605 value = &sa->sa_any[i];
608 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
609 j += SLAP_INDEX_SUBSTR_STEP )
611 HASH_Init( &HASHcontext );
612 if( prefix != NULL && prefix->bv_len > 0 ) {
613 HASH_Update( &HASHcontext,
614 prefix->bv_val, prefix->bv_len );
616 HASH_Update( &HASHcontext,
617 &pre, sizeof( pre ) );
618 HASH_Update( &HASHcontext,
619 syntax->ssyn_oid, slen );
620 HASH_Update( &HASHcontext,
622 HASH_Update( &HASHcontext,
623 &value->bv_val[j], klen );
624 HASH_Final( HASHdigest, &HASHcontext );
626 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
631 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
632 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
634 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
635 value = &sa->sa_final;
637 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
638 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
640 HASH_Init( &HASHcontext );
641 if( prefix != NULL && prefix->bv_len > 0 ) {
642 HASH_Update( &HASHcontext,
643 prefix->bv_val, prefix->bv_len );
645 HASH_Update( &HASHcontext,
646 &pre, sizeof( pre ) );
647 HASH_Update( &HASHcontext,
648 syntax->ssyn_oid, slen );
649 HASH_Update( &HASHcontext,
651 HASH_Update( &HASHcontext,
652 &value->bv_val[value->bv_len-klen], klen );
653 HASH_Final( HASHdigest, &HASHcontext );
655 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
659 keys[nkeys].bv_val = NULL;
676 /* very unforgiving validation, requires no normalization
677 * before simplistic matching
679 if( in->bv_len < 3 ) {
680 return LDAP_INVALID_SYNTAX;
684 * RFC 2252 section 6.3 Bit String
685 * bitstring = "'" *binary-digit "'B"
686 * binary-digit = "0" / "1"
687 * example: '0101111101'B
690 if( in->bv_val[0] != '\'' ||
691 in->bv_val[in->bv_len-2] != '\'' ||
692 in->bv_val[in->bv_len-1] != 'B' )
694 return LDAP_INVALID_SYNTAX;
697 for( i=in->bv_len-3; i>0; i-- ) {
698 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
699 return LDAP_INVALID_SYNTAX;
714 if( in->bv_len == 0 ) return LDAP_SUCCESS;
716 ber_dupbv( &dn, in );
717 if( !dn.bv_val ) return LDAP_OTHER;
719 if( dn.bv_val[dn.bv_len-1] == 'B'
720 && dn.bv_val[dn.bv_len-2] == '\'' )
722 /* assume presence of optional UID */
725 for(i=dn.bv_len-3; i>1; i--) {
726 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
730 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
731 ber_memfree( dn.bv_val );
732 return LDAP_INVALID_SYNTAX;
735 /* trim the UID to allow use of dnValidate */
736 dn.bv_val[i-1] = '\0';
740 rc = dnValidate( NULL, &dn );
742 ber_memfree( dn.bv_val );
747 uniqueMemberNormalize(
752 struct berval *normalized,
758 ber_dupbv( &out, val );
759 if( out.bv_len != 0 ) {
760 struct berval uid = { 0, NULL };
762 if( out.bv_val[out.bv_len-1] == 'B'
763 && out.bv_val[out.bv_len-2] == '\'' )
765 /* assume presence of optional UID */
766 uid.bv_val = strrchr( out.bv_val, '#' );
768 if( uid.bv_val == NULL ) {
770 return LDAP_INVALID_SYNTAX;
773 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
774 out.bv_len -= uid.bv_len--;
776 /* temporarily trim the UID */
777 *(uid.bv_val++) = '\0';
780 rc = dnNormalize2( NULL, &out, normalized, ctx );
782 if( rc != LDAP_SUCCESS ) {
784 return LDAP_INVALID_SYNTAX;
788 normalized->bv_val = ch_realloc( normalized->bv_val,
789 normalized->bv_len + uid.bv_len + sizeof("#") );
791 /* insert the separator */
792 normalized->bv_val[normalized->bv_len++] = '#';
795 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
796 uid.bv_val, uid.bv_len );
797 normalized->bv_len += uid.bv_len;
800 normalized->bv_val[normalized->bv_len] = '\0';
810 * Handling boolean syntax and matching is quite rigid.
811 * A more flexible approach would be to allow a variety
812 * of strings to be normalized and prettied into TRUE
820 /* very unforgiving validation, requires no normalization
821 * before simplistic matching
824 if( in->bv_len == 4 ) {
825 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
828 } else if( in->bv_len == 5 ) {
829 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
834 return LDAP_INVALID_SYNTAX;
843 struct berval *value,
844 void *assertedValue )
846 /* simplistic matching allowed by rigid validation */
847 struct berval *asserted = (struct berval *) assertedValue;
848 *matchp = value->bv_len != asserted->bv_len;
852 /*-------------------------------------------------------------------
853 LDAP/X.500 string syntax / matching rules have a few oddities. This
854 comment attempts to detail how slapd(8) treats them.
857 StringSyntax X.500 LDAP Matching/Comments
858 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
859 PrintableString subset subset i/e + ignore insignificant spaces
860 PrintableString subset subset i/e + ignore insignificant spaces
861 NumericString subset subset ignore all spaces
862 IA5String ASCII ASCII i/e + ignore insignificant spaces
863 TeletexString T.61 T.61 i/e + ignore insignificant spaces
865 TelephoneNumber subset subset i + ignore all spaces and "-"
867 See draft-ietf-ldapbis-strpro for details (once published).
871 In X.500(93), a directory string can be either a PrintableString,
872 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
873 In later versions, more CHOICEs were added. In all cases the string
876 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
877 A directory string cannot be zero length.
879 For matching, there are both case ignore and exact rules. Both
880 also require that "insignificant" spaces be ignored.
881 spaces before the first non-space are ignored;
882 spaces after the last non-space are ignored;
883 spaces after a space are ignored.
884 Note: by these rules (and as clarified in X.520), a string of only
885 spaces is to be treated as if held one space, not empty (which
886 would be a syntax error).
889 In ASN.1, numeric string is just a string of digits and spaces
890 and could be empty. However, in X.500, all attribute values of
891 numeric string carry a non-empty constraint. For example:
893 internationalISDNNumber ATTRIBUTE ::= {
894 WITH SYNTAX InternationalISDNNumber
895 EQUALITY MATCHING RULE numericStringMatch
896 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
897 ID id-at-internationalISDNNumber }
898 InternationalISDNNumber ::=
899 NumericString (SIZE(1..ub-international-isdn-number))
901 Unforunately, some assertion values are don't carry the same
902 constraint (but its unclear how such an assertion could ever
903 be true). In LDAP, there is one syntax (numericString) not two
904 (numericString with constraint, numericString without constraint).
905 This should be treated as numericString with non-empty constraint.
906 Note that while someone may have no ISDN number, there are no ISDN
907 numbers which are zero length.
909 In matching, spaces are ignored.
912 In ASN.1, Printable string is just a string of printable characters
913 and can be empty. In X.500, semantics much like NumericString (see
914 serialNumber for a like example) excepting uses insignificant space
915 handling instead of ignore all spaces.
918 Basically same as PrintableString. There are no examples in X.500,
919 but same logic applies. So we require them to be non-empty as
922 -------------------------------------------------------------------*/
931 unsigned char *u = in->bv_val;
933 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
934 /* directory strings cannot be empty */
935 return LDAP_INVALID_SYNTAX;
938 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
939 /* get the length indicated by the first byte */
940 len = LDAP_UTF8_CHARLEN2( u, len );
942 /* very basic checks */
945 if( (u[5] & 0xC0) != 0x80 ) {
946 return LDAP_INVALID_SYNTAX;
949 if( (u[4] & 0xC0) != 0x80 ) {
950 return LDAP_INVALID_SYNTAX;
953 if( (u[3] & 0xC0) != 0x80 ) {
954 return LDAP_INVALID_SYNTAX;
957 if( (u[2] & 0xC0 )!= 0x80 ) {
958 return LDAP_INVALID_SYNTAX;
961 if( (u[1] & 0xC0) != 0x80 ) {
962 return LDAP_INVALID_SYNTAX;
965 /* CHARLEN already validated it */
968 return LDAP_INVALID_SYNTAX;
971 /* make sure len corresponds with the offset
972 to the next character */
973 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
977 return LDAP_INVALID_SYNTAX;
989 struct berval *normalized,
992 struct berval tmp, nvalue;
996 if( val->bv_val == NULL ) {
997 /* assume we're dealing with a syntax (e.g., UTF8String)
998 * which allows empty strings
1000 normalized->bv_len = 0;
1001 normalized->bv_val = NULL;
1002 return LDAP_SUCCESS;
1005 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1006 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1007 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1008 ? LDAP_UTF8_APPROX : 0;
1010 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1015 /* collapse spaces (in place) */
1017 nvalue.bv_val = tmp.bv_val;
1019 wasspace=1; /* trim leading spaces */
1020 for( i=0; i<tmp.bv_len; i++) {
1021 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1022 if( wasspace++ == 0 ) {
1023 /* trim repeated spaces */
1024 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1028 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1032 if( nvalue.bv_len ) {
1034 /* last character was a space, trim it */
1037 nvalue.bv_val[nvalue.bv_len] = '\0';
1040 /* string of all spaces is treated as one space */
1041 nvalue.bv_val[0] = ' ';
1042 nvalue.bv_val[1] = '\0';
1046 *normalized = nvalue;
1047 return LDAP_SUCCESS;
1050 #ifndef SLAP_NVALUES
1052 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1053 #if defined(SLAPD_APPROX_INITIALS)
1054 #define SLAPD_APPROX_DELIMITER "._ "
1055 #define SLAPD_APPROX_WORDLEN 2
1057 #define SLAPD_APPROX_DELIMITER " "
1058 #define SLAPD_APPROX_WORDLEN 1
1067 struct berval *value,
1068 void *assertedValue )
1070 struct berval *nval, *assertv;
1071 char *val, **values, **words, *c;
1072 int i, count, len, nextchunk=0, nextavail=0;
1074 /* Yes, this is necessary */
1075 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1076 if( nval == NULL ) {
1078 return LDAP_SUCCESS;
1081 /* Yes, this is necessary */
1082 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1083 NULL, LDAP_UTF8_APPROX );
1084 if( assertv == NULL ) {
1087 return LDAP_SUCCESS;
1090 /* Isolate how many words there are */
1091 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1092 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1093 if ( c == NULL ) break;
1098 /* Get a phonetic copy of each word */
1099 words = (char **)ch_malloc( count * sizeof(char *) );
1100 values = (char **)ch_malloc( count * sizeof(char *) );
1101 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1103 values[i] = phonetic(c);
1106 /* Work through the asserted value's words, to see if at least some
1107 of the words are there, in the same order. */
1109 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1110 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1115 #if defined(SLAPD_APPROX_INITIALS)
1116 else if( len == 1 ) {
1117 /* Single letter words need to at least match one word's initial */
1118 for( i=nextavail; i<count; i++ )
1119 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1126 /* Isolate the next word in the asserted value and phonetic it */
1127 assertv->bv_val[nextchunk+len] = '\0';
1128 val = phonetic( assertv->bv_val + nextchunk );
1130 /* See if this phonetic chunk is in the remaining words of *value */
1131 for( i=nextavail; i<count; i++ ){
1132 if( !strcmp( val, values[i] ) ){
1140 /* This chunk in the asserted value was NOT within the *value. */
1146 /* Go on to the next word in the asserted value */
1150 /* If some of the words were seen, call it a match */
1151 if( nextavail > 0 ) {
1158 /* Cleanup allocs */
1159 ber_bvfree( assertv );
1160 for( i=0; i<count; i++ ) {
1161 ch_free( values[i] );
1167 return LDAP_SUCCESS;
1176 struct berval *prefix,
1181 int i,j, len, wordcount, keycount=0;
1182 struct berval *newkeys;
1183 BerVarray keys=NULL;
1185 for( j=0; values[j].bv_val != NULL; j++ ) {
1186 struct berval val = { 0, NULL };
1187 /* Yes, this is necessary */
1188 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1189 assert( val.bv_val != NULL );
1191 /* Isolate how many words there are. There will be a key for each */
1192 for( wordcount = 0, c = val.bv_val; *c; c++) {
1193 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1194 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1196 if (*c == '\0') break;
1200 /* Allocate/increase storage to account for new keys */
1201 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1202 * sizeof(struct berval) );
1203 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1204 if( keys ) ch_free( keys );
1207 /* Get a phonetic copy of each word */
1208 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1210 if( len < SLAPD_APPROX_WORDLEN ) continue;
1211 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1216 ber_memfree( val.bv_val );
1218 keys[keycount].bv_val = NULL;
1221 return LDAP_SUCCESS;
1230 struct berval *prefix,
1231 void * assertedValue,
1239 /* Yes, this is necessary */
1240 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1241 NULL, LDAP_UTF8_APPROX );
1242 if( val == NULL || val->bv_val == NULL ) {
1243 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1244 keys[0].bv_val = NULL;
1247 return LDAP_SUCCESS;
1250 /* Isolate how many words there are. There will be a key for each */
1251 for( count = 0,c = val->bv_val; *c; c++) {
1252 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1253 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1255 if (*c == '\0') break;
1259 /* Allocate storage for new keys */
1260 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1262 /* Get a phonetic copy of each word */
1263 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1265 if( len < SLAPD_APPROX_WORDLEN ) continue;
1266 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1272 keys[count].bv_val = NULL;
1275 return LDAP_SUCCESS;
1279 /* No other form of Approximate Matching is defined */
1287 struct berval *value,
1288 void *assertedValue )
1290 char *vapprox, *avapprox;
1293 /* Yes, this is necessary */
1294 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1297 return LDAP_SUCCESS;
1300 /* Yes, this is necessary */
1301 t = UTF8normalize( ((struct berval *)assertedValue),
1306 return LDAP_SUCCESS;
1309 vapprox = phonetic( strip8bitChars( s ) );
1310 avapprox = phonetic( strip8bitChars( t ) );
1315 *matchp = strcmp( vapprox, avapprox );
1318 ch_free( avapprox );
1320 return LDAP_SUCCESS;
1329 struct berval *prefix,
1337 for( i=0; values[i].bv_val != NULL; i++ ) {
1338 /* empty - just count them */
1341 /* we should have at least one value at this point */
1344 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1346 /* Copy each value and run it through phonetic() */
1347 for( i=0; values[i].bv_val != NULL; i++ ) {
1348 /* Yes, this is necessary */
1349 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1351 /* strip 8-bit chars and run through phonetic() */
1352 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1355 keys[i].bv_val = NULL;
1358 return LDAP_SUCCESS;
1367 struct berval *prefix,
1368 void * assertedValue,
1374 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1376 /* Yes, this is necessary */
1377 s = UTF8normalize( ((struct berval *)assertedValue),
1382 /* strip 8-bit chars and run through phonetic() */
1383 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1389 return LDAP_SUCCESS;
1392 #endif /* !SLAP_NVALUES */
1394 /* Remove all spaces and '-' characters */
1396 telephoneNumberNormalize(
1401 struct berval *normalized,
1406 /* validator should have refused an empty string */
1407 assert( val->bv_len );
1409 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1411 for( p = val->bv_val; *p; p++ ) {
1412 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1418 normalized->bv_len = q - normalized->bv_val;
1420 if( normalized->bv_len == 0 ) {
1421 sl_free( normalized->bv_val, ctx );
1422 return LDAP_INVALID_SYNTAX;
1425 return LDAP_SUCCESS;
1431 struct berval *val )
1435 if( val->bv_len == 0 ) {
1436 /* disallow empty strings */
1437 return LDAP_INVALID_SYNTAX;
1440 if( OID_LEADCHAR(val->bv_val[0]) ) {
1442 for(i=1; i < val->bv_len; i++) {
1443 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1444 if( dot++ ) return 1;
1445 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1448 return LDAP_INVALID_SYNTAX;
1452 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1454 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1455 for(i=1; i < val->bv_len; i++) {
1456 if( !DESC_CHAR(val->bv_val[i] ) ) {
1457 return LDAP_INVALID_SYNTAX;
1461 return LDAP_SUCCESS;
1464 return LDAP_INVALID_SYNTAX;
1473 struct berval *value,
1474 void *assertedValue )
1477 int vsign = 1, avsign = 1; /* default sign = '+' */
1478 struct berval *asserted;
1479 ber_len_t vlen, avlen;
1482 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1484 vlen = value->bv_len;
1486 #ifndef SLAP_NVALUES
1487 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1488 char *tmp = memchr( v, '$', vlen );
1489 if( tmp ) vlen = tmp - v;
1490 while( vlen && ASCII_SPACE( v[vlen-1] )) vlen--;
1494 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) { /* ANSI 2.2.1 */
1495 if( *v == '-' ) vsign = -1;
1498 if( vlen == 0 ) vsign = 0;
1500 /* Do the same with the *assertedValue number */
1501 asserted = (struct berval *) assertedValue;
1502 av = asserted->bv_val;
1503 avlen = asserted->bv_len;
1504 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1510 match = vsign - avsign;
1512 match = (vlen != avlen
1513 ? ( vlen < avlen ? -1 : 1 )
1514 : memcmp( v, av, vlen ));
1515 if( vsign < 0 ) match = -match;
1519 return LDAP_SUCCESS;
1525 struct berval *val )
1529 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1531 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1532 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1534 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1535 return LDAP_INVALID_SYNTAX;
1538 for( i=1; i < val->bv_len; i++ ) {
1539 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1542 return LDAP_SUCCESS;
1551 struct berval *normalized,
1561 /* Ignore leading spaces */
1562 while ( len && ( *p == ' ' )) {
1569 negative = ( *p == '-' );
1570 if(( *p == '-' ) || ( *p == '+' )) {
1576 /* Ignore leading zeros */
1577 while ( len && ( *p == '0' )) {
1582 /* If there are no non-zero digits left, the number is zero, otherwise
1583 allocate space for the number and copy it into the buffer */
1585 normalized->bv_val = ber_strdup_x("0", ctx);
1586 normalized->bv_len = 1;
1589 normalized->bv_len = len+negative;
1590 normalized->bv_val = sl_malloc( normalized->bv_len + 1, ctx );
1591 if( negative ) normalized->bv_val[0] = '-';
1592 AC_MEMCPY( normalized->bv_val + negative, p, len );
1593 normalized->bv_val[len+negative] = '\0';
1596 return LDAP_SUCCESS;
1600 countryStringValidate(
1602 struct berval *val )
1604 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1606 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1607 return LDAP_INVALID_SYNTAX;
1609 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1610 return LDAP_INVALID_SYNTAX;
1613 return LDAP_SUCCESS;
1617 printableStringValidate(
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( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1627 return LDAP_INVALID_SYNTAX;
1631 return LDAP_SUCCESS;
1635 printablesStringValidate(
1637 struct berval *val )
1641 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1643 for(i=0,len=0; i < val->bv_len; i++) {
1644 int c = val->bv_val[i];
1648 return LDAP_INVALID_SYNTAX;
1652 } else if ( SLAP_PRINTABLE(c) ) {
1655 return LDAP_INVALID_SYNTAX;
1660 return LDAP_INVALID_SYNTAX;
1663 return LDAP_SUCCESS;
1669 struct berval *val )
1673 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1675 for(i=0; i < val->bv_len; i++) {
1676 if( !LDAP_ASCII(val->bv_val[i]) ) {
1677 return LDAP_INVALID_SYNTAX;
1681 return LDAP_SUCCESS;
1690 struct berval *normalized,
1694 int casefold = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactIA5Match );
1696 assert( val->bv_len );
1700 /* Ignore initial whitespace */
1701 while ( ASCII_SPACE( *p ) ) {
1705 normalized->bv_val = ber_strdup_x( p, ctx );
1706 p = q = normalized->bv_val;
1709 if ( ASCII_SPACE( *p ) ) {
1712 /* Ignore the extra whitespace */
1713 while ( ASCII_SPACE( *p ) ) {
1717 } else if ( casefold ) {
1718 /* Most IA5 rules require casefolding */
1719 *q++ = TOLOWER(*p++);
1726 assert( normalized->bv_val <= p );
1730 * If the string ended in space, backup the pointer one
1731 * position. One is enough because the above loop collapsed
1732 * all whitespace to a single space.
1735 if ( ASCII_SPACE( q[-1] ) ) {
1739 /* null terminate */
1742 normalized->bv_len = q - normalized->bv_val;
1744 if( normalized->bv_len == 0 ) {
1745 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1746 normalized->bv_val[0] = ' ';
1747 normalized->bv_val[1] = '\0';
1748 normalized->bv_len = 1;
1751 return LDAP_SUCCESS;
1755 numericStringValidate(
1761 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1763 for(i=0; i < in->bv_len; i++) {
1764 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1765 return LDAP_INVALID_SYNTAX;
1769 return LDAP_SUCCESS;
1773 numericStringNormalize(
1778 struct berval *normalized,
1781 /* removal all spaces */
1784 assert( val->bv_len );
1786 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1789 q = normalized->bv_val;
1792 if ( ASCII_SPACE( *p ) ) {
1793 /* Ignore whitespace */
1800 /* we should have copied no more then is in val */
1801 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1803 /* null terminate */
1806 normalized->bv_len = q - normalized->bv_val;
1808 if( normalized->bv_len == 0 ) {
1809 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1810 normalized->bv_val[0] = ' ';
1811 normalized->bv_val[1] = '\0';
1812 normalized->bv_len = 1;
1815 return LDAP_SUCCESS;
1818 #ifndef SLAP_NVALUES
1820 objectIdentifierFirstComponentMatch(
1825 struct berval *value,
1826 void *assertedValue )
1828 int rc = LDAP_SUCCESS;
1830 struct berval *asserted = (struct berval *) assertedValue;
1834 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1835 return LDAP_INVALID_SYNTAX;
1838 /* trim leading white space */
1839 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1843 /* grab next word */
1844 oid.bv_val = &value->bv_val[i];
1845 j = value->bv_len - i;
1846 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1851 /* insert attributeTypes, objectclass check here */
1852 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1853 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1856 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1857 MatchingRule *asserted_mr = mr_bvfind( asserted );
1858 MatchingRule *stored_mr = mr_bvfind( &oid );
1860 if( asserted_mr == NULL ) {
1861 rc = SLAPD_COMPARE_UNDEFINED;
1863 match = asserted_mr != stored_mr;
1866 } else if ( !strcmp( syntax->ssyn_oid,
1867 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1869 AttributeType *asserted_at = at_bvfind( asserted );
1870 AttributeType *stored_at = at_bvfind( &oid );
1872 if( asserted_at == NULL ) {
1873 rc = SLAPD_COMPARE_UNDEFINED;
1875 match = asserted_at != stored_at;
1878 } else if ( !strcmp( syntax->ssyn_oid,
1879 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1881 ObjectClass *asserted_oc = oc_bvfind( asserted );
1882 ObjectClass *stored_oc = oc_bvfind( &oid );
1884 if( asserted_oc == NULL ) {
1885 rc = SLAPD_COMPARE_UNDEFINED;
1887 match = asserted_oc != stored_oc;
1893 LDAP_LOG( CONFIG, ENTRY,
1894 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1895 match, value->bv_val, asserted->bv_val );
1897 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1898 "%d\n\t\"%s\"\n\t\"%s\"\n",
1899 match, value->bv_val, asserted->bv_val );
1902 if( rc == LDAP_SUCCESS ) *matchp = match;
1913 struct berval *value,
1914 void *assertedValue )
1916 long lValue, lAssertedValue;
1918 /* safe to assume integers are NUL terminated? */
1919 lValue = strtol(value->bv_val, NULL, 10);
1920 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1921 return LDAP_CONSTRAINT_VIOLATION;
1924 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1925 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1926 && errno == ERANGE )
1928 return LDAP_CONSTRAINT_VIOLATION;
1931 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1932 return LDAP_SUCCESS;
1941 struct berval *value,
1942 void *assertedValue )
1944 long lValue, lAssertedValue;
1946 /* safe to assume integers are NUL terminated? */
1947 lValue = strtol(value->bv_val, NULL, 10);
1948 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1949 return LDAP_CONSTRAINT_VIOLATION;
1952 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1953 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1954 && errno == ERANGE )
1956 return LDAP_CONSTRAINT_VIOLATION;
1959 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1960 return LDAP_SUCCESS;
1963 #ifndef SLAP_NVALUES
1965 #include <openssl/x509.h>
1966 #include <openssl/err.h>
1969 * Next function returns a string representation of a ASN1_INTEGER.
1970 * It works for unlimited lengths.
1973 static struct berval *
1974 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1978 static char digit[] = "0123456789";
1980 /* We work backwards, make it fill from the end of buf */
1981 p = buf + sizeof(buf) - 1;
1984 if ( a == NULL || a->length == 0 ) {
1992 /* We want to preserve the original */
1993 copy = ch_malloc(n*sizeof(unsigned int));
1994 for (i = 0; i<n; i++) {
1995 copy[i] = a->data[i];
1999 * base indicates the index of the most significant
2000 * byte that might be nonzero. When it goes off the
2001 * end, we now there is nothing left to do.
2007 for (i = base; i<n; i++ ) {
2008 copy[i] += carry*256;
2009 carry = copy[i] % 10;
2014 * Way too large, we need to leave
2015 * room for sign if negative
2020 *--p = digit[carry];
2022 if (copy[base] == 0) base++;
2027 if ( a->type == V_ASN1_NEG_INTEGER ) {
2031 return ber_str2bv( p, 0, 1, bv );
2035 * Given a certificate in DER format, extract the corresponding
2036 * assertion value for certificateExactMatch
2039 certificateExactConvert(
2041 struct berval * out )
2044 unsigned char *p = in->bv_val;
2045 struct berval serial;
2046 struct berval issuer_dn;
2048 xcert = d2i_X509(NULL, &p, in->bv_len);
2051 LDAP_LOG( CONFIG, ENTRY,
2052 "certificateExactConvert: error parsing cert: %s\n",
2053 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2055 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2056 "error parsing cert: %s\n",
2057 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2059 return LDAP_INVALID_SYNTAX;
2062 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2064 return LDAP_INVALID_SYNTAX;
2066 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2070 ber_memfree(serial.bv_val);
2071 return LDAP_INVALID_SYNTAX;
2076 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2077 out->bv_val = ch_malloc(out->bv_len);
2079 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2081 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2083 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2084 p += issuer_dn.bv_len;
2088 LDAP_LOG( CONFIG, ARGS,
2089 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2091 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2093 out->bv_val, NULL, NULL );
2096 ber_memfree(serial.bv_val);
2097 ber_memfree(issuer_dn.bv_val);
2099 return LDAP_SUCCESS;
2103 serial_and_issuer_parse(
2104 struct berval *assertion,
2105 struct berval *serial,
2106 struct berval *issuer_dn )
2113 begin = assertion->bv_val;
2114 end = assertion->bv_val+assertion->bv_len-1;
2115 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2116 if ( p > end ) return LDAP_INVALID_SYNTAX;
2118 /* p now points at the $ sign, now use
2119 * begin and end to delimit the serial number
2121 while (ASCII_SPACE(*begin)) begin++;
2123 while (ASCII_SPACE(*end)) end--;
2125 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2127 bv.bv_len = end-begin+1;
2129 ber_dupbv(serial, &bv);
2131 /* now extract the issuer, remember p was at the dollar sign */
2133 end = assertion->bv_val+assertion->bv_len-1;
2134 while (ASCII_SPACE(*begin)) begin++;
2135 /* should we trim spaces at the end too? is it safe always? no, no */
2137 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2140 bv.bv_len = end-begin+1;
2143 dnNormalize2( NULL, &bv, issuer_dn );
2146 return LDAP_SUCCESS;
2150 certificateExactMatch(
2155 struct berval *value,
2156 void *assertedValue )
2159 unsigned char *p = value->bv_val;
2160 struct berval serial;
2161 struct berval issuer_dn;
2162 struct berval asserted_serial;
2163 struct berval asserted_issuer_dn;
2166 xcert = d2i_X509(NULL, &p, value->bv_len);
2169 LDAP_LOG( CONFIG, ENTRY,
2170 "certificateExactMatch: error parsing cert: %s\n",
2171 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2173 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2174 "error parsing cert: %s\n",
2175 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2177 return LDAP_INVALID_SYNTAX;
2180 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2181 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2185 serial_and_issuer_parse(assertedValue,
2186 &asserted_serial, &asserted_issuer_dn);
2191 slap_schema.si_syn_integer,
2192 slap_schema.si_mr_integerMatch,
2195 if ( ret == LDAP_SUCCESS ) {
2196 if ( *matchp == 0 ) {
2197 /* We need to normalize everything for dnMatch */
2201 slap_schema.si_syn_distinguishedName,
2202 slap_schema.si_mr_distinguishedNameMatch,
2204 &asserted_issuer_dn);
2209 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2210 "%d\n\t\"%s $ %s\"\n",
2211 *matchp, serial.bv_val, issuer_dn.bv_val );
2212 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2213 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2216 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2217 "%d\n\t\"%s $ %s\"\n",
2218 *matchp, serial.bv_val, issuer_dn.bv_val );
2219 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2220 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2224 ber_memfree(serial.bv_val);
2225 ber_memfree(issuer_dn.bv_val);
2226 ber_memfree(asserted_serial.bv_val);
2227 ber_memfree(asserted_issuer_dn.bv_val);
2233 * Index generation function
2234 * We just index the serials, in most scenarios the issuer DN is one of
2235 * a very small set of values.
2237 static int certificateExactIndexer(
2242 struct berval *prefix,
2250 struct berval serial;
2252 /* we should have at least one value at this point */
2253 assert( values != NULL && values[0].bv_val != NULL );
2255 for( i=0; values[i].bv_val != NULL; i++ ) {
2256 /* empty -- just count them */
2259 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2261 for( i=0; values[i].bv_val != NULL; i++ ) {
2262 p = values[i].bv_val;
2263 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2266 LDAP_LOG( CONFIG, ENTRY,
2267 "certificateExactIndexer: error parsing cert: %s\n",
2268 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2270 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2271 "error parsing cert: %s\n",
2272 ERR_error_string(ERR_get_error(),NULL),
2275 /* Do we leak keys on error? */
2276 return LDAP_INVALID_SYNTAX;
2279 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2281 xintegerNormalize( slap_schema.si_syn_integer,
2282 &serial, &keys[i] );
2283 ber_memfree(serial.bv_val);
2285 LDAP_LOG( CONFIG, ENTRY,
2286 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2288 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2295 keys[i].bv_val = NULL;
2297 return LDAP_SUCCESS;
2300 /* Index generation function */
2301 /* We think this is always called with a value in matching rule syntax */
2302 static int certificateExactFilter(
2307 struct berval *prefix,
2308 void * assertedValue,
2312 struct berval asserted_serial;
2315 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2316 if( ret != LDAP_SUCCESS ) return ret;
2318 keys = ch_malloc( sizeof( struct berval ) * 2 );
2319 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2320 keys[1].bv_val = NULL;
2323 ber_memfree(asserted_serial.bv_val);
2324 return LDAP_SUCCESS;
2330 check_time_syntax (struct berval *val,
2334 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2335 static int mdays[2][12] = {
2336 /* non-leap years */
2337 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2339 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2342 int part, c, tzoffset, leapyear = 0 ;
2344 if( val->bv_len == 0 ) {
2345 return LDAP_INVALID_SYNTAX;
2348 p = (char *)val->bv_val;
2349 e = p + val->bv_len;
2351 /* Ignore initial whitespace */
2352 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2356 if (e - p < 13 - (2 * start)) {
2357 return LDAP_INVALID_SYNTAX;
2360 for (part = 0; part < 9; part++) {
2364 for (part = start; part < 7; part++) {
2366 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2373 return LDAP_INVALID_SYNTAX;
2375 if (c < 0 || c > 9) {
2376 return LDAP_INVALID_SYNTAX;
2382 return LDAP_INVALID_SYNTAX;
2384 if (c < 0 || c > 9) {
2385 return LDAP_INVALID_SYNTAX;
2390 if (part == 2 || part == 3) {
2393 if (parts[part] < 0) {
2394 return LDAP_INVALID_SYNTAX;
2396 if (parts[part] > ceiling[part]) {
2397 return LDAP_INVALID_SYNTAX;
2401 /* leapyear check for the Gregorian calendar (year>1581) */
2402 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2403 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2408 if (parts[3] > mdays[leapyear][parts[2]]) {
2409 return LDAP_INVALID_SYNTAX;
2414 tzoffset = 0; /* UTC */
2415 } else if (c != '+' && c != '-') {
2416 return LDAP_INVALID_SYNTAX;
2420 } else /* c == '+' */ {
2425 return LDAP_INVALID_SYNTAX;
2428 for (part = 7; part < 9; part++) {
2430 if (c < 0 || c > 9) {
2431 return LDAP_INVALID_SYNTAX;
2436 if (c < 0 || c > 9) {
2437 return LDAP_INVALID_SYNTAX;
2441 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2442 return LDAP_INVALID_SYNTAX;
2447 /* Ignore trailing whitespace */
2448 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2452 return LDAP_INVALID_SYNTAX;
2455 switch ( tzoffset ) {
2456 case -1: /* negativ offset to UTC, ie west of Greenwich */
2457 parts[4] += parts[7];
2458 parts[5] += parts[8];
2459 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2463 c = mdays[leapyear][parts[2]];
2465 if (parts[part] > c) {
2466 parts[part] -= c + 1;
2471 case 1: /* positive offset to UTC, ie east of Greenwich */
2472 parts[4] -= parts[7];
2473 parts[5] -= parts[8];
2474 for (part = 6; --part > 0; ) {
2478 /* first arg to % needs to be non negativ */
2479 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2481 if (parts[part] < 0) {
2482 parts[part] += c + 1;
2487 case 0: /* already UTC */
2491 return LDAP_SUCCESS;
2494 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2499 struct berval *normalized )
2503 rc = check_time_syntax(val, 1, parts);
2504 if (rc != LDAP_SUCCESS) {
2508 normalized->bv_val = ch_malloc( 14 );
2509 if ( normalized->bv_val == NULL ) {
2510 return LBER_ERROR_MEMORY;
2513 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2514 parts[1], parts[2] + 1, parts[3] + 1,
2515 parts[4], parts[5], parts[6] );
2516 normalized->bv_len = 13;
2518 return LDAP_SUCCESS;
2527 return check_time_syntax(in, 1, parts);
2532 generalizedTimeValidate(
2537 return check_time_syntax(in, 0, parts);
2541 generalizedTimeNormalize(
2546 struct berval *normalized,
2551 rc = check_time_syntax(val, 0, parts);
2552 if (rc != LDAP_SUCCESS) {
2556 normalized->bv_val = sl_malloc( 16, ctx );
2557 if ( normalized->bv_val == NULL ) {
2558 return LBER_ERROR_MEMORY;
2561 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2562 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2563 parts[4], parts[5], parts[6] );
2564 normalized->bv_len = 15;
2566 return LDAP_SUCCESS;
2570 nisNetgroupTripleValidate(
2572 struct berval *val )
2577 if ( val->bv_len == 0 ) {
2578 return LDAP_INVALID_SYNTAX;
2581 p = (char *)val->bv_val;
2582 e = p + val->bv_len;
2584 if ( *p != '(' /*')'*/ ) {
2585 return LDAP_INVALID_SYNTAX;
2588 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2592 return LDAP_INVALID_SYNTAX;
2595 } else if ( !AD_CHAR( *p ) ) {
2596 return LDAP_INVALID_SYNTAX;
2600 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2601 return LDAP_INVALID_SYNTAX;
2607 return LDAP_INVALID_SYNTAX;
2610 return LDAP_SUCCESS;
2614 bootParameterValidate(
2616 struct berval *val )
2620 if ( val->bv_len == 0 ) {
2621 return LDAP_INVALID_SYNTAX;
2624 p = (char *)val->bv_val;
2625 e = p + val->bv_len;
2628 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2629 if ( !AD_CHAR( *p ) ) {
2630 return LDAP_INVALID_SYNTAX;
2635 return LDAP_INVALID_SYNTAX;
2639 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2640 if ( !AD_CHAR( *p ) ) {
2641 return LDAP_INVALID_SYNTAX;
2646 return LDAP_INVALID_SYNTAX;
2650 for ( p++; p < e; p++ ) {
2651 if ( !SLAP_PRINTABLE( *p ) ) {
2652 return LDAP_INVALID_SYNTAX;
2656 return LDAP_SUCCESS;
2659 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2660 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2662 static slap_syntax_defs_rec syntax_defs[] = {
2663 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2664 X_BINARY X_NOT_H_R ")",
2665 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2666 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2668 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2670 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2672 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2673 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2675 SLAP_SYNTAX_BER, berValidate, NULL},
2676 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2677 0, bitStringValidate, NULL },
2678 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2679 0, booleanValidate, NULL},
2680 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2681 X_BINARY X_NOT_H_R ")",
2682 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2683 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
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.10 DESC 'Certificate Pair' "
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.11 DESC 'Country String' )",
2690 0, countryStringValidate, NULL},
2691 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2692 0, dnValidate, dnPretty2},
2693 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2695 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2697 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2698 0, UTF8StringValidate, NULL},
2699 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2701 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2703 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2705 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2707 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2709 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2710 0, printablesStringValidate, NULL},
2711 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2712 SLAP_SYNTAX_BLOB, NULL, NULL},
2713 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2714 0, generalizedTimeValidate, NULL},
2715 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2717 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2718 0, IA5StringValidate, NULL},
2719 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2720 0, integerValidate, NULL},
2721 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2722 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2723 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2725 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2727 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2729 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2731 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2733 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2734 0, nameUIDValidate, NULL},
2735 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2737 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2738 0, numericStringValidate, NULL},
2739 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2741 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2742 0, oidValidate, NULL},
2743 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2744 0, IA5StringValidate, NULL},
2745 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2746 0, blobValidate, NULL},
2747 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2748 0, UTF8StringValidate, NULL},
2749 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2751 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2753 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2754 0, printableStringValidate, NULL},
2755 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2756 X_BINARY X_NOT_H_R ")",
2757 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2758 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2759 X_BINARY X_NOT_H_R ")",
2760 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2761 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2762 0, printableStringValidate, NULL},
2763 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2765 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2766 0, printablesStringValidate, NULL},
2767 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2768 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2769 0, utcTimeValidate, NULL},
2771 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2773 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2775 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2777 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2779 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2782 /* RFC 2307 NIS Syntaxes */
2783 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2784 0, nisNetgroupTripleValidate, NULL},
2785 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2786 0, bootParameterValidate, NULL},
2790 /* These OIDs are not published yet, but will be in the next
2791 * I-D for PKIX LDAPv3 schema as have been advanced by David
2792 * Chadwick in private mail.
2794 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2795 0, UTF8StringValidate, NULL},
2798 /* OpenLDAP Experimental Syntaxes */
2799 #ifdef SLAPD_ACI_ENABLED
2800 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2802 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2806 #ifdef SLAPD_AUTHPASSWD
2807 /* needs updating */
2808 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2809 SLAP_SYNTAX_HIDE, NULL, NULL},
2812 /* OpenLDAP Void Syntax */
2813 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2814 SLAP_SYNTAX_HIDE, inValidate, NULL},
2815 {NULL, 0, NULL, NULL}
2819 char *certificateExactMatchSyntaxes[] = {
2820 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2824 char *directoryStringSyntaxes[] = {
2825 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2828 char *integerFirstComponentMatchSyntaxes[] = {
2829 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2830 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2833 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2834 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2835 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2836 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2837 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2838 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2839 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2840 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2841 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2846 * Other matching rules in X.520 that we do not use (yet):
2848 * 2.5.13.9 numericStringOrderingMatch
2849 * 2.5.13.25 uTCTimeMatch
2850 * 2.5.13.26 uTCTimeOrderingMatch
2851 * 2.5.13.31 directoryStringFirstComponentMatch
2852 * 2.5.13.32 wordMatch
2853 * 2.5.13.33 keywordMatch
2854 * 2.5.13.35 certificateMatch
2855 * 2.5.13.36 certificatePairExactMatch
2856 * 2.5.13.37 certificatePairMatch
2857 * 2.5.13.38 certificateListExactMatch
2858 * 2.5.13.39 certificateListMatch
2859 * 2.5.13.40 algorithmIdentifierMatch
2860 * 2.5.13.41 storedPrefixMatch
2861 * 2.5.13.42 attributeCertificateMatch
2862 * 2.5.13.43 readerAndKeyIDMatch
2863 * 2.5.13.44 attributeIntegrityMatch
2865 static slap_mrule_defs_rec mrule_defs[] = {
2867 * EQUALITY matching rules must be listed after associated APPROX
2868 * matching rules. So, we list all APPROX matching rules first.
2870 #ifndef SLAP_NVALUES
2871 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2872 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2873 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2874 NULL, NULL, directoryStringApproxMatch,
2875 directoryStringApproxIndexer, directoryStringApproxFilter,
2878 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2879 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2880 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2881 NULL, NULL, IA5StringApproxMatch,
2882 IA5StringApproxIndexer, IA5StringApproxFilter,
2887 * Other matching rules
2890 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2891 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2892 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2893 NULL, objectIdentifierNormalize, octetStringMatch,
2894 octetStringIndexer, octetStringFilter,
2897 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2898 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2899 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2900 NULL, dnNormalize, dnMatch,
2901 octetStringIndexer, octetStringFilter,
2904 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2905 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2906 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2907 NULL, UTF8StringNormalize, octetStringMatch,
2908 octetStringIndexer, octetStringFilter,
2909 directoryStringApproxMatchOID },
2911 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2912 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2913 SLAP_MR_ORDERING, directoryStringSyntaxes,
2914 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2916 "caseIgnoreMatch" },
2918 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2919 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2920 SLAP_MR_SUBSTR, NULL,
2921 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2922 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2923 "caseIgnoreMatch" },
2925 {"( 2.5.13.5 NAME 'caseExactMatch' "
2926 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2927 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2928 NULL, UTF8StringNormalize, octetStringMatch,
2929 octetStringIndexer, octetStringFilter,
2930 directoryStringApproxMatchOID },
2932 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2933 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2934 SLAP_MR_ORDERING, directoryStringSyntaxes,
2935 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2939 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2940 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2941 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2942 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2943 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2946 {"( 2.5.13.8 NAME 'numericStringMatch' "
2947 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2948 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2949 NULL, numericStringNormalize, octetStringSubstringsMatch,
2950 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2953 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2954 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2955 SLAP_MR_SUBSTR, NULL,
2956 NULL, numericStringNormalize, octetStringSubstringsMatch,
2957 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2958 "numericStringMatch" },
2960 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2962 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2963 NULL, NULL, NULL, NULL, NULL, NULL },
2965 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2966 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2967 SLAP_MR_SUBSTR, NULL,
2968 NULL, NULL, NULL, NULL, NULL,
2969 "caseIgnoreListMatch" },
2971 {"( 2.5.13.13 NAME 'booleanMatch' "
2972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2973 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2974 NULL, NULL, booleanMatch,
2975 octetStringIndexer, octetStringFilter,
2978 {"( 2.5.13.14 NAME 'integerMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2980 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2981 NULL, integerNormalize, integerMatch,
2982 octetStringIndexer, octetStringFilter,
2985 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2987 SLAP_MR_ORDERING, NULL,
2988 NULL, integerNormalize, integerOrderingMatch,
2992 {"( 2.5.13.16 NAME 'bitStringMatch' "
2993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2994 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2995 NULL, NULL, octetStringMatch,
2996 octetStringIndexer, octetStringFilter,
2999 {"( 2.5.13.17 NAME 'octetStringMatch' "
3000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3001 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3002 NULL, NULL, octetStringMatch,
3003 octetStringIndexer, octetStringFilter,
3006 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3008 SLAP_MR_ORDERING, NULL,
3009 NULL, NULL, octetStringOrderingMatch,
3011 "octetStringMatch" },
3013 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3015 SLAP_MR_SUBSTR, NULL,
3016 NULL, NULL, octetStringSubstringsMatch,
3017 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3018 "octetStringMatch" },
3020 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3021 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3022 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3024 telephoneNumberNormalize, octetStringMatch,
3025 octetStringIndexer, octetStringFilter,
3028 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3029 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3030 SLAP_MR_SUBSTR, NULL,
3031 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3032 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3033 "telephoneNumberMatch" },
3035 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3036 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3037 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3038 NULL, NULL, NULL, NULL, NULL, NULL },
3040 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3041 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3042 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3043 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3047 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3049 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3050 NULL, NULL, NULL, NULL, NULL, NULL },
3052 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3054 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3055 NULL, generalizedTimeNormalize, octetStringMatch,
3059 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3061 SLAP_MR_ORDERING, NULL,
3062 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3064 "generalizedTimeMatch" },
3066 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3068 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3069 NULL, integerFirstComponentNormalize, integerMatch,
3073 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3074 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3075 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3076 objectIdentifierFirstComponentMatchSyntaxes,
3077 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3078 octetStringIndexer, octetStringFilter,
3081 #ifndef SLAP_NVALUES
3083 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3084 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3085 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3086 certificateExactConvert, NULL, certificateExactMatch,
3087 certificateExactIndexer, certificateExactFilter,
3092 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3094 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3095 NULL, IA5StringNormalize, octetStringMatch,
3096 octetStringIndexer, octetStringFilter,
3097 IA5StringApproxMatchOID },
3099 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3101 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3102 NULL, IA5StringNormalize, octetStringMatch,
3103 octetStringIndexer, octetStringFilter,
3104 IA5StringApproxMatchOID },
3106 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3108 SLAP_MR_SUBSTR, NULL,
3109 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3110 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3111 "caseIgnoreIA5Match" },
3113 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3115 SLAP_MR_SUBSTR, NULL,
3116 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3117 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3118 "caseExactIA5Match" },
3120 #ifdef SLAPD_AUTHPASSWD
3121 /* needs updating */
3122 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3123 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3124 SLAP_MR_EQUALITY, NULL,
3125 NULL, NULL, authPasswordMatch,
3130 #ifdef SLAPD_ACI_ENABLED
3131 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3132 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3133 SLAP_MR_EQUALITY, NULL,
3134 NULL, NULL, OpenLDAPaciMatch,
3139 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3140 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3142 NULL, integerNormalize, integerBitAndMatch,
3146 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3147 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3149 NULL, integerNormalize, integerBitOrMatch,
3153 {NULL, SLAP_MR_NONE, NULL,
3154 NULL, NULL, NULL, NULL, NULL,
3159 slap_schema_init( void )
3164 /* we should only be called once (from main) */
3165 assert( schema_init_done == 0 );
3167 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3168 res = register_syntax( &syntax_defs[i] );
3171 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3172 syntax_defs[i].sd_desc );
3177 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3178 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3179 mrule_defs[i].mrd_compat_syntaxes == NULL )
3182 "slap_schema_init: Ignoring unusable matching rule %s\n",
3183 mrule_defs[i].mrd_desc );
3187 res = register_matching_rule( &mrule_defs[i] );
3191 "slap_schema_init: Error registering matching rule %s\n",
3192 mrule_defs[i].mrd_desc );
3197 res = slap_schema_load();
3198 schema_init_done = 1;
3203 schema_destroy( void )