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,
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 = ch_malloc( sizeof( struct berval ) * (i+1) );
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( &keys[i], &digest );
167 keys[i].bv_val = NULL;
175 /* Index generation function */
176 int octetStringFilter(
181 struct berval *prefix,
182 void * assertedValue,
187 HASH_CONTEXT HASHcontext;
188 unsigned char HASHdigest[HASH_BYTES];
189 struct berval *value = (struct berval *) assertedValue;
190 struct berval digest;
191 digest.bv_val = HASHdigest;
192 digest.bv_len = sizeof(HASHdigest);
194 slen = syntax->ssyn_oidlen;
195 mlen = mr->smr_oidlen;
197 keys = ch_malloc( sizeof( struct berval ) * 2 );
199 HASH_Init( &HASHcontext );
200 if( prefix != NULL && prefix->bv_len > 0 ) {
201 HASH_Update( &HASHcontext,
202 prefix->bv_val, prefix->bv_len );
204 HASH_Update( &HASHcontext,
205 syntax->ssyn_oid, slen );
206 HASH_Update( &HASHcontext,
208 HASH_Update( &HASHcontext,
209 value->bv_val, value->bv_len );
210 HASH_Final( HASHdigest, &HASHcontext );
212 ber_dupbv( keys, &digest );
213 keys[1].bv_val = NULL;
222 octetStringSubstringsMatch(
227 struct berval *value,
228 void *assertedValue )
231 SubstringsAssertion *sub = assertedValue;
232 struct berval left = *value;
236 /* Add up asserted input length */
237 if( sub->sa_initial.bv_val ) {
238 inlen += sub->sa_initial.bv_len;
241 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
242 inlen += sub->sa_any[i].bv_len;
245 if( sub->sa_final.bv_val ) {
246 inlen += sub->sa_final.bv_len;
249 if( sub->sa_initial.bv_val ) {
250 if( inlen > left.bv_len ) {
255 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
256 sub->sa_initial.bv_len );
262 left.bv_val += sub->sa_initial.bv_len;
263 left.bv_len -= sub->sa_initial.bv_len;
264 inlen -= sub->sa_initial.bv_len;
267 if( sub->sa_final.bv_val ) {
268 if( inlen > left.bv_len ) {
273 match = memcmp( sub->sa_final.bv_val,
274 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
275 sub->sa_final.bv_len );
281 left.bv_len -= sub->sa_final.bv_len;
282 inlen -= sub->sa_final.bv_len;
286 for(i=0; sub->sa_any[i].bv_val; i++) {
291 if( inlen > left.bv_len ) {
292 /* not enough length */
297 if( sub->sa_any[i].bv_len == 0 ) {
301 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
308 idx = p - left.bv_val;
310 if( idx >= left.bv_len ) {
311 /* this shouldn't happen */
318 if( sub->sa_any[i].bv_len > left.bv_len ) {
319 /* not enough left */
324 match = memcmp( left.bv_val,
325 sub->sa_any[i].bv_val,
326 sub->sa_any[i].bv_len );
334 left.bv_val += sub->sa_any[i].bv_len;
335 left.bv_len -= sub->sa_any[i].bv_len;
336 inlen -= sub->sa_any[i].bv_len;
345 /* Substrings Index generation function */
347 octetStringSubstringsIndexer(
352 struct berval *prefix,
356 ber_len_t i, j, nkeys;
360 HASH_CONTEXT HASHcontext;
361 unsigned char HASHdigest[HASH_BYTES];
362 struct berval digest;
363 digest.bv_val = HASHdigest;
364 digest.bv_len = sizeof(HASHdigest);
368 for( i=0; values[i].bv_val != NULL; i++ ) {
369 /* count number of indices to generate */
370 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
374 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
375 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
376 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
377 (SLAP_INDEX_SUBSTR_MINLEN - 1);
379 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
383 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
384 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
385 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
389 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
390 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
391 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
392 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
394 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
400 /* no keys to generate */
405 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
407 slen = syntax->ssyn_oidlen;
408 mlen = mr->smr_oidlen;
411 for( i=0; values[i].bv_val != NULL; i++ ) {
414 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
416 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
417 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
419 char pre = SLAP_INDEX_SUBSTR_PREFIX;
420 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
422 for( j=0; j<max; j++ ) {
423 HASH_Init( &HASHcontext );
424 if( prefix != NULL && prefix->bv_len > 0 ) {
425 HASH_Update( &HASHcontext,
426 prefix->bv_val, prefix->bv_len );
429 HASH_Update( &HASHcontext,
430 &pre, sizeof( pre ) );
431 HASH_Update( &HASHcontext,
432 syntax->ssyn_oid, slen );
433 HASH_Update( &HASHcontext,
435 HASH_Update( &HASHcontext,
436 &values[i].bv_val[j],
437 SLAP_INDEX_SUBSTR_MAXLEN );
438 HASH_Final( HASHdigest, &HASHcontext );
440 ber_dupbv( &keys[nkeys++], &digest );
444 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
445 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
447 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
450 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
451 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
452 HASH_Init( &HASHcontext );
453 if( prefix != NULL && prefix->bv_len > 0 ) {
454 HASH_Update( &HASHcontext,
455 prefix->bv_val, prefix->bv_len );
457 HASH_Update( &HASHcontext,
458 &pre, sizeof( pre ) );
459 HASH_Update( &HASHcontext,
460 syntax->ssyn_oid, slen );
461 HASH_Update( &HASHcontext,
463 HASH_Update( &HASHcontext,
464 values[i].bv_val, j );
465 HASH_Final( HASHdigest, &HASHcontext );
467 ber_dupbv( &keys[nkeys++], &digest );
470 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
471 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
472 HASH_Init( &HASHcontext );
473 if( prefix != NULL && prefix->bv_len > 0 ) {
474 HASH_Update( &HASHcontext,
475 prefix->bv_val, prefix->bv_len );
477 HASH_Update( &HASHcontext,
478 &pre, sizeof( pre ) );
479 HASH_Update( &HASHcontext,
480 syntax->ssyn_oid, slen );
481 HASH_Update( &HASHcontext,
483 HASH_Update( &HASHcontext,
484 &values[i].bv_val[values[i].bv_len-j], j );
485 HASH_Final( HASHdigest, &HASHcontext );
487 ber_dupbv( &keys[nkeys++], &digest );
495 keys[nkeys].bv_val = NULL;
506 octetStringSubstringsFilter (
511 struct berval *prefix,
512 void * assertedValue,
515 SubstringsAssertion *sa;
519 size_t slen, mlen, klen;
521 HASH_CONTEXT HASHcontext;
522 unsigned char HASHdigest[HASH_BYTES];
523 struct berval *value;
524 struct berval digest;
526 sa = (SubstringsAssertion *) assertedValue;
528 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
529 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
534 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
536 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
537 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
538 /* don't bother accounting for stepping */
539 nkeys += sa->sa_any[i].bv_len -
540 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
545 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
546 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
556 digest.bv_val = HASHdigest;
557 digest.bv_len = sizeof(HASHdigest);
559 slen = syntax->ssyn_oidlen;
560 mlen = mr->smr_oidlen;
562 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
565 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
566 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
568 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
569 value = &sa->sa_initial;
571 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
572 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
574 HASH_Init( &HASHcontext );
575 if( prefix != NULL && prefix->bv_len > 0 ) {
576 HASH_Update( &HASHcontext,
577 prefix->bv_val, prefix->bv_len );
579 HASH_Update( &HASHcontext,
580 &pre, sizeof( pre ) );
581 HASH_Update( &HASHcontext,
582 syntax->ssyn_oid, slen );
583 HASH_Update( &HASHcontext,
585 HASH_Update( &HASHcontext,
586 value->bv_val, klen );
587 HASH_Final( HASHdigest, &HASHcontext );
589 ber_dupbv( &keys[nkeys++], &digest );
592 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
594 pre = SLAP_INDEX_SUBSTR_PREFIX;
595 klen = SLAP_INDEX_SUBSTR_MAXLEN;
597 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
598 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
602 value = &sa->sa_any[i];
605 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
606 j += SLAP_INDEX_SUBSTR_STEP )
608 HASH_Init( &HASHcontext );
609 if( prefix != NULL && prefix->bv_len > 0 ) {
610 HASH_Update( &HASHcontext,
611 prefix->bv_val, prefix->bv_len );
613 HASH_Update( &HASHcontext,
614 &pre, sizeof( pre ) );
615 HASH_Update( &HASHcontext,
616 syntax->ssyn_oid, slen );
617 HASH_Update( &HASHcontext,
619 HASH_Update( &HASHcontext,
620 &value->bv_val[j], klen );
621 HASH_Final( HASHdigest, &HASHcontext );
623 ber_dupbv( &keys[nkeys++], &digest );
628 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
629 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
631 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
632 value = &sa->sa_final;
634 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
635 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
637 HASH_Init( &HASHcontext );
638 if( prefix != NULL && prefix->bv_len > 0 ) {
639 HASH_Update( &HASHcontext,
640 prefix->bv_val, prefix->bv_len );
642 HASH_Update( &HASHcontext,
643 &pre, sizeof( pre ) );
644 HASH_Update( &HASHcontext,
645 syntax->ssyn_oid, slen );
646 HASH_Update( &HASHcontext,
648 HASH_Update( &HASHcontext,
649 &value->bv_val[value->bv_len-klen], klen );
650 HASH_Final( HASHdigest, &HASHcontext );
652 ber_dupbv( &keys[nkeys++], &digest );
656 keys[nkeys].bv_val = NULL;
673 /* very unforgiving validation, requires no normalization
674 * before simplistic matching
676 if( in->bv_len < 3 ) {
677 return LDAP_INVALID_SYNTAX;
681 * RFC 2252 section 6.3 Bit String
682 * bitstring = "'" *binary-digit "'B"
683 * binary-digit = "0" / "1"
684 * example: '0101111101'B
687 if( in->bv_val[0] != '\'' ||
688 in->bv_val[in->bv_len-2] != '\'' ||
689 in->bv_val[in->bv_len-1] != 'B' )
691 return LDAP_INVALID_SYNTAX;
694 for( i=in->bv_len-3; i>0; i-- ) {
695 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
696 return LDAP_INVALID_SYNTAX;
711 if( in->bv_len == 0 ) return LDAP_SUCCESS;
713 ber_dupbv( &dn, in );
714 if( !dn.bv_val ) return LDAP_OTHER;
716 if( dn.bv_val[dn.bv_len-1] == 'B'
717 && dn.bv_val[dn.bv_len-2] == '\'' )
719 /* assume presence of optional UID */
722 for(i=dn.bv_len-3; i>1; i--) {
723 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
727 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
728 ber_memfree( dn.bv_val );
729 return LDAP_INVALID_SYNTAX;
732 /* trim the UID to allow use of dnValidate */
733 dn.bv_val[i-1] = '\0';
737 rc = dnValidate( NULL, &dn );
739 ber_memfree( dn.bv_val );
744 uniqueMemberNormalize(
749 struct berval *normalized )
754 ber_dupbv( &out, val );
755 if( out.bv_len != 0 ) {
756 struct berval uid = { 0, NULL };
758 if( out.bv_val[out.bv_len-1] == 'B'
759 && out.bv_val[out.bv_len-2] == '\'' )
761 /* assume presence of optional UID */
762 uid.bv_val = strrchr( out.bv_val, '#' );
764 if( uid.bv_val == NULL ) {
766 return LDAP_INVALID_SYNTAX;
769 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
770 out.bv_len -= uid.bv_len--;
772 /* temporarily trim the UID */
773 *(uid.bv_val++) = '\0';
776 rc = dnNormalize2( NULL, &out, normalized );
778 if( rc != LDAP_SUCCESS ) {
780 return LDAP_INVALID_SYNTAX;
784 normalized->bv_val = ch_realloc( normalized->bv_val,
785 normalized->bv_len + uid.bv_len + sizeof("#") );
787 /* insert the separator */
788 normalized->bv_val[normalized->bv_len++] = '#';
791 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
792 uid.bv_val, uid.bv_len );
793 normalized->bv_len += uid.bv_len;
796 normalized->bv_val[normalized->bv_len] = '\0';
806 * Handling boolean syntax and matching is quite rigid.
807 * A more flexible approach would be to allow a variety
808 * of strings to be normalized and prettied into TRUE
816 /* very unforgiving validation, requires no normalization
817 * before simplistic matching
820 if( in->bv_len == 4 ) {
821 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
824 } else if( in->bv_len == 5 ) {
825 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
830 return LDAP_INVALID_SYNTAX;
839 struct berval *value,
840 void *assertedValue )
842 /* simplistic matching allowed by rigid validation */
843 struct berval *asserted = (struct berval *) assertedValue;
844 *matchp = value->bv_len != asserted->bv_len;
848 /*-------------------------------------------------------------------
849 LDAP/X.500 string syntax / matching rules have a few oddities. This
850 comment attempts to detail how slapd(8) treats them.
853 StringSyntax X.500 LDAP Matching/Comments
854 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
855 PrintableString subset subset i/e + ignore insignificant spaces
856 PrintableString subset subset i/e + ignore insignificant spaces
857 NumericString subset subset ignore all spaces
858 IA5String ASCII ASCII i/e + ignore insignificant spaces
859 TeletexString T.61 T.61 i/e + ignore insignificant spaces
861 TelephoneNumber subset subset i + ignore all spaces and "-"
863 See draft-ietf-ldapbis-strpro for details (once published).
867 In X.500(93), a directory string can be either a PrintableString,
868 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
869 In later versions, more CHOICEs were added. In all cases the string
872 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
873 A directory string cannot be zero length.
875 For matching, there are both case ignore and exact rules. Both
876 also require that "insignificant" spaces be ignored.
877 spaces before the first non-space are ignored;
878 spaces after the last non-space are ignored;
879 spaces after a space are ignored.
880 Note: by these rules (and as clarified in X.520), a string of only
881 spaces is to be treated as if held one space, not empty (which
882 would be a syntax error).
885 In ASN.1, numeric string is just a string of digits and spaces
886 and could be empty. However, in X.500, all attribute values of
887 numeric string carry a non-empty constraint. For example:
889 internationalISDNNumber ATTRIBUTE ::= {
890 WITH SYNTAX InternationalISDNNumber
891 EQUALITY MATCHING RULE numericStringMatch
892 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
893 ID id-at-internationalISDNNumber }
894 InternationalISDNNumber ::=
895 NumericString (SIZE(1..ub-international-isdn-number))
897 Unforunately, some assertion values are don't carry the same
898 constraint (but its unclear how such an assertion could ever
899 be true). In LDAP, there is one syntax (numericString) not two
900 (numericString with constraint, numericString without constraint).
901 This should be treated as numericString with non-empty constraint.
902 Note that while someone may have no ISDN number, there are no ISDN
903 numbers which are zero length.
905 In matching, spaces are ignored.
908 In ASN.1, Printable string is just a string of printable characters
909 and can be empty. In X.500, semantics much like NumericString (see
910 serialNumber for a like example) excepting uses insignificant space
911 handling instead of ignore all spaces.
914 Basically same as PrintableString. There are no examples in X.500,
915 but same logic applies. So we require them to be non-empty as
918 -------------------------------------------------------------------*/
927 unsigned char *u = in->bv_val;
929 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
930 /* directory strings cannot be empty */
931 return LDAP_INVALID_SYNTAX;
934 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
935 /* get the length indicated by the first byte */
936 len = LDAP_UTF8_CHARLEN2( u, len );
938 /* very basic checks */
941 if( (u[5] & 0xC0) != 0x80 ) {
942 return LDAP_INVALID_SYNTAX;
945 if( (u[4] & 0xC0) != 0x80 ) {
946 return LDAP_INVALID_SYNTAX;
949 if( (u[3] & 0xC0) != 0x80 ) {
950 return LDAP_INVALID_SYNTAX;
953 if( (u[2] & 0xC0 )!= 0x80 ) {
954 return LDAP_INVALID_SYNTAX;
957 if( (u[1] & 0xC0) != 0x80 ) {
958 return LDAP_INVALID_SYNTAX;
961 /* CHARLEN already validated it */
964 return LDAP_INVALID_SYNTAX;
967 /* make sure len corresponds with the offset
968 to the next character */
969 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
973 return LDAP_INVALID_SYNTAX;
985 struct berval *normalized )
987 struct berval tmp, nvalue;
991 if( val->bv_val == NULL ) {
992 /* assume we're dealing with a syntax (e.g., UTF8String)
993 * which allows empty strings
995 normalized->bv_len = 0;
996 normalized->bv_val = NULL;
1000 flags = (mr == slap_schema.si_mr_caseExactMatch)
1001 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1002 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1003 ? LDAP_UTF8_APPROX : 0;
1005 val = UTF8bvnormalize( val, &tmp, flags );
1010 /* collapse spaces (in place) */
1012 nvalue.bv_val = tmp.bv_val;
1014 wasspace=1; /* trim leading spaces */
1015 for( i=0; i<tmp.bv_len; i++) {
1016 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1017 if( wasspace++ == 0 ) {
1018 /* trim repeated spaces */
1019 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1023 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1027 if( nvalue.bv_len ) {
1029 /* last character was a space, trim it */
1032 nvalue.bv_val[nvalue.bv_len] = '\0';
1035 /* string of all spaces is treated as one space */
1036 nvalue.bv_val[0] = ' ';
1037 nvalue.bv_val[1] = '\0';
1041 *normalized = nvalue;
1042 return LDAP_SUCCESS;
1045 #ifndef SLAP_NVALUES
1047 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1048 #if defined(SLAPD_APPROX_INITIALS)
1049 #define SLAPD_APPROX_DELIMITER "._ "
1050 #define SLAPD_APPROX_WORDLEN 2
1052 #define SLAPD_APPROX_DELIMITER " "
1053 #define SLAPD_APPROX_WORDLEN 1
1062 struct berval *value,
1063 void *assertedValue )
1065 struct berval *nval, *assertv;
1066 char *val, **values, **words, *c;
1067 int i, count, len, nextchunk=0, nextavail=0;
1069 /* Yes, this is necessary */
1070 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1071 if( nval == NULL ) {
1073 return LDAP_SUCCESS;
1076 /* Yes, this is necessary */
1077 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1078 NULL, LDAP_UTF8_APPROX );
1079 if( assertv == NULL ) {
1082 return LDAP_SUCCESS;
1085 /* Isolate how many words there are */
1086 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1087 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1088 if ( c == NULL ) break;
1093 /* Get a phonetic copy of each word */
1094 words = (char **)ch_malloc( count * sizeof(char *) );
1095 values = (char **)ch_malloc( count * sizeof(char *) );
1096 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1098 values[i] = phonetic(c);
1101 /* Work through the asserted value's words, to see if at least some
1102 of the words are there, in the same order. */
1104 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1105 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1110 #if defined(SLAPD_APPROX_INITIALS)
1111 else if( len == 1 ) {
1112 /* Single letter words need to at least match one word's initial */
1113 for( i=nextavail; i<count; i++ )
1114 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1121 /* Isolate the next word in the asserted value and phonetic it */
1122 assertv->bv_val[nextchunk+len] = '\0';
1123 val = phonetic( assertv->bv_val + nextchunk );
1125 /* See if this phonetic chunk is in the remaining words of *value */
1126 for( i=nextavail; i<count; i++ ){
1127 if( !strcmp( val, values[i] ) ){
1135 /* This chunk in the asserted value was NOT within the *value. */
1141 /* Go on to the next word in the asserted value */
1145 /* If some of the words were seen, call it a match */
1146 if( nextavail > 0 ) {
1153 /* Cleanup allocs */
1154 ber_bvfree( assertv );
1155 for( i=0; i<count; i++ ) {
1156 ch_free( values[i] );
1162 return LDAP_SUCCESS;
1171 struct berval *prefix,
1176 int i,j, len, wordcount, keycount=0;
1177 struct berval *newkeys;
1178 BerVarray keys=NULL;
1180 for( j=0; values[j].bv_val != NULL; j++ ) {
1181 struct berval val = { 0, NULL };
1182 /* Yes, this is necessary */
1183 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1184 assert( val.bv_val != NULL );
1186 /* Isolate how many words there are. There will be a key for each */
1187 for( wordcount = 0, c = val.bv_val; *c; c++) {
1188 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1189 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1191 if (*c == '\0') break;
1195 /* Allocate/increase storage to account for new keys */
1196 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1197 * sizeof(struct berval) );
1198 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1199 if( keys ) ch_free( keys );
1202 /* Get a phonetic copy of each word */
1203 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1205 if( len < SLAPD_APPROX_WORDLEN ) continue;
1206 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1211 ber_memfree( val.bv_val );
1213 keys[keycount].bv_val = NULL;
1216 return LDAP_SUCCESS;
1225 struct berval *prefix,
1226 void * assertedValue,
1234 /* Yes, this is necessary */
1235 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1236 NULL, LDAP_UTF8_APPROX );
1237 if( val == NULL || val->bv_val == NULL ) {
1238 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1239 keys[0].bv_val = NULL;
1242 return LDAP_SUCCESS;
1245 /* Isolate how many words there are. There will be a key for each */
1246 for( count = 0,c = val->bv_val; *c; c++) {
1247 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1248 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1250 if (*c == '\0') break;
1254 /* Allocate storage for new keys */
1255 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1257 /* Get a phonetic copy of each word */
1258 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1260 if( len < SLAPD_APPROX_WORDLEN ) continue;
1261 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1267 keys[count].bv_val = NULL;
1270 return LDAP_SUCCESS;
1274 /* No other form of Approximate Matching is defined */
1282 struct berval *value,
1283 void *assertedValue )
1285 char *vapprox, *avapprox;
1288 /* Yes, this is necessary */
1289 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1292 return LDAP_SUCCESS;
1295 /* Yes, this is necessary */
1296 t = UTF8normalize( ((struct berval *)assertedValue),
1301 return LDAP_SUCCESS;
1304 vapprox = phonetic( strip8bitChars( s ) );
1305 avapprox = phonetic( strip8bitChars( t ) );
1310 *matchp = strcmp( vapprox, avapprox );
1313 ch_free( avapprox );
1315 return LDAP_SUCCESS;
1324 struct berval *prefix,
1332 for( i=0; values[i].bv_val != NULL; i++ ) {
1333 /* empty - just count them */
1336 /* we should have at least one value at this point */
1339 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1341 /* Copy each value and run it through phonetic() */
1342 for( i=0; values[i].bv_val != NULL; i++ ) {
1343 /* Yes, this is necessary */
1344 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1346 /* strip 8-bit chars and run through phonetic() */
1347 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1350 keys[i].bv_val = NULL;
1353 return LDAP_SUCCESS;
1362 struct berval *prefix,
1363 void * assertedValue,
1369 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1371 /* Yes, this is necessary */
1372 s = UTF8normalize( ((struct berval *)assertedValue),
1377 /* strip 8-bit chars and run through phonetic() */
1378 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1384 return LDAP_SUCCESS;
1387 #endif /* !SLAP_NVALUES */
1389 /* Remove all spaces and '-' characters */
1391 telephoneNumberNormalize(
1396 struct berval *normalized )
1400 /* validator should have refused an empty string */
1401 assert( val->bv_len );
1403 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1405 for( p = val->bv_val; *p; p++ ) {
1406 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1412 normalized->bv_len = q - normalized->bv_val;
1414 if( normalized->bv_len == 0 ) {
1415 free( normalized->bv_val );
1416 return LDAP_INVALID_SYNTAX;
1419 return LDAP_SUCCESS;
1425 struct berval *val )
1429 if( val->bv_len == 0 ) {
1430 /* disallow empty strings */
1431 return LDAP_INVALID_SYNTAX;
1434 if( OID_LEADCHAR(val->bv_val[0]) ) {
1436 for(i=1; i < val->bv_len; i++) {
1437 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1438 if( dot++ ) return 1;
1439 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1442 return LDAP_INVALID_SYNTAX;
1446 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1448 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1449 for(i=1; i < val->bv_len; i++) {
1450 if( !DESC_CHAR(val->bv_val[i] ) ) {
1451 return LDAP_INVALID_SYNTAX;
1455 return LDAP_SUCCESS;
1458 return LDAP_INVALID_SYNTAX;
1467 struct berval *value,
1468 void *assertedValue )
1471 int vsign = 1, avsign = 1; /* default sign = '+' */
1472 struct berval *asserted;
1473 ber_len_t vlen, avlen;
1476 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1478 vlen = value->bv_len;
1480 #ifndef SLAP_NVALUES
1481 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1482 char *tmp = memchr( v, '$', vlen );
1483 if( tmp ) vlen = tmp - v;
1484 while( vlen && ASCII_SPACE( v[vlen-1] )) vlen--;
1488 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) { /* ANSI 2.2.1 */
1489 if( *v == '-' ) vsign = -1;
1492 if( vlen == 0 ) vsign = 0;
1494 /* Do the same with the *assertedValue number */
1495 asserted = (struct berval *) assertedValue;
1496 av = asserted->bv_val;
1497 avlen = asserted->bv_len;
1498 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1504 match = vsign - avsign;
1506 match = (vlen != avlen
1507 ? ( vlen < avlen ? -1 : 1 )
1508 : memcmp( v, av, vlen ));
1509 if( vsign < 0 ) match = -match;
1513 return LDAP_SUCCESS;
1519 struct berval *val )
1523 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1525 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1526 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1528 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1529 return LDAP_INVALID_SYNTAX;
1532 for( i=1; i < val->bv_len; i++ ) {
1533 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1536 return LDAP_SUCCESS;
1545 struct berval *normalized )
1554 /* Ignore leading spaces */
1555 while ( len && ( *p == ' ' )) {
1562 negative = ( *p == '-' );
1563 if(( *p == '-' ) || ( *p == '+' )) {
1569 /* Ignore leading zeros */
1570 while ( len && ( *p == '0' )) {
1575 /* If there are no non-zero digits left, the number is zero, otherwise
1576 allocate space for the number and copy it into the buffer */
1578 normalized->bv_val = ch_strdup("0");
1579 normalized->bv_len = 1;
1582 normalized->bv_len = len+negative;
1583 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1584 if( negative ) normalized->bv_val[0] = '-';
1585 AC_MEMCPY( normalized->bv_val + negative, p, len );
1586 normalized->bv_val[len+negative] = '\0';
1589 return LDAP_SUCCESS;
1593 countryStringValidate(
1595 struct berval *val )
1597 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1599 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1600 return LDAP_INVALID_SYNTAX;
1602 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1603 return LDAP_INVALID_SYNTAX;
1606 return LDAP_SUCCESS;
1610 printableStringValidate(
1612 struct berval *val )
1616 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1618 for(i=0; i < val->bv_len; i++) {
1619 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1620 return LDAP_INVALID_SYNTAX;
1624 return LDAP_SUCCESS;
1628 printablesStringValidate(
1630 struct berval *val )
1634 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1636 for(i=0,len=0; i < val->bv_len; i++) {
1637 int c = val->bv_val[i];
1641 return LDAP_INVALID_SYNTAX;
1645 } else if ( SLAP_PRINTABLE(c) ) {
1648 return LDAP_INVALID_SYNTAX;
1653 return LDAP_INVALID_SYNTAX;
1656 return LDAP_SUCCESS;
1662 struct berval *val )
1666 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1668 for(i=0; i < val->bv_len; i++) {
1669 if( !LDAP_ASCII(val->bv_val[i]) ) {
1670 return LDAP_INVALID_SYNTAX;
1674 return LDAP_SUCCESS;
1683 struct berval *normalized )
1686 int casefold = (mr != slap_schema.si_mr_caseExactIA5Match);
1688 assert( val->bv_len );
1692 /* Ignore initial whitespace */
1693 while ( ASCII_SPACE( *p ) ) {
1697 normalized->bv_val = ch_strdup( p );
1698 p = q = normalized->bv_val;
1701 if ( ASCII_SPACE( *p ) ) {
1704 /* Ignore the extra whitespace */
1705 while ( ASCII_SPACE( *p ) ) {
1709 } else if ( casefold ) {
1710 /* Most IA5 rules require casefolding */
1711 *q++ = TOLOWER(*p++);
1718 assert( normalized->bv_val <= p );
1722 * If the string ended in space, backup the pointer one
1723 * position. One is enough because the above loop collapsed
1724 * all whitespace to a single space.
1727 if ( ASCII_SPACE( q[-1] ) ) {
1731 /* null terminate */
1734 normalized->bv_len = q - normalized->bv_val;
1736 if( normalized->bv_len == 0 ) {
1737 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1738 normalized->bv_val[0] = ' ';
1739 normalized->bv_val[1] = '\0';
1740 normalized->bv_len = 1;
1743 return LDAP_SUCCESS;
1747 numericStringValidate(
1753 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1755 for(i=0; i < in->bv_len; i++) {
1756 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1757 return LDAP_INVALID_SYNTAX;
1761 return LDAP_SUCCESS;
1765 numericStringNormalize(
1770 struct berval *normalized )
1772 /* removal all spaces */
1775 assert( val->bv_len );
1777 normalized->bv_val = ch_malloc( val->bv_len + 1 );
1780 q = normalized->bv_val;
1783 if ( ASCII_SPACE( *p ) ) {
1784 /* Ignore whitespace */
1791 /* we should have copied no more then is in val */
1792 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1794 /* null terminate */
1797 normalized->bv_len = q - normalized->bv_val;
1799 if( normalized->bv_len == 0 ) {
1800 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1801 normalized->bv_val[0] = ' ';
1802 normalized->bv_val[1] = '\0';
1803 normalized->bv_len = 1;
1806 return LDAP_SUCCESS;
1809 #ifndef SLAP_NVALUES
1811 objectIdentifierFirstComponentMatch(
1816 struct berval *value,
1817 void *assertedValue )
1819 int rc = LDAP_SUCCESS;
1821 struct berval *asserted = (struct berval *) assertedValue;
1825 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1826 return LDAP_INVALID_SYNTAX;
1829 /* trim leading white space */
1830 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1834 /* grab next word */
1835 oid.bv_val = &value->bv_val[i];
1836 j = value->bv_len - i;
1837 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1842 /* insert attributeTypes, objectclass check here */
1843 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1844 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1847 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1848 MatchingRule *asserted_mr = mr_bvfind( asserted );
1849 MatchingRule *stored_mr = mr_bvfind( &oid );
1851 if( asserted_mr == NULL ) {
1852 rc = SLAPD_COMPARE_UNDEFINED;
1854 match = asserted_mr != stored_mr;
1857 } else if ( !strcmp( syntax->ssyn_oid,
1858 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1860 AttributeType *asserted_at = at_bvfind( asserted );
1861 AttributeType *stored_at = at_bvfind( &oid );
1863 if( asserted_at == NULL ) {
1864 rc = SLAPD_COMPARE_UNDEFINED;
1866 match = asserted_at != stored_at;
1869 } else if ( !strcmp( syntax->ssyn_oid,
1870 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1872 ObjectClass *asserted_oc = oc_bvfind( asserted );
1873 ObjectClass *stored_oc = oc_bvfind( &oid );
1875 if( asserted_oc == NULL ) {
1876 rc = SLAPD_COMPARE_UNDEFINED;
1878 match = asserted_oc != stored_oc;
1884 LDAP_LOG( CONFIG, ENTRY,
1885 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1886 match, value->bv_val, asserted->bv_val );
1888 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1889 "%d\n\t\"%s\"\n\t\"%s\"\n",
1890 match, value->bv_val, asserted->bv_val );
1893 if( rc == LDAP_SUCCESS ) *matchp = match;
1904 struct berval *value,
1905 void *assertedValue )
1907 long lValue, lAssertedValue;
1909 /* safe to assume integers are NUL terminated? */
1910 lValue = strtol(value->bv_val, NULL, 10);
1911 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1912 return LDAP_CONSTRAINT_VIOLATION;
1915 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1916 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1917 && errno == ERANGE )
1919 return LDAP_CONSTRAINT_VIOLATION;
1922 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1923 return LDAP_SUCCESS;
1932 struct berval *value,
1933 void *assertedValue )
1935 long lValue, lAssertedValue;
1937 /* safe to assume integers are NUL terminated? */
1938 lValue = strtol(value->bv_val, NULL, 10);
1939 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1940 return LDAP_CONSTRAINT_VIOLATION;
1943 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1944 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1945 && errno == ERANGE )
1947 return LDAP_CONSTRAINT_VIOLATION;
1950 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1951 return LDAP_SUCCESS;
1954 #ifndef SLAP_NVALUES
1956 #include <openssl/x509.h>
1957 #include <openssl/err.h>
1960 * Next function returns a string representation of a ASN1_INTEGER.
1961 * It works for unlimited lengths.
1964 static struct berval *
1965 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1969 static char digit[] = "0123456789";
1971 /* We work backwards, make it fill from the end of buf */
1972 p = buf + sizeof(buf) - 1;
1975 if ( a == NULL || a->length == 0 ) {
1983 /* We want to preserve the original */
1984 copy = ch_malloc(n*sizeof(unsigned int));
1985 for (i = 0; i<n; i++) {
1986 copy[i] = a->data[i];
1990 * base indicates the index of the most significant
1991 * byte that might be nonzero. When it goes off the
1992 * end, we now there is nothing left to do.
1998 for (i = base; i<n; i++ ) {
1999 copy[i] += carry*256;
2000 carry = copy[i] % 10;
2005 * Way too large, we need to leave
2006 * room for sign if negative
2011 *--p = digit[carry];
2013 if (copy[base] == 0) base++;
2018 if ( a->type == V_ASN1_NEG_INTEGER ) {
2022 return ber_str2bv( p, 0, 1, bv );
2026 * Given a certificate in DER format, extract the corresponding
2027 * assertion value for certificateExactMatch
2030 certificateExactConvert(
2032 struct berval * out )
2035 unsigned char *p = in->bv_val;
2036 struct berval serial;
2037 struct berval issuer_dn;
2039 xcert = d2i_X509(NULL, &p, in->bv_len);
2042 LDAP_LOG( CONFIG, ENTRY,
2043 "certificateExactConvert: error parsing cert: %s\n",
2044 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2046 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2047 "error parsing cert: %s\n",
2048 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2050 return LDAP_INVALID_SYNTAX;
2053 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2055 return LDAP_INVALID_SYNTAX;
2057 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2061 ber_memfree(serial.bv_val);
2062 return LDAP_INVALID_SYNTAX;
2067 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2068 out->bv_val = ch_malloc(out->bv_len);
2070 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2072 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2074 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2075 p += issuer_dn.bv_len;
2079 LDAP_LOG( CONFIG, ARGS,
2080 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2082 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2084 out->bv_val, NULL, NULL );
2087 ber_memfree(serial.bv_val);
2088 ber_memfree(issuer_dn.bv_val);
2090 return LDAP_SUCCESS;
2094 serial_and_issuer_parse(
2095 struct berval *assertion,
2096 struct berval *serial,
2097 struct berval *issuer_dn )
2104 begin = assertion->bv_val;
2105 end = assertion->bv_val+assertion->bv_len-1;
2106 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2107 if ( p > end ) return LDAP_INVALID_SYNTAX;
2109 /* p now points at the $ sign, now use
2110 * begin and end to delimit the serial number
2112 while (ASCII_SPACE(*begin)) begin++;
2114 while (ASCII_SPACE(*end)) end--;
2116 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2118 bv.bv_len = end-begin+1;
2120 ber_dupbv(serial, &bv);
2122 /* now extract the issuer, remember p was at the dollar sign */
2124 end = assertion->bv_val+assertion->bv_len-1;
2125 while (ASCII_SPACE(*begin)) begin++;
2126 /* should we trim spaces at the end too? is it safe always? no, no */
2128 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2131 bv.bv_len = end-begin+1;
2134 dnNormalize2( NULL, &bv, issuer_dn );
2137 return LDAP_SUCCESS;
2141 certificateExactMatch(
2146 struct berval *value,
2147 void *assertedValue )
2150 unsigned char *p = value->bv_val;
2151 struct berval serial;
2152 struct berval issuer_dn;
2153 struct berval asserted_serial;
2154 struct berval asserted_issuer_dn;
2157 xcert = d2i_X509(NULL, &p, value->bv_len);
2160 LDAP_LOG( CONFIG, ENTRY,
2161 "certificateExactMatch: error parsing cert: %s\n",
2162 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2164 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2165 "error parsing cert: %s\n",
2166 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2168 return LDAP_INVALID_SYNTAX;
2171 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2172 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2176 serial_and_issuer_parse(assertedValue,
2177 &asserted_serial, &asserted_issuer_dn);
2182 slap_schema.si_syn_integer,
2183 slap_schema.si_mr_integerMatch,
2186 if ( ret == LDAP_SUCCESS ) {
2187 if ( *matchp == 0 ) {
2188 /* We need to normalize everything for dnMatch */
2192 slap_schema.si_syn_distinguishedName,
2193 slap_schema.si_mr_distinguishedNameMatch,
2195 &asserted_issuer_dn);
2200 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2201 "%d\n\t\"%s $ %s\"\n",
2202 *matchp, serial.bv_val, issuer_dn.bv_val );
2203 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2204 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2207 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2208 "%d\n\t\"%s $ %s\"\n",
2209 *matchp, serial.bv_val, issuer_dn.bv_val );
2210 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2211 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2215 ber_memfree(serial.bv_val);
2216 ber_memfree(issuer_dn.bv_val);
2217 ber_memfree(asserted_serial.bv_val);
2218 ber_memfree(asserted_issuer_dn.bv_val);
2224 * Index generation function
2225 * We just index the serials, in most scenarios the issuer DN is one of
2226 * a very small set of values.
2228 static int certificateExactIndexer(
2233 struct berval *prefix,
2241 struct berval serial;
2243 /* we should have at least one value at this point */
2244 assert( values != NULL && values[0].bv_val != NULL );
2246 for( i=0; values[i].bv_val != NULL; i++ ) {
2247 /* empty -- just count them */
2250 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2252 for( i=0; values[i].bv_val != NULL; i++ ) {
2253 p = values[i].bv_val;
2254 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2257 LDAP_LOG( CONFIG, ENTRY,
2258 "certificateExactIndexer: error parsing cert: %s\n",
2259 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2261 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2262 "error parsing cert: %s\n",
2263 ERR_error_string(ERR_get_error(),NULL),
2266 /* Do we leak keys on error? */
2267 return LDAP_INVALID_SYNTAX;
2270 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2272 xintegerNormalize( slap_schema.si_syn_integer,
2273 &serial, &keys[i] );
2274 ber_memfree(serial.bv_val);
2276 LDAP_LOG( CONFIG, ENTRY,
2277 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2279 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2286 keys[i].bv_val = NULL;
2288 return LDAP_SUCCESS;
2291 /* Index generation function */
2292 /* We think this is always called with a value in matching rule syntax */
2293 static int certificateExactFilter(
2298 struct berval *prefix,
2299 void * assertedValue,
2303 struct berval asserted_serial;
2306 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2307 if( ret != LDAP_SUCCESS ) return ret;
2309 keys = ch_malloc( sizeof( struct berval ) * 2 );
2310 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2311 keys[1].bv_val = NULL;
2314 ber_memfree(asserted_serial.bv_val);
2315 return LDAP_SUCCESS;
2321 check_time_syntax (struct berval *val,
2325 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2326 static int mdays[2][12] = {
2327 /* non-leap years */
2328 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2330 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2333 int part, c, tzoffset, leapyear = 0 ;
2335 if( val->bv_len == 0 ) {
2336 return LDAP_INVALID_SYNTAX;
2339 p = (char *)val->bv_val;
2340 e = p + val->bv_len;
2342 /* Ignore initial whitespace */
2343 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2347 if (e - p < 13 - (2 * start)) {
2348 return LDAP_INVALID_SYNTAX;
2351 for (part = 0; part < 9; part++) {
2355 for (part = start; part < 7; part++) {
2357 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2364 return LDAP_INVALID_SYNTAX;
2366 if (c < 0 || c > 9) {
2367 return LDAP_INVALID_SYNTAX;
2373 return LDAP_INVALID_SYNTAX;
2375 if (c < 0 || c > 9) {
2376 return LDAP_INVALID_SYNTAX;
2381 if (part == 2 || part == 3) {
2384 if (parts[part] < 0) {
2385 return LDAP_INVALID_SYNTAX;
2387 if (parts[part] > ceiling[part]) {
2388 return LDAP_INVALID_SYNTAX;
2392 /* leapyear check for the Gregorian calendar (year>1581) */
2393 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2394 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2399 if (parts[3] > mdays[leapyear][parts[2]]) {
2400 return LDAP_INVALID_SYNTAX;
2405 tzoffset = 0; /* UTC */
2406 } else if (c != '+' && c != '-') {
2407 return LDAP_INVALID_SYNTAX;
2411 } else /* c == '+' */ {
2416 return LDAP_INVALID_SYNTAX;
2419 for (part = 7; part < 9; part++) {
2421 if (c < 0 || c > 9) {
2422 return LDAP_INVALID_SYNTAX;
2427 if (c < 0 || c > 9) {
2428 return LDAP_INVALID_SYNTAX;
2432 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2433 return LDAP_INVALID_SYNTAX;
2438 /* Ignore trailing whitespace */
2439 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2443 return LDAP_INVALID_SYNTAX;
2446 switch ( tzoffset ) {
2447 case -1: /* negativ offset to UTC, ie west of Greenwich */
2448 parts[4] += parts[7];
2449 parts[5] += parts[8];
2450 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2454 c = mdays[leapyear][parts[2]];
2456 if (parts[part] > c) {
2457 parts[part] -= c + 1;
2462 case 1: /* positive offset to UTC, ie east of Greenwich */
2463 parts[4] -= parts[7];
2464 parts[5] -= parts[8];
2465 for (part = 6; --part > 0; ) {
2469 /* first arg to % needs to be non negativ */
2470 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2472 if (parts[part] < 0) {
2473 parts[part] += c + 1;
2478 case 0: /* already UTC */
2482 return LDAP_SUCCESS;
2485 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2490 struct berval *normalized )
2494 rc = check_time_syntax(val, 1, parts);
2495 if (rc != LDAP_SUCCESS) {
2499 normalized->bv_val = ch_malloc( 14 );
2500 if ( normalized->bv_val == NULL ) {
2501 return LBER_ERROR_MEMORY;
2504 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2505 parts[1], parts[2] + 1, parts[3] + 1,
2506 parts[4], parts[5], parts[6] );
2507 normalized->bv_len = 13;
2509 return LDAP_SUCCESS;
2518 return check_time_syntax(in, 1, parts);
2523 generalizedTimeValidate(
2528 return check_time_syntax(in, 0, parts);
2532 generalizedTimeNormalize(
2537 struct berval *normalized )
2541 rc = check_time_syntax(val, 0, parts);
2542 if (rc != LDAP_SUCCESS) {
2546 normalized->bv_val = ch_malloc( 16 );
2547 if ( normalized->bv_val == NULL ) {
2548 return LBER_ERROR_MEMORY;
2551 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2552 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2553 parts[4], parts[5], parts[6] );
2554 normalized->bv_len = 15;
2556 return LDAP_SUCCESS;
2560 nisNetgroupTripleValidate(
2562 struct berval *val )
2567 if ( val->bv_len == 0 ) {
2568 return LDAP_INVALID_SYNTAX;
2571 p = (char *)val->bv_val;
2572 e = p + val->bv_len;
2574 if ( *p != '(' /*')'*/ ) {
2575 return LDAP_INVALID_SYNTAX;
2578 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2582 return LDAP_INVALID_SYNTAX;
2585 } else if ( !AD_CHAR( *p ) ) {
2586 return LDAP_INVALID_SYNTAX;
2590 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2591 return LDAP_INVALID_SYNTAX;
2597 return LDAP_INVALID_SYNTAX;
2600 return LDAP_SUCCESS;
2604 bootParameterValidate(
2606 struct berval *val )
2610 if ( val->bv_len == 0 ) {
2611 return LDAP_INVALID_SYNTAX;
2614 p = (char *)val->bv_val;
2615 e = p + val->bv_len;
2618 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2619 if ( !AD_CHAR( *p ) ) {
2620 return LDAP_INVALID_SYNTAX;
2625 return LDAP_INVALID_SYNTAX;
2629 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2630 if ( !AD_CHAR( *p ) ) {
2631 return LDAP_INVALID_SYNTAX;
2636 return LDAP_INVALID_SYNTAX;
2640 for ( p++; p < e; p++ ) {
2641 if ( !SLAP_PRINTABLE( *p ) ) {
2642 return LDAP_INVALID_SYNTAX;
2646 return LDAP_SUCCESS;
2649 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2650 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2652 static slap_syntax_defs_rec syntax_defs[] = {
2653 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2654 X_BINARY X_NOT_H_R ")",
2655 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2656 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2658 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2660 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2662 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2663 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2665 SLAP_SYNTAX_BER, berValidate, NULL},
2666 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2667 0, bitStringValidate, NULL },
2668 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2669 0, booleanValidate, NULL},
2670 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2671 X_BINARY X_NOT_H_R ")",
2672 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2673 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2674 X_BINARY X_NOT_H_R ")",
2675 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2676 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2677 X_BINARY X_NOT_H_R ")",
2678 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2679 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2680 0, countryStringValidate, NULL},
2681 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2682 0, dnValidate, dnPretty2},
2683 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2685 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2687 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2688 0, UTF8StringValidate, NULL},
2689 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2691 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2693 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2695 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2697 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2699 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2700 0, printablesStringValidate, NULL},
2701 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2702 SLAP_SYNTAX_BLOB, NULL, NULL},
2703 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2704 0, generalizedTimeValidate, NULL},
2705 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2707 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2708 0, IA5StringValidate, NULL},
2709 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2710 0, integerValidate, NULL},
2711 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2712 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2713 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2715 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2717 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2719 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2721 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2723 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2724 0, nameUIDValidate, NULL},
2725 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2727 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2728 0, numericStringValidate, NULL},
2729 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2731 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2732 0, oidValidate, NULL},
2733 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2734 0, IA5StringValidate, NULL},
2735 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2736 0, blobValidate, NULL},
2737 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2738 0, UTF8StringValidate, NULL},
2739 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2741 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2743 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2744 0, printableStringValidate, NULL},
2745 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2746 X_BINARY X_NOT_H_R ")",
2747 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2748 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2749 X_BINARY X_NOT_H_R ")",
2750 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2751 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2752 0, printableStringValidate, NULL},
2753 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2755 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2756 0, printablesStringValidate, NULL},
2757 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2758 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2759 0, utcTimeValidate, NULL},
2761 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2763 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2765 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2767 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2769 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2772 /* RFC 2307 NIS Syntaxes */
2773 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2774 0, nisNetgroupTripleValidate, NULL},
2775 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2776 0, bootParameterValidate, NULL},
2780 /* These OIDs are not published yet, but will be in the next
2781 * I-D for PKIX LDAPv3 schema as have been advanced by David
2782 * Chadwick in private mail.
2784 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2785 0, UTF8StringValidate, NULL},
2788 /* OpenLDAP Experimental Syntaxes */
2789 #ifdef SLAPD_ACI_ENABLED
2790 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2792 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2796 #ifdef SLAPD_AUTHPASSWD
2797 /* needs updating */
2798 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2799 SLAP_SYNTAX_HIDE, NULL, NULL},
2802 /* OpenLDAP Void Syntax */
2803 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2804 SLAP_SYNTAX_HIDE, inValidate, NULL},
2805 {NULL, 0, NULL, NULL}
2809 char *certificateExactMatchSyntaxes[] = {
2810 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2814 char *directoryStringSyntaxes[] = {
2815 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2818 char *integerFirstComponentMatchSyntaxes[] = {
2819 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2820 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2823 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2824 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2825 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2826 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2827 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2828 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2829 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2830 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2831 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2836 * Other matching rules in X.520 that we do not use (yet):
2838 * 2.5.13.9 numericStringOrderingMatch
2839 * 2.5.13.25 uTCTimeMatch
2840 * 2.5.13.26 uTCTimeOrderingMatch
2841 * 2.5.13.31 directoryStringFirstComponentMatch
2842 * 2.5.13.32 wordMatch
2843 * 2.5.13.33 keywordMatch
2844 * 2.5.13.35 certificateMatch
2845 * 2.5.13.36 certificatePairExactMatch
2846 * 2.5.13.37 certificatePairMatch
2847 * 2.5.13.38 certificateListExactMatch
2848 * 2.5.13.39 certificateListMatch
2849 * 2.5.13.40 algorithmIdentifierMatch
2850 * 2.5.13.41 storedPrefixMatch
2851 * 2.5.13.42 attributeCertificateMatch
2852 * 2.5.13.43 readerAndKeyIDMatch
2853 * 2.5.13.44 attributeIntegrityMatch
2855 static slap_mrule_defs_rec mrule_defs[] = {
2857 * EQUALITY matching rules must be listed after associated APPROX
2858 * matching rules. So, we list all APPROX matching rules first.
2860 #ifndef SLAP_NVALUES
2861 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2862 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2863 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2864 NULL, NULL, directoryStringApproxMatch,
2865 directoryStringApproxIndexer, directoryStringApproxFilter,
2868 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2869 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2870 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2871 NULL, NULL, IA5StringApproxMatch,
2872 IA5StringApproxIndexer, IA5StringApproxFilter,
2877 * Other matching rules
2880 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2881 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2882 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2883 NULL, objectIdentifierNormalize, octetStringMatch,
2884 octetStringIndexer, octetStringFilter,
2887 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2888 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2889 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2890 NULL, dnNormalize, dnMatch,
2891 octetStringIndexer, octetStringFilter,
2894 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2895 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2896 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2897 NULL, UTF8StringNormalize, octetStringMatch,
2898 octetStringIndexer, octetStringFilter,
2899 directoryStringApproxMatchOID },
2901 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2902 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2903 SLAP_MR_ORDERING, directoryStringSyntaxes,
2904 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2908 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2909 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2910 SLAP_MR_SUBSTR, NULL,
2911 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2912 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2915 {"( 2.5.13.5 NAME 'caseExactMatch' "
2916 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2917 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2918 NULL, UTF8StringNormalize, octetStringMatch,
2919 octetStringIndexer, octetStringFilter,
2920 directoryStringApproxMatchOID },
2922 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2923 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2924 SLAP_MR_ORDERING, directoryStringSyntaxes,
2925 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2929 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2930 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2931 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2932 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2933 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2936 {"( 2.5.13.8 NAME 'numericStringMatch' "
2937 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2938 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2939 NULL, numericStringNormalize, octetStringSubstringsMatch,
2940 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2943 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2944 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2945 SLAP_MR_SUBSTR, NULL,
2946 NULL, numericStringNormalize, octetStringSubstringsMatch,
2947 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2950 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2951 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2952 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2953 NULL, NULL, NULL, NULL, NULL, NULL},
2955 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2957 SLAP_MR_SUBSTR, NULL,
2958 NULL, NULL, NULL, NULL, NULL, NULL},
2960 {"( 2.5.13.13 NAME 'booleanMatch' "
2961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2962 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2963 NULL, NULL, booleanMatch,
2964 octetStringIndexer, octetStringFilter,
2967 {"( 2.5.13.14 NAME 'integerMatch' "
2968 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2969 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2970 NULL, integerNormalize, integerMatch,
2971 octetStringIndexer, octetStringFilter,
2974 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2975 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2976 SLAP_MR_ORDERING, NULL,
2977 NULL, integerNormalize, integerOrderingMatch,
2981 {"( 2.5.13.16 NAME 'bitStringMatch' "
2982 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2983 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2984 NULL, NULL, octetStringMatch,
2985 octetStringIndexer, octetStringFilter,
2988 {"( 2.5.13.17 NAME 'octetStringMatch' "
2989 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2990 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2991 NULL, NULL, octetStringMatch,
2992 octetStringIndexer, octetStringFilter,
2995 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2996 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2997 SLAP_MR_ORDERING, NULL,
2998 NULL, NULL, octetStringOrderingMatch,
3002 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3003 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3004 SLAP_MR_SUBSTR, NULL,
3005 NULL, NULL, octetStringSubstringsMatch,
3006 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3009 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3010 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3011 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3013 telephoneNumberNormalize, octetStringMatch,
3014 octetStringIndexer, octetStringFilter,
3017 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3018 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3019 SLAP_MR_SUBSTR, NULL,
3020 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3021 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3024 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3025 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3026 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3027 NULL, NULL, NULL, NULL, NULL, NULL},
3029 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3030 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3031 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3032 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3036 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3037 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3038 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3039 NULL, NULL, NULL, NULL, NULL, NULL},
3041 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3042 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3043 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3044 NULL, generalizedTimeNormalize, octetStringMatch,
3048 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3049 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3050 SLAP_MR_ORDERING, NULL,
3051 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3055 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3056 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3057 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3058 NULL, integerFirstComponentNormalize, integerMatch,
3062 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3063 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3064 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3065 objectIdentifierFirstComponentMatchSyntaxes,
3066 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3067 octetStringIndexer, octetStringFilter,
3070 #ifndef SLAP_NVALUES
3072 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3073 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3074 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3075 certificateExactConvert, NULL, certificateExactMatch,
3076 certificateExactIndexer, certificateExactFilter,
3081 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3082 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3083 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3084 NULL, IA5StringNormalize, octetStringMatch,
3085 octetStringIndexer, octetStringFilter,
3086 IA5StringApproxMatchOID },
3088 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3089 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3090 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3091 NULL, IA5StringNormalize, octetStringMatch,
3092 octetStringIndexer, octetStringFilter,
3093 IA5StringApproxMatchOID },
3095 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3096 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3097 SLAP_MR_SUBSTR, NULL,
3098 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3099 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3102 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3103 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3104 SLAP_MR_SUBSTR, NULL,
3105 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3106 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3109 #ifdef SLAPD_AUTHPASSWD
3110 /* needs updating */
3111 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3112 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3113 SLAP_MR_EQUALITY, NULL,
3114 NULL, NULL, authPasswordMatch,
3119 #ifdef SLAPD_ACI_ENABLED
3120 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3121 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3122 SLAP_MR_EQUALITY, NULL,
3123 NULL, NULL, OpenLDAPaciMatch,
3128 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3129 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3131 NULL, NULL, integerBitAndMatch,
3135 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3136 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3138 NULL, NULL, integerBitOrMatch,
3142 {NULL, SLAP_MR_NONE, NULL,
3143 NULL, NULL, NULL, NULL, NULL,
3148 slap_schema_init( void )
3153 /* we should only be called once (from main) */
3154 assert( schema_init_done == 0 );
3156 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3157 res = register_syntax( &syntax_defs[i] );
3160 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3161 syntax_defs[i].sd_desc );
3166 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3167 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3168 mrule_defs[i].mrd_compat_syntaxes == NULL )
3171 "slap_schema_init: Ignoring unusable matching rule %s\n",
3172 mrule_defs[i].mrd_desc );
3176 res = register_matching_rule( &mrule_defs[i] );
3180 "slap_schema_init: Error registering matching rule %s\n",
3181 mrule_defs[i].mrd_desc );
3186 res = slap_schema_load();
3187 schema_init_done = 1;
3192 schema_destroy( void )