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;
1821 serialNumberAndIssuerValidate(
1825 int rc = LDAP_INVALID_SYNTAX;
1826 struct berval serialNumber, issuer;
1828 serialNumber.bv_val = in->bv_val;
1829 for( serialNumber.bv_len = 0;
1830 serialNumber.bv_len < in->bv_len;
1831 serialNumber.bv_len++ )
1833 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1834 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1835 issuer.bv_len = in->bv_len - (serialNumber.bv_len+1);
1837 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1839 rc = integerValidate( NULL, &serialNumber );
1842 rc = dnValidate( NULL, &issuer );
1851 serialNumberAndIssuerNormalize(
1856 struct berval *normalized,
1859 int rc = LDAP_INVALID_SYNTAX;
1860 struct berval serialNumber, issuer, nissuer;
1862 serialNumber.bv_val = val->bv_val;
1863 for( serialNumber.bv_len = 0;
1864 serialNumber.bv_len < val->bv_len;
1865 serialNumber.bv_len++ )
1867 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1868 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1869 issuer.bv_len = val->bv_len - (serialNumber.bv_len+1);
1871 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1873 rc = dnNormalize( usage, syntax, mr, &issuer, &nissuer, ctx );
1876 normalized->bv_len = serialNumber.bv_len + 1 + nissuer.bv_len;
1877 normalized->bv_val = ch_malloc( normalized->bv_len + 1);
1879 AC_MEMCPY( normalized->bv_val,
1880 serialNumber.bv_val, serialNumber.bv_len );
1881 normalized->bv_val[serialNumber.bv_len] = '$';
1882 AC_MEMCPY( &normalized->bv_val[serialNumber.bv_len+1],
1883 nissuer.bv_val, nissuer.bv_len );
1884 normalized->bv_val[normalized->bv_len] = '\0';
1893 #include <openssl/x509.h>
1894 #include <openssl/err.h>
1897 * Next function returns a string representation of a ASN1_INTEGER.
1898 * It works for unlimited lengths.
1901 static struct berval *
1902 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1906 static char digit[] = "0123456789";
1908 /* We work backwards, make it fill from the end of buf */
1909 p = buf + sizeof(buf) - 1;
1912 if ( a == NULL || a->length == 0 ) {
1920 /* We want to preserve the original */
1921 copy = ch_malloc(n*sizeof(unsigned int));
1922 for (i = 0; i<n; i++) {
1923 copy[i] = a->data[i];
1927 * base indicates the index of the most significant
1928 * byte that might be nonzero. When it goes off the
1929 * end, we now there is nothing left to do.
1935 for (i = base; i<n; i++ ) {
1936 copy[i] += carry*256;
1937 carry = copy[i] % 10;
1942 * Way too large, we need to leave
1943 * room for sign if negative
1948 *--p = digit[carry];
1950 if (copy[base] == 0) base++;
1955 if ( a->type == V_ASN1_NEG_INTEGER ) {
1959 return ber_str2bv( p, 0, 1, bv );
1963 * Given a certificate in DER format, extract the corresponding
1964 * assertion value for certificateExactMatch
1967 certificateExactConvert(
1969 struct berval * out )
1973 unsigned char *p = in->bv_val;
1974 struct berval serial;
1975 struct berval issuer_dn;
1977 xcert = d2i_X509(NULL, &p, in->bv_len);
1980 LDAP_LOG( CONFIG, ENTRY,
1981 "certificateExactConvert: error parsing cert: %s\n",
1982 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
1984 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
1985 "error parsing cert: %s\n",
1986 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
1988 return LDAP_INVALID_SYNTAX;
1991 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
1993 return LDAP_INVALID_SYNTAX;
1996 rc = dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn );
1997 if( rc != LDAP_SUCCESS ) {
1999 ber_memfree(serial.bv_val);
2000 return LDAP_INVALID_SYNTAX;
2005 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2006 out->bv_val = ch_malloc(out->bv_len);
2008 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2010 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2012 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2013 p += issuer_dn.bv_len;
2017 LDAP_LOG( CONFIG, ARGS,
2018 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2020 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2022 out->bv_val, NULL, NULL );
2025 ber_memfree(serial.bv_val);
2026 ber_memfree(issuer_dn.bv_val);
2028 return LDAP_SUCCESS;
2032 certificateExactNormalize(
2037 struct berval *normalized,
2042 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage ) ) {
2043 rc = serialNumberAndIssuerNormalize( usage, syntax, mr,
2044 val, normalized, ctx );
2047 rc = certificateExactConvert( val, normalized );
2052 #endif /* HAVE_TLS */
2056 check_time_syntax (struct berval *val,
2060 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2061 static int mdays[2][12] = {
2062 /* non-leap years */
2063 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2065 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2068 int part, c, tzoffset, leapyear = 0 ;
2070 if( val->bv_len == 0 ) {
2071 return LDAP_INVALID_SYNTAX;
2074 p = (char *)val->bv_val;
2075 e = p + val->bv_len;
2077 /* Ignore initial whitespace */
2078 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2082 if (e - p < 13 - (2 * start)) {
2083 return LDAP_INVALID_SYNTAX;
2086 for (part = 0; part < 9; part++) {
2090 for (part = start; part < 7; part++) {
2092 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2099 return LDAP_INVALID_SYNTAX;
2101 if (c < 0 || c > 9) {
2102 return LDAP_INVALID_SYNTAX;
2108 return LDAP_INVALID_SYNTAX;
2110 if (c < 0 || c > 9) {
2111 return LDAP_INVALID_SYNTAX;
2116 if (part == 2 || part == 3) {
2119 if (parts[part] < 0) {
2120 return LDAP_INVALID_SYNTAX;
2122 if (parts[part] > ceiling[part]) {
2123 return LDAP_INVALID_SYNTAX;
2127 /* leapyear check for the Gregorian calendar (year>1581) */
2128 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2129 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2134 if (parts[3] > mdays[leapyear][parts[2]]) {
2135 return LDAP_INVALID_SYNTAX;
2140 tzoffset = 0; /* UTC */
2141 } else if (c != '+' && c != '-') {
2142 return LDAP_INVALID_SYNTAX;
2146 } else /* c == '+' */ {
2151 return LDAP_INVALID_SYNTAX;
2154 for (part = 7; part < 9; part++) {
2156 if (c < 0 || c > 9) {
2157 return LDAP_INVALID_SYNTAX;
2162 if (c < 0 || c > 9) {
2163 return LDAP_INVALID_SYNTAX;
2167 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2168 return LDAP_INVALID_SYNTAX;
2173 /* Ignore trailing whitespace */
2174 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2178 return LDAP_INVALID_SYNTAX;
2181 switch ( tzoffset ) {
2182 case -1: /* negativ offset to UTC, ie west of Greenwich */
2183 parts[4] += parts[7];
2184 parts[5] += parts[8];
2185 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2189 c = mdays[leapyear][parts[2]];
2191 if (parts[part] > c) {
2192 parts[part] -= c + 1;
2197 case 1: /* positive offset to UTC, ie east of Greenwich */
2198 parts[4] -= parts[7];
2199 parts[5] -= parts[8];
2200 for (part = 6; --part > 0; ) {
2204 /* first arg to % needs to be non negativ */
2205 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2207 if (parts[part] < 0) {
2208 parts[part] += c + 1;
2213 case 0: /* already UTC */
2217 return LDAP_SUCCESS;
2220 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2225 struct berval *normalized )
2229 rc = check_time_syntax(val, 1, parts);
2230 if (rc != LDAP_SUCCESS) {
2234 normalized->bv_val = ch_malloc( 14 );
2235 if ( normalized->bv_val == NULL ) {
2236 return LBER_ERROR_MEMORY;
2239 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2240 parts[1], parts[2] + 1, parts[3] + 1,
2241 parts[4], parts[5], parts[6] );
2242 normalized->bv_len = 13;
2244 return LDAP_SUCCESS;
2253 return check_time_syntax(in, 1, parts);
2258 generalizedTimeValidate(
2263 return check_time_syntax(in, 0, parts);
2267 generalizedTimeNormalize(
2272 struct berval *normalized,
2277 rc = check_time_syntax(val, 0, parts);
2278 if (rc != LDAP_SUCCESS) {
2282 normalized->bv_val = sl_malloc( 16, ctx );
2283 if ( normalized->bv_val == NULL ) {
2284 return LBER_ERROR_MEMORY;
2287 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2288 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2289 parts[4], parts[5], parts[6] );
2290 normalized->bv_len = 15;
2292 return LDAP_SUCCESS;
2296 nisNetgroupTripleValidate(
2298 struct berval *val )
2303 if ( val->bv_len == 0 ) {
2304 return LDAP_INVALID_SYNTAX;
2307 p = (char *)val->bv_val;
2308 e = p + val->bv_len;
2310 if ( *p != '(' /*')'*/ ) {
2311 return LDAP_INVALID_SYNTAX;
2314 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2318 return LDAP_INVALID_SYNTAX;
2321 } else if ( !AD_CHAR( *p ) ) {
2322 return LDAP_INVALID_SYNTAX;
2326 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2327 return LDAP_INVALID_SYNTAX;
2333 return LDAP_INVALID_SYNTAX;
2336 return LDAP_SUCCESS;
2340 bootParameterValidate(
2342 struct berval *val )
2346 if ( val->bv_len == 0 ) {
2347 return LDAP_INVALID_SYNTAX;
2350 p = (char *)val->bv_val;
2351 e = p + val->bv_len;
2354 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2355 if ( !AD_CHAR( *p ) ) {
2356 return LDAP_INVALID_SYNTAX;
2361 return LDAP_INVALID_SYNTAX;
2365 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2366 if ( !AD_CHAR( *p ) ) {
2367 return LDAP_INVALID_SYNTAX;
2372 return LDAP_INVALID_SYNTAX;
2376 for ( p++; p < e; p++ ) {
2377 if ( !SLAP_PRINTABLE( *p ) ) {
2378 return LDAP_INVALID_SYNTAX;
2382 return LDAP_SUCCESS;
2386 firstComponentNormalize(
2391 struct berval *normalized,
2398 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2400 if( val->bv_val[0] != '(' /*')'*/ &&
2401 val->bv_val[0] != '{' /*'}'*/ )
2403 return LDAP_INVALID_SYNTAX;
2406 /* trim leading white space */
2408 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2414 /* grab next word */
2415 oid.bv_val = &val->bv_val[len];
2416 len = val->bv_len - len;
2418 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2424 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2425 rc = numericoidValidate( NULL, &oid );
2426 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2427 rc = integerValidate( NULL, &oid );
2429 rc = LDAP_INVALID_SYNTAX;
2433 if( rc == LDAP_SUCCESS ) {
2434 ber_dupbv_x( normalized, &oid, ctx );
2440 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2441 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2443 static slap_syntax_defs_rec syntax_defs[] = {
2444 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2445 X_BINARY X_NOT_H_R ")",
2446 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2447 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2449 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2451 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2453 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2454 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2456 SLAP_SYNTAX_BER, berValidate, NULL},
2457 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2458 0, bitStringValidate, NULL },
2459 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2460 0, booleanValidate, NULL},
2461 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2462 X_BINARY X_NOT_H_R ")",
2463 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2464 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2465 X_BINARY X_NOT_H_R ")",
2466 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2467 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2468 X_BINARY X_NOT_H_R ")",
2469 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2470 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2471 0, countryStringValidate, NULL},
2472 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2473 0, dnValidate, dnPretty},
2474 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2476 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2478 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2479 0, UTF8StringValidate, NULL},
2480 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2482 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2484 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2486 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2488 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2490 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2491 0, printablesStringValidate, NULL},
2492 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2493 SLAP_SYNTAX_BLOB, NULL, NULL},
2494 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2495 0, generalizedTimeValidate, NULL},
2496 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2498 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2499 0, IA5StringValidate, NULL},
2500 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2501 0, integerValidate, NULL},
2502 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2503 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2504 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2506 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2508 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2510 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2512 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2514 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2515 0, nameUIDValidate, NULL},
2516 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2518 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2519 0, numericStringValidate, NULL},
2520 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2522 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2523 0, numericoidValidate, NULL},
2524 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2525 0, IA5StringValidate, NULL},
2526 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2527 0, blobValidate, NULL},
2528 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2529 0, UTF8StringValidate, NULL},
2530 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2532 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2534 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2535 0, printableStringValidate, NULL},
2536 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2537 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2538 0, subtreeSpecificationValidate, NULL},
2539 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2540 X_BINARY X_NOT_H_R ")",
2541 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2542 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2543 0, printableStringValidate, NULL},
2544 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2546 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2547 0, printablesStringValidate, NULL},
2548 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2549 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2550 0, utcTimeValidate, NULL},
2552 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2554 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2556 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2558 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2560 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2563 /* RFC 2307 NIS Syntaxes */
2564 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2565 0, nisNetgroupTripleValidate, NULL},
2566 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2567 0, bootParameterValidate, NULL},
2570 /* These OIDs are not published yet, but will be in the next
2571 * I-D for PKIX LDAPv3 schema as have been advanced by David
2572 * Chadwick in private mail.
2574 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2575 0, serialNumberAndIssuerValidate, NULL},
2577 /* OpenLDAP Experimental Syntaxes */
2578 #ifdef SLAPD_ACI_ENABLED
2579 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2581 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2585 #ifdef SLAPD_AUTHPASSWD
2586 /* needs updating */
2587 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2588 SLAP_SYNTAX_HIDE, NULL, NULL},
2591 /* OpenLDAP Void Syntax */
2592 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2593 SLAP_SYNTAX_HIDE, inValidate, NULL},
2594 {NULL, 0, NULL, NULL}
2598 char *certificateExactMatchSyntaxes[] = {
2599 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2603 char *directoryStringSyntaxes[] = {
2604 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2607 char *integerFirstComponentMatchSyntaxes[] = {
2608 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2609 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2612 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2613 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2614 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2615 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2616 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2617 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2618 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2619 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2620 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2625 * Other matching rules in X.520 that we do not use (yet):
2627 * 2.5.13.9 numericStringOrderingMatch
2628 * 2.5.13.25 uTCTimeMatch
2629 * 2.5.13.26 uTCTimeOrderingMatch
2630 * 2.5.13.31 directoryStringFirstComponentMatch
2631 * 2.5.13.32 wordMatch
2632 * 2.5.13.33 keywordMatch
2633 * 2.5.13.35 certificateMatch
2634 * 2.5.13.36 certificatePairExactMatch
2635 * 2.5.13.37 certificatePairMatch
2636 * 2.5.13.38 certificateListExactMatch
2637 * 2.5.13.39 certificateListMatch
2638 * 2.5.13.40 algorithmIdentifierMatch
2639 * 2.5.13.41 storedPrefixMatch
2640 * 2.5.13.42 attributeCertificateMatch
2641 * 2.5.13.43 readerAndKeyIDMatch
2642 * 2.5.13.44 attributeIntegrityMatch
2644 static slap_mrule_defs_rec mrule_defs[] = {
2646 * EQUALITY matching rules must be listed after associated APPROX
2647 * matching rules. So, we list all APPROX matching rules first.
2649 #ifndef SLAP_NVALUES
2650 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2651 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2652 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2653 NULL, NULL, directoryStringApproxMatch,
2654 directoryStringApproxIndexer, directoryStringApproxFilter,
2657 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2658 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2659 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2660 NULL, NULL, IA5StringApproxMatch,
2661 IA5StringApproxIndexer, IA5StringApproxFilter,
2666 * Other matching rules
2669 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2670 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2671 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2672 NULL, NULL, octetStringMatch,
2673 octetStringIndexer, octetStringFilter,
2676 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2677 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2678 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2679 NULL, dnNormalize, dnMatch,
2680 octetStringIndexer, octetStringFilter,
2683 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2684 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2685 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2686 NULL, UTF8StringNormalize, octetStringMatch,
2687 octetStringIndexer, octetStringFilter,
2688 directoryStringApproxMatchOID },
2690 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2691 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2692 SLAP_MR_ORDERING, directoryStringSyntaxes,
2693 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2695 "caseIgnoreMatch" },
2697 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2698 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2699 SLAP_MR_SUBSTR, NULL,
2700 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2701 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2702 "caseIgnoreMatch" },
2704 {"( 2.5.13.5 NAME 'caseExactMatch' "
2705 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2706 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2707 NULL, UTF8StringNormalize, octetStringMatch,
2708 octetStringIndexer, octetStringFilter,
2709 directoryStringApproxMatchOID },
2711 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2712 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2713 SLAP_MR_ORDERING, directoryStringSyntaxes,
2714 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2718 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2719 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2720 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2721 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2722 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2725 {"( 2.5.13.8 NAME 'numericStringMatch' "
2726 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2727 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2728 NULL, numericStringNormalize, octetStringSubstringsMatch,
2729 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2732 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2733 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2734 SLAP_MR_SUBSTR, NULL,
2735 NULL, numericStringNormalize, octetStringSubstringsMatch,
2736 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2737 "numericStringMatch" },
2739 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2740 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2741 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2742 NULL, NULL, NULL, NULL, NULL, NULL },
2744 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2745 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2746 SLAP_MR_SUBSTR, NULL,
2747 NULL, NULL, NULL, NULL, NULL,
2748 "caseIgnoreListMatch" },
2750 {"( 2.5.13.13 NAME 'booleanMatch' "
2751 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2752 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2753 NULL, NULL, booleanMatch,
2754 octetStringIndexer, octetStringFilter,
2757 {"( 2.5.13.14 NAME 'integerMatch' "
2758 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2759 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2760 NULL, NULL, integerMatch,
2761 octetStringIndexer, octetStringFilter,
2764 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2765 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2766 SLAP_MR_ORDERING, NULL,
2767 NULL, NULL, integerMatch,
2771 {"( 2.5.13.16 NAME 'bitStringMatch' "
2772 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2773 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2774 NULL, NULL, octetStringMatch,
2775 octetStringIndexer, octetStringFilter,
2778 {"( 2.5.13.17 NAME 'octetStringMatch' "
2779 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2780 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2781 NULL, NULL, octetStringMatch,
2782 octetStringIndexer, octetStringFilter,
2785 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2786 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2787 SLAP_MR_ORDERING, NULL,
2788 NULL, NULL, octetStringOrderingMatch,
2790 "octetStringMatch" },
2792 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2793 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2794 SLAP_MR_SUBSTR, NULL,
2795 NULL, NULL, octetStringSubstringsMatch,
2796 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2797 "octetStringMatch" },
2799 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2800 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2801 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2803 telephoneNumberNormalize, octetStringMatch,
2804 octetStringIndexer, octetStringFilter,
2807 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2809 SLAP_MR_SUBSTR, NULL,
2810 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2811 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2812 "telephoneNumberMatch" },
2814 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2816 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2817 NULL, NULL, NULL, NULL, NULL, NULL },
2819 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2820 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2821 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2822 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2826 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2827 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2828 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2829 NULL, NULL, NULL, NULL, NULL, NULL },
2831 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2832 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2833 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2834 NULL, generalizedTimeNormalize, octetStringMatch,
2838 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2839 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2840 SLAP_MR_ORDERING, NULL,
2841 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
2843 "generalizedTimeMatch" },
2845 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
2846 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2847 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2848 integerFirstComponentMatchSyntaxes,
2849 NULL, firstComponentNormalize, integerMatch,
2850 octetStringIndexer, octetStringFilter,
2853 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
2854 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2855 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2856 objectIdentifierFirstComponentMatchSyntaxes,
2857 NULL, firstComponentNormalize, octetStringMatch,
2858 octetStringIndexer, octetStringFilter,
2862 {"( 2.5.13.34 NAME 'certificateExactMatch' "
2863 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
2864 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
2865 NULL, certificateExactNormalize, octetStringMatch,
2866 octetStringIndexer, octetStringFilter,
2870 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
2871 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2872 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2873 NULL, IA5StringNormalize, octetStringMatch,
2874 octetStringIndexer, octetStringFilter,
2875 IA5StringApproxMatchOID },
2877 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
2878 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2879 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2880 NULL, IA5StringNormalize, octetStringMatch,
2881 octetStringIndexer, octetStringFilter,
2882 IA5StringApproxMatchOID },
2884 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
2885 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2886 SLAP_MR_SUBSTR, NULL,
2887 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2888 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2889 "caseIgnoreIA5Match" },
2891 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
2892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2893 SLAP_MR_SUBSTR, NULL,
2894 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2895 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2896 "caseExactIA5Match" },
2898 #ifdef SLAPD_AUTHPASSWD
2899 /* needs updating */
2900 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
2901 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2902 SLAP_MR_EQUALITY, NULL,
2903 NULL, NULL, authPasswordMatch,
2908 #ifdef SLAPD_ACI_ENABLED
2909 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
2910 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
2911 SLAP_MR_EQUALITY, NULL,
2912 NULL, NULL, OpenLDAPaciMatch,
2917 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
2918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2920 NULL, NULL, integerBitAndMatch,
2924 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
2925 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2927 NULL, NULL, integerBitOrMatch,
2931 {NULL, SLAP_MR_NONE, NULL,
2932 NULL, NULL, NULL, NULL, NULL,
2937 slap_schema_init( void )
2942 /* we should only be called once (from main) */
2943 assert( schema_init_done == 0 );
2945 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
2946 res = register_syntax( &syntax_defs[i] );
2949 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
2950 syntax_defs[i].sd_desc );
2955 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
2956 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
2957 mrule_defs[i].mrd_compat_syntaxes == NULL )
2960 "slap_schema_init: Ignoring unusable matching rule %s\n",
2961 mrule_defs[i].mrd_desc );
2965 res = register_matching_rule( &mrule_defs[i] );
2969 "slap_schema_init: Error registering matching rule %s\n",
2970 mrule_defs[i].mrd_desc );
2975 res = slap_schema_load();
2976 schema_init_done = 1;
2981 schema_destroy( void )