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 uniqueMemberMatch NULL
36 #define OpenLDAPaciMatch NULL
38 /* approx matching rules */
40 #define directoryStringApproxMatchOID NULL
41 #define IA5StringApproxMatchOID NULL
43 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
44 #define directoryStringApproxMatch approxMatch
45 #define directoryStringApproxIndexer approxIndexer
46 #define directoryStringApproxFilter approxFilter
47 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
48 #define IA5StringApproxMatch approxMatch
49 #define IA5StringApproxIndexer approxIndexer
50 #define IA5StringApproxFilter approxFilter
58 /* no value allowed */
59 return LDAP_INVALID_SYNTAX;
67 /* any value allowed */
71 #define berValidate blobValidate
82 struct berval *asserted = (struct berval *) assertedValue;
83 int match = value->bv_len - asserted->bv_len;
86 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
94 octetStringOrderingMatch(
100 void *assertedValue )
102 struct berval *asserted = (struct berval *) assertedValue;
103 ber_len_t v_len = value->bv_len;
104 ber_len_t av_len = asserted->bv_len;
106 int match = memcmp( value->bv_val, asserted->bv_val,
107 (v_len < av_len ? v_len : av_len) );
109 if( match == 0 ) match = v_len - av_len;
115 /* Index generation function */
116 int octetStringIndexer(
121 struct berval *prefix,
129 HASH_CONTEXT HASHcontext;
130 unsigned char HASHdigest[HASH_BYTES];
131 struct berval digest;
132 digest.bv_val = HASHdigest;
133 digest.bv_len = sizeof(HASHdigest);
135 for( i=0; values[i].bv_val != NULL; i++ ) {
136 /* just count them */
139 /* we should have at least one value at this point */
142 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
144 slen = syntax->ssyn_oidlen;
145 mlen = mr->smr_oidlen;
147 for( i=0; values[i].bv_val != NULL; i++ ) {
148 HASH_Init( &HASHcontext );
149 if( prefix != NULL && prefix->bv_len > 0 ) {
150 HASH_Update( &HASHcontext,
151 prefix->bv_val, prefix->bv_len );
153 HASH_Update( &HASHcontext,
154 syntax->ssyn_oid, slen );
155 HASH_Update( &HASHcontext,
157 HASH_Update( &HASHcontext,
158 values[i].bv_val, values[i].bv_len );
159 HASH_Final( HASHdigest, &HASHcontext );
161 ber_dupbv_x( &keys[i], &digest, ctx );
164 keys[i].bv_val = NULL;
172 /* Index generation function */
173 int octetStringFilter(
178 struct berval *prefix,
179 void * assertedValue,
185 HASH_CONTEXT HASHcontext;
186 unsigned char HASHdigest[HASH_BYTES];
187 struct berval *value = (struct berval *) assertedValue;
188 struct berval digest;
189 digest.bv_val = HASHdigest;
190 digest.bv_len = sizeof(HASHdigest);
192 slen = syntax->ssyn_oidlen;
193 mlen = mr->smr_oidlen;
195 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
197 HASH_Init( &HASHcontext );
198 if( prefix != NULL && prefix->bv_len > 0 ) {
199 HASH_Update( &HASHcontext,
200 prefix->bv_val, prefix->bv_len );
202 HASH_Update( &HASHcontext,
203 syntax->ssyn_oid, slen );
204 HASH_Update( &HASHcontext,
206 HASH_Update( &HASHcontext,
207 value->bv_val, value->bv_len );
208 HASH_Final( HASHdigest, &HASHcontext );
210 ber_dupbv_x( keys, &digest, ctx );
211 keys[1].bv_val = NULL;
220 octetStringSubstringsMatch(
225 struct berval *value,
226 void *assertedValue )
229 SubstringsAssertion *sub = assertedValue;
230 struct berval left = *value;
234 /* Add up asserted input length */
235 if( sub->sa_initial.bv_val ) {
236 inlen += sub->sa_initial.bv_len;
239 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
240 inlen += sub->sa_any[i].bv_len;
243 if( sub->sa_final.bv_val ) {
244 inlen += sub->sa_final.bv_len;
247 if( sub->sa_initial.bv_val ) {
248 if( inlen > left.bv_len ) {
253 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
254 sub->sa_initial.bv_len );
260 left.bv_val += sub->sa_initial.bv_len;
261 left.bv_len -= sub->sa_initial.bv_len;
262 inlen -= sub->sa_initial.bv_len;
265 if( sub->sa_final.bv_val ) {
266 if( inlen > left.bv_len ) {
271 match = memcmp( sub->sa_final.bv_val,
272 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
273 sub->sa_final.bv_len );
279 left.bv_len -= sub->sa_final.bv_len;
280 inlen -= sub->sa_final.bv_len;
284 for(i=0; sub->sa_any[i].bv_val; i++) {
289 if( inlen > left.bv_len ) {
290 /* not enough length */
295 if( sub->sa_any[i].bv_len == 0 ) {
299 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
306 idx = p - left.bv_val;
308 if( idx >= left.bv_len ) {
309 /* this shouldn't happen */
316 if( sub->sa_any[i].bv_len > left.bv_len ) {
317 /* not enough left */
322 match = memcmp( left.bv_val,
323 sub->sa_any[i].bv_val,
324 sub->sa_any[i].bv_len );
332 left.bv_val += sub->sa_any[i].bv_len;
333 left.bv_len -= sub->sa_any[i].bv_len;
334 inlen -= sub->sa_any[i].bv_len;
343 /* Substrings Index generation function */
345 octetStringSubstringsIndexer(
350 struct berval *prefix,
355 ber_len_t i, j, nkeys;
359 HASH_CONTEXT HASHcontext;
360 unsigned char HASHdigest[HASH_BYTES];
361 struct berval digest;
362 digest.bv_val = HASHdigest;
363 digest.bv_len = sizeof(HASHdigest);
367 for( i=0; values[i].bv_val != NULL; i++ ) {
368 /* count number of indices to generate */
369 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
373 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
374 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
375 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
376 (SLAP_INDEX_SUBSTR_MINLEN - 1);
378 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
382 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
383 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
384 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
388 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
389 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
390 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
391 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
393 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
399 /* no keys to generate */
404 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
406 slen = syntax->ssyn_oidlen;
407 mlen = mr->smr_oidlen;
410 for( i=0; values[i].bv_val != NULL; i++ ) {
413 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
415 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
416 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
418 char pre = SLAP_INDEX_SUBSTR_PREFIX;
419 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
421 for( j=0; j<max; j++ ) {
422 HASH_Init( &HASHcontext );
423 if( prefix != NULL && prefix->bv_len > 0 ) {
424 HASH_Update( &HASHcontext,
425 prefix->bv_val, prefix->bv_len );
428 HASH_Update( &HASHcontext,
429 &pre, sizeof( pre ) );
430 HASH_Update( &HASHcontext,
431 syntax->ssyn_oid, slen );
432 HASH_Update( &HASHcontext,
434 HASH_Update( &HASHcontext,
435 &values[i].bv_val[j],
436 SLAP_INDEX_SUBSTR_MAXLEN );
437 HASH_Final( HASHdigest, &HASHcontext );
439 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
443 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
444 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
446 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
449 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
450 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
451 HASH_Init( &HASHcontext );
452 if( prefix != NULL && prefix->bv_len > 0 ) {
453 HASH_Update( &HASHcontext,
454 prefix->bv_val, prefix->bv_len );
456 HASH_Update( &HASHcontext,
457 &pre, sizeof( pre ) );
458 HASH_Update( &HASHcontext,
459 syntax->ssyn_oid, slen );
460 HASH_Update( &HASHcontext,
462 HASH_Update( &HASHcontext,
463 values[i].bv_val, j );
464 HASH_Final( HASHdigest, &HASHcontext );
466 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
469 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
470 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
471 HASH_Init( &HASHcontext );
472 if( prefix != NULL && prefix->bv_len > 0 ) {
473 HASH_Update( &HASHcontext,
474 prefix->bv_val, prefix->bv_len );
476 HASH_Update( &HASHcontext,
477 &pre, sizeof( pre ) );
478 HASH_Update( &HASHcontext,
479 syntax->ssyn_oid, slen );
480 HASH_Update( &HASHcontext,
482 HASH_Update( &HASHcontext,
483 &values[i].bv_val[values[i].bv_len-j], j );
484 HASH_Final( HASHdigest, &HASHcontext );
486 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
494 keys[nkeys].bv_val = NULL;
505 octetStringSubstringsFilter (
510 struct berval *prefix,
511 void * assertedValue,
515 SubstringsAssertion *sa;
518 size_t slen, mlen, klen;
520 HASH_CONTEXT HASHcontext;
521 unsigned char HASHdigest[HASH_BYTES];
522 struct berval *value;
523 struct berval digest;
525 sa = (SubstringsAssertion *) assertedValue;
527 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
528 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
533 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
535 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
536 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
537 /* don't bother accounting for stepping */
538 nkeys += sa->sa_any[i].bv_len -
539 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
544 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
545 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
555 digest.bv_val = HASHdigest;
556 digest.bv_len = sizeof(HASHdigest);
558 slen = syntax->ssyn_oidlen;
559 mlen = mr->smr_oidlen;
561 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
564 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
565 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
567 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
568 value = &sa->sa_initial;
570 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
571 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
573 HASH_Init( &HASHcontext );
574 if( prefix != NULL && prefix->bv_len > 0 ) {
575 HASH_Update( &HASHcontext,
576 prefix->bv_val, prefix->bv_len );
578 HASH_Update( &HASHcontext,
579 &pre, sizeof( pre ) );
580 HASH_Update( &HASHcontext,
581 syntax->ssyn_oid, slen );
582 HASH_Update( &HASHcontext,
584 HASH_Update( &HASHcontext,
585 value->bv_val, klen );
586 HASH_Final( HASHdigest, &HASHcontext );
588 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
591 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
593 pre = SLAP_INDEX_SUBSTR_PREFIX;
594 klen = SLAP_INDEX_SUBSTR_MAXLEN;
596 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
597 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
601 value = &sa->sa_any[i];
604 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
605 j += SLAP_INDEX_SUBSTR_STEP )
607 HASH_Init( &HASHcontext );
608 if( prefix != NULL && prefix->bv_len > 0 ) {
609 HASH_Update( &HASHcontext,
610 prefix->bv_val, prefix->bv_len );
612 HASH_Update( &HASHcontext,
613 &pre, sizeof( pre ) );
614 HASH_Update( &HASHcontext,
615 syntax->ssyn_oid, slen );
616 HASH_Update( &HASHcontext,
618 HASH_Update( &HASHcontext,
619 &value->bv_val[j], klen );
620 HASH_Final( HASHdigest, &HASHcontext );
622 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
627 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
628 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
630 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
631 value = &sa->sa_final;
633 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
634 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
636 HASH_Init( &HASHcontext );
637 if( prefix != NULL && prefix->bv_len > 0 ) {
638 HASH_Update( &HASHcontext,
639 prefix->bv_val, prefix->bv_len );
641 HASH_Update( &HASHcontext,
642 &pre, sizeof( pre ) );
643 HASH_Update( &HASHcontext,
644 syntax->ssyn_oid, slen );
645 HASH_Update( &HASHcontext,
647 HASH_Update( &HASHcontext,
648 &value->bv_val[value->bv_len-klen], klen );
649 HASH_Final( HASHdigest, &HASHcontext );
651 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
655 keys[nkeys].bv_val = NULL;
672 /* very unforgiving validation, requires no normalization
673 * before simplistic matching
675 if( in->bv_len < 3 ) {
676 return LDAP_INVALID_SYNTAX;
680 * RFC 2252 section 6.3 Bit String
681 * bitstring = "'" *binary-digit "'B"
682 * binary-digit = "0" / "1"
683 * example: '0101111101'B
686 if( in->bv_val[0] != '\'' ||
687 in->bv_val[in->bv_len-2] != '\'' ||
688 in->bv_val[in->bv_len-1] != 'B' )
690 return LDAP_INVALID_SYNTAX;
693 for( i=in->bv_len-3; i>0; i-- ) {
694 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
695 return LDAP_INVALID_SYNTAX;
710 if( in->bv_len == 0 ) return LDAP_SUCCESS;
712 ber_dupbv( &dn, in );
713 if( !dn.bv_val ) return LDAP_OTHER;
715 if( dn.bv_val[dn.bv_len-1] == 'B'
716 && dn.bv_val[dn.bv_len-2] == '\'' )
718 /* assume presence of optional UID */
721 for(i=dn.bv_len-3; i>1; i--) {
722 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
726 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
727 ber_memfree( dn.bv_val );
728 return LDAP_INVALID_SYNTAX;
731 /* trim the UID to allow use of dnValidate */
732 dn.bv_val[i-1] = '\0';
736 rc = dnValidate( NULL, &dn );
738 ber_memfree( dn.bv_val );
743 uniqueMemberNormalize(
748 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 = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
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( bvmatch( in, &slap_true_bv ) ) {
824 } else if( in->bv_len == 5 ) {
825 if( bvmatch( in, &slap_false_bv ) ) {
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,
988 struct berval tmp, nvalue;
992 if( val->bv_val == NULL ) {
993 /* assume we're dealing with a syntax (e.g., UTF8String)
994 * which allows empty strings
996 normalized->bv_len = 0;
997 normalized->bv_val = NULL;
1001 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1002 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1003 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1004 ? LDAP_UTF8_APPROX : 0;
1006 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1011 /* collapse spaces (in place) */
1013 nvalue.bv_val = tmp.bv_val;
1015 wasspace=1; /* trim leading spaces */
1016 for( i=0; i<tmp.bv_len; i++) {
1017 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1018 if( wasspace++ == 0 ) {
1019 /* trim repeated spaces */
1020 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1024 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1028 if( nvalue.bv_len ) {
1030 /* last character was a space, trim it */
1033 nvalue.bv_val[nvalue.bv_len] = '\0';
1036 /* string of all spaces is treated as one space */
1037 nvalue.bv_val[0] = ' ';
1038 nvalue.bv_val[1] = '\0';
1042 *normalized = nvalue;
1043 return LDAP_SUCCESS;
1046 #ifndef SLAP_NVALUES
1048 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1049 #if defined(SLAPD_APPROX_INITIALS)
1050 #define SLAPD_APPROX_DELIMITER "._ "
1051 #define SLAPD_APPROX_WORDLEN 2
1053 #define SLAPD_APPROX_DELIMITER " "
1054 #define SLAPD_APPROX_WORDLEN 1
1063 struct berval *value,
1064 void *assertedValue )
1066 struct berval *nval, *assertv;
1067 char *val, **values, **words, *c;
1068 int i, count, len, nextchunk=0, nextavail=0;
1070 /* Yes, this is necessary */
1071 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1072 if( nval == NULL ) {
1074 return LDAP_SUCCESS;
1077 /* Yes, this is necessary */
1078 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1079 NULL, LDAP_UTF8_APPROX );
1080 if( assertv == NULL ) {
1083 return LDAP_SUCCESS;
1086 /* Isolate how many words there are */
1087 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1088 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1089 if ( c == NULL ) break;
1094 /* Get a phonetic copy of each word */
1095 words = (char **)ch_malloc( count * sizeof(char *) );
1096 values = (char **)ch_malloc( count * sizeof(char *) );
1097 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1099 values[i] = phonetic(c);
1102 /* Work through the asserted value's words, to see if at least some
1103 of the words are there, in the same order. */
1105 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1106 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1111 #if defined(SLAPD_APPROX_INITIALS)
1112 else if( len == 1 ) {
1113 /* Single letter words need to at least match one word's initial */
1114 for( i=nextavail; i<count; i++ )
1115 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1122 /* Isolate the next word in the asserted value and phonetic it */
1123 assertv->bv_val[nextchunk+len] = '\0';
1124 val = phonetic( assertv->bv_val + nextchunk );
1126 /* See if this phonetic chunk is in the remaining words of *value */
1127 for( i=nextavail; i<count; i++ ){
1128 if( !strcmp( val, values[i] ) ){
1136 /* This chunk in the asserted value was NOT within the *value. */
1142 /* Go on to the next word in the asserted value */
1146 /* If some of the words were seen, call it a match */
1147 if( nextavail > 0 ) {
1154 /* Cleanup allocs */
1155 ber_bvfree( assertv );
1156 for( i=0; i<count; i++ ) {
1157 ch_free( values[i] );
1163 return LDAP_SUCCESS;
1172 struct berval *prefix,
1177 int i,j, len, wordcount, keycount=0;
1178 struct berval *newkeys;
1179 BerVarray keys=NULL;
1181 for( j=0; values[j].bv_val != NULL; j++ ) {
1182 struct berval val = { 0, NULL };
1183 /* Yes, this is necessary */
1184 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1185 assert( val.bv_val != NULL );
1187 /* Isolate how many words there are. There will be a key for each */
1188 for( wordcount = 0, c = val.bv_val; *c; c++) {
1189 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1190 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1192 if (*c == '\0') break;
1196 /* Allocate/increase storage to account for new keys */
1197 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1198 * sizeof(struct berval) );
1199 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1200 if( keys ) ch_free( keys );
1203 /* Get a phonetic copy of each word */
1204 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1206 if( len < SLAPD_APPROX_WORDLEN ) continue;
1207 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1212 ber_memfree( val.bv_val );
1214 keys[keycount].bv_val = NULL;
1217 return LDAP_SUCCESS;
1226 struct berval *prefix,
1227 void * assertedValue,
1235 /* Yes, this is necessary */
1236 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1237 NULL, LDAP_UTF8_APPROX );
1238 if( val == NULL || val->bv_val == NULL ) {
1239 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1240 keys[0].bv_val = NULL;
1243 return LDAP_SUCCESS;
1246 /* Isolate how many words there are. There will be a key for each */
1247 for( count = 0,c = val->bv_val; *c; c++) {
1248 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1249 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1251 if (*c == '\0') break;
1255 /* Allocate storage for new keys */
1256 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1258 /* Get a phonetic copy of each word */
1259 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1261 if( len < SLAPD_APPROX_WORDLEN ) continue;
1262 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1268 keys[count].bv_val = NULL;
1271 return LDAP_SUCCESS;
1275 /* No other form of Approximate Matching is defined */
1283 struct berval *value,
1284 void *assertedValue )
1286 char *vapprox, *avapprox;
1289 /* Yes, this is necessary */
1290 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1293 return LDAP_SUCCESS;
1296 /* Yes, this is necessary */
1297 t = UTF8normalize( ((struct berval *)assertedValue),
1302 return LDAP_SUCCESS;
1305 vapprox = phonetic( strip8bitChars( s ) );
1306 avapprox = phonetic( strip8bitChars( t ) );
1311 *matchp = strcmp( vapprox, avapprox );
1314 ch_free( avapprox );
1316 return LDAP_SUCCESS;
1325 struct berval *prefix,
1333 for( i=0; values[i].bv_val != NULL; i++ ) {
1334 /* empty - just count them */
1337 /* we should have at least one value at this point */
1340 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1342 /* Copy each value and run it through phonetic() */
1343 for( i=0; values[i].bv_val != NULL; i++ ) {
1344 /* Yes, this is necessary */
1345 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1347 /* strip 8-bit chars and run through phonetic() */
1348 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1351 keys[i].bv_val = NULL;
1354 return LDAP_SUCCESS;
1363 struct berval *prefix,
1364 void * assertedValue,
1370 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1372 /* Yes, this is necessary */
1373 s = UTF8normalize( ((struct berval *)assertedValue),
1378 /* strip 8-bit chars and run through phonetic() */
1379 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1385 return LDAP_SUCCESS;
1388 #endif /* !SLAP_NVALUES */
1390 /* Remove all spaces and '-' characters */
1392 telephoneNumberNormalize(
1397 struct berval *normalized,
1402 /* validator should have refused an empty string */
1403 assert( val->bv_len );
1405 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1407 for( p = val->bv_val; *p; p++ ) {
1408 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1414 normalized->bv_len = q - normalized->bv_val;
1416 if( normalized->bv_len == 0 ) {
1417 sl_free( normalized->bv_val, ctx );
1418 return LDAP_INVALID_SYNTAX;
1421 return LDAP_SUCCESS;
1429 struct berval val = *in;
1431 if( val.bv_len == 0 ) {
1432 /* disallow empty strings */
1433 return LDAP_INVALID_SYNTAX;
1436 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1437 if ( val.bv_len == 1 ) {
1438 return LDAP_SUCCESS;
1441 if ( val.bv_val[0] == '0' ) {
1448 while ( OID_LEADCHAR( val.bv_val[0] )) {
1452 if ( val.bv_len == 0 ) {
1453 return LDAP_SUCCESS;
1457 if( !OID_SEPARATOR( val.bv_val[0] )) {
1465 return LDAP_INVALID_SYNTAX;
1474 struct berval val = *in;
1476 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1478 if ( val.bv_val[0] == '-' ) {
1482 if( val.bv_len == 0 ) { /* bare "-" */
1483 return LDAP_INVALID_SYNTAX;
1486 if( val.bv_val[0] == '0' ) { /* "-0" */
1487 return LDAP_INVALID_SYNTAX;
1490 } else if ( val.bv_val[0] == '0' ) {
1491 if( val.bv_len > 1 ) { /* "0<more>" */
1492 return LDAP_INVALID_SYNTAX;
1495 return LDAP_SUCCESS;
1498 for( i=0; i < val.bv_len; i++ ) {
1499 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1500 return LDAP_INVALID_SYNTAX;
1504 return LDAP_SUCCESS;
1513 struct berval *value,
1514 void *assertedValue )
1516 struct berval *asserted = (struct berval *) assertedValue;
1517 int vsign = 1, asign = 1; /* default sign = '+' */
1522 if( v.bv_val[0] == '-' ) {
1528 if( v.bv_len == 0 ) vsign = 0;
1531 if( a.bv_val[0] == '-' ) {
1537 if( a.bv_len == 0 ) vsign = 0;
1539 match = vsign - asign;
1541 match = ( v.bv_len != a.bv_len
1542 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1543 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1544 if( vsign < 0 ) match = -match;
1548 return LDAP_SUCCESS;
1552 countryStringValidate(
1554 struct berval *val )
1556 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1558 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1559 return LDAP_INVALID_SYNTAX;
1561 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1562 return LDAP_INVALID_SYNTAX;
1565 return LDAP_SUCCESS;
1569 printableStringValidate(
1571 struct berval *val )
1575 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1577 for(i=0; i < val->bv_len; i++) {
1578 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1579 return LDAP_INVALID_SYNTAX;
1583 return LDAP_SUCCESS;
1587 printablesStringValidate(
1589 struct berval *val )
1593 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1595 for(i=0,len=0; i < val->bv_len; i++) {
1596 int c = val->bv_val[i];
1600 return LDAP_INVALID_SYNTAX;
1604 } else if ( SLAP_PRINTABLE(c) ) {
1607 return LDAP_INVALID_SYNTAX;
1612 return LDAP_INVALID_SYNTAX;
1615 return LDAP_SUCCESS;
1621 struct berval *val )
1625 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1627 for(i=0; i < val->bv_len; i++) {
1628 if( !LDAP_ASCII(val->bv_val[i]) ) {
1629 return LDAP_INVALID_SYNTAX;
1633 return LDAP_SUCCESS;
1642 struct berval *normalized,
1646 int casefold = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1648 assert( val->bv_len );
1652 /* Ignore initial whitespace */
1653 while ( ASCII_SPACE( *p ) ) p++;
1655 normalized->bv_val = ber_strdup_x( p, ctx );
1656 p = q = normalized->bv_val;
1659 if ( ASCII_SPACE( *p ) ) {
1662 /* Ignore the extra whitespace */
1663 while ( ASCII_SPACE( *p ) ) {
1667 } else if ( casefold ) {
1668 /* Most IA5 rules require casefolding */
1669 *q++ = TOLOWER(*p++);
1676 assert( normalized->bv_val <= p );
1680 * If the string ended in space, backup the pointer one
1681 * position. One is enough because the above loop collapsed
1682 * all whitespace to a single space.
1684 if ( ASCII_SPACE( q[-1] ) ) --q;
1686 /* null terminate */
1689 normalized->bv_len = q - normalized->bv_val;
1690 if( normalized->bv_len == 0 ) {
1691 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1692 normalized->bv_val[0] = ' ';
1693 normalized->bv_val[1] = '\0';
1694 normalized->bv_len = 1;
1697 return LDAP_SUCCESS;
1701 numericStringValidate(
1707 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1709 for(i=0; i < in->bv_len; i++) {
1710 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1711 return LDAP_INVALID_SYNTAX;
1715 return LDAP_SUCCESS;
1719 numericStringNormalize(
1724 struct berval *normalized,
1727 /* removal all spaces */
1730 assert( val->bv_len );
1732 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1735 q = normalized->bv_val;
1738 if ( ASCII_SPACE( *p ) ) {
1739 /* Ignore whitespace */
1746 /* we should have copied no more then is in val */
1747 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1749 /* null terminate */
1752 normalized->bv_len = q - normalized->bv_val;
1754 if( normalized->bv_len == 0 ) {
1755 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1756 normalized->bv_val[0] = ' ';
1757 normalized->bv_val[1] = '\0';
1758 normalized->bv_len = 1;
1761 return LDAP_SUCCESS;
1770 struct berval *value,
1771 void *assertedValue )
1773 long lValue, lAssertedValue;
1775 /* safe to assume integers are NUL terminated? */
1776 lValue = strtol(value->bv_val, NULL, 10);
1777 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1778 return LDAP_CONSTRAINT_VIOLATION;
1781 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1782 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1783 && errno == ERANGE )
1785 return LDAP_CONSTRAINT_VIOLATION;
1788 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1789 return LDAP_SUCCESS;
1798 struct berval *value,
1799 void *assertedValue )
1801 long lValue, lAssertedValue;
1803 /* safe to assume integers are NUL terminated? */
1804 lValue = strtol(value->bv_val, NULL, 10);
1805 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1806 return LDAP_CONSTRAINT_VIOLATION;
1809 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1810 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1811 && errno == ERANGE )
1813 return LDAP_CONSTRAINT_VIOLATION;
1816 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1817 return LDAP_SUCCESS;
1820 #ifndef SLAP_NVALUES
1822 #include <openssl/x509.h>
1823 #include <openssl/err.h>
1826 * Next function returns a string representation of a ASN1_INTEGER.
1827 * It works for unlimited lengths.
1830 static struct berval *
1831 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1835 static char digit[] = "0123456789";
1837 /* We work backwards, make it fill from the end of buf */
1838 p = buf + sizeof(buf) - 1;
1841 if ( a == NULL || a->length == 0 ) {
1849 /* We want to preserve the original */
1850 copy = ch_malloc(n*sizeof(unsigned int));
1851 for (i = 0; i<n; i++) {
1852 copy[i] = a->data[i];
1856 * base indicates the index of the most significant
1857 * byte that might be nonzero. When it goes off the
1858 * end, we now there is nothing left to do.
1864 for (i = base; i<n; i++ ) {
1865 copy[i] += carry*256;
1866 carry = copy[i] % 10;
1871 * Way too large, we need to leave
1872 * room for sign if negative
1877 *--p = digit[carry];
1879 if (copy[base] == 0) base++;
1884 if ( a->type == V_ASN1_NEG_INTEGER ) {
1888 return ber_str2bv( p, 0, 1, bv );
1892 * Given a certificate in DER format, extract the corresponding
1893 * assertion value for certificateExactMatch
1896 certificateExactConvert(
1898 struct berval * out )
1901 unsigned char *p = in->bv_val;
1902 struct berval serial;
1903 struct berval issuer_dn;
1905 xcert = d2i_X509(NULL, &p, in->bv_len);
1908 LDAP_LOG( CONFIG, ENTRY,
1909 "certificateExactConvert: error parsing cert: %s\n",
1910 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
1912 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
1913 "error parsing cert: %s\n",
1914 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
1916 return LDAP_INVALID_SYNTAX;
1919 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
1921 return LDAP_INVALID_SYNTAX;
1923 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
1927 ber_memfree(serial.bv_val);
1928 return LDAP_INVALID_SYNTAX;
1933 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
1934 out->bv_val = ch_malloc(out->bv_len);
1936 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
1938 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
1940 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
1941 p += issuer_dn.bv_len;
1945 LDAP_LOG( CONFIG, ARGS,
1946 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
1948 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
1950 out->bv_val, NULL, NULL );
1953 ber_memfree(serial.bv_val);
1954 ber_memfree(issuer_dn.bv_val);
1956 return LDAP_SUCCESS;
1960 serial_and_issuer_parse(
1961 struct berval *assertion,
1962 struct berval *serial,
1963 struct berval *issuer_dn )
1970 begin = assertion->bv_val;
1971 end = assertion->bv_val+assertion->bv_len-1;
1972 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
1973 if ( p > end ) return LDAP_INVALID_SYNTAX;
1975 /* p now points at the $ sign, now use
1976 * begin and end to delimit the serial number
1978 while (ASCII_SPACE(*begin)) begin++;
1980 while (ASCII_SPACE(*end)) end--;
1982 if( end <= begin ) return LDAP_INVALID_SYNTAX;
1984 bv.bv_len = end-begin+1;
1986 ber_dupbv(serial, &bv);
1988 /* now extract the issuer, remember p was at the dollar sign */
1990 end = assertion->bv_val+assertion->bv_len-1;
1991 while (ASCII_SPACE(*begin)) begin++;
1992 /* should we trim spaces at the end too? is it safe always? no, no */
1994 if( end <= begin ) return LDAP_INVALID_SYNTAX;
1997 bv.bv_len = end-begin+1;
2000 return dnNormalize( 0, NULL, NULL, &bv, issuer_dn );
2003 return LDAP_SUCCESS;
2007 certificateExactMatch(
2012 struct berval *value,
2013 void *assertedValue )
2016 unsigned char *p = value->bv_val;
2017 struct berval serial;
2018 struct berval issuer_dn;
2019 struct berval asserted_serial;
2020 struct berval asserted_issuer_dn;
2023 xcert = d2i_X509(NULL, &p, value->bv_len);
2026 LDAP_LOG( CONFIG, ENTRY,
2027 "certificateExactMatch: error parsing cert: %s\n",
2028 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2030 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2031 "error parsing cert: %s\n",
2032 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2034 return LDAP_INVALID_SYNTAX;
2037 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2038 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2042 serial_and_issuer_parse(assertedValue,
2043 &asserted_serial, &asserted_issuer_dn);
2048 slap_schema.si_syn_integer,
2049 slap_schema.si_mr_integerMatch,
2052 if ( ret == LDAP_SUCCESS ) {
2053 if ( *matchp == 0 ) {
2054 /* We need to normalize everything for dnMatch */
2058 slap_schema.si_syn_distinguishedName,
2059 slap_schema.si_mr_distinguishedNameMatch,
2061 &asserted_issuer_dn);
2066 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2067 "%d\n\t\"%s $ %s\"\n",
2068 *matchp, serial.bv_val, issuer_dn.bv_val );
2069 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2070 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2073 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2074 "%d\n\t\"%s $ %s\"\n",
2075 *matchp, serial.bv_val, issuer_dn.bv_val );
2076 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2077 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2081 ber_memfree(serial.bv_val);
2082 ber_memfree(issuer_dn.bv_val);
2083 ber_memfree(asserted_serial.bv_val);
2084 ber_memfree(asserted_issuer_dn.bv_val);
2090 * Index generation function
2091 * We just index the serials, in most scenarios the issuer DN is one of
2092 * a very small set of values.
2094 static int certificateExactIndexer(
2099 struct berval *prefix,
2107 struct berval serial;
2109 /* we should have at least one value at this point */
2110 assert( values != NULL && values[0].bv_val != NULL );
2112 for( i=0; values[i].bv_val != NULL; i++ ) {
2113 /* empty -- just count them */
2116 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2118 for( i=0; values[i].bv_val != NULL; i++ ) {
2119 p = values[i].bv_val;
2120 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2123 LDAP_LOG( CONFIG, ENTRY,
2124 "certificateExactIndexer: error parsing cert: %s\n",
2125 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2127 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2128 "error parsing cert: %s\n",
2129 ERR_error_string(ERR_get_error(),NULL),
2132 /* Do we leak keys on error? */
2133 return LDAP_INVALID_SYNTAX;
2136 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2138 xintegerNormalize( slap_schema.si_syn_integer,
2139 &serial, &keys[i] );
2140 ber_memfree(serial.bv_val);
2142 LDAP_LOG( CONFIG, ENTRY,
2143 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2145 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2152 keys[i].bv_val = NULL;
2154 return LDAP_SUCCESS;
2157 /* Index generation function */
2158 /* We think this is always called with a value in matching rule syntax */
2159 static int certificateExactFilter(
2164 struct berval *prefix,
2165 void * assertedValue,
2169 struct berval asserted_serial;
2172 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2173 if( ret != LDAP_SUCCESS ) return ret;
2175 keys = ch_malloc( sizeof( struct berval ) * 2 );
2176 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2177 keys[1].bv_val = NULL;
2180 ber_memfree(asserted_serial.bv_val);
2181 return LDAP_SUCCESS;
2187 check_time_syntax (struct berval *val,
2191 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2192 static int mdays[2][12] = {
2193 /* non-leap years */
2194 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2196 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2199 int part, c, tzoffset, leapyear = 0 ;
2201 if( val->bv_len == 0 ) {
2202 return LDAP_INVALID_SYNTAX;
2205 p = (char *)val->bv_val;
2206 e = p + val->bv_len;
2208 /* Ignore initial whitespace */
2209 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2213 if (e - p < 13 - (2 * start)) {
2214 return LDAP_INVALID_SYNTAX;
2217 for (part = 0; part < 9; part++) {
2221 for (part = start; part < 7; part++) {
2223 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2230 return LDAP_INVALID_SYNTAX;
2232 if (c < 0 || c > 9) {
2233 return LDAP_INVALID_SYNTAX;
2239 return LDAP_INVALID_SYNTAX;
2241 if (c < 0 || c > 9) {
2242 return LDAP_INVALID_SYNTAX;
2247 if (part == 2 || part == 3) {
2250 if (parts[part] < 0) {
2251 return LDAP_INVALID_SYNTAX;
2253 if (parts[part] > ceiling[part]) {
2254 return LDAP_INVALID_SYNTAX;
2258 /* leapyear check for the Gregorian calendar (year>1581) */
2259 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2260 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2265 if (parts[3] > mdays[leapyear][parts[2]]) {
2266 return LDAP_INVALID_SYNTAX;
2271 tzoffset = 0; /* UTC */
2272 } else if (c != '+' && c != '-') {
2273 return LDAP_INVALID_SYNTAX;
2277 } else /* c == '+' */ {
2282 return LDAP_INVALID_SYNTAX;
2285 for (part = 7; part < 9; part++) {
2287 if (c < 0 || c > 9) {
2288 return LDAP_INVALID_SYNTAX;
2293 if (c < 0 || c > 9) {
2294 return LDAP_INVALID_SYNTAX;
2298 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2299 return LDAP_INVALID_SYNTAX;
2304 /* Ignore trailing whitespace */
2305 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2309 return LDAP_INVALID_SYNTAX;
2312 switch ( tzoffset ) {
2313 case -1: /* negativ offset to UTC, ie west of Greenwich */
2314 parts[4] += parts[7];
2315 parts[5] += parts[8];
2316 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2320 c = mdays[leapyear][parts[2]];
2322 if (parts[part] > c) {
2323 parts[part] -= c + 1;
2328 case 1: /* positive offset to UTC, ie east of Greenwich */
2329 parts[4] -= parts[7];
2330 parts[5] -= parts[8];
2331 for (part = 6; --part > 0; ) {
2335 /* first arg to % needs to be non negativ */
2336 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2338 if (parts[part] < 0) {
2339 parts[part] += c + 1;
2344 case 0: /* already UTC */
2348 return LDAP_SUCCESS;
2351 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2356 struct berval *normalized )
2360 rc = check_time_syntax(val, 1, parts);
2361 if (rc != LDAP_SUCCESS) {
2365 normalized->bv_val = ch_malloc( 14 );
2366 if ( normalized->bv_val == NULL ) {
2367 return LBER_ERROR_MEMORY;
2370 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2371 parts[1], parts[2] + 1, parts[3] + 1,
2372 parts[4], parts[5], parts[6] );
2373 normalized->bv_len = 13;
2375 return LDAP_SUCCESS;
2384 return check_time_syntax(in, 1, parts);
2389 generalizedTimeValidate(
2394 return check_time_syntax(in, 0, parts);
2398 generalizedTimeNormalize(
2403 struct berval *normalized,
2408 rc = check_time_syntax(val, 0, parts);
2409 if (rc != LDAP_SUCCESS) {
2413 normalized->bv_val = sl_malloc( 16, ctx );
2414 if ( normalized->bv_val == NULL ) {
2415 return LBER_ERROR_MEMORY;
2418 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2419 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2420 parts[4], parts[5], parts[6] );
2421 normalized->bv_len = 15;
2423 return LDAP_SUCCESS;
2427 nisNetgroupTripleValidate(
2429 struct berval *val )
2434 if ( val->bv_len == 0 ) {
2435 return LDAP_INVALID_SYNTAX;
2438 p = (char *)val->bv_val;
2439 e = p + val->bv_len;
2441 if ( *p != '(' /*')'*/ ) {
2442 return LDAP_INVALID_SYNTAX;
2445 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2449 return LDAP_INVALID_SYNTAX;
2452 } else if ( !AD_CHAR( *p ) ) {
2453 return LDAP_INVALID_SYNTAX;
2457 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2458 return LDAP_INVALID_SYNTAX;
2464 return LDAP_INVALID_SYNTAX;
2467 return LDAP_SUCCESS;
2471 bootParameterValidate(
2473 struct berval *val )
2477 if ( val->bv_len == 0 ) {
2478 return LDAP_INVALID_SYNTAX;
2481 p = (char *)val->bv_val;
2482 e = p + val->bv_len;
2485 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2486 if ( !AD_CHAR( *p ) ) {
2487 return LDAP_INVALID_SYNTAX;
2492 return LDAP_INVALID_SYNTAX;
2496 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2497 if ( !AD_CHAR( *p ) ) {
2498 return LDAP_INVALID_SYNTAX;
2503 return LDAP_INVALID_SYNTAX;
2507 for ( p++; p < e; p++ ) {
2508 if ( !SLAP_PRINTABLE( *p ) ) {
2509 return LDAP_INVALID_SYNTAX;
2513 return LDAP_SUCCESS;
2517 firstComponentNormalize(
2522 struct berval *normalized,
2529 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2531 if( val->bv_val[0] != '(' /*')'*/ &&
2532 val->bv_val[0] != '{' /*'}'*/ )
2534 return LDAP_INVALID_SYNTAX;
2537 /* trim leading white space */
2539 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2545 /* grab next word */
2546 oid.bv_val = &val->bv_val[len];
2547 len = val->bv_len - len;
2549 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2555 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2556 rc = numericoidValidate( NULL, &oid );
2557 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2558 rc = integerValidate( NULL, &oid );
2560 rc = LDAP_INVALID_SYNTAX;
2564 if( rc == LDAP_SUCCESS ) {
2565 ber_dupbv_x( normalized, &oid, ctx );
2571 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2572 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2574 static slap_syntax_defs_rec syntax_defs[] = {
2575 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2576 X_BINARY X_NOT_H_R ")",
2577 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2578 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2580 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2582 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2584 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2585 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2587 SLAP_SYNTAX_BER, berValidate, NULL},
2588 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2589 0, bitStringValidate, NULL },
2590 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2591 0, booleanValidate, NULL},
2592 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2593 X_BINARY X_NOT_H_R ")",
2594 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2595 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2596 X_BINARY X_NOT_H_R ")",
2597 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2598 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2599 X_BINARY X_NOT_H_R ")",
2600 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2601 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2602 0, countryStringValidate, NULL},
2603 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2604 0, dnValidate, dnPretty},
2605 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2607 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2609 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2610 0, UTF8StringValidate, NULL},
2611 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2613 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2615 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2617 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2619 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2621 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2622 0, printablesStringValidate, NULL},
2623 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2624 SLAP_SYNTAX_BLOB, NULL, NULL},
2625 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2626 0, generalizedTimeValidate, NULL},
2627 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2629 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2630 0, IA5StringValidate, NULL},
2631 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2632 0, integerValidate, NULL},
2633 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2634 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2635 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2637 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2639 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2641 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2643 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2645 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2646 0, nameUIDValidate, NULL},
2647 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2649 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2650 0, numericStringValidate, NULL},
2651 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2653 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2654 0, numericoidValidate, NULL},
2655 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2656 0, IA5StringValidate, NULL},
2657 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2658 0, blobValidate, NULL},
2659 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2660 0, UTF8StringValidate, NULL},
2661 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2663 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2665 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2666 0, printableStringValidate, NULL},
2667 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2668 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2669 0, subtreeSpecificationValidate, NULL},
2670 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
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.50 DESC 'Telephone Number' )",
2674 0, printableStringValidate, NULL},
2675 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2677 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2678 0, printablesStringValidate, NULL},
2679 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2680 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2681 0, utcTimeValidate, NULL},
2683 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2685 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2687 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2689 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2691 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2694 /* RFC 2307 NIS Syntaxes */
2695 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2696 0, nisNetgroupTripleValidate, NULL},
2697 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2698 0, bootParameterValidate, NULL},
2702 /* These OIDs are not published yet, but will be in the next
2703 * I-D for PKIX LDAPv3 schema as have been advanced by David
2704 * Chadwick in private mail.
2706 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2707 0, UTF8StringValidate, NULL},
2710 /* OpenLDAP Experimental Syntaxes */
2711 #ifdef SLAPD_ACI_ENABLED
2712 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2714 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2718 #ifdef SLAPD_AUTHPASSWD
2719 /* needs updating */
2720 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2721 SLAP_SYNTAX_HIDE, NULL, NULL},
2724 /* OpenLDAP Void Syntax */
2725 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2726 SLAP_SYNTAX_HIDE, inValidate, NULL},
2727 {NULL, 0, NULL, NULL}
2731 char *certificateExactMatchSyntaxes[] = {
2732 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2736 char *directoryStringSyntaxes[] = {
2737 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2740 char *integerFirstComponentMatchSyntaxes[] = {
2741 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2742 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2745 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2746 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2747 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2748 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2749 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2750 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2751 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2752 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2753 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2758 * Other matching rules in X.520 that we do not use (yet):
2760 * 2.5.13.9 numericStringOrderingMatch
2761 * 2.5.13.25 uTCTimeMatch
2762 * 2.5.13.26 uTCTimeOrderingMatch
2763 * 2.5.13.31 directoryStringFirstComponentMatch
2764 * 2.5.13.32 wordMatch
2765 * 2.5.13.33 keywordMatch
2766 * 2.5.13.35 certificateMatch
2767 * 2.5.13.36 certificatePairExactMatch
2768 * 2.5.13.37 certificatePairMatch
2769 * 2.5.13.38 certificateListExactMatch
2770 * 2.5.13.39 certificateListMatch
2771 * 2.5.13.40 algorithmIdentifierMatch
2772 * 2.5.13.41 storedPrefixMatch
2773 * 2.5.13.42 attributeCertificateMatch
2774 * 2.5.13.43 readerAndKeyIDMatch
2775 * 2.5.13.44 attributeIntegrityMatch
2777 static slap_mrule_defs_rec mrule_defs[] = {
2779 * EQUALITY matching rules must be listed after associated APPROX
2780 * matching rules. So, we list all APPROX matching rules first.
2782 #ifndef SLAP_NVALUES
2783 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2784 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2785 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2786 NULL, NULL, directoryStringApproxMatch,
2787 directoryStringApproxIndexer, directoryStringApproxFilter,
2790 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2791 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2792 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2793 NULL, NULL, IA5StringApproxMatch,
2794 IA5StringApproxIndexer, IA5StringApproxFilter,
2799 * Other matching rules
2802 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2803 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2804 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2805 NULL, NULL, octetStringMatch,
2806 octetStringIndexer, octetStringFilter,
2809 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2810 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2811 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2812 NULL, dnNormalize, dnMatch,
2813 octetStringIndexer, octetStringFilter,
2816 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2817 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2818 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2819 NULL, UTF8StringNormalize, octetStringMatch,
2820 octetStringIndexer, octetStringFilter,
2821 directoryStringApproxMatchOID },
2823 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2824 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2825 SLAP_MR_ORDERING, directoryStringSyntaxes,
2826 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2828 "caseIgnoreMatch" },
2830 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2831 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2832 SLAP_MR_SUBSTR, NULL,
2833 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2834 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2835 "caseIgnoreMatch" },
2837 {"( 2.5.13.5 NAME 'caseExactMatch' "
2838 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2839 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2840 NULL, UTF8StringNormalize, octetStringMatch,
2841 octetStringIndexer, octetStringFilter,
2842 directoryStringApproxMatchOID },
2844 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2845 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2846 SLAP_MR_ORDERING, directoryStringSyntaxes,
2847 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2851 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2852 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2853 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2854 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2855 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2858 {"( 2.5.13.8 NAME 'numericStringMatch' "
2859 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2860 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2861 NULL, numericStringNormalize, octetStringSubstringsMatch,
2862 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2865 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2866 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2867 SLAP_MR_SUBSTR, NULL,
2868 NULL, numericStringNormalize, octetStringSubstringsMatch,
2869 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2870 "numericStringMatch" },
2872 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2873 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2874 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2875 NULL, NULL, NULL, NULL, NULL, NULL },
2877 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2878 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2879 SLAP_MR_SUBSTR, NULL,
2880 NULL, NULL, NULL, NULL, NULL,
2881 "caseIgnoreListMatch" },
2883 {"( 2.5.13.13 NAME 'booleanMatch' "
2884 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2885 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2886 NULL, NULL, booleanMatch,
2887 octetStringIndexer, octetStringFilter,
2890 {"( 2.5.13.14 NAME 'integerMatch' "
2891 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2892 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2893 NULL, NULL, integerMatch,
2894 octetStringIndexer, octetStringFilter,
2897 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2898 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2899 SLAP_MR_ORDERING, NULL,
2900 NULL, NULL, integerMatch,
2904 {"( 2.5.13.16 NAME 'bitStringMatch' "
2905 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2906 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2907 NULL, NULL, octetStringMatch,
2908 octetStringIndexer, octetStringFilter,
2911 {"( 2.5.13.17 NAME 'octetStringMatch' "
2912 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2913 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2914 NULL, NULL, octetStringMatch,
2915 octetStringIndexer, octetStringFilter,
2918 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2919 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2920 SLAP_MR_ORDERING, NULL,
2921 NULL, NULL, octetStringOrderingMatch,
2923 "octetStringMatch" },
2925 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2926 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2927 SLAP_MR_SUBSTR, NULL,
2928 NULL, NULL, octetStringSubstringsMatch,
2929 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2930 "octetStringMatch" },
2932 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2933 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2934 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2936 telephoneNumberNormalize, octetStringMatch,
2937 octetStringIndexer, octetStringFilter,
2940 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2941 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2942 SLAP_MR_SUBSTR, NULL,
2943 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2944 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2945 "telephoneNumberMatch" },
2947 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2948 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2949 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2950 NULL, NULL, NULL, NULL, NULL, NULL },
2952 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2953 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2954 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2955 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2959 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2960 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2961 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2962 NULL, NULL, NULL, NULL, NULL, NULL },
2964 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2965 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2966 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2967 NULL, generalizedTimeNormalize, octetStringMatch,
2971 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2973 SLAP_MR_ORDERING, NULL,
2974 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
2976 "generalizedTimeMatch" },
2978 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2980 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2981 integerFirstComponentMatchSyntaxes,
2982 NULL, firstComponentNormalize, integerMatch,
2983 octetStringIndexer, octetStringFilter,
2986 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
2987 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2988 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2989 objectIdentifierFirstComponentMatchSyntaxes,
2990 NULL, firstComponentNormalize, octetStringMatch,
2991 octetStringIndexer, octetStringFilter,
2994 #ifndef SLAP_NVALUES
2996 {"( 2.5.13.34 NAME 'certificateExactMatch' "
2997 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
2998 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
2999 certificateExactConvert, NULL, certificateExactMatch,
3000 certificateExactIndexer, certificateExactFilter,
3005 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3006 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3007 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3008 NULL, IA5StringNormalize, octetStringMatch,
3009 octetStringIndexer, octetStringFilter,
3010 IA5StringApproxMatchOID },
3012 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3013 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3014 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3015 NULL, IA5StringNormalize, octetStringMatch,
3016 octetStringIndexer, octetStringFilter,
3017 IA5StringApproxMatchOID },
3019 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3020 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3021 SLAP_MR_SUBSTR, NULL,
3022 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3023 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3024 "caseIgnoreIA5Match" },
3026 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3027 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3028 SLAP_MR_SUBSTR, NULL,
3029 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3030 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3031 "caseExactIA5Match" },
3033 #ifdef SLAPD_AUTHPASSWD
3034 /* needs updating */
3035 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3036 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3037 SLAP_MR_EQUALITY, NULL,
3038 NULL, NULL, authPasswordMatch,
3043 #ifdef SLAPD_ACI_ENABLED
3044 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3045 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3046 SLAP_MR_EQUALITY, NULL,
3047 NULL, NULL, OpenLDAPaciMatch,
3052 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3055 NULL, NULL, integerBitAndMatch,
3059 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3062 NULL, NULL, integerBitOrMatch,
3066 {NULL, SLAP_MR_NONE, NULL,
3067 NULL, NULL, NULL, NULL, NULL,
3072 slap_schema_init( void )
3077 /* we should only be called once (from main) */
3078 assert( schema_init_done == 0 );
3080 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3081 res = register_syntax( &syntax_defs[i] );
3084 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3085 syntax_defs[i].sd_desc );
3090 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3091 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3092 mrule_defs[i].mrd_compat_syntaxes == NULL )
3095 "slap_schema_init: Ignoring unusable matching rule %s\n",
3096 mrule_defs[i].mrd_desc );
3100 res = register_matching_rule( &mrule_defs[i] );
3104 "slap_schema_init: Error registering matching rule %s\n",
3105 mrule_defs[i].mrd_desc );
3110 res = slap_schema_load();
3111 schema_init_done = 1;
3116 schema_destroy( void )