1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
31 #include "ldap_utf8.h"
34 #include <openssl/x509.h>
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/crypto.h>
38 #include <openssl/pem.h>
39 #include <openssl/bio.h>
40 #include <openssl/asn1.h>
41 #include <openssl/x509v3.h>
42 #include <openssl/ssl.h>
45 #include "lutil_hash.h"
46 #define HASH_BYTES LUTIL_HASH_BYTES
47 #define HASH_CONTEXT lutil_HASH_CTX
48 #define HASH_Init(c) lutil_HASHInit(c)
49 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
50 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
52 #define OpenLDAPaciMatch NULL
54 /* approx matching rules */
55 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
56 #define directoryStringApproxMatch approxMatch
57 #define directoryStringApproxIndexer approxIndexer
58 #define directoryStringApproxFilter approxFilter
59 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
60 #define IA5StringApproxMatch approxMatch
61 #define IA5StringApproxIndexer approxIndexer
62 #define IA5StringApproxFilter approxFilter
69 /* no value allowed */
70 return LDAP_INVALID_SYNTAX;
78 /* any value allowed */
82 #define berValidate blobValidate
89 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
90 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
97 static int certificateValidate( Syntax *syntax, struct berval *in )
100 unsigned char *p = (unsigned char *)in->bv_val;
102 xcert = d2i_X509(NULL, &p, in->bv_len);
103 if ( !xcert ) return LDAP_INVALID_SYNTAX;
108 #define certificateValidate sequenceValidate
117 struct berval *value,
118 void *assertedValue )
120 struct berval *asserted = (struct berval *) assertedValue;
121 int match = value->bv_len - asserted->bv_len;
124 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
132 octetStringOrderingMatch(
137 struct berval *value,
138 void *assertedValue )
140 struct berval *asserted = (struct berval *) assertedValue;
141 ber_len_t v_len = value->bv_len;
142 ber_len_t av_len = asserted->bv_len;
144 int match = memcmp( value->bv_val, asserted->bv_val,
145 (v_len < av_len ? v_len : av_len) );
147 if( match == 0 ) match = v_len - av_len;
153 /* Index generation function */
154 int octetStringIndexer(
159 struct berval *prefix,
167 HASH_CONTEXT HASHcontext;
168 unsigned char HASHdigest[HASH_BYTES];
169 struct berval digest;
170 digest.bv_val = (char *)HASHdigest;
171 digest.bv_len = sizeof(HASHdigest);
173 for( i=0; values[i].bv_val != NULL; i++ ) {
174 /* just count them */
177 /* we should have at least one value at this point */
180 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
182 slen = syntax->ssyn_oidlen;
183 mlen = mr->smr_oidlen;
185 for( i=0; values[i].bv_val != NULL; i++ ) {
186 HASH_Init( &HASHcontext );
187 if( prefix != NULL && prefix->bv_len > 0 ) {
188 HASH_Update( &HASHcontext,
189 (unsigned char *)prefix->bv_val,
192 HASH_Update( &HASHcontext,
193 (unsigned char *)syntax->ssyn_oid, slen );
194 HASH_Update( &HASHcontext,
195 (unsigned char *)mr->smr_oid, mlen );
196 HASH_Update( &HASHcontext,
197 (unsigned char *)values[i].bv_val, values[i].bv_len );
198 HASH_Final( HASHdigest, &HASHcontext );
200 ber_dupbv_x( &keys[i], &digest, ctx );
203 keys[i].bv_val = NULL;
211 /* Index generation function */
212 int octetStringFilter(
217 struct berval *prefix,
218 void * assertedValue,
224 HASH_CONTEXT HASHcontext;
225 unsigned char HASHdigest[HASH_BYTES];
226 struct berval *value = (struct berval *) assertedValue;
227 struct berval digest;
228 digest.bv_val = (char *)HASHdigest;
229 digest.bv_len = sizeof(HASHdigest);
231 slen = syntax->ssyn_oidlen;
232 mlen = mr->smr_oidlen;
234 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
236 HASH_Init( &HASHcontext );
237 if( prefix != NULL && prefix->bv_len > 0 ) {
238 HASH_Update( &HASHcontext,
239 (unsigned char *)prefix->bv_val, prefix->bv_len );
241 HASH_Update( &HASHcontext,
242 (unsigned char *)syntax->ssyn_oid, slen );
243 HASH_Update( &HASHcontext,
244 (unsigned char *)mr->smr_oid, mlen );
245 HASH_Update( &HASHcontext,
246 (unsigned char *)value->bv_val, value->bv_len );
247 HASH_Final( HASHdigest, &HASHcontext );
249 ber_dupbv_x( keys, &digest, ctx );
250 keys[1].bv_val = NULL;
259 octetStringSubstringsMatch(
264 struct berval *value,
265 void *assertedValue )
268 SubstringsAssertion *sub = assertedValue;
269 struct berval left = *value;
273 /* Add up asserted input length */
274 if( sub->sa_initial.bv_val ) {
275 inlen += sub->sa_initial.bv_len;
278 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
279 inlen += sub->sa_any[i].bv_len;
282 if( sub->sa_final.bv_val ) {
283 inlen += sub->sa_final.bv_len;
286 if( sub->sa_initial.bv_val ) {
287 if( inlen > left.bv_len ) {
292 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
293 sub->sa_initial.bv_len );
299 left.bv_val += sub->sa_initial.bv_len;
300 left.bv_len -= sub->sa_initial.bv_len;
301 inlen -= sub->sa_initial.bv_len;
304 if( sub->sa_final.bv_val ) {
305 if( inlen > left.bv_len ) {
310 match = memcmp( sub->sa_final.bv_val,
311 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
312 sub->sa_final.bv_len );
318 left.bv_len -= sub->sa_final.bv_len;
319 inlen -= sub->sa_final.bv_len;
323 for(i=0; sub->sa_any[i].bv_val; i++) {
328 if( inlen > left.bv_len ) {
329 /* not enough length */
334 if( sub->sa_any[i].bv_len == 0 ) {
338 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
345 idx = p - left.bv_val;
347 if( idx >= left.bv_len ) {
348 /* this shouldn't happen */
355 if( sub->sa_any[i].bv_len > left.bv_len ) {
356 /* not enough left */
361 match = memcmp( left.bv_val,
362 sub->sa_any[i].bv_val,
363 sub->sa_any[i].bv_len );
371 left.bv_val += sub->sa_any[i].bv_len;
372 left.bv_len -= sub->sa_any[i].bv_len;
373 inlen -= sub->sa_any[i].bv_len;
382 /* Substrings Index generation function */
384 octetStringSubstringsIndexer(
389 struct berval *prefix,
394 ber_len_t i, j, nkeys;
398 HASH_CONTEXT HASHcontext;
399 unsigned char HASHdigest[HASH_BYTES];
400 struct berval digest;
401 digest.bv_val = (char *)HASHdigest;
402 digest.bv_len = sizeof(HASHdigest);
406 for( i=0; values[i].bv_val != NULL; i++ ) {
407 /* count number of indices to generate */
408 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
412 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
413 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
414 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
415 (SLAP_INDEX_SUBSTR_MINLEN - 1);
417 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
421 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
422 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
423 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
427 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
428 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
429 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
430 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
432 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
438 /* no keys to generate */
443 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
445 slen = syntax->ssyn_oidlen;
446 mlen = mr->smr_oidlen;
449 for( i=0; values[i].bv_val != NULL; i++ ) {
452 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
454 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
455 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
457 char pre = SLAP_INDEX_SUBSTR_PREFIX;
458 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
460 for( j=0; j<max; j++ ) {
461 HASH_Init( &HASHcontext );
462 if( prefix != NULL && prefix->bv_len > 0 ) {
463 HASH_Update( &HASHcontext,
464 (unsigned char *)prefix->bv_val, prefix->bv_len );
467 HASH_Update( &HASHcontext,
468 (unsigned char *)&pre, sizeof( pre ) );
469 HASH_Update( &HASHcontext,
470 (unsigned char *)syntax->ssyn_oid, slen );
471 HASH_Update( &HASHcontext,
472 (unsigned char *)mr->smr_oid, mlen );
473 HASH_Update( &HASHcontext,
474 (unsigned char *)&values[i].bv_val[j],
475 SLAP_INDEX_SUBSTR_MAXLEN );
476 HASH_Final( HASHdigest, &HASHcontext );
478 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
482 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
483 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
485 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
488 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
489 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
490 HASH_Init( &HASHcontext );
491 if( prefix != NULL && prefix->bv_len > 0 ) {
492 HASH_Update( &HASHcontext,
493 (unsigned char *)prefix->bv_val, prefix->bv_len );
495 HASH_Update( &HASHcontext,
496 (unsigned char *)&pre, sizeof( pre ) );
497 HASH_Update( &HASHcontext,
498 (unsigned char *)syntax->ssyn_oid, slen );
499 HASH_Update( &HASHcontext,
500 (unsigned char *)mr->smr_oid, mlen );
501 HASH_Update( &HASHcontext,
502 (unsigned char *)values[i].bv_val, j );
503 HASH_Final( HASHdigest, &HASHcontext );
505 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
508 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
509 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
510 HASH_Init( &HASHcontext );
511 if( prefix != NULL && prefix->bv_len > 0 ) {
512 HASH_Update( &HASHcontext,
513 (unsigned char *)prefix->bv_val, prefix->bv_len );
515 HASH_Update( &HASHcontext,
516 (unsigned char *)&pre, sizeof( pre ) );
517 HASH_Update( &HASHcontext,
518 (unsigned char *)syntax->ssyn_oid, slen );
519 HASH_Update( &HASHcontext,
520 (unsigned char *)mr->smr_oid, mlen );
521 HASH_Update( &HASHcontext,
522 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
523 HASH_Final( HASHdigest, &HASHcontext );
525 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
533 keys[nkeys].bv_val = NULL;
544 octetStringSubstringsFilter (
549 struct berval *prefix,
550 void * assertedValue,
554 SubstringsAssertion *sa;
557 size_t slen, mlen, klen;
559 HASH_CONTEXT HASHcontext;
560 unsigned char HASHdigest[HASH_BYTES];
561 struct berval *value;
562 struct berval digest;
564 sa = (SubstringsAssertion *) assertedValue;
566 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
567 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
572 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
574 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
575 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
576 /* don't bother accounting for stepping */
577 nkeys += sa->sa_any[i].bv_len -
578 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
583 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
584 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
594 digest.bv_val = (char *)HASHdigest;
595 digest.bv_len = sizeof(HASHdigest);
597 slen = syntax->ssyn_oidlen;
598 mlen = mr->smr_oidlen;
600 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
603 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
604 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
606 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
607 value = &sa->sa_initial;
609 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
610 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
612 HASH_Init( &HASHcontext );
613 if( prefix != NULL && prefix->bv_len > 0 ) {
614 HASH_Update( &HASHcontext,
615 (unsigned char *)prefix->bv_val, prefix->bv_len );
617 HASH_Update( &HASHcontext,
618 (unsigned char *)&pre, sizeof( pre ) );
619 HASH_Update( &HASHcontext,
620 (unsigned char *)syntax->ssyn_oid, slen );
621 HASH_Update( &HASHcontext,
622 (unsigned char *)mr->smr_oid, mlen );
623 HASH_Update( &HASHcontext,
624 (unsigned char *)value->bv_val, klen );
625 HASH_Final( HASHdigest, &HASHcontext );
627 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
630 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
632 pre = SLAP_INDEX_SUBSTR_PREFIX;
633 klen = SLAP_INDEX_SUBSTR_MAXLEN;
635 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
636 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
640 value = &sa->sa_any[i];
643 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
644 j += SLAP_INDEX_SUBSTR_STEP )
646 HASH_Init( &HASHcontext );
647 if( prefix != NULL && prefix->bv_len > 0 ) {
648 HASH_Update( &HASHcontext,
649 (unsigned char *)prefix->bv_val, prefix->bv_len );
651 HASH_Update( &HASHcontext,
652 (unsigned char *)&pre, sizeof( pre ) );
653 HASH_Update( &HASHcontext,
654 (unsigned char *)syntax->ssyn_oid, slen );
655 HASH_Update( &HASHcontext,
656 (unsigned char *)mr->smr_oid, mlen );
657 HASH_Update( &HASHcontext,
658 (unsigned char *)&value->bv_val[j], klen );
659 HASH_Final( HASHdigest, &HASHcontext );
661 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
666 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
667 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
669 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
670 value = &sa->sa_final;
672 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
673 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
675 HASH_Init( &HASHcontext );
676 if( prefix != NULL && prefix->bv_len > 0 ) {
677 HASH_Update( &HASHcontext,
678 (unsigned char *)prefix->bv_val, prefix->bv_len );
680 HASH_Update( &HASHcontext,
681 (unsigned char *)&pre, sizeof( pre ) );
682 HASH_Update( &HASHcontext,
683 (unsigned char *)syntax->ssyn_oid, slen );
684 HASH_Update( &HASHcontext,
685 (unsigned char *)mr->smr_oid, mlen );
686 HASH_Update( &HASHcontext,
687 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
688 HASH_Final( HASHdigest, &HASHcontext );
690 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
694 keys[nkeys].bv_val = NULL;
711 /* very unforgiving validation, requires no normalization
712 * before simplistic matching
714 if( in->bv_len < 3 ) {
715 return LDAP_INVALID_SYNTAX;
719 * RFC 2252 section 6.3 Bit String
720 * bitstring = "'" *binary-digit "'B"
721 * binary-digit = "0" / "1"
722 * example: '0101111101'B
725 if( in->bv_val[0] != '\'' ||
726 in->bv_val[in->bv_len-2] != '\'' ||
727 in->bv_val[in->bv_len-1] != 'B' )
729 return LDAP_INVALID_SYNTAX;
732 for( i=in->bv_len-3; i>0; i-- ) {
733 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
734 return LDAP_INVALID_SYNTAX;
749 if( in->bv_len == 0 ) return LDAP_SUCCESS;
751 ber_dupbv( &dn, in );
752 if( !dn.bv_val ) return LDAP_OTHER;
754 if( dn.bv_val[dn.bv_len-1] == 'B'
755 && dn.bv_val[dn.bv_len-2] == '\'' )
757 /* assume presence of optional UID */
760 for(i=dn.bv_len-3; i>1; i--) {
761 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
765 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
766 ber_memfree( dn.bv_val );
767 return LDAP_INVALID_SYNTAX;
770 /* trim the UID to allow use of dnValidate */
771 dn.bv_val[i-1] = '\0';
775 rc = dnValidate( NULL, &dn );
777 ber_memfree( dn.bv_val );
793 LDAP_LOG( OPERATION, ARGS, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
795 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
798 if( val->bv_len == 0 ) {
799 ber_dupbv_x( out, val, ctx );
801 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
802 return LDAP_INVALID_SYNTAX;
806 struct berval dnval = *val;
807 struct berval uidval = BER_BVNULL;
809 if( val->bv_val[val->bv_len-1] == 'B'
810 && val->bv_val[val->bv_len-2] == '\'' )
812 uidval.bv_val=strrchr( val->bv_val, '#' );
813 if( uidval.bv_val ) {
814 dnval.bv_len = uidval.bv_val - dnval.bv_val;
815 uidval.bv_len = val->bv_len - dnval.bv_len;
822 rc = dnPretty( syntax, &dnval, out, ctx );
823 if( rc != LDAP_SUCCESS ) return rc;
825 if( uidval.bv_val ) {
826 char *tmp = sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx );
829 ber_memfree_x( out->bv_val, ctx );
833 out->bv_val[out->bv_len++] = '#';
835 got1 = uidval.bv_len < sizeof("'0'B");
836 for(i=0; i<uidval.bv_len; i++) {
837 c = uidval.bv_val[i];
840 if( got1 ) out->bv_val[out->bv_len++] = c;
845 out->bv_val[out->bv_len++] = c;
849 out->bv_val[out->bv_len] = '\0';
854 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
856 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
863 uniqueMemberNormalize(
868 struct berval *normalized,
874 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
876 ber_dupbv_x( &out, val, ctx );
877 if( BER_BVISEMPTY( &out ) ) {
881 struct berval uid = BER_BVNULL;
883 if( out.bv_val[out.bv_len-1] == 'B'
884 && out.bv_val[out.bv_len-2] == '\'' )
886 /* assume presence of optional UID */
887 uid.bv_val = strrchr( out.bv_val, '#' );
889 if( uid.bv_val == NULL ) {
890 sl_free( out.bv_val, ctx );
891 return LDAP_INVALID_SYNTAX;
894 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
895 out.bv_len -= uid.bv_len--;
897 /* temporarily trim the UID */
898 *(uid.bv_val++) = '\0';
901 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
903 if( rc != LDAP_SUCCESS ) {
904 sl_free( out.bv_val, ctx );
905 return LDAP_INVALID_SYNTAX;
909 normalized->bv_val = ch_realloc( normalized->bv_val,
910 normalized->bv_len + uid.bv_len + sizeof("#") );
912 /* insert the separator */
913 normalized->bv_val[normalized->bv_len++] = '#';
916 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
917 uid.bv_val, uid.bv_len );
918 normalized->bv_len += uid.bv_len;
921 normalized->bv_val[normalized->bv_len] = '\0';
924 sl_free( out.bv_val, ctx );
936 struct berval *value,
937 void *assertedValue )
940 struct berval *asserted = (struct berval *) assertedValue;
941 struct berval assertedDN = BER_BVNULL;
942 struct berval assertedUID = BER_BVNULL;
943 struct berval valueDN = BER_BVNULL;
944 struct berval valueUID = BER_BVNULL;
946 if( asserted->bv_len != 0 ) {
947 assertedDN = *asserted;
949 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
950 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
952 /* assume presence of optional UID */
953 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
955 if( assertedUID.bv_val == NULL ) {
956 return LDAP_INVALID_SYNTAX;
959 assertedUID.bv_len = assertedDN.bv_len -
960 (assertedUID.bv_val - assertedDN.bv_val);
961 assertedDN.bv_len -= assertedUID.bv_len--;
963 /* trim the separator */
964 assertedUID.bv_val++;
968 if( value->bv_len != 0 ) {
971 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
972 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
974 /* assume presence of optional UID */
975 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
977 if( valueUID.bv_val == NULL ) {
978 return LDAP_INVALID_SYNTAX;
981 valueUID.bv_len = valueDN.bv_len -
982 (assertedUID.bv_val - assertedDN.bv_val);
983 valueDN.bv_len -= valueUID.bv_len--;
985 /* trim the separator */
990 if( valueUID.bv_len && assertedUID.bv_len ) {
991 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
998 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1002 * Handling boolean syntax and matching is quite rigid.
1003 * A more flexible approach would be to allow a variety
1004 * of strings to be normalized and prettied into TRUE
1012 /* very unforgiving validation, requires no normalization
1013 * before simplistic matching
1016 if( in->bv_len == 4 ) {
1017 if( bvmatch( in, &slap_true_bv ) ) {
1018 return LDAP_SUCCESS;
1020 } else if( in->bv_len == 5 ) {
1021 if( bvmatch( in, &slap_false_bv ) ) {
1022 return LDAP_SUCCESS;
1026 return LDAP_INVALID_SYNTAX;
1035 struct berval *value,
1036 void *assertedValue )
1038 /* simplistic matching allowed by rigid validation */
1039 struct berval *asserted = (struct berval *) assertedValue;
1040 *matchp = value->bv_len != asserted->bv_len;
1041 return LDAP_SUCCESS;
1044 /*-------------------------------------------------------------------
1045 LDAP/X.500 string syntax / matching rules have a few oddities. This
1046 comment attempts to detail how slapd(8) treats them.
1049 StringSyntax X.500 LDAP Matching/Comments
1050 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1051 PrintableString subset subset i/e + ignore insignificant spaces
1052 PrintableString subset subset i/e + ignore insignificant spaces
1053 NumericString subset subset ignore all spaces
1054 IA5String ASCII ASCII i/e + ignore insignificant spaces
1055 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1057 TelephoneNumber subset subset i + ignore all spaces and "-"
1059 See draft-ietf-ldapbis-strpro for details (once published).
1063 In X.500(93), a directory string can be either a PrintableString,
1064 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1065 In later versions, more CHOICEs were added. In all cases the string
1068 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1069 A directory string cannot be zero length.
1071 For matching, there are both case ignore and exact rules. Both
1072 also require that "insignificant" spaces be ignored.
1073 spaces before the first non-space are ignored;
1074 spaces after the last non-space are ignored;
1075 spaces after a space are ignored.
1076 Note: by these rules (and as clarified in X.520), a string of only
1077 spaces is to be treated as if held one space, not empty (which
1078 would be a syntax error).
1081 In ASN.1, numeric string is just a string of digits and spaces
1082 and could be empty. However, in X.500, all attribute values of
1083 numeric string carry a non-empty constraint. For example:
1085 internationalISDNNumber ATTRIBUTE ::= {
1086 WITH SYNTAX InternationalISDNNumber
1087 EQUALITY MATCHING RULE numericStringMatch
1088 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1089 ID id-at-internationalISDNNumber }
1090 InternationalISDNNumber ::=
1091 NumericString (SIZE(1..ub-international-isdn-number))
1093 Unforunately, some assertion values are don't carry the same
1094 constraint (but its unclear how such an assertion could ever
1095 be true). In LDAP, there is one syntax (numericString) not two
1096 (numericString with constraint, numericString without constraint).
1097 This should be treated as numericString with non-empty constraint.
1098 Note that while someone may have no ISDN number, there are no ISDN
1099 numbers which are zero length.
1101 In matching, spaces are ignored.
1104 In ASN.1, Printable string is just a string of printable characters
1105 and can be empty. In X.500, semantics much like NumericString (see
1106 serialNumber for a like example) excepting uses insignificant space
1107 handling instead of ignore all spaces.
1110 Basically same as PrintableString. There are no examples in X.500,
1111 but same logic applies. So we require them to be non-empty as
1114 -------------------------------------------------------------------*/
1123 unsigned char *u = (unsigned char *)in->bv_val;
1125 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1126 /* directory strings cannot be empty */
1127 return LDAP_INVALID_SYNTAX;
1130 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1131 /* get the length indicated by the first byte */
1132 len = LDAP_UTF8_CHARLEN2( u, len );
1134 /* very basic checks */
1137 if( (u[5] & 0xC0) != 0x80 ) {
1138 return LDAP_INVALID_SYNTAX;
1141 if( (u[4] & 0xC0) != 0x80 ) {
1142 return LDAP_INVALID_SYNTAX;
1145 if( (u[3] & 0xC0) != 0x80 ) {
1146 return LDAP_INVALID_SYNTAX;
1149 if( (u[2] & 0xC0 )!= 0x80 ) {
1150 return LDAP_INVALID_SYNTAX;
1153 if( (u[1] & 0xC0) != 0x80 ) {
1154 return LDAP_INVALID_SYNTAX;
1157 /* CHARLEN already validated it */
1160 return LDAP_INVALID_SYNTAX;
1163 /* make sure len corresponds with the offset
1164 to the next character */
1165 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1169 return LDAP_INVALID_SYNTAX;
1172 return LDAP_SUCCESS;
1176 UTF8StringNormalize(
1181 struct berval *normalized,
1184 struct berval tmp, nvalue;
1188 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1190 if( val->bv_val == NULL ) {
1191 /* assume we're dealing with a syntax (e.g., UTF8String)
1192 * which allows empty strings
1194 normalized->bv_len = 0;
1195 normalized->bv_val = NULL;
1196 return LDAP_SUCCESS;
1199 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1200 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1201 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1202 ? LDAP_UTF8_APPROX : 0;
1204 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1209 /* collapse spaces (in place) */
1211 nvalue.bv_val = tmp.bv_val;
1213 wasspace=1; /* trim leading spaces */
1214 for( i=0; i<tmp.bv_len; i++) {
1215 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1216 if( wasspace++ == 0 ) {
1217 /* trim repeated spaces */
1218 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1222 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1226 if( nvalue.bv_len ) {
1228 /* last character was a space, trim it */
1231 nvalue.bv_val[nvalue.bv_len] = '\0';
1234 /* string of all spaces is treated as one space */
1235 nvalue.bv_val[0] = ' ';
1236 nvalue.bv_val[1] = '\0';
1240 *normalized = nvalue;
1241 return LDAP_SUCCESS;
1244 #if defined(SLAPD_APPROX_INITIALS)
1245 # define SLAPD_APPROX_DELIMITER "._ "
1246 # define SLAPD_APPROX_WORDLEN 2
1248 # define SLAPD_APPROX_DELIMITER " "
1249 # define SLAPD_APPROX_WORDLEN 1
1258 struct berval *value,
1259 void *assertedValue )
1261 struct berval *nval, *assertv;
1262 char *val, **values, **words, *c;
1263 int i, count, len, nextchunk=0, nextavail=0;
1265 /* Yes, this is necessary */
1266 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1267 if( nval == NULL ) {
1269 return LDAP_SUCCESS;
1272 /* Yes, this is necessary */
1273 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1274 NULL, LDAP_UTF8_APPROX, NULL );
1275 if( assertv == NULL ) {
1278 return LDAP_SUCCESS;
1281 /* Isolate how many words there are */
1282 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1283 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1284 if ( c == NULL ) break;
1289 /* Get a phonetic copy of each word */
1290 words = (char **)ch_malloc( count * sizeof(char *) );
1291 values = (char **)ch_malloc( count * sizeof(char *) );
1292 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1294 values[i] = phonetic(c);
1297 /* Work through the asserted value's words, to see if at least some
1298 of the words are there, in the same order. */
1300 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1301 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1306 #if defined(SLAPD_APPROX_INITIALS)
1307 else if( len == 1 ) {
1308 /* Single letter words need to at least match one word's initial */
1309 for( i=nextavail; i<count; i++ )
1310 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1317 /* Isolate the next word in the asserted value and phonetic it */
1318 assertv->bv_val[nextchunk+len] = '\0';
1319 val = phonetic( assertv->bv_val + nextchunk );
1321 /* See if this phonetic chunk is in the remaining words of *value */
1322 for( i=nextavail; i<count; i++ ){
1323 if( !strcmp( val, values[i] ) ){
1331 /* This chunk in the asserted value was NOT within the *value. */
1337 /* Go on to the next word in the asserted value */
1341 /* If some of the words were seen, call it a match */
1342 if( nextavail > 0 ) {
1349 /* Cleanup allocs */
1350 ber_bvfree( assertv );
1351 for( i=0; i<count; i++ ) {
1352 ch_free( values[i] );
1358 return LDAP_SUCCESS;
1367 struct berval *prefix,
1373 int i,j, len, wordcount, keycount=0;
1374 struct berval *newkeys;
1375 BerVarray keys=NULL;
1377 for( j=0; values[j].bv_val != NULL; j++ ) {
1378 struct berval val = BER_BVNULL;
1379 /* Yes, this is necessary */
1380 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1381 assert( val.bv_val != NULL );
1383 /* Isolate how many words there are. There will be a key for each */
1384 for( wordcount = 0, c = val.bv_val; *c; c++) {
1385 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1386 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1388 if (*c == '\0') break;
1392 /* Allocate/increase storage to account for new keys */
1393 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1394 * sizeof(struct berval) );
1395 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1396 if( keys ) ch_free( keys );
1399 /* Get a phonetic copy of each word */
1400 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1402 if( len < SLAPD_APPROX_WORDLEN ) continue;
1403 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1408 ber_memfree( val.bv_val );
1410 keys[keycount].bv_val = NULL;
1413 return LDAP_SUCCESS;
1422 struct berval *prefix,
1423 void * assertedValue,
1432 /* Yes, this is necessary */
1433 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1434 NULL, LDAP_UTF8_APPROX, NULL );
1435 if( val == NULL || val->bv_val == NULL ) {
1436 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1437 keys[0].bv_val = NULL;
1440 return LDAP_SUCCESS;
1443 /* Isolate how many words there are. There will be a key for each */
1444 for( count = 0,c = val->bv_val; *c; c++) {
1445 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1446 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1448 if (*c == '\0') break;
1452 /* Allocate storage for new keys */
1453 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1455 /* Get a phonetic copy of each word */
1456 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1458 if( len < SLAPD_APPROX_WORDLEN ) continue;
1459 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1465 keys[count].bv_val = NULL;
1468 return LDAP_SUCCESS;
1471 /* Remove all spaces and '-' characters */
1473 telephoneNumberNormalize(
1478 struct berval *normalized,
1483 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1485 /* validator should have refused an empty string */
1486 assert( val->bv_len );
1488 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1490 for( p = val->bv_val; *p; p++ ) {
1491 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1497 normalized->bv_len = q - normalized->bv_val;
1499 if( normalized->bv_len == 0 ) {
1500 sl_free( normalized->bv_val, ctx );
1501 normalized->bv_val = NULL;
1502 return LDAP_INVALID_SYNTAX;
1505 return LDAP_SUCCESS;
1513 struct berval val = *in;
1515 if( val.bv_len == 0 ) {
1516 /* disallow empty strings */
1517 return LDAP_INVALID_SYNTAX;
1520 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1521 if ( val.bv_len == 1 ) {
1522 return LDAP_SUCCESS;
1525 if ( val.bv_val[0] == '0' ) {
1532 while ( OID_LEADCHAR( val.bv_val[0] )) {
1536 if ( val.bv_len == 0 ) {
1537 return LDAP_SUCCESS;
1541 if( !OID_SEPARATOR( val.bv_val[0] )) {
1549 return LDAP_INVALID_SYNTAX;
1558 struct berval val = *in;
1560 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1562 if ( val.bv_val[0] == '-' ) {
1566 if( val.bv_len == 0 ) { /* bare "-" */
1567 return LDAP_INVALID_SYNTAX;
1570 if( val.bv_val[0] == '0' ) { /* "-0" */
1571 return LDAP_INVALID_SYNTAX;
1574 } else if ( val.bv_val[0] == '0' ) {
1575 if( val.bv_len > 1 ) { /* "0<more>" */
1576 return LDAP_INVALID_SYNTAX;
1579 return LDAP_SUCCESS;
1582 for( i=0; i < val.bv_len; i++ ) {
1583 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1584 return LDAP_INVALID_SYNTAX;
1588 return LDAP_SUCCESS;
1597 struct berval *value,
1598 void *assertedValue )
1600 struct berval *asserted = (struct berval *) assertedValue;
1601 int vsign = 1, asign = 1; /* default sign = '+' */
1606 if( v.bv_val[0] == '-' ) {
1612 if( v.bv_len == 0 ) vsign = 0;
1615 if( a.bv_val[0] == '-' ) {
1621 if( a.bv_len == 0 ) vsign = 0;
1623 match = vsign - asign;
1625 match = ( v.bv_len != a.bv_len
1626 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1627 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1628 if( vsign < 0 ) match = -match;
1632 return LDAP_SUCCESS;
1636 countryStringValidate(
1638 struct berval *val )
1640 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1642 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1643 return LDAP_INVALID_SYNTAX;
1645 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1646 return LDAP_INVALID_SYNTAX;
1649 return LDAP_SUCCESS;
1653 printableStringValidate(
1655 struct berval *val )
1659 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1661 for(i=0; i < val->bv_len; i++) {
1662 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1663 return LDAP_INVALID_SYNTAX;
1667 return LDAP_SUCCESS;
1671 printablesStringValidate(
1673 struct berval *val )
1677 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1679 for(i=0,len=0; i < val->bv_len; i++) {
1680 int c = val->bv_val[i];
1684 return LDAP_INVALID_SYNTAX;
1688 } else if ( SLAP_PRINTABLE(c) ) {
1691 return LDAP_INVALID_SYNTAX;
1696 return LDAP_INVALID_SYNTAX;
1699 return LDAP_SUCCESS;
1705 struct berval *val )
1709 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1711 for(i=0; i < val->bv_len; i++) {
1712 if( !LDAP_ASCII(val->bv_val[i]) ) {
1713 return LDAP_INVALID_SYNTAX;
1717 return LDAP_SUCCESS;
1726 struct berval *normalized,
1730 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1732 assert( val->bv_len );
1734 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1738 /* Ignore initial whitespace */
1739 while ( ASCII_SPACE( *p ) ) p++;
1741 normalized->bv_val = ber_strdup_x( p, ctx );
1742 p = q = normalized->bv_val;
1745 if ( ASCII_SPACE( *p ) ) {
1748 /* Ignore the extra whitespace */
1749 while ( ASCII_SPACE( *p ) ) {
1753 } else if ( casefold ) {
1754 /* Most IA5 rules require casefolding */
1755 *q++ = TOLOWER(*p); p++;
1762 assert( normalized->bv_val <= p );
1766 * If the string ended in space, backup the pointer one
1767 * position. One is enough because the above loop collapsed
1768 * all whitespace to a single space.
1770 if ( ASCII_SPACE( q[-1] ) ) --q;
1772 /* null terminate */
1775 normalized->bv_len = q - normalized->bv_val;
1776 if( normalized->bv_len == 0 ) {
1777 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1778 normalized->bv_val[0] = ' ';
1779 normalized->bv_val[1] = '\0';
1780 normalized->bv_len = 1;
1783 return LDAP_SUCCESS;
1792 if( in->bv_len != 36 ) {
1794 return LDAP_INVALID_SYNTAX;
1797 for( i=0; i<36; i++ ) {
1803 if( in->bv_val[i] != '-' ) {
1804 return LDAP_INVALID_SYNTAX;
1808 if( !ASCII_HEX( in->bv_val[i]) ) {
1809 return LDAP_INVALID_SYNTAX;
1814 return LDAP_SUCCESS;
1823 struct berval *normalized,
1826 unsigned char octet = '\0';
1829 normalized->bv_len = 16;
1830 normalized->bv_val = sl_malloc( normalized->bv_len+1, ctx );
1832 for( i=0, j=0; i<36; i++ ) {
1833 unsigned char nibble;
1834 if( val->bv_val[i] == '-' ) {
1837 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1838 nibble = val->bv_val[i] - '0';
1840 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1841 nibble = val->bv_val[i] - ('a'-10);
1843 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1844 nibble = val->bv_val[i] - ('A'-10);
1847 sl_free( normalized->bv_val, ctx );
1848 return LDAP_INVALID_SYNTAX;
1853 normalized->bv_val[j>>1] = octet;
1855 octet = nibble << 4;
1860 normalized->bv_val[normalized->bv_len] = 0;
1861 return LDAP_SUCCESS;
1867 numericStringValidate(
1873 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1875 for(i=0; i < in->bv_len; i++) {
1876 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1877 return LDAP_INVALID_SYNTAX;
1881 return LDAP_SUCCESS;
1885 numericStringNormalize(
1890 struct berval *normalized,
1893 /* removal all spaces */
1896 assert( val->bv_len );
1898 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1901 q = normalized->bv_val;
1904 if ( ASCII_SPACE( *p ) ) {
1905 /* Ignore whitespace */
1912 /* we should have copied no more then is in val */
1913 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1915 /* null terminate */
1918 normalized->bv_len = q - normalized->bv_val;
1920 if( normalized->bv_len == 0 ) {
1921 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1922 normalized->bv_val[0] = ' ';
1923 normalized->bv_val[1] = '\0';
1924 normalized->bv_len = 1;
1927 return LDAP_SUCCESS;
1931 * Integer conversion macros that will use the largest available
1934 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1935 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1936 # define SLAP_LONG_MAX LLONG_MAX
1937 # define SLAP_LONG_MIN LLONG_MIN
1938 # define SLAP_LONG long long
1940 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1941 # define SLAP_LONG_MAX LONG_MAX
1942 # define SLAP_LONG_MIN LONG_MIN
1943 # define SLAP_LONG long
1944 #endif /* HAVE_STRTOLL ... */
1952 struct berval *value,
1953 void *assertedValue )
1955 SLAP_LONG lValue, lAssertedValue;
1957 /* safe to assume integers are NUL terminated? */
1958 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1959 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
1960 return LDAP_CONSTRAINT_VIOLATION;
1963 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1964 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1965 && errno == ERANGE )
1967 return LDAP_CONSTRAINT_VIOLATION;
1970 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1971 return LDAP_SUCCESS;
1980 struct berval *value,
1981 void *assertedValue )
1983 SLAP_LONG lValue, lAssertedValue;
1985 /* safe to assume integers are NUL terminated? */
1986 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1987 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
1990 return LDAP_CONSTRAINT_VIOLATION;
1993 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
1995 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1996 && errno == ERANGE )
1998 return LDAP_CONSTRAINT_VIOLATION;
2001 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2002 return LDAP_SUCCESS;
2006 serialNumberAndIssuerValidate(
2013 struct berval sn, i;
2014 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2016 i.bv_val = strchr( in->bv_val, '$' );
2017 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2019 sn.bv_val = in->bv_val;
2020 sn.bv_len = i.bv_val - in->bv_val;
2023 i.bv_len = in->bv_len - (sn.bv_len + 1);
2025 /* validate serial number (strict for now) */
2026 for( n=0; n < sn.bv_len; n++ ) {
2027 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2028 return LDAP_INVALID_SYNTAX;
2033 rc = dnValidate( NULL, &i );
2034 if( rc ) return LDAP_INVALID_SYNTAX;
2036 return LDAP_SUCCESS;
2040 serialNumberAndIssuerPretty(
2049 struct berval sn, i, newi;
2055 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2056 val->bv_val, 0, 0 );
2058 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2059 val->bv_val, 0, 0 );
2062 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2064 i.bv_val = strchr( val->bv_val, '$' );
2065 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2067 sn.bv_val = val->bv_val;
2068 sn.bv_len = i.bv_val - val->bv_val;
2071 i.bv_len = val->bv_len - (sn.bv_len + 1);
2073 /* eat leading zeros */
2074 for( n=0; n < (sn.bv_len-1); n++ ) {
2075 if( sn.bv_val[n] != '0' ) break;
2080 for( n=0; n < sn.bv_len; n++ ) {
2081 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2082 return LDAP_INVALID_SYNTAX;
2087 rc = dnPretty( syntax, &i, &newi, ctx );
2088 if( rc ) return LDAP_INVALID_SYNTAX;
2090 /* make room from sn + "$" */
2091 out->bv_len = sn.bv_len + newi.bv_len + 1;
2092 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2094 if( out->bv_val == NULL ) {
2095 sl_free( newi.bv_val, ctx );
2099 /* push issuer over */
2100 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2101 /* insert sn and "$" */
2102 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2103 out->bv_val[sn.bv_len] = '$';
2105 out->bv_val[out->bv_len] = '\0';
2108 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2109 out->bv_val, 0, 0 );
2111 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2112 out->bv_val, 0, 0 );
2115 return LDAP_SUCCESS;
2119 * This routine is called by certificateExactNormalize when
2120 * certificateExactNormalize receives a search string instead of
2121 * a certificate. This routine checks if the search value is valid
2122 * and then returns the normalized value
2125 serialNumberAndIssuerNormalize(
2136 struct berval sn, i, newi;
2142 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2143 val->bv_val, 0, 0 );
2145 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2146 val->bv_val, 0, 0 );
2149 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2151 i.bv_val = strchr( val->bv_val, '$' );
2152 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2154 sn.bv_val = val->bv_val;
2155 sn.bv_len = i.bv_val - val->bv_val;
2158 i.bv_len = val->bv_len - (sn.bv_len + 1);
2160 /* eat leading zeros */
2161 for( n=0; n < (sn.bv_len-1); n++ ) {
2162 if( sn.bv_val[n] != '0' ) break;
2167 for( n=0; n < sn.bv_len; n++ ) {
2168 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2169 return LDAP_INVALID_SYNTAX;
2174 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2175 if( rc ) return LDAP_INVALID_SYNTAX;
2177 /* make room from sn + "$" */
2178 out->bv_len = sn.bv_len + newi.bv_len + 1;
2179 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2181 if( out->bv_val == NULL ) {
2182 sl_free( newi.bv_val, ctx );
2186 /* push issuer over */
2187 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2188 /* insert sn and "$" */
2189 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2190 out->bv_val[sn.bv_len] = '$';
2192 out->bv_val[out->bv_len] = '\0';
2195 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2196 out->bv_val, 0, 0 );
2198 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2199 out->bv_val, 0, 0 );
2207 certificateExactNormalize(
2212 struct berval *normalized,
2215 int rc = LDAP_INVALID_SYNTAX;
2217 char *serial = NULL;
2218 ber_len_t seriallen;
2219 struct berval issuer_dn = BER_BVNULL;
2220 X509_NAME *name = NULL;
2221 ASN1_INTEGER *sn = NULL;
2224 if( val->bv_len == 0 ) goto done;
2226 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2227 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2230 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2232 p = (unsigned char *)val->bv_val;
2233 xcert = d2i_X509( NULL, &p, val->bv_len);
2234 if( xcert == NULL ) goto done;
2236 sn=X509_get_serialNumber(xcert);
2237 if ( sn == NULL ) goto done;
2238 serial=i2s_ASN1_INTEGER(0, sn );
2239 if( serial == NULL ) goto done;
2240 seriallen=strlen(serial);
2242 name=X509_get_issuer_name(xcert);
2243 if( name == NULL ) goto done;
2244 rc = dnX509normalize( name, &issuer_dn );
2245 if( rc != LDAP_SUCCESS ) goto done;
2247 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2248 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2249 p = (unsigned char *)normalized->bv_val;
2250 AC_MEMCPY(p, serial, seriallen);
2253 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2254 p += issuer_dn.bv_len;
2258 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2259 normalized->bv_val, 0, 0 );
2261 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2262 normalized->bv_val, NULL, NULL );
2266 if (xcert) X509_free(xcert);
2267 if (serial) ch_free(serial);
2268 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2272 #endif /* HAVE_TLS */
2275 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2276 /* slight optimization - does not need the start parameter */
2277 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2282 check_time_syntax (struct berval *val,
2285 struct berval *fraction)
2288 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2289 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2290 * GeneralizedTime supports leap seconds, UTCTime does not.
2292 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2293 static const int mdays[2][12] = {
2294 /* non-leap years */
2295 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2297 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2300 int part, c, c1, c2, tzoffset, leapyear = 0;
2303 e = p + val->bv_len;
2305 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2306 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2308 for (part = start; part < 7 && p < e; part++) {
2310 if (!ASCII_DIGIT(c1)) {
2315 return LDAP_INVALID_SYNTAX;
2318 if (!ASCII_DIGIT(c)) {
2319 return LDAP_INVALID_SYNTAX;
2321 c += c1 * 10 - '0' * 11;
2322 if ((part | 1) == 3) {
2325 return LDAP_INVALID_SYNTAX;
2328 if (c >= ceiling[part]) {
2329 if (! (c == 60 && part == 6 && start == 0))
2330 return LDAP_INVALID_SYNTAX;
2334 if (part < 5 + start) {
2335 return LDAP_INVALID_SYNTAX;
2337 for (; part < 9; part++) {
2341 /* leapyear check for the Gregorian calendar (year>1581) */
2342 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2347 if (parts[3] >= mdays[leapyear][parts[2]]) {
2348 return LDAP_INVALID_SYNTAX;
2352 fraction->bv_val = p;
2353 fraction->bv_len = 0;
2354 if (p < e && (*p == '.' || *p == ',')) {
2356 while (++p < e && ASCII_DIGIT(*p))
2358 if (p - fraction->bv_val == 1) {
2359 return LDAP_INVALID_SYNTAX;
2361 for (end_num = p; end_num[-1] == '0'; --end_num)
2363 c = end_num - fraction->bv_val;
2365 fraction->bv_len = c;
2371 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2377 return LDAP_INVALID_SYNTAX;
2383 for (part = 7; part < 9 && p < e; part++) {
2385 if (!ASCII_DIGIT(c1)) {
2390 return LDAP_INVALID_SYNTAX;
2393 if (!ASCII_DIGIT(c2)) {
2394 return LDAP_INVALID_SYNTAX;
2396 parts[part] = c1 * 10 + c2 - '0' * 11;
2397 if (parts[part] >= ceiling[part]) {
2398 return LDAP_INVALID_SYNTAX;
2401 if (part < 8 + start) {
2402 return LDAP_INVALID_SYNTAX;
2405 if (tzoffset == '-') {
2406 /* negative offset to UTC, ie west of Greenwich */
2407 parts[4] += parts[7];
2408 parts[5] += parts[8];
2409 /* offset is just hhmm, no seconds */
2410 for (part = 6; --part >= 0; ) {
2414 c = mdays[leapyear][parts[2]];
2416 if (parts[part] >= c) {
2418 return LDAP_INVALID_SYNTAX;
2423 } else if (part != 5) {
2428 /* positive offset to UTC, ie east of Greenwich */
2429 parts[4] -= parts[7];
2430 parts[5] -= parts[8];
2431 for (part = 6; --part >= 0; ) {
2432 if (parts[part] < 0) {
2434 return LDAP_INVALID_SYNTAX;
2439 /* make first arg to % non-negative */
2440 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2445 } else if (part != 5) {
2452 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2455 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2462 struct berval *normalized )
2466 rc = check_time_syntax(val, 1, parts, NULL);
2467 if (rc != LDAP_SUCCESS) {
2471 normalized->bv_val = ch_malloc( 14 );
2472 if ( normalized->bv_val == NULL ) {
2473 return LBER_ERROR_MEMORY;
2476 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2477 parts[1], parts[2] + 1, parts[3] + 1,
2478 parts[4], parts[5], parts[6] );
2479 normalized->bv_len = 13;
2481 return LDAP_SUCCESS;
2491 return check_time_syntax(in, 1, parts, NULL);
2494 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2497 generalizedTimeValidate(
2502 struct berval fraction;
2503 return check_time_syntax(in, 0, parts, &fraction);
2507 generalizedTimeNormalize(
2512 struct berval *normalized,
2517 struct berval fraction;
2519 rc = check_time_syntax(val, 0, parts, &fraction);
2520 if (rc != LDAP_SUCCESS) {
2524 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2525 normalized->bv_val = sl_malloc( len + 1, ctx );
2526 if ( normalized->bv_val == NULL ) {
2527 return LBER_ERROR_MEMORY;
2530 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2531 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2532 parts[4], parts[5], parts[6] );
2533 if ( fraction.bv_len ) {
2534 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2535 fraction.bv_val, fraction.bv_len );
2536 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2538 strcpy( normalized->bv_val + len-1, "Z" );
2539 normalized->bv_len = len;
2541 return LDAP_SUCCESS;
2545 generalizedTimeOrderingMatch(
2550 struct berval *value,
2551 void *assertedValue )
2553 struct berval *asserted = (struct berval *) assertedValue;
2554 ber_len_t v_len = value->bv_len;
2555 ber_len_t av_len = asserted->bv_len;
2557 /* ignore trailing 'Z' when comparing */
2558 int match = memcmp( value->bv_val, asserted->bv_val,
2559 (v_len < av_len ? v_len : av_len) - 1 );
2560 if ( match == 0 ) match = v_len - av_len;
2563 return LDAP_SUCCESS;
2567 deliveryMethodValidate(
2569 struct berval *val )
2572 #define LENOF(s) (sizeof(s)-1)
2573 struct berval tmp = *val;
2575 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2576 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2577 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2580 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2582 switch( tmp.bv_val[0] ) {
2585 if(( tmp.bv_len >= LENOF("any") ) &&
2586 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2588 tmp.bv_len -= LENOF("any");
2589 tmp.bv_val += LENOF("any");
2592 return LDAP_INVALID_SYNTAX;
2596 if(( tmp.bv_len >= LENOF("mhs") ) &&
2597 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2599 tmp.bv_len -= LENOF("mhs");
2600 tmp.bv_val += LENOF("mhs");
2603 return LDAP_INVALID_SYNTAX;
2607 if(( tmp.bv_len >= LENOF("physical") ) &&
2608 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2610 tmp.bv_len -= LENOF("physical");
2611 tmp.bv_val += LENOF("physical");
2614 return LDAP_INVALID_SYNTAX;
2617 case 'T': /* telex or teletex or telephone */
2618 if(( tmp.bv_len >= LENOF("telex") ) &&
2619 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2621 tmp.bv_len -= LENOF("telex");
2622 tmp.bv_val += LENOF("telex");
2625 if(( tmp.bv_len >= LENOF("teletex") ) &&
2626 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2628 tmp.bv_len -= LENOF("teletex");
2629 tmp.bv_val += LENOF("teletex");
2632 if(( tmp.bv_len >= LENOF("telephone") ) &&
2633 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2635 tmp.bv_len -= LENOF("telephone");
2636 tmp.bv_val += LENOF("telephone");
2639 return LDAP_INVALID_SYNTAX;
2642 case 'G': /* g3fax or g4fax */
2643 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2644 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2645 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2647 tmp.bv_len -= LENOF("g3fax");
2648 tmp.bv_val += LENOF("g3fax");
2651 return LDAP_INVALID_SYNTAX;
2655 if(( tmp.bv_len >= LENOF("ia5") ) &&
2656 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2658 tmp.bv_len -= LENOF("ia5");
2659 tmp.bv_val += LENOF("ia5");
2662 return LDAP_INVALID_SYNTAX;
2666 if(( tmp.bv_len >= LENOF("videotex") ) &&
2667 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2669 tmp.bv_len -= LENOF("videotex");
2670 tmp.bv_val += LENOF("videotex");
2673 return LDAP_INVALID_SYNTAX;
2676 return LDAP_INVALID_SYNTAX;
2679 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2681 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2685 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2689 return LDAP_INVALID_SYNTAX;
2691 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2700 nisNetgroupTripleValidate(
2702 struct berval *val )
2707 if ( val->bv_len == 0 ) {
2708 return LDAP_INVALID_SYNTAX;
2711 p = (char *)val->bv_val;
2712 e = p + val->bv_len;
2714 if ( *p != '(' /*')'*/ ) {
2715 return LDAP_INVALID_SYNTAX;
2718 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2722 return LDAP_INVALID_SYNTAX;
2725 } else if ( !AD_CHAR( *p ) ) {
2726 return LDAP_INVALID_SYNTAX;
2730 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2731 return LDAP_INVALID_SYNTAX;
2737 return LDAP_INVALID_SYNTAX;
2740 return LDAP_SUCCESS;
2744 bootParameterValidate(
2746 struct berval *val )
2750 if ( val->bv_len == 0 ) {
2751 return LDAP_INVALID_SYNTAX;
2754 p = (char *)val->bv_val;
2755 e = p + val->bv_len;
2758 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2759 if ( !AD_CHAR( *p ) ) {
2760 return LDAP_INVALID_SYNTAX;
2765 return LDAP_INVALID_SYNTAX;
2769 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2770 if ( !AD_CHAR( *p ) ) {
2771 return LDAP_INVALID_SYNTAX;
2776 return LDAP_INVALID_SYNTAX;
2780 for ( p++; p < e; p++ ) {
2781 if ( !SLAP_PRINTABLE( *p ) ) {
2782 return LDAP_INVALID_SYNTAX;
2786 return LDAP_SUCCESS;
2790 firstComponentNormalize(
2795 struct berval *normalized,
2802 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2803 ber_dupbv_x( normalized, val, ctx );
2804 return LDAP_SUCCESS;
2807 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2809 if( val->bv_val[0] != '(' /*')'*/ &&
2810 val->bv_val[0] != '{' /*'}'*/ )
2812 return LDAP_INVALID_SYNTAX;
2815 /* trim leading white space */
2817 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2823 /* grab next word */
2824 comp.bv_val = &val->bv_val[len];
2825 len = val->bv_len - len;
2827 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2833 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2834 rc = numericoidValidate( NULL, &comp );
2835 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2836 rc = integerValidate( NULL, &comp );
2838 rc = LDAP_INVALID_SYNTAX;
2842 if( rc == LDAP_SUCCESS ) {
2843 ber_dupbv_x( normalized, &comp, ctx );
2850 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2851 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2853 static slap_syntax_defs_rec syntax_defs[] = {
2854 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2855 X_BINARY X_NOT_H_R ")",
2856 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2857 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2859 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2861 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2863 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2864 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2866 SLAP_SYNTAX_BER, berValidate, NULL},
2867 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2868 0, bitStringValidate, NULL },
2869 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2870 0, booleanValidate, NULL},
2871 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2872 X_BINARY X_NOT_H_R ")",
2873 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2874 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2875 X_BINARY X_NOT_H_R ")",
2876 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2877 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2878 X_BINARY X_NOT_H_R ")",
2879 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2880 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2881 0, countryStringValidate, NULL},
2882 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2883 0, dnValidate, dnPretty},
2884 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2886 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2887 0, deliveryMethodValidate, NULL},
2888 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2889 0, UTF8StringValidate, NULL},
2890 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2892 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2894 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2896 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2898 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2900 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2901 0, printablesStringValidate, NULL},
2902 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2903 SLAP_SYNTAX_BLOB, NULL, NULL},
2904 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2905 0, generalizedTimeValidate, NULL},
2906 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2908 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2909 0, IA5StringValidate, NULL},
2910 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2911 0, integerValidate, NULL},
2912 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2913 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2914 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2916 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2918 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2920 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2922 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2924 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2925 0, nameUIDValidate, nameUIDPretty },
2926 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2928 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2929 0, numericStringValidate, NULL},
2930 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2932 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2933 0, numericoidValidate, NULL},
2934 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2935 0, IA5StringValidate, NULL},
2936 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2937 0, blobValidate, NULL},
2938 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2939 0, UTF8StringValidate, NULL},
2940 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2942 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2944 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2945 0, printableStringValidate, NULL},
2946 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2947 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2948 0, subtreeSpecificationValidate, NULL},
2949 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2950 X_BINARY X_NOT_H_R ")",
2951 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2952 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2953 0, printableStringValidate, NULL},
2954 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2956 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2957 0, printablesStringValidate, NULL},
2958 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2959 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2960 0, utcTimeValidate, NULL},
2962 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2964 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2966 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2968 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2970 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2973 /* RFC 2307 NIS Syntaxes */
2974 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2975 0, nisNetgroupTripleValidate, NULL},
2976 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2977 0, bootParameterValidate, NULL},
2979 /* From PKIX *//* This OID is not published yet. */
2980 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
2982 serialNumberAndIssuerValidate,
2983 serialNumberAndIssuerPretty},
2985 #ifdef SLAPD_ACI_ENABLED
2986 /* OpenLDAP Experimental Syntaxes */
2987 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2989 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2993 #ifdef SLAPD_AUTHPASSWD
2994 /* needs updating */
2995 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2996 SLAP_SYNTAX_HIDE, NULL, NULL},
2999 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3000 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3002 /* OpenLDAP Void Syntax */
3003 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3004 SLAP_SYNTAX_HIDE, inValidate, NULL},
3005 {NULL, 0, NULL, NULL}
3008 char *certificateExactMatchSyntaxes[] = {
3009 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3012 char *directoryStringSyntaxes[] = {
3013 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3016 char *integerFirstComponentMatchSyntaxes[] = {
3017 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3018 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3021 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3022 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3023 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3024 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3025 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3026 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3027 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3028 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3029 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3034 * Other matching rules in X.520 that we do not use (yet):
3036 * 2.5.13.25 uTCTimeMatch
3037 * 2.5.13.26 uTCTimeOrderingMatch
3038 * 2.5.13.31* directoryStringFirstComponentMatch
3039 * 2.5.13.32* wordMatch
3040 * 2.5.13.33* keywordMatch
3041 * 2.5.13.36 certificatePairExactMatch
3042 * 2.5.13.37 certificatePairMatch
3043 * 2.5.13.38 certificateListExactMatch
3044 * 2.5.13.39 certificateListMatch
3045 * 2.5.13.40 algorithmIdentifierMatch
3046 * 2.5.13.41* storedPrefixMatch
3047 * 2.5.13.42 attributeCertificateMatch
3048 * 2.5.13.43 readerAndKeyIDMatch
3049 * 2.5.13.44 attributeIntegrityMatch
3051 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3053 static slap_mrule_defs_rec mrule_defs[] = {
3055 * EQUALITY matching rules must be listed after associated APPROX
3056 * matching rules. So, we list all APPROX matching rules first.
3058 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3059 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3060 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3061 NULL, NULL, directoryStringApproxMatch,
3062 directoryStringApproxIndexer, directoryStringApproxFilter,
3065 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3066 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3067 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3068 NULL, NULL, IA5StringApproxMatch,
3069 IA5StringApproxIndexer, IA5StringApproxFilter,
3073 * Other matching rules
3076 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3077 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3078 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3079 NULL, NULL, octetStringMatch,
3080 octetStringIndexer, octetStringFilter,
3083 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3084 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3085 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3086 NULL, dnNormalize, dnMatch,
3087 octetStringIndexer, octetStringFilter,
3090 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3091 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3092 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3093 NULL, UTF8StringNormalize, octetStringMatch,
3094 octetStringIndexer, octetStringFilter,
3095 directoryStringApproxMatchOID },
3097 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3098 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3099 SLAP_MR_ORDERING, directoryStringSyntaxes,
3100 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3102 "caseIgnoreMatch" },
3104 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3105 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3106 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3107 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3108 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3109 "caseIgnoreMatch" },
3111 {"( 2.5.13.5 NAME 'caseExactMatch' "
3112 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3113 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3114 NULL, UTF8StringNormalize, octetStringMatch,
3115 octetStringIndexer, octetStringFilter,
3116 directoryStringApproxMatchOID },
3118 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3119 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3120 SLAP_MR_ORDERING, directoryStringSyntaxes,
3121 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3125 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3126 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3127 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3128 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3129 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3132 {"( 2.5.13.8 NAME 'numericStringMatch' "
3133 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3134 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3135 NULL, numericStringNormalize, octetStringMatch,
3136 octetStringIndexer, octetStringFilter,
3139 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3140 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3141 SLAP_MR_ORDERING, NULL,
3142 NULL, numericStringNormalize, octetStringOrderingMatch,
3144 "numericStringMatch" },
3146 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3147 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3148 SLAP_MR_SUBSTR, NULL,
3149 NULL, numericStringNormalize, octetStringSubstringsMatch,
3150 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3151 "numericStringMatch" },
3153 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3154 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3155 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3156 NULL, NULL, NULL, NULL, NULL, NULL },
3158 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3159 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3160 SLAP_MR_SUBSTR, NULL,
3161 NULL, NULL, NULL, NULL, NULL,
3162 "caseIgnoreListMatch" },
3164 {"( 2.5.13.13 NAME 'booleanMatch' "
3165 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3166 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3167 NULL, NULL, booleanMatch,
3168 octetStringIndexer, octetStringFilter,
3171 {"( 2.5.13.14 NAME 'integerMatch' "
3172 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3173 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3174 NULL, NULL, integerMatch,
3175 octetStringIndexer, octetStringFilter,
3178 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3179 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3180 SLAP_MR_ORDERING, NULL,
3181 NULL, NULL, integerMatch,
3185 {"( 2.5.13.16 NAME 'bitStringMatch' "
3186 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3187 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3188 NULL, NULL, octetStringMatch,
3189 octetStringIndexer, octetStringFilter,
3192 {"( 2.5.13.17 NAME 'octetStringMatch' "
3193 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3194 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3195 NULL, NULL, octetStringMatch,
3196 octetStringIndexer, octetStringFilter,
3199 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3200 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3201 SLAP_MR_ORDERING, NULL,
3202 NULL, NULL, octetStringOrderingMatch,
3204 "octetStringMatch" },
3206 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3207 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3208 SLAP_MR_SUBSTR, NULL,
3209 NULL, NULL, octetStringSubstringsMatch,
3210 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3211 "octetStringMatch" },
3213 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3214 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3215 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3217 telephoneNumberNormalize, octetStringMatch,
3218 octetStringIndexer, octetStringFilter,
3221 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3222 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3223 SLAP_MR_SUBSTR, NULL,
3224 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3225 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3226 "telephoneNumberMatch" },
3228 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3229 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3230 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3231 NULL, NULL, NULL, NULL, NULL, NULL },
3233 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3234 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3235 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3236 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3240 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3241 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3242 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3243 NULL, NULL, NULL, NULL, NULL, NULL },
3245 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3246 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3247 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3248 NULL, generalizedTimeNormalize, octetStringMatch,
3252 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3253 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3254 SLAP_MR_ORDERING, NULL,
3255 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3257 "generalizedTimeMatch" },
3259 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3260 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3261 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3262 integerFirstComponentMatchSyntaxes,
3263 NULL, firstComponentNormalize, integerMatch,
3264 octetStringIndexer, octetStringFilter,
3267 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3268 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3269 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3270 objectIdentifierFirstComponentMatchSyntaxes,
3271 NULL, firstComponentNormalize, octetStringMatch,
3272 octetStringIndexer, octetStringFilter,
3275 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3276 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3277 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3279 NULL, certificateExactNormalize, octetStringMatch,
3280 octetStringIndexer, octetStringFilter,
3282 NULL, NULL, NULL, NULL, NULL,
3286 {"( 2.5.13.35 NAME 'certificateMatch' "
3287 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3288 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3290 NULL, NULL, octetStringMatch,
3291 octetStringIndexer, octetStringFilter,
3293 NULL, NULL, NULL, NULL, NULL,
3297 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3298 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3299 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3300 NULL, IA5StringNormalize, octetStringMatch,
3301 octetStringIndexer, octetStringFilter,
3302 IA5StringApproxMatchOID },
3304 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3305 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3306 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3307 NULL, IA5StringNormalize, octetStringMatch,
3308 octetStringIndexer, octetStringFilter,
3309 IA5StringApproxMatchOID },
3311 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3312 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3313 SLAP_MR_SUBSTR, NULL,
3314 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3315 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3316 "caseIgnoreIA5Match" },
3318 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3319 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3320 SLAP_MR_SUBSTR, NULL,
3321 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3322 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3323 "caseExactIA5Match" },
3325 #ifdef SLAPD_AUTHPASSWD
3326 /* needs updating */
3327 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3328 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3329 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3330 NULL, NULL, authPasswordMatch,
3335 #ifdef SLAPD_ACI_ENABLED
3336 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3337 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3338 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3339 NULL, NULL, OpenLDAPaciMatch,
3344 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3345 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3347 NULL, NULL, integerBitAndMatch,
3351 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3352 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3354 NULL, NULL, integerBitOrMatch,
3358 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3359 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3360 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3361 NULL, UUIDNormalize, octetStringMatch,
3362 octetStringIndexer, octetStringFilter,
3365 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3366 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3367 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3368 NULL, UUIDNormalize, octetStringOrderingMatch,
3369 octetStringIndexer, octetStringFilter,
3372 {NULL, SLAP_MR_NONE, NULL,
3373 NULL, NULL, NULL, NULL, NULL,
3378 slap_schema_init( void )
3383 /* we should only be called once (from main) */
3384 assert( schema_init_done == 0 );
3386 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3387 res = register_syntax( &syntax_defs[i] );
3390 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3391 syntax_defs[i].sd_desc );
3396 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3397 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3398 mrule_defs[i].mrd_compat_syntaxes == NULL )
3401 "slap_schema_init: Ignoring unusable matching rule %s\n",
3402 mrule_defs[i].mrd_desc );
3406 res = register_matching_rule( &mrule_defs[i] );
3410 "slap_schema_init: Error registering matching rule %s\n",
3411 mrule_defs[i].mrd_desc );
3416 res = slap_schema_load();
3417 schema_init_done = 1;
3422 schema_destroy( void )