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 /* not yet implemented */
32 #define uniqueMemberMatch NULL
34 #define OpenLDAPaciMatch NULL
36 /* approx matching rules */
37 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
38 #define directoryStringApproxMatch approxMatch
39 #define directoryStringApproxIndexer approxIndexer
40 #define directoryStringApproxFilter approxFilter
41 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
42 #define IA5StringApproxMatch approxMatch
43 #define IA5StringApproxIndexer approxIndexer
44 #define IA5StringApproxFilter approxFilter
51 /* no value allowed */
52 return LDAP_INVALID_SYNTAX;
60 /* any value allowed */
64 #define berValidate blobValidate
75 struct berval *asserted = (struct berval *) assertedValue;
76 int match = value->bv_len - asserted->bv_len;
79 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
87 octetStringOrderingMatch(
95 struct berval *asserted = (struct berval *) assertedValue;
96 ber_len_t v_len = value->bv_len;
97 ber_len_t av_len = asserted->bv_len;
99 int match = memcmp( value->bv_val, asserted->bv_val,
100 (v_len < av_len ? v_len : av_len) );
102 if( match == 0 ) match = v_len - av_len;
108 /* Index generation function */
109 int octetStringIndexer(
114 struct berval *prefix,
122 HASH_CONTEXT HASHcontext;
123 unsigned char HASHdigest[HASH_BYTES];
124 struct berval digest;
125 digest.bv_val = HASHdigest;
126 digest.bv_len = sizeof(HASHdigest);
128 for( i=0; values[i].bv_val != NULL; i++ ) {
129 /* just count them */
132 /* we should have at least one value at this point */
135 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
137 slen = syntax->ssyn_oidlen;
138 mlen = mr->smr_oidlen;
140 for( i=0; values[i].bv_val != NULL; i++ ) {
141 HASH_Init( &HASHcontext );
142 if( prefix != NULL && prefix->bv_len > 0 ) {
143 HASH_Update( &HASHcontext,
144 prefix->bv_val, prefix->bv_len );
146 HASH_Update( &HASHcontext,
147 syntax->ssyn_oid, slen );
148 HASH_Update( &HASHcontext,
150 HASH_Update( &HASHcontext,
151 values[i].bv_val, values[i].bv_len );
152 HASH_Final( HASHdigest, &HASHcontext );
154 ber_dupbv_x( &keys[i], &digest, ctx );
157 keys[i].bv_val = NULL;
165 /* Index generation function */
166 int octetStringFilter(
171 struct berval *prefix,
172 void * assertedValue,
178 HASH_CONTEXT HASHcontext;
179 unsigned char HASHdigest[HASH_BYTES];
180 struct berval *value = (struct berval *) assertedValue;
181 struct berval digest;
182 digest.bv_val = HASHdigest;
183 digest.bv_len = sizeof(HASHdigest);
185 slen = syntax->ssyn_oidlen;
186 mlen = mr->smr_oidlen;
188 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
190 HASH_Init( &HASHcontext );
191 if( prefix != NULL && prefix->bv_len > 0 ) {
192 HASH_Update( &HASHcontext,
193 prefix->bv_val, prefix->bv_len );
195 HASH_Update( &HASHcontext,
196 syntax->ssyn_oid, slen );
197 HASH_Update( &HASHcontext,
199 HASH_Update( &HASHcontext,
200 value->bv_val, value->bv_len );
201 HASH_Final( HASHdigest, &HASHcontext );
203 ber_dupbv_x( keys, &digest, ctx );
204 keys[1].bv_val = NULL;
213 octetStringSubstringsMatch(
218 struct berval *value,
219 void *assertedValue )
222 SubstringsAssertion *sub = assertedValue;
223 struct berval left = *value;
227 /* Add up asserted input length */
228 if( sub->sa_initial.bv_val ) {
229 inlen += sub->sa_initial.bv_len;
232 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
233 inlen += sub->sa_any[i].bv_len;
236 if( sub->sa_final.bv_val ) {
237 inlen += sub->sa_final.bv_len;
240 if( sub->sa_initial.bv_val ) {
241 if( inlen > left.bv_len ) {
246 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
247 sub->sa_initial.bv_len );
253 left.bv_val += sub->sa_initial.bv_len;
254 left.bv_len -= sub->sa_initial.bv_len;
255 inlen -= sub->sa_initial.bv_len;
258 if( sub->sa_final.bv_val ) {
259 if( inlen > left.bv_len ) {
264 match = memcmp( sub->sa_final.bv_val,
265 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
266 sub->sa_final.bv_len );
272 left.bv_len -= sub->sa_final.bv_len;
273 inlen -= sub->sa_final.bv_len;
277 for(i=0; sub->sa_any[i].bv_val; i++) {
282 if( inlen > left.bv_len ) {
283 /* not enough length */
288 if( sub->sa_any[i].bv_len == 0 ) {
292 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
299 idx = p - left.bv_val;
301 if( idx >= left.bv_len ) {
302 /* this shouldn't happen */
309 if( sub->sa_any[i].bv_len > left.bv_len ) {
310 /* not enough left */
315 match = memcmp( left.bv_val,
316 sub->sa_any[i].bv_val,
317 sub->sa_any[i].bv_len );
325 left.bv_val += sub->sa_any[i].bv_len;
326 left.bv_len -= sub->sa_any[i].bv_len;
327 inlen -= sub->sa_any[i].bv_len;
336 /* Substrings Index generation function */
338 octetStringSubstringsIndexer(
343 struct berval *prefix,
348 ber_len_t i, j, nkeys;
352 HASH_CONTEXT HASHcontext;
353 unsigned char HASHdigest[HASH_BYTES];
354 struct berval digest;
355 digest.bv_val = HASHdigest;
356 digest.bv_len = sizeof(HASHdigest);
360 for( i=0; values[i].bv_val != NULL; i++ ) {
361 /* count number of indices to generate */
362 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
366 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
367 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
368 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
369 (SLAP_INDEX_SUBSTR_MINLEN - 1);
371 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
375 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
376 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
377 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
381 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
382 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
383 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
384 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
386 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
392 /* no keys to generate */
397 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
399 slen = syntax->ssyn_oidlen;
400 mlen = mr->smr_oidlen;
403 for( i=0; values[i].bv_val != NULL; i++ ) {
406 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
408 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
409 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
411 char pre = SLAP_INDEX_SUBSTR_PREFIX;
412 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
414 for( j=0; j<max; j++ ) {
415 HASH_Init( &HASHcontext );
416 if( prefix != NULL && prefix->bv_len > 0 ) {
417 HASH_Update( &HASHcontext,
418 prefix->bv_val, prefix->bv_len );
421 HASH_Update( &HASHcontext,
422 &pre, sizeof( pre ) );
423 HASH_Update( &HASHcontext,
424 syntax->ssyn_oid, slen );
425 HASH_Update( &HASHcontext,
427 HASH_Update( &HASHcontext,
428 &values[i].bv_val[j],
429 SLAP_INDEX_SUBSTR_MAXLEN );
430 HASH_Final( HASHdigest, &HASHcontext );
432 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
436 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
437 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
439 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
442 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
443 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
444 HASH_Init( &HASHcontext );
445 if( prefix != NULL && prefix->bv_len > 0 ) {
446 HASH_Update( &HASHcontext,
447 prefix->bv_val, prefix->bv_len );
449 HASH_Update( &HASHcontext,
450 &pre, sizeof( pre ) );
451 HASH_Update( &HASHcontext,
452 syntax->ssyn_oid, slen );
453 HASH_Update( &HASHcontext,
455 HASH_Update( &HASHcontext,
456 values[i].bv_val, j );
457 HASH_Final( HASHdigest, &HASHcontext );
459 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
462 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
463 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
464 HASH_Init( &HASHcontext );
465 if( prefix != NULL && prefix->bv_len > 0 ) {
466 HASH_Update( &HASHcontext,
467 prefix->bv_val, prefix->bv_len );
469 HASH_Update( &HASHcontext,
470 &pre, sizeof( pre ) );
471 HASH_Update( &HASHcontext,
472 syntax->ssyn_oid, slen );
473 HASH_Update( &HASHcontext,
475 HASH_Update( &HASHcontext,
476 &values[i].bv_val[values[i].bv_len-j], j );
477 HASH_Final( HASHdigest, &HASHcontext );
479 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
487 keys[nkeys].bv_val = NULL;
498 octetStringSubstringsFilter (
503 struct berval *prefix,
504 void * assertedValue,
508 SubstringsAssertion *sa;
511 size_t slen, mlen, klen;
513 HASH_CONTEXT HASHcontext;
514 unsigned char HASHdigest[HASH_BYTES];
515 struct berval *value;
516 struct berval digest;
518 sa = (SubstringsAssertion *) assertedValue;
520 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
521 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
526 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
528 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
529 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
530 /* don't bother accounting for stepping */
531 nkeys += sa->sa_any[i].bv_len -
532 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
537 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
538 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
548 digest.bv_val = HASHdigest;
549 digest.bv_len = sizeof(HASHdigest);
551 slen = syntax->ssyn_oidlen;
552 mlen = mr->smr_oidlen;
554 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
557 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
558 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
560 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
561 value = &sa->sa_initial;
563 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
564 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
566 HASH_Init( &HASHcontext );
567 if( prefix != NULL && prefix->bv_len > 0 ) {
568 HASH_Update( &HASHcontext,
569 prefix->bv_val, prefix->bv_len );
571 HASH_Update( &HASHcontext,
572 &pre, sizeof( pre ) );
573 HASH_Update( &HASHcontext,
574 syntax->ssyn_oid, slen );
575 HASH_Update( &HASHcontext,
577 HASH_Update( &HASHcontext,
578 value->bv_val, klen );
579 HASH_Final( HASHdigest, &HASHcontext );
581 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
584 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
586 pre = SLAP_INDEX_SUBSTR_PREFIX;
587 klen = SLAP_INDEX_SUBSTR_MAXLEN;
589 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
590 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
594 value = &sa->sa_any[i];
597 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
598 j += SLAP_INDEX_SUBSTR_STEP )
600 HASH_Init( &HASHcontext );
601 if( prefix != NULL && prefix->bv_len > 0 ) {
602 HASH_Update( &HASHcontext,
603 prefix->bv_val, prefix->bv_len );
605 HASH_Update( &HASHcontext,
606 &pre, sizeof( pre ) );
607 HASH_Update( &HASHcontext,
608 syntax->ssyn_oid, slen );
609 HASH_Update( &HASHcontext,
611 HASH_Update( &HASHcontext,
612 &value->bv_val[j], klen );
613 HASH_Final( HASHdigest, &HASHcontext );
615 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
620 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
621 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
623 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
624 value = &sa->sa_final;
626 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
627 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
629 HASH_Init( &HASHcontext );
630 if( prefix != NULL && prefix->bv_len > 0 ) {
631 HASH_Update( &HASHcontext,
632 prefix->bv_val, prefix->bv_len );
634 HASH_Update( &HASHcontext,
635 &pre, sizeof( pre ) );
636 HASH_Update( &HASHcontext,
637 syntax->ssyn_oid, slen );
638 HASH_Update( &HASHcontext,
640 HASH_Update( &HASHcontext,
641 &value->bv_val[value->bv_len-klen], klen );
642 HASH_Final( HASHdigest, &HASHcontext );
644 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
648 keys[nkeys].bv_val = NULL;
665 /* very unforgiving validation, requires no normalization
666 * before simplistic matching
668 if( in->bv_len < 3 ) {
669 return LDAP_INVALID_SYNTAX;
673 * RFC 2252 section 6.3 Bit String
674 * bitstring = "'" *binary-digit "'B"
675 * binary-digit = "0" / "1"
676 * example: '0101111101'B
679 if( in->bv_val[0] != '\'' ||
680 in->bv_val[in->bv_len-2] != '\'' ||
681 in->bv_val[in->bv_len-1] != 'B' )
683 return LDAP_INVALID_SYNTAX;
686 for( i=in->bv_len-3; i>0; i-- ) {
687 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
688 return LDAP_INVALID_SYNTAX;
703 if( in->bv_len == 0 ) return LDAP_SUCCESS;
705 ber_dupbv( &dn, in );
706 if( !dn.bv_val ) return LDAP_OTHER;
708 if( dn.bv_val[dn.bv_len-1] == 'B'
709 && dn.bv_val[dn.bv_len-2] == '\'' )
711 /* assume presence of optional UID */
714 for(i=dn.bv_len-3; i>1; i--) {
715 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
719 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
720 ber_memfree( dn.bv_val );
721 return LDAP_INVALID_SYNTAX;
724 /* trim the UID to allow use of dnValidate */
725 dn.bv_val[i-1] = '\0';
729 rc = dnValidate( NULL, &dn );
731 ber_memfree( dn.bv_val );
736 uniqueMemberNormalize(
741 struct berval *normalized,
747 ber_dupbv( &out, val );
748 if( out.bv_len != 0 ) {
749 struct berval uid = { 0, NULL };
751 if( out.bv_val[out.bv_len-1] == 'B'
752 && out.bv_val[out.bv_len-2] == '\'' )
754 /* assume presence of optional UID */
755 uid.bv_val = strrchr( out.bv_val, '#' );
757 if( uid.bv_val == NULL ) {
759 return LDAP_INVALID_SYNTAX;
762 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
763 out.bv_len -= uid.bv_len--;
765 /* temporarily trim the UID */
766 *(uid.bv_val++) = '\0';
769 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
771 if( rc != LDAP_SUCCESS ) {
773 return LDAP_INVALID_SYNTAX;
777 normalized->bv_val = ch_realloc( normalized->bv_val,
778 normalized->bv_len + uid.bv_len + sizeof("#") );
780 /* insert the separator */
781 normalized->bv_val[normalized->bv_len++] = '#';
784 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
785 uid.bv_val, uid.bv_len );
786 normalized->bv_len += uid.bv_len;
789 normalized->bv_val[normalized->bv_len] = '\0';
799 * Handling boolean syntax and matching is quite rigid.
800 * A more flexible approach would be to allow a variety
801 * of strings to be normalized and prettied into TRUE
809 /* very unforgiving validation, requires no normalization
810 * before simplistic matching
813 if( in->bv_len == 4 ) {
814 if( bvmatch( in, &slap_true_bv ) ) {
817 } else if( in->bv_len == 5 ) {
818 if( bvmatch( in, &slap_false_bv ) ) {
823 return LDAP_INVALID_SYNTAX;
832 struct berval *value,
833 void *assertedValue )
835 /* simplistic matching allowed by rigid validation */
836 struct berval *asserted = (struct berval *) assertedValue;
837 *matchp = value->bv_len != asserted->bv_len;
841 /*-------------------------------------------------------------------
842 LDAP/X.500 string syntax / matching rules have a few oddities. This
843 comment attempts to detail how slapd(8) treats them.
846 StringSyntax X.500 LDAP Matching/Comments
847 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
848 PrintableString subset subset i/e + ignore insignificant spaces
849 PrintableString subset subset i/e + ignore insignificant spaces
850 NumericString subset subset ignore all spaces
851 IA5String ASCII ASCII i/e + ignore insignificant spaces
852 TeletexString T.61 T.61 i/e + ignore insignificant spaces
854 TelephoneNumber subset subset i + ignore all spaces and "-"
856 See draft-ietf-ldapbis-strpro for details (once published).
860 In X.500(93), a directory string can be either a PrintableString,
861 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
862 In later versions, more CHOICEs were added. In all cases the string
865 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
866 A directory string cannot be zero length.
868 For matching, there are both case ignore and exact rules. Both
869 also require that "insignificant" spaces be ignored.
870 spaces before the first non-space are ignored;
871 spaces after the last non-space are ignored;
872 spaces after a space are ignored.
873 Note: by these rules (and as clarified in X.520), a string of only
874 spaces is to be treated as if held one space, not empty (which
875 would be a syntax error).
878 In ASN.1, numeric string is just a string of digits and spaces
879 and could be empty. However, in X.500, all attribute values of
880 numeric string carry a non-empty constraint. For example:
882 internationalISDNNumber ATTRIBUTE ::= {
883 WITH SYNTAX InternationalISDNNumber
884 EQUALITY MATCHING RULE numericStringMatch
885 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
886 ID id-at-internationalISDNNumber }
887 InternationalISDNNumber ::=
888 NumericString (SIZE(1..ub-international-isdn-number))
890 Unforunately, some assertion values are don't carry the same
891 constraint (but its unclear how such an assertion could ever
892 be true). In LDAP, there is one syntax (numericString) not two
893 (numericString with constraint, numericString without constraint).
894 This should be treated as numericString with non-empty constraint.
895 Note that while someone may have no ISDN number, there are no ISDN
896 numbers which are zero length.
898 In matching, spaces are ignored.
901 In ASN.1, Printable string is just a string of printable characters
902 and can be empty. In X.500, semantics much like NumericString (see
903 serialNumber for a like example) excepting uses insignificant space
904 handling instead of ignore all spaces.
907 Basically same as PrintableString. There are no examples in X.500,
908 but same logic applies. So we require them to be non-empty as
911 -------------------------------------------------------------------*/
920 unsigned char *u = in->bv_val;
922 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
923 /* directory strings cannot be empty */
924 return LDAP_INVALID_SYNTAX;
927 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
928 /* get the length indicated by the first byte */
929 len = LDAP_UTF8_CHARLEN2( u, len );
931 /* very basic checks */
934 if( (u[5] & 0xC0) != 0x80 ) {
935 return LDAP_INVALID_SYNTAX;
938 if( (u[4] & 0xC0) != 0x80 ) {
939 return LDAP_INVALID_SYNTAX;
942 if( (u[3] & 0xC0) != 0x80 ) {
943 return LDAP_INVALID_SYNTAX;
946 if( (u[2] & 0xC0 )!= 0x80 ) {
947 return LDAP_INVALID_SYNTAX;
950 if( (u[1] & 0xC0) != 0x80 ) {
951 return LDAP_INVALID_SYNTAX;
954 /* CHARLEN already validated it */
957 return LDAP_INVALID_SYNTAX;
960 /* make sure len corresponds with the offset
961 to the next character */
962 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
966 return LDAP_INVALID_SYNTAX;
978 struct berval *normalized,
981 struct berval tmp, nvalue;
985 if( val->bv_val == NULL ) {
986 /* assume we're dealing with a syntax (e.g., UTF8String)
987 * which allows empty strings
989 normalized->bv_len = 0;
990 normalized->bv_val = NULL;
994 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
995 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
996 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
997 ? LDAP_UTF8_APPROX : 0;
999 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1004 /* collapse spaces (in place) */
1006 nvalue.bv_val = tmp.bv_val;
1008 wasspace=1; /* trim leading spaces */
1009 for( i=0; i<tmp.bv_len; i++) {
1010 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1011 if( wasspace++ == 0 ) {
1012 /* trim repeated spaces */
1013 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1017 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1021 if( nvalue.bv_len ) {
1023 /* last character was a space, trim it */
1026 nvalue.bv_val[nvalue.bv_len] = '\0';
1029 /* string of all spaces is treated as one space */
1030 nvalue.bv_val[0] = ' ';
1031 nvalue.bv_val[1] = '\0';
1035 *normalized = nvalue;
1036 return LDAP_SUCCESS;
1039 #if defined(SLAPD_APPROX_INITIALS)
1040 # define SLAPD_APPROX_DELIMITER "._ "
1041 # define SLAPD_APPROX_WORDLEN 2
1043 # define SLAPD_APPROX_DELIMITER " "
1044 # define SLAPD_APPROX_WORDLEN 1
1053 struct berval *value,
1054 void *assertedValue )
1056 struct berval *nval, *assertv;
1057 char *val, **values, **words, *c;
1058 int i, count, len, nextchunk=0, nextavail=0;
1060 /* Yes, this is necessary */
1061 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1062 if( nval == NULL ) {
1064 return LDAP_SUCCESS;
1067 /* Yes, this is necessary */
1068 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1069 NULL, LDAP_UTF8_APPROX, NULL );
1070 if( assertv == NULL ) {
1073 return LDAP_SUCCESS;
1076 /* Isolate how many words there are */
1077 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1078 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1079 if ( c == NULL ) break;
1084 /* Get a phonetic copy of each word */
1085 words = (char **)ch_malloc( count * sizeof(char *) );
1086 values = (char **)ch_malloc( count * sizeof(char *) );
1087 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1089 values[i] = phonetic(c);
1092 /* Work through the asserted value's words, to see if at least some
1093 of the words are there, in the same order. */
1095 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1096 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1101 #if defined(SLAPD_APPROX_INITIALS)
1102 else if( len == 1 ) {
1103 /* Single letter words need to at least match one word's initial */
1104 for( i=nextavail; i<count; i++ )
1105 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1112 /* Isolate the next word in the asserted value and phonetic it */
1113 assertv->bv_val[nextchunk+len] = '\0';
1114 val = phonetic( assertv->bv_val + nextchunk );
1116 /* See if this phonetic chunk is in the remaining words of *value */
1117 for( i=nextavail; i<count; i++ ){
1118 if( !strcmp( val, values[i] ) ){
1126 /* This chunk in the asserted value was NOT within the *value. */
1132 /* Go on to the next word in the asserted value */
1136 /* If some of the words were seen, call it a match */
1137 if( nextavail > 0 ) {
1144 /* Cleanup allocs */
1145 ber_bvfree( assertv );
1146 for( i=0; i<count; i++ ) {
1147 ch_free( values[i] );
1153 return LDAP_SUCCESS;
1162 struct berval *prefix,
1168 int i,j, len, wordcount, keycount=0;
1169 struct berval *newkeys;
1170 BerVarray keys=NULL;
1172 for( j=0; values[j].bv_val != NULL; j++ ) {
1173 struct berval val = { 0, NULL };
1174 /* Yes, this is necessary */
1175 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1176 assert( val.bv_val != NULL );
1178 /* Isolate how many words there are. There will be a key for each */
1179 for( wordcount = 0, c = val.bv_val; *c; c++) {
1180 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1181 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1183 if (*c == '\0') break;
1187 /* Allocate/increase storage to account for new keys */
1188 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1189 * sizeof(struct berval) );
1190 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1191 if( keys ) ch_free( keys );
1194 /* Get a phonetic copy of each word */
1195 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1197 if( len < SLAPD_APPROX_WORDLEN ) continue;
1198 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1203 ber_memfree( val.bv_val );
1205 keys[keycount].bv_val = NULL;
1208 return LDAP_SUCCESS;
1217 struct berval *prefix,
1218 void * assertedValue,
1227 /* Yes, this is necessary */
1228 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1229 NULL, LDAP_UTF8_APPROX, NULL );
1230 if( val == NULL || val->bv_val == NULL ) {
1231 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1232 keys[0].bv_val = NULL;
1235 return LDAP_SUCCESS;
1238 /* Isolate how many words there are. There will be a key for each */
1239 for( count = 0,c = val->bv_val; *c; c++) {
1240 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1241 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1243 if (*c == '\0') break;
1247 /* Allocate storage for new keys */
1248 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1250 /* Get a phonetic copy of each word */
1251 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1253 if( len < SLAPD_APPROX_WORDLEN ) continue;
1254 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1260 keys[count].bv_val = NULL;
1263 return LDAP_SUCCESS;
1266 /* Remove all spaces and '-' characters */
1268 telephoneNumberNormalize(
1273 struct berval *normalized,
1278 /* validator should have refused an empty string */
1279 assert( val->bv_len );
1281 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1283 for( p = val->bv_val; *p; p++ ) {
1284 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1290 normalized->bv_len = q - normalized->bv_val;
1292 if( normalized->bv_len == 0 ) {
1293 sl_free( normalized->bv_val, ctx );
1294 return LDAP_INVALID_SYNTAX;
1297 return LDAP_SUCCESS;
1305 struct berval val = *in;
1307 if( val.bv_len == 0 ) {
1308 /* disallow empty strings */
1309 return LDAP_INVALID_SYNTAX;
1312 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1313 if ( val.bv_len == 1 ) {
1314 return LDAP_SUCCESS;
1317 if ( val.bv_val[0] == '0' ) {
1324 while ( OID_LEADCHAR( val.bv_val[0] )) {
1328 if ( val.bv_len == 0 ) {
1329 return LDAP_SUCCESS;
1333 if( !OID_SEPARATOR( val.bv_val[0] )) {
1341 return LDAP_INVALID_SYNTAX;
1350 struct berval val = *in;
1352 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1354 if ( val.bv_val[0] == '-' ) {
1358 if( val.bv_len == 0 ) { /* bare "-" */
1359 return LDAP_INVALID_SYNTAX;
1362 if( val.bv_val[0] == '0' ) { /* "-0" */
1363 return LDAP_INVALID_SYNTAX;
1366 } else if ( val.bv_val[0] == '0' ) {
1367 if( val.bv_len > 1 ) { /* "0<more>" */
1368 return LDAP_INVALID_SYNTAX;
1371 return LDAP_SUCCESS;
1374 for( i=0; i < val.bv_len; i++ ) {
1375 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1376 return LDAP_INVALID_SYNTAX;
1380 return LDAP_SUCCESS;
1389 struct berval *value,
1390 void *assertedValue )
1392 struct berval *asserted = (struct berval *) assertedValue;
1393 int vsign = 1, asign = 1; /* default sign = '+' */
1398 if( v.bv_val[0] == '-' ) {
1404 if( v.bv_len == 0 ) vsign = 0;
1407 if( a.bv_val[0] == '-' ) {
1413 if( a.bv_len == 0 ) vsign = 0;
1415 match = vsign - asign;
1417 match = ( v.bv_len != a.bv_len
1418 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1419 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1420 if( vsign < 0 ) match = -match;
1424 return LDAP_SUCCESS;
1428 countryStringValidate(
1430 struct berval *val )
1432 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1434 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1435 return LDAP_INVALID_SYNTAX;
1437 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1438 return LDAP_INVALID_SYNTAX;
1441 return LDAP_SUCCESS;
1445 printableStringValidate(
1447 struct berval *val )
1451 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1453 for(i=0; i < val->bv_len; i++) {
1454 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1455 return LDAP_INVALID_SYNTAX;
1459 return LDAP_SUCCESS;
1463 printablesStringValidate(
1465 struct berval *val )
1469 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1471 for(i=0,len=0; i < val->bv_len; i++) {
1472 int c = val->bv_val[i];
1476 return LDAP_INVALID_SYNTAX;
1480 } else if ( SLAP_PRINTABLE(c) ) {
1483 return LDAP_INVALID_SYNTAX;
1488 return LDAP_INVALID_SYNTAX;
1491 return LDAP_SUCCESS;
1497 struct berval *val )
1501 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1503 for(i=0; i < val->bv_len; i++) {
1504 if( !LDAP_ASCII(val->bv_val[i]) ) {
1505 return LDAP_INVALID_SYNTAX;
1509 return LDAP_SUCCESS;
1518 struct berval *normalized,
1522 int casefold = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1524 assert( val->bv_len );
1528 /* Ignore initial whitespace */
1529 while ( ASCII_SPACE( *p ) ) p++;
1531 normalized->bv_val = ber_strdup_x( p, ctx );
1532 p = q = normalized->bv_val;
1535 if ( ASCII_SPACE( *p ) ) {
1538 /* Ignore the extra whitespace */
1539 while ( ASCII_SPACE( *p ) ) {
1543 } else if ( casefold ) {
1544 /* Most IA5 rules require casefolding */
1545 *q++ = TOLOWER(*p++);
1552 assert( normalized->bv_val <= p );
1556 * If the string ended in space, backup the pointer one
1557 * position. One is enough because the above loop collapsed
1558 * all whitespace to a single space.
1560 if ( ASCII_SPACE( q[-1] ) ) --q;
1562 /* null terminate */
1565 normalized->bv_len = q - normalized->bv_val;
1566 if( normalized->bv_len == 0 ) {
1567 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1568 normalized->bv_val[0] = ' ';
1569 normalized->bv_val[1] = '\0';
1570 normalized->bv_len = 1;
1573 return LDAP_SUCCESS;
1577 numericStringValidate(
1583 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1585 for(i=0; i < in->bv_len; i++) {
1586 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1587 return LDAP_INVALID_SYNTAX;
1591 return LDAP_SUCCESS;
1595 numericStringNormalize(
1600 struct berval *normalized,
1603 /* removal all spaces */
1606 assert( val->bv_len );
1608 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1611 q = normalized->bv_val;
1614 if ( ASCII_SPACE( *p ) ) {
1615 /* Ignore whitespace */
1622 /* we should have copied no more then is in val */
1623 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1625 /* null terminate */
1628 normalized->bv_len = q - normalized->bv_val;
1630 if( normalized->bv_len == 0 ) {
1631 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1632 normalized->bv_val[0] = ' ';
1633 normalized->bv_val[1] = '\0';
1634 normalized->bv_len = 1;
1637 return LDAP_SUCCESS;
1646 struct berval *value,
1647 void *assertedValue )
1649 long lValue, lAssertedValue;
1651 /* safe to assume integers are NUL terminated? */
1652 lValue = strtol(value->bv_val, NULL, 10);
1653 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1654 return LDAP_CONSTRAINT_VIOLATION;
1657 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1658 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1659 && errno == ERANGE )
1661 return LDAP_CONSTRAINT_VIOLATION;
1664 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1665 return LDAP_SUCCESS;
1674 struct berval *value,
1675 void *assertedValue )
1677 long lValue, lAssertedValue;
1679 /* safe to assume integers are NUL terminated? */
1680 lValue = strtol(value->bv_val, NULL, 10);
1681 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1682 return LDAP_CONSTRAINT_VIOLATION;
1685 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1686 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1687 && errno == ERANGE )
1689 return LDAP_CONSTRAINT_VIOLATION;
1692 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1693 return LDAP_SUCCESS;
1697 serialNumberAndIssuerValidate(
1701 int rc = LDAP_INVALID_SYNTAX;
1702 struct berval serialNumber, issuer;
1704 serialNumber.bv_val = in->bv_val;
1705 for( serialNumber.bv_len = 0;
1706 serialNumber.bv_len < in->bv_len;
1707 serialNumber.bv_len++ )
1709 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1710 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1711 issuer.bv_len = in->bv_len - (serialNumber.bv_len+1);
1713 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1715 rc = integerValidate( NULL, &serialNumber );
1718 rc = dnValidate( NULL, &issuer );
1727 serialNumberAndIssuerNormalize(
1732 struct berval *normalized,
1735 int rc = LDAP_INVALID_SYNTAX;
1736 struct berval serialNumber, issuer, nissuer;
1738 serialNumber.bv_val = val->bv_val;
1739 for( serialNumber.bv_len = 0;
1740 serialNumber.bv_len < val->bv_len;
1741 serialNumber.bv_len++ )
1743 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1744 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1745 issuer.bv_len = val->bv_len - (serialNumber.bv_len+1);
1747 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1749 rc = dnNormalize( usage, syntax, mr, &issuer, &nissuer, ctx );
1752 normalized->bv_len = serialNumber.bv_len + 1 + nissuer.bv_len;
1753 normalized->bv_val = ch_malloc( normalized->bv_len + 1);
1755 AC_MEMCPY( normalized->bv_val,
1756 serialNumber.bv_val, serialNumber.bv_len );
1757 normalized->bv_val[serialNumber.bv_len] = '$';
1758 AC_MEMCPY( &normalized->bv_val[serialNumber.bv_len+1],
1759 nissuer.bv_val, nissuer.bv_len );
1760 normalized->bv_val[normalized->bv_len] = '\0';
1769 #include <openssl/x509.h>
1770 #include <openssl/err.h>
1773 * Next function returns a string representation of a ASN1_INTEGER.
1774 * It works for unlimited lengths.
1777 static struct berval *
1778 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1782 static char digit[] = "0123456789";
1784 /* We work backwards, make it fill from the end of buf */
1785 p = buf + sizeof(buf) - 1;
1788 if ( a == NULL || a->length == 0 ) {
1796 /* We want to preserve the original */
1797 copy = ch_malloc(n*sizeof(unsigned int));
1798 for (i = 0; i<n; i++) {
1799 copy[i] = a->data[i];
1803 * base indicates the index of the most significant
1804 * byte that might be nonzero. When it goes off the
1805 * end, we now there is nothing left to do.
1811 for (i = base; i<n; i++ ) {
1812 copy[i] += carry*256;
1813 carry = copy[i] % 10;
1818 * Way too large, we need to leave
1819 * room for sign if negative
1824 *--p = digit[carry];
1826 if (copy[base] == 0) base++;
1831 if ( a->type == V_ASN1_NEG_INTEGER ) {
1835 return ber_str2bv( p, 0, 1, bv );
1839 * Given a certificate in DER format, extract the corresponding
1840 * assertion value for certificateExactMatch
1843 certificateExactConvert(
1845 struct berval * out )
1849 unsigned char *p = in->bv_val;
1850 struct berval serial;
1851 struct berval issuer_dn;
1853 xcert = d2i_X509(NULL, &p, in->bv_len);
1856 LDAP_LOG( CONFIG, ENTRY,
1857 "certificateExactConvert: error parsing cert: %s\n",
1858 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
1860 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
1861 "error parsing cert: %s\n",
1862 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
1864 return LDAP_INVALID_SYNTAX;
1867 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
1869 return LDAP_INVALID_SYNTAX;
1872 rc = dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn );
1873 if( rc != LDAP_SUCCESS ) {
1875 ber_memfree(serial.bv_val);
1876 return LDAP_INVALID_SYNTAX;
1881 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
1882 out->bv_val = ch_malloc(out->bv_len);
1884 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
1886 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
1888 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
1889 p += issuer_dn.bv_len;
1893 LDAP_LOG( CONFIG, ARGS,
1894 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
1896 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
1898 out->bv_val, NULL, NULL );
1901 ber_memfree(serial.bv_val);
1902 ber_memfree(issuer_dn.bv_val);
1904 return LDAP_SUCCESS;
1908 certificateExactNormalize(
1913 struct berval *normalized,
1918 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage ) ) {
1919 rc = serialNumberAndIssuerNormalize( usage, syntax, mr,
1920 val, normalized, ctx );
1923 rc = certificateExactConvert( val, normalized );
1928 #endif /* HAVE_TLS */
1932 check_time_syntax (struct berval *val,
1936 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
1937 static int mdays[2][12] = {
1938 /* non-leap years */
1939 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
1941 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
1944 int part, c, tzoffset, leapyear = 0 ;
1946 if( val->bv_len == 0 ) {
1947 return LDAP_INVALID_SYNTAX;
1950 p = (char *)val->bv_val;
1951 e = p + val->bv_len;
1953 /* Ignore initial whitespace */
1954 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
1958 if (e - p < 13 - (2 * start)) {
1959 return LDAP_INVALID_SYNTAX;
1962 for (part = 0; part < 9; part++) {
1966 for (part = start; part < 7; part++) {
1968 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
1975 return LDAP_INVALID_SYNTAX;
1977 if (c < 0 || c > 9) {
1978 return LDAP_INVALID_SYNTAX;
1984 return LDAP_INVALID_SYNTAX;
1986 if (c < 0 || c > 9) {
1987 return LDAP_INVALID_SYNTAX;
1992 if (part == 2 || part == 3) {
1995 if (parts[part] < 0) {
1996 return LDAP_INVALID_SYNTAX;
1998 if (parts[part] > ceiling[part]) {
1999 return LDAP_INVALID_SYNTAX;
2003 /* leapyear check for the Gregorian calendar (year>1581) */
2004 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2005 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2010 if (parts[3] > mdays[leapyear][parts[2]]) {
2011 return LDAP_INVALID_SYNTAX;
2016 tzoffset = 0; /* UTC */
2017 } else if (c != '+' && c != '-') {
2018 return LDAP_INVALID_SYNTAX;
2022 } else /* c == '+' */ {
2027 return LDAP_INVALID_SYNTAX;
2030 for (part = 7; part < 9; part++) {
2032 if (c < 0 || c > 9) {
2033 return LDAP_INVALID_SYNTAX;
2038 if (c < 0 || c > 9) {
2039 return LDAP_INVALID_SYNTAX;
2043 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2044 return LDAP_INVALID_SYNTAX;
2049 /* Ignore trailing whitespace */
2050 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2054 return LDAP_INVALID_SYNTAX;
2057 switch ( tzoffset ) {
2058 case -1: /* negativ offset to UTC, ie west of Greenwich */
2059 parts[4] += parts[7];
2060 parts[5] += parts[8];
2061 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2065 c = mdays[leapyear][parts[2]];
2067 if (parts[part] > c) {
2068 parts[part] -= c + 1;
2073 case 1: /* positive offset to UTC, ie east of Greenwich */
2074 parts[4] -= parts[7];
2075 parts[5] -= parts[8];
2076 for (part = 6; --part > 0; ) {
2080 /* first arg to % needs to be non negativ */
2081 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2083 if (parts[part] < 0) {
2084 parts[part] += c + 1;
2089 case 0: /* already UTC */
2093 return LDAP_SUCCESS;
2096 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2101 struct berval *normalized )
2105 rc = check_time_syntax(val, 1, parts);
2106 if (rc != LDAP_SUCCESS) {
2110 normalized->bv_val = ch_malloc( 14 );
2111 if ( normalized->bv_val == NULL ) {
2112 return LBER_ERROR_MEMORY;
2115 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2116 parts[1], parts[2] + 1, parts[3] + 1,
2117 parts[4], parts[5], parts[6] );
2118 normalized->bv_len = 13;
2120 return LDAP_SUCCESS;
2129 return check_time_syntax(in, 1, parts);
2134 generalizedTimeValidate(
2139 return check_time_syntax(in, 0, parts);
2143 generalizedTimeNormalize(
2148 struct berval *normalized,
2153 rc = check_time_syntax(val, 0, parts);
2154 if (rc != LDAP_SUCCESS) {
2158 normalized->bv_val = sl_malloc( sizeof("YYYYmmddHHMMSSZ"), ctx );
2159 if ( normalized->bv_val == NULL ) {
2160 return LBER_ERROR_MEMORY;
2163 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2164 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2165 parts[4], parts[5], parts[6] );
2166 normalized->bv_len = 15;
2168 return LDAP_SUCCESS;
2172 nisNetgroupTripleValidate(
2174 struct berval *val )
2179 if ( val->bv_len == 0 ) {
2180 return LDAP_INVALID_SYNTAX;
2183 p = (char *)val->bv_val;
2184 e = p + val->bv_len;
2186 if ( *p != '(' /*')'*/ ) {
2187 return LDAP_INVALID_SYNTAX;
2190 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2194 return LDAP_INVALID_SYNTAX;
2197 } else if ( !AD_CHAR( *p ) ) {
2198 return LDAP_INVALID_SYNTAX;
2202 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2203 return LDAP_INVALID_SYNTAX;
2209 return LDAP_INVALID_SYNTAX;
2212 return LDAP_SUCCESS;
2216 bootParameterValidate(
2218 struct berval *val )
2222 if ( val->bv_len == 0 ) {
2223 return LDAP_INVALID_SYNTAX;
2226 p = (char *)val->bv_val;
2227 e = p + val->bv_len;
2230 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2231 if ( !AD_CHAR( *p ) ) {
2232 return LDAP_INVALID_SYNTAX;
2237 return LDAP_INVALID_SYNTAX;
2241 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2242 if ( !AD_CHAR( *p ) ) {
2243 return LDAP_INVALID_SYNTAX;
2248 return LDAP_INVALID_SYNTAX;
2252 for ( p++; p < e; p++ ) {
2253 if ( !SLAP_PRINTABLE( *p ) ) {
2254 return LDAP_INVALID_SYNTAX;
2258 return LDAP_SUCCESS;
2262 firstComponentNormalize(
2267 struct berval *normalized,
2274 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2276 if( val->bv_val[0] != '(' /*')'*/ &&
2277 val->bv_val[0] != '{' /*'}'*/ )
2279 return LDAP_INVALID_SYNTAX;
2282 /* trim leading white space */
2284 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2290 /* grab next word */
2291 oid.bv_val = &val->bv_val[len];
2292 len = val->bv_len - len;
2294 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2300 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2301 rc = numericoidValidate( NULL, &oid );
2302 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2303 rc = integerValidate( NULL, &oid );
2305 rc = LDAP_INVALID_SYNTAX;
2309 if( rc == LDAP_SUCCESS ) {
2310 ber_dupbv_x( normalized, &oid, ctx );
2316 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2317 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2319 static slap_syntax_defs_rec syntax_defs[] = {
2320 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2321 X_BINARY X_NOT_H_R ")",
2322 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2323 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2325 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2327 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2329 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2330 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2332 SLAP_SYNTAX_BER, berValidate, NULL},
2333 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2334 0, bitStringValidate, NULL },
2335 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2336 0, booleanValidate, NULL},
2337 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2338 X_BINARY X_NOT_H_R ")",
2339 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2340 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2341 X_BINARY X_NOT_H_R ")",
2342 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2343 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2344 X_BINARY X_NOT_H_R ")",
2345 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2346 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2347 0, countryStringValidate, NULL},
2348 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2349 0, dnValidate, dnPretty},
2350 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2352 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2354 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2355 0, UTF8StringValidate, NULL},
2356 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2358 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2360 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2362 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2364 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2366 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2367 0, printablesStringValidate, NULL},
2368 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2369 SLAP_SYNTAX_BLOB, NULL, NULL},
2370 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2371 0, generalizedTimeValidate, NULL},
2372 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2374 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2375 0, IA5StringValidate, NULL},
2376 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2377 0, integerValidate, NULL},
2378 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2379 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2380 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2382 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2384 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2386 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2388 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2390 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2391 0, nameUIDValidate, NULL},
2392 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2394 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2395 0, numericStringValidate, NULL},
2396 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2398 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2399 0, numericoidValidate, NULL},
2400 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2401 0, IA5StringValidate, NULL},
2402 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2403 0, blobValidate, NULL},
2404 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2405 0, UTF8StringValidate, NULL},
2406 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2408 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2410 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2411 0, printableStringValidate, NULL},
2412 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2413 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2414 0, subtreeSpecificationValidate, NULL},
2415 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2416 X_BINARY X_NOT_H_R ")",
2417 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2418 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2419 0, printableStringValidate, NULL},
2420 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2422 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2423 0, printablesStringValidate, NULL},
2424 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2425 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2426 0, utcTimeValidate, NULL},
2428 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2430 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2432 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2434 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2436 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2439 /* RFC 2307 NIS Syntaxes */
2440 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2441 0, nisNetgroupTripleValidate, NULL},
2442 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2443 0, bootParameterValidate, NULL},
2446 /* These OIDs are not published yet, but will be in the next
2447 * I-D for PKIX LDAPv3 schema as have been advanced by David
2448 * Chadwick in private mail.
2450 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2451 0, serialNumberAndIssuerValidate, NULL},
2453 /* OpenLDAP Experimental Syntaxes */
2454 #ifdef SLAPD_ACI_ENABLED
2455 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2457 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2461 #ifdef SLAPD_AUTHPASSWD
2462 /* needs updating */
2463 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2464 SLAP_SYNTAX_HIDE, NULL, NULL},
2467 /* OpenLDAP Void Syntax */
2468 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2469 SLAP_SYNTAX_HIDE, inValidate, NULL},
2470 {NULL, 0, NULL, NULL}
2474 char *certificateExactMatchSyntaxes[] = {
2475 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2479 char *directoryStringSyntaxes[] = {
2480 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2483 char *integerFirstComponentMatchSyntaxes[] = {
2484 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2485 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2488 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2489 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2490 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2491 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2492 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2493 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2494 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2495 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2496 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2501 * Other matching rules in X.520 that we do not use (yet):
2503 * 2.5.13.9 numericStringOrderingMatch
2504 * 2.5.13.25 uTCTimeMatch
2505 * 2.5.13.26 uTCTimeOrderingMatch
2506 * 2.5.13.31 directoryStringFirstComponentMatch
2507 * 2.5.13.32 wordMatch
2508 * 2.5.13.33 keywordMatch
2509 * 2.5.13.35 certificateMatch
2510 * 2.5.13.36 certificatePairExactMatch
2511 * 2.5.13.37 certificatePairMatch
2512 * 2.5.13.38 certificateListExactMatch
2513 * 2.5.13.39 certificateListMatch
2514 * 2.5.13.40 algorithmIdentifierMatch
2515 * 2.5.13.41 storedPrefixMatch
2516 * 2.5.13.42 attributeCertificateMatch
2517 * 2.5.13.43 readerAndKeyIDMatch
2518 * 2.5.13.44 attributeIntegrityMatch
2520 static slap_mrule_defs_rec mrule_defs[] = {
2522 * EQUALITY matching rules must be listed after associated APPROX
2523 * matching rules. So, we list all APPROX matching rules first.
2525 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2527 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2528 NULL, NULL, directoryStringApproxMatch,
2529 directoryStringApproxIndexer, directoryStringApproxFilter,
2532 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2534 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2535 NULL, NULL, IA5StringApproxMatch,
2536 IA5StringApproxIndexer, IA5StringApproxFilter,
2540 * Other matching rules
2543 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2545 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2546 NULL, NULL, octetStringMatch,
2547 octetStringIndexer, octetStringFilter,
2550 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2552 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2553 NULL, dnNormalize, dnMatch,
2554 octetStringIndexer, octetStringFilter,
2557 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2559 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2560 NULL, UTF8StringNormalize, octetStringMatch,
2561 octetStringIndexer, octetStringFilter,
2562 directoryStringApproxMatchOID },
2564 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2566 SLAP_MR_ORDERING, directoryStringSyntaxes,
2567 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2569 "caseIgnoreMatch" },
2571 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2572 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2573 SLAP_MR_SUBSTR, NULL,
2574 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2575 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2576 "caseIgnoreMatch" },
2578 {"( 2.5.13.5 NAME 'caseExactMatch' "
2579 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2580 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2581 NULL, UTF8StringNormalize, octetStringMatch,
2582 octetStringIndexer, octetStringFilter,
2583 directoryStringApproxMatchOID },
2585 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2586 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2587 SLAP_MR_ORDERING, directoryStringSyntaxes,
2588 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2592 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2593 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2594 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2595 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2596 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2599 {"( 2.5.13.8 NAME 'numericStringMatch' "
2600 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2601 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2602 NULL, numericStringNormalize, octetStringSubstringsMatch,
2603 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2606 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2607 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2608 SLAP_MR_SUBSTR, NULL,
2609 NULL, numericStringNormalize, octetStringSubstringsMatch,
2610 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2611 "numericStringMatch" },
2613 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2614 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2615 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2616 NULL, NULL, NULL, NULL, NULL, NULL },
2618 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2619 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2620 SLAP_MR_SUBSTR, NULL,
2621 NULL, NULL, NULL, NULL, NULL,
2622 "caseIgnoreListMatch" },
2624 {"( 2.5.13.13 NAME 'booleanMatch' "
2625 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2626 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2627 NULL, NULL, booleanMatch,
2628 octetStringIndexer, octetStringFilter,
2631 {"( 2.5.13.14 NAME 'integerMatch' "
2632 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2633 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2634 NULL, NULL, integerMatch,
2635 octetStringIndexer, octetStringFilter,
2638 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2639 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2640 SLAP_MR_ORDERING, NULL,
2641 NULL, NULL, integerMatch,
2645 {"( 2.5.13.16 NAME 'bitStringMatch' "
2646 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2647 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2648 NULL, NULL, octetStringMatch,
2649 octetStringIndexer, octetStringFilter,
2652 {"( 2.5.13.17 NAME 'octetStringMatch' "
2653 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2654 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2655 NULL, NULL, octetStringMatch,
2656 octetStringIndexer, octetStringFilter,
2659 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2660 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2661 SLAP_MR_ORDERING, NULL,
2662 NULL, NULL, octetStringOrderingMatch,
2664 "octetStringMatch" },
2666 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2667 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2668 SLAP_MR_SUBSTR, NULL,
2669 NULL, NULL, octetStringSubstringsMatch,
2670 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2671 "octetStringMatch" },
2673 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2674 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2675 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2677 telephoneNumberNormalize, octetStringMatch,
2678 octetStringIndexer, octetStringFilter,
2681 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2682 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2683 SLAP_MR_SUBSTR, NULL,
2684 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2685 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2686 "telephoneNumberMatch" },
2688 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2689 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2690 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2691 NULL, NULL, NULL, NULL, NULL, NULL },
2693 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2695 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2696 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2700 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2702 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2703 NULL, NULL, NULL, NULL, NULL, NULL },
2705 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2706 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2707 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2708 NULL, generalizedTimeNormalize, octetStringMatch,
2712 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2713 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2714 SLAP_MR_ORDERING, NULL,
2715 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
2717 "generalizedTimeMatch" },
2719 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
2720 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2721 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2722 integerFirstComponentMatchSyntaxes,
2723 NULL, firstComponentNormalize, integerMatch,
2724 octetStringIndexer, octetStringFilter,
2727 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
2728 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2729 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2730 objectIdentifierFirstComponentMatchSyntaxes,
2731 NULL, firstComponentNormalize, octetStringMatch,
2732 octetStringIndexer, octetStringFilter,
2736 {"( 2.5.13.34 NAME 'certificateExactMatch' "
2737 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
2738 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
2739 NULL, certificateExactNormalize, octetStringMatch,
2740 octetStringIndexer, octetStringFilter,
2744 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
2745 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2746 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2747 NULL, IA5StringNormalize, octetStringMatch,
2748 octetStringIndexer, octetStringFilter,
2749 IA5StringApproxMatchOID },
2751 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
2752 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2753 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2754 NULL, IA5StringNormalize, octetStringMatch,
2755 octetStringIndexer, octetStringFilter,
2756 IA5StringApproxMatchOID },
2758 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
2759 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2760 SLAP_MR_SUBSTR, NULL,
2761 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2762 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2763 "caseIgnoreIA5Match" },
2765 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
2766 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2767 SLAP_MR_SUBSTR, NULL,
2768 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2769 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2770 "caseExactIA5Match" },
2772 #ifdef SLAPD_AUTHPASSWD
2773 /* needs updating */
2774 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
2775 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2776 SLAP_MR_EQUALITY, NULL,
2777 NULL, NULL, authPasswordMatch,
2782 #ifdef SLAPD_ACI_ENABLED
2783 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
2784 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
2785 SLAP_MR_EQUALITY, NULL,
2786 NULL, NULL, OpenLDAPaciMatch,
2791 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
2792 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2794 NULL, NULL, integerBitAndMatch,
2798 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
2799 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2801 NULL, NULL, integerBitOrMatch,
2805 {NULL, SLAP_MR_NONE, NULL,
2806 NULL, NULL, NULL, NULL, NULL,
2811 slap_schema_init( void )
2816 /* we should only be called once (from main) */
2817 assert( schema_init_done == 0 );
2819 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
2820 res = register_syntax( &syntax_defs[i] );
2823 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
2824 syntax_defs[i].sd_desc );
2829 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
2830 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
2831 mrule_defs[i].mrd_compat_syntaxes == NULL )
2834 "slap_schema_init: Ignoring unusable matching rule %s\n",
2835 mrule_defs[i].mrd_desc );
2839 res = register_matching_rule( &mrule_defs[i] );
2843 "slap_schema_init: Error registering matching rule %s\n",
2844 mrule_defs[i].mrd_desc );
2849 res = slap_schema_load();
2850 schema_init_done = 1;
2855 schema_destroy( void )