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 = slap_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 = slap_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( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
409 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MAXLEN ) {
410 nkeys += SLAP_INDEX_SUBSTR_IF_MAXLEN -
411 (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
412 } else if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN ) {
413 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
417 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
418 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) {
419 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_ANY_LEN - 1);
423 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
424 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MAXLEN ) {
425 nkeys += SLAP_INDEX_SUBSTR_IF_MAXLEN -
426 ( SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
427 } else if( values[i].bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN ) {
428 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_IF_MINLEN - 1);
434 /* no keys to generate */
439 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
441 slen = syntax->ssyn_oidlen;
442 mlen = mr->smr_oidlen;
445 for( i=0; values[i].bv_val != NULL; i++ ) {
448 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
449 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) )
451 char pre = SLAP_INDEX_SUBSTR_PREFIX;
452 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_ANY_LEN - 1);
454 for( j=0; j<max; j++ ) {
455 HASH_Init( &HASHcontext );
456 if( prefix != NULL && prefix->bv_len > 0 ) {
457 HASH_Update( &HASHcontext,
458 (unsigned char *)prefix->bv_val, prefix->bv_len );
461 HASH_Update( &HASHcontext,
462 (unsigned char *)&pre, sizeof( pre ) );
463 HASH_Update( &HASHcontext,
464 (unsigned char *)syntax->ssyn_oid, slen );
465 HASH_Update( &HASHcontext,
466 (unsigned char *)mr->smr_oid, mlen );
467 HASH_Update( &HASHcontext,
468 (unsigned char *)&values[i].bv_val[j],
469 SLAP_INDEX_SUBSTR_ANY_LEN );
470 HASH_Final( HASHdigest, &HASHcontext );
472 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
476 /* skip if too short */
477 if( values[i].bv_len < SLAP_INDEX_SUBSTR_IF_MINLEN ) continue;
479 max = SLAP_INDEX_SUBSTR_IF_MAXLEN < values[i].bv_len
480 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : values[i].bv_len;
482 for( j=SLAP_INDEX_SUBSTR_IF_MINLEN; j<=max; j++ ) {
485 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
486 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
487 HASH_Init( &HASHcontext );
488 if( prefix != NULL && prefix->bv_len > 0 ) {
489 HASH_Update( &HASHcontext,
490 (unsigned char *)prefix->bv_val, prefix->bv_len );
492 HASH_Update( &HASHcontext,
493 (unsigned char *)&pre, sizeof( pre ) );
494 HASH_Update( &HASHcontext,
495 (unsigned char *)syntax->ssyn_oid, slen );
496 HASH_Update( &HASHcontext,
497 (unsigned char *)mr->smr_oid, mlen );
498 HASH_Update( &HASHcontext,
499 (unsigned char *)values[i].bv_val, j );
500 HASH_Final( HASHdigest, &HASHcontext );
502 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
505 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
506 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
507 HASH_Init( &HASHcontext );
508 if( prefix != NULL && prefix->bv_len > 0 ) {
509 HASH_Update( &HASHcontext,
510 (unsigned char *)prefix->bv_val, prefix->bv_len );
512 HASH_Update( &HASHcontext,
513 (unsigned char *)&pre, sizeof( pre ) );
514 HASH_Update( &HASHcontext,
515 (unsigned char *)syntax->ssyn_oid, slen );
516 HASH_Update( &HASHcontext,
517 (unsigned char *)mr->smr_oid, mlen );
518 HASH_Update( &HASHcontext,
519 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
520 HASH_Final( HASHdigest, &HASHcontext );
522 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
529 keys[nkeys].bv_val = NULL;
540 octetStringSubstringsFilter (
545 struct berval *prefix,
546 void * assertedValue,
550 SubstringsAssertion *sa;
553 size_t slen, mlen, klen;
555 HASH_CONTEXT HASHcontext;
556 unsigned char HASHdigest[HASH_BYTES];
557 struct berval *value;
558 struct berval digest;
560 sa = (SubstringsAssertion *) assertedValue;
562 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
563 sa->sa_initial.bv_val != NULL &&
564 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
569 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
571 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
572 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_ANY_LEN ) {
573 /* don't bother accounting with stepping */
574 nkeys += sa->sa_any[i].bv_len -
575 ( SLAP_INDEX_SUBSTR_ANY_LEN - 1 );
580 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
581 sa->sa_final.bv_val != NULL &&
582 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
592 digest.bv_val = (char *)HASHdigest;
593 digest.bv_len = sizeof(HASHdigest);
595 slen = syntax->ssyn_oidlen;
596 mlen = mr->smr_oidlen;
598 keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
601 if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
602 sa->sa_initial.bv_val != NULL &&
603 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
605 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
606 value = &sa->sa_initial;
608 klen = SLAP_INDEX_SUBSTR_IF_MAXLEN < value->bv_len
609 ? SLAP_INDEX_SUBSTR_IF_MAXLEN : value->bv_len;
611 HASH_Init( &HASHcontext );
612 if( prefix != NULL && prefix->bv_len > 0 ) {
613 HASH_Update( &HASHcontext,
614 (unsigned char *)prefix->bv_val, prefix->bv_len );
616 HASH_Update( &HASHcontext,
617 (unsigned char *)&pre, sizeof( pre ) );
618 HASH_Update( &HASHcontext,
619 (unsigned char *)syntax->ssyn_oid, slen );
620 HASH_Update( &HASHcontext,
621 (unsigned char *)mr->smr_oid, mlen );
622 HASH_Update( &HASHcontext,
623 (unsigned char *)value->bv_val, klen );
624 HASH_Final( HASHdigest, &HASHcontext );
626 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
629 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
631 pre = SLAP_INDEX_SUBSTR_PREFIX;
632 klen = SLAP_INDEX_SUBSTR_ANY_LEN;
634 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
635 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_ANY_LEN ) {
639 value = &sa->sa_any[i];
642 j <= value->bv_len - SLAP_INDEX_SUBSTR_ANY_LEN;
643 j += SLAP_INDEX_SUBSTR_ANY_STEP )
645 HASH_Init( &HASHcontext );
646 if( prefix != NULL && prefix->bv_len > 0 ) {
647 HASH_Update( &HASHcontext,
648 (unsigned char *)prefix->bv_val, prefix->bv_len );
650 HASH_Update( &HASHcontext,
651 (unsigned char *)&pre, sizeof( pre ) );
652 HASH_Update( &HASHcontext,
653 (unsigned char *)syntax->ssyn_oid, slen );
654 HASH_Update( &HASHcontext,
655 (unsigned char *)mr->smr_oid, mlen );
656 HASH_Update( &HASHcontext,
657 (unsigned char *)&value->bv_val[j], klen );
658 HASH_Final( HASHdigest, &HASHcontext );
660 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
665 if( flags & SLAP_INDEX_SUBSTR_FINAL &&
666 sa->sa_final.bv_val != NULL &&
667 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_IF_MINLEN )
669 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
670 value = &sa->sa_final;
672 klen = SLAP_INDEX_SUBSTR_IF_MAXLEN < value->bv_len
673 ? SLAP_INDEX_SUBSTR_IF_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 == NULL
814 || uidval.bv_val < val->bv_val
815 || ( uidval.bv_val > val->bv_val && uidval.bv_val[-1] == '\\' ) )
817 return LDAP_INVALID_SYNTAX;
820 ber_dupbv_x( &dnval, val, ctx );
822 dnval.bv_len = uidval.bv_val - val->bv_val;
823 uidval.bv_len = val->bv_len - dnval.bv_len;
825 dnval.bv_val[dnval.bv_len] = '\0';
831 rc = dnPretty( syntax, &dnval, out, ctx );
832 if ( dnval.bv_val != val->bv_val ) {
833 slap_sl_free( dnval.bv_val, ctx );
835 if( rc != LDAP_SUCCESS ) {
839 if( uidval.bv_val ) {
843 tmp = slap_sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx );
845 ber_memfree_x( out->bv_val, ctx );
849 out->bv_val[out->bv_len++] = '#';
850 out->bv_val[out->bv_len++] = '\'';
852 got1 = uidval.bv_len < sizeof("'0'B");
853 for( i = 1; i < uidval.bv_len - 2; i++ ) {
854 c = uidval.bv_val[i];
857 if( got1 ) out->bv_val[out->bv_len++] = c;
861 out->bv_val[out->bv_len++] = c;
864 return LDAP_INVALID_SYNTAX;
868 out->bv_val[out->bv_len++] = '\'';
869 out->bv_val[out->bv_len++] = 'B';
870 out->bv_val[out->bv_len] = '\0';
875 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
877 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
884 uniqueMemberNormalize(
889 struct berval *normalized,
895 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
897 ber_dupbv_x( &out, val, ctx );
898 if ( BER_BVISEMPTY( &out ) ) {
902 struct berval uid = BER_BVNULL;
904 if( out.bv_val[out.bv_len-1] == 'B'
905 && out.bv_val[out.bv_len-2] == '\'' )
907 /* assume presence of optional UID */
908 uid.bv_val = strrchr( out.bv_val, '#' );
910 /* if no '#', or '#' before the beginning
911 * of the string, or preceded
912 * by an escape char '\\'...
913 * (a string of "#'<UID>'B" should be valid,
914 * since the empty "" DN is legal) */
915 if( uid.bv_val == NULL
916 || uid.bv_val < out.bv_val
917 || ( uid.bv_val > out.bv_val && uid.bv_val[-1] == '\\' ) )
919 slap_sl_free( out.bv_val, ctx );
920 return LDAP_INVALID_SYNTAX;
923 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
924 out.bv_len -= uid.bv_len--;
926 /* temporarily trim the UID */
927 *(uid.bv_val++) = '\0';
930 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
932 if( rc != LDAP_SUCCESS ) {
933 slap_sl_free( out.bv_val, ctx );
934 return LDAP_INVALID_SYNTAX;
938 normalized->bv_val = ch_realloc( normalized->bv_val,
939 normalized->bv_len + uid.bv_len
940 + STRLENOF("#") + 1 );
942 /* insert the separator */
943 normalized->bv_val[normalized->bv_len++] = '#';
946 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
947 uid.bv_val, uid.bv_len );
948 normalized->bv_len += uid.bv_len;
951 normalized->bv_val[normalized->bv_len] = '\0';
954 slap_sl_free( out.bv_val, ctx );
966 struct berval *value,
967 void *assertedValue )
970 struct berval *asserted = (struct berval *) assertedValue;
971 struct berval assertedDN = BER_BVNULL;
972 struct berval assertedUID = BER_BVNULL;
973 struct berval valueDN = BER_BVNULL;
974 struct berval valueUID = BER_BVNULL;
976 if( asserted->bv_len != 0 ) {
977 assertedDN = *asserted;
979 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
980 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
982 /* assume presence of optional UID */
983 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
985 if( assertedUID.bv_val == NULL
986 || assertedUID.bv_val < assertedDN.bv_val
987 || ( assertedUID.bv_val > assertedDN.bv_val && assertedUID.bv_val[-1] == '\\' ) )
989 return LDAP_INVALID_SYNTAX;
992 assertedUID.bv_len = assertedDN.bv_len -
993 (assertedUID.bv_val - assertedDN.bv_val);
994 assertedDN.bv_len -= assertedUID.bv_len;
996 /* trim the separator */
997 assertedUID.bv_len--;
998 assertedUID.bv_val++;
1002 if( value->bv_len != 0 ) {
1005 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
1006 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
1008 /* assume presence of optional UID */
1009 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1011 if( valueUID.bv_val == NULL
1012 || valueUID.bv_val < valueDN.bv_val
1013 || ( valueUID.bv_val > valueDN.bv_val && valueUID.bv_val[-1] == '\\' ) )
1015 return LDAP_INVALID_SYNTAX;
1018 valueUID.bv_len = valueDN.bv_len -
1019 (valueUID.bv_val - valueDN.bv_val);
1020 valueDN.bv_len -= valueUID.bv_len;
1022 /* trim the separator */
1028 if( valueUID.bv_len && assertedUID.bv_len ) {
1029 match = valueUID.bv_len - assertedUID.bv_len;
1032 return LDAP_SUCCESS;
1035 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1038 return LDAP_SUCCESS;
1042 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1046 * Handling boolean syntax and matching is quite rigid.
1047 * A more flexible approach would be to allow a variety
1048 * of strings to be normalized and prettied into TRUE
1056 /* very unforgiving validation, requires no normalization
1057 * before simplistic matching
1060 if( in->bv_len == 4 ) {
1061 if( bvmatch( in, &slap_true_bv ) ) {
1062 return LDAP_SUCCESS;
1064 } else if( in->bv_len == 5 ) {
1065 if( bvmatch( in, &slap_false_bv ) ) {
1066 return LDAP_SUCCESS;
1070 return LDAP_INVALID_SYNTAX;
1079 struct berval *value,
1080 void *assertedValue )
1082 /* simplistic matching allowed by rigid validation */
1083 struct berval *asserted = (struct berval *) assertedValue;
1084 *matchp = value->bv_len != asserted->bv_len;
1085 return LDAP_SUCCESS;
1088 /*-------------------------------------------------------------------
1089 LDAP/X.500 string syntax / matching rules have a few oddities. This
1090 comment attempts to detail how slapd(8) treats them.
1093 StringSyntax X.500 LDAP Matching/Comments
1094 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1095 PrintableString subset subset i/e + ignore insignificant spaces
1096 PrintableString subset subset i/e + ignore insignificant spaces
1097 NumericString subset subset ignore all spaces
1098 IA5String ASCII ASCII i/e + ignore insignificant spaces
1099 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1101 TelephoneNumber subset subset i + ignore all spaces and "-"
1103 See draft-ietf-ldapbis-strpro for details (once published).
1107 In X.500(93), a directory string can be either a PrintableString,
1108 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1109 In later versions, more CHOICEs were added. In all cases the string
1112 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1113 A directory string cannot be zero length.
1115 For matching, there are both case ignore and exact rules. Both
1116 also require that "insignificant" spaces be ignored.
1117 spaces before the first non-space are ignored;
1118 spaces after the last non-space are ignored;
1119 spaces after a space are ignored.
1120 Note: by these rules (and as clarified in X.520), a string of only
1121 spaces is to be treated as if held one space, not empty (which
1122 would be a syntax error).
1125 In ASN.1, numeric string is just a string of digits and spaces
1126 and could be empty. However, in X.500, all attribute values of
1127 numeric string carry a non-empty constraint. For example:
1129 internationalISDNNumber ATTRIBUTE ::= {
1130 WITH SYNTAX InternationalISDNNumber
1131 EQUALITY MATCHING RULE numericStringMatch
1132 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1133 ID id-at-internationalISDNNumber }
1134 InternationalISDNNumber ::=
1135 NumericString (SIZE(1..ub-international-isdn-number))
1137 Unforunately, some assertion values are don't carry the same
1138 constraint (but its unclear how such an assertion could ever
1139 be true). In LDAP, there is one syntax (numericString) not two
1140 (numericString with constraint, numericString without constraint).
1141 This should be treated as numericString with non-empty constraint.
1142 Note that while someone may have no ISDN number, there are no ISDN
1143 numbers which are zero length.
1145 In matching, spaces are ignored.
1148 In ASN.1, Printable string is just a string of printable characters
1149 and can be empty. In X.500, semantics much like NumericString (see
1150 serialNumber for a like example) excepting uses insignificant space
1151 handling instead of ignore all spaces.
1154 Basically same as PrintableString. There are no examples in X.500,
1155 but same logic applies. So we require them to be non-empty as
1158 -------------------------------------------------------------------*/
1167 unsigned char *u = (unsigned char *)in->bv_val;
1169 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1170 /* directory strings cannot be empty */
1171 return LDAP_INVALID_SYNTAX;
1174 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1175 /* get the length indicated by the first byte */
1176 len = LDAP_UTF8_CHARLEN2( u, len );
1178 /* very basic checks */
1181 if( (u[5] & 0xC0) != 0x80 ) {
1182 return LDAP_INVALID_SYNTAX;
1185 if( (u[4] & 0xC0) != 0x80 ) {
1186 return LDAP_INVALID_SYNTAX;
1189 if( (u[3] & 0xC0) != 0x80 ) {
1190 return LDAP_INVALID_SYNTAX;
1193 if( (u[2] & 0xC0 )!= 0x80 ) {
1194 return LDAP_INVALID_SYNTAX;
1197 if( (u[1] & 0xC0) != 0x80 ) {
1198 return LDAP_INVALID_SYNTAX;
1201 /* CHARLEN already validated it */
1204 return LDAP_INVALID_SYNTAX;
1207 /* make sure len corresponds with the offset
1208 to the next character */
1209 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1213 return LDAP_INVALID_SYNTAX;
1216 return LDAP_SUCCESS;
1220 UTF8StringNormalize(
1225 struct berval *normalized,
1228 struct berval tmp, nvalue;
1232 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1234 if( val->bv_val == NULL ) {
1235 /* assume we're dealing with a syntax (e.g., UTF8String)
1236 * which allows empty strings
1238 normalized->bv_len = 0;
1239 normalized->bv_val = NULL;
1240 return LDAP_SUCCESS;
1243 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1244 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1245 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1246 ? LDAP_UTF8_APPROX : 0;
1248 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1253 /* collapse spaces (in place) */
1255 nvalue.bv_val = tmp.bv_val;
1257 wasspace=1; /* trim leading spaces */
1258 for( i=0; i<tmp.bv_len; i++) {
1259 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1260 if( wasspace++ == 0 ) {
1261 /* trim repeated spaces */
1262 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1266 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1270 if( nvalue.bv_len ) {
1272 /* last character was a space, trim it */
1275 nvalue.bv_val[nvalue.bv_len] = '\0';
1278 /* string of all spaces is treated as one space */
1279 nvalue.bv_val[0] = ' ';
1280 nvalue.bv_val[1] = '\0';
1284 *normalized = nvalue;
1285 return LDAP_SUCCESS;
1288 #if defined(SLAPD_APPROX_INITIALS)
1289 # define SLAPD_APPROX_DELIMITER "._ "
1290 # define SLAPD_APPROX_WORDLEN 2
1292 # define SLAPD_APPROX_DELIMITER " "
1293 # define SLAPD_APPROX_WORDLEN 1
1302 struct berval *value,
1303 void *assertedValue )
1305 struct berval *nval, *assertv;
1306 char *val, **values, **words, *c;
1307 int i, count, len, nextchunk=0, nextavail=0;
1309 /* Yes, this is necessary */
1310 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1311 if( nval == NULL ) {
1313 return LDAP_SUCCESS;
1316 /* Yes, this is necessary */
1317 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1318 NULL, LDAP_UTF8_APPROX, NULL );
1319 if( assertv == NULL ) {
1322 return LDAP_SUCCESS;
1325 /* Isolate how many words there are */
1326 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1327 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1328 if ( c == NULL ) break;
1333 /* Get a phonetic copy of each word */
1334 words = (char **)ch_malloc( count * sizeof(char *) );
1335 values = (char **)ch_malloc( count * sizeof(char *) );
1336 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1338 values[i] = phonetic(c);
1341 /* Work through the asserted value's words, to see if at least some
1342 of the words are there, in the same order. */
1344 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1345 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1350 #if defined(SLAPD_APPROX_INITIALS)
1351 else if( len == 1 ) {
1352 /* Single letter words need to at least match one word's initial */
1353 for( i=nextavail; i<count; i++ )
1354 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1361 /* Isolate the next word in the asserted value and phonetic it */
1362 assertv->bv_val[nextchunk+len] = '\0';
1363 val = phonetic( assertv->bv_val + nextchunk );
1365 /* See if this phonetic chunk is in the remaining words of *value */
1366 for( i=nextavail; i<count; i++ ){
1367 if( !strcmp( val, values[i] ) ){
1375 /* This chunk in the asserted value was NOT within the *value. */
1381 /* Go on to the next word in the asserted value */
1385 /* If some of the words were seen, call it a match */
1386 if( nextavail > 0 ) {
1393 /* Cleanup allocs */
1394 ber_bvfree( assertv );
1395 for( i=0; i<count; i++ ) {
1396 ch_free( values[i] );
1402 return LDAP_SUCCESS;
1411 struct berval *prefix,
1417 int i,j, len, wordcount, keycount=0;
1418 struct berval *newkeys;
1419 BerVarray keys=NULL;
1421 for( j=0; values[j].bv_val != NULL; j++ ) {
1422 struct berval val = BER_BVNULL;
1423 /* Yes, this is necessary */
1424 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1425 assert( val.bv_val != NULL );
1427 /* Isolate how many words there are. There will be a key for each */
1428 for( wordcount = 0, c = val.bv_val; *c; c++) {
1429 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1430 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1432 if (*c == '\0') break;
1436 /* Allocate/increase storage to account for new keys */
1437 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1438 * sizeof(struct berval) );
1439 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1440 if( keys ) ch_free( keys );
1443 /* Get a phonetic copy of each word */
1444 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1446 if( len < SLAPD_APPROX_WORDLEN ) continue;
1447 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1452 ber_memfree( val.bv_val );
1454 keys[keycount].bv_val = NULL;
1457 return LDAP_SUCCESS;
1466 struct berval *prefix,
1467 void * assertedValue,
1476 /* Yes, this is necessary */
1477 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1478 NULL, LDAP_UTF8_APPROX, NULL );
1479 if( val == NULL || val->bv_val == NULL ) {
1480 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1481 keys[0].bv_val = NULL;
1484 return LDAP_SUCCESS;
1487 /* Isolate how many words there are. There will be a key for each */
1488 for( count = 0,c = val->bv_val; *c; c++) {
1489 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1490 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1492 if (*c == '\0') break;
1496 /* Allocate storage for new keys */
1497 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1499 /* Get a phonetic copy of each word */
1500 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1502 if( len < SLAPD_APPROX_WORDLEN ) continue;
1503 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1509 keys[count].bv_val = NULL;
1512 return LDAP_SUCCESS;
1515 /* Remove all spaces and '-' characters */
1517 telephoneNumberNormalize(
1522 struct berval *normalized,
1527 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1529 /* validator should have refused an empty string */
1530 assert( val->bv_len );
1532 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1534 for( p = val->bv_val; *p; p++ ) {
1535 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1541 normalized->bv_len = q - normalized->bv_val;
1543 if( normalized->bv_len == 0 ) {
1544 slap_sl_free( normalized->bv_val, ctx );
1545 normalized->bv_val = NULL;
1546 return LDAP_INVALID_SYNTAX;
1549 return LDAP_SUCCESS;
1557 struct berval val = *in;
1559 if( val.bv_len == 0 ) {
1560 /* disallow empty strings */
1561 return LDAP_INVALID_SYNTAX;
1564 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1565 if ( val.bv_len == 1 ) {
1566 return LDAP_SUCCESS;
1569 if ( val.bv_val[0] == '0' ) {
1576 while ( OID_LEADCHAR( val.bv_val[0] )) {
1580 if ( val.bv_len == 0 ) {
1581 return LDAP_SUCCESS;
1585 if( !OID_SEPARATOR( val.bv_val[0] )) {
1593 return LDAP_INVALID_SYNTAX;
1602 struct berval val = *in;
1604 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1606 if ( val.bv_val[0] == '-' ) {
1610 if( val.bv_len == 0 ) { /* bare "-" */
1611 return LDAP_INVALID_SYNTAX;
1614 if( val.bv_val[0] == '0' ) { /* "-0" */
1615 return LDAP_INVALID_SYNTAX;
1618 } else if ( val.bv_val[0] == '0' ) {
1619 if( val.bv_len > 1 ) { /* "0<more>" */
1620 return LDAP_INVALID_SYNTAX;
1623 return LDAP_SUCCESS;
1626 for( i=0; i < val.bv_len; i++ ) {
1627 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1628 return LDAP_INVALID_SYNTAX;
1632 return LDAP_SUCCESS;
1641 struct berval *value,
1642 void *assertedValue )
1644 struct berval *asserted = (struct berval *) assertedValue;
1645 int vsign = 1, asign = 1; /* default sign = '+' */
1650 if( v.bv_val[0] == '-' ) {
1656 if( v.bv_len == 0 ) vsign = 0;
1659 if( a.bv_val[0] == '-' ) {
1665 if( a.bv_len == 0 ) vsign = 0;
1667 match = vsign - asign;
1669 match = ( v.bv_len != a.bv_len
1670 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1671 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1672 if( vsign < 0 ) match = -match;
1676 return LDAP_SUCCESS;
1680 countryStringValidate(
1682 struct berval *val )
1684 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1686 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1687 return LDAP_INVALID_SYNTAX;
1689 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1690 return LDAP_INVALID_SYNTAX;
1693 return LDAP_SUCCESS;
1697 printableStringValidate(
1699 struct berval *val )
1703 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1705 for(i=0; i < val->bv_len; i++) {
1706 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1707 return LDAP_INVALID_SYNTAX;
1711 return LDAP_SUCCESS;
1715 printablesStringValidate(
1717 struct berval *val )
1721 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1723 for(i=0,len=0; i < val->bv_len; i++) {
1724 int c = val->bv_val[i];
1728 return LDAP_INVALID_SYNTAX;
1732 } else if ( SLAP_PRINTABLE(c) ) {
1735 return LDAP_INVALID_SYNTAX;
1740 return LDAP_INVALID_SYNTAX;
1743 return LDAP_SUCCESS;
1749 struct berval *val )
1753 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1755 for(i=0; i < val->bv_len; i++) {
1756 if( !LDAP_ASCII(val->bv_val[i]) ) {
1757 return LDAP_INVALID_SYNTAX;
1761 return LDAP_SUCCESS;
1770 struct berval *normalized,
1774 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1776 assert( val->bv_len );
1778 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1782 /* Ignore initial whitespace */
1783 while ( ASCII_SPACE( *p ) ) p++;
1785 normalized->bv_val = ber_strdup_x( p, ctx );
1786 p = q = normalized->bv_val;
1789 if ( ASCII_SPACE( *p ) ) {
1792 /* Ignore the extra whitespace */
1793 while ( ASCII_SPACE( *p ) ) {
1797 } else if ( casefold ) {
1798 /* Most IA5 rules require casefolding */
1799 *q++ = TOLOWER(*p); p++;
1806 assert( normalized->bv_val <= p );
1810 * If the string ended in space, backup the pointer one
1811 * position. One is enough because the above loop collapsed
1812 * all whitespace to a single space.
1814 if ( ASCII_SPACE( q[-1] ) ) --q;
1816 /* null terminate */
1819 normalized->bv_len = q - normalized->bv_val;
1820 if( normalized->bv_len == 0 ) {
1821 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1822 normalized->bv_val[0] = ' ';
1823 normalized->bv_val[1] = '\0';
1824 normalized->bv_len = 1;
1827 return LDAP_SUCCESS;
1836 if( in->bv_len != 36 ) {
1838 return LDAP_INVALID_SYNTAX;
1841 for( i=0; i<36; i++ ) {
1847 if( in->bv_val[i] != '-' ) {
1848 return LDAP_INVALID_SYNTAX;
1852 if( !ASCII_HEX( in->bv_val[i]) ) {
1853 return LDAP_INVALID_SYNTAX;
1858 return LDAP_SUCCESS;
1867 struct berval *normalized,
1870 unsigned char octet = '\0';
1873 normalized->bv_len = 16;
1874 normalized->bv_val = slap_sl_malloc( normalized->bv_len+1, ctx );
1876 for( i=0, j=0; i<36; i++ ) {
1877 unsigned char nibble;
1878 if( val->bv_val[i] == '-' ) {
1881 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1882 nibble = val->bv_val[i] - '0';
1884 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1885 nibble = val->bv_val[i] - ('a'-10);
1887 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1888 nibble = val->bv_val[i] - ('A'-10);
1891 slap_sl_free( normalized->bv_val, ctx );
1892 return LDAP_INVALID_SYNTAX;
1897 normalized->bv_val[j>>1] = octet;
1899 octet = nibble << 4;
1904 normalized->bv_val[normalized->bv_len] = 0;
1905 return LDAP_SUCCESS;
1911 numericStringValidate(
1917 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1919 for(i=0; i < in->bv_len; i++) {
1920 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1921 return LDAP_INVALID_SYNTAX;
1925 return LDAP_SUCCESS;
1929 numericStringNormalize(
1934 struct berval *normalized,
1937 /* removal all spaces */
1940 assert( val->bv_len );
1942 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1945 q = normalized->bv_val;
1948 if ( ASCII_SPACE( *p ) ) {
1949 /* Ignore whitespace */
1956 /* we should have copied no more then is in val */
1957 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1959 /* null terminate */
1962 normalized->bv_len = q - normalized->bv_val;
1964 if( normalized->bv_len == 0 ) {
1965 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1966 normalized->bv_val[0] = ' ';
1967 normalized->bv_val[1] = '\0';
1968 normalized->bv_len = 1;
1971 return LDAP_SUCCESS;
1975 * Integer conversion macros that will use the largest available
1978 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1979 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1980 # define SLAP_LONG_MAX LLONG_MAX
1981 # define SLAP_LONG_MIN LLONG_MIN
1982 # define SLAP_LONG long long
1984 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1985 # define SLAP_LONG_MAX LONG_MAX
1986 # define SLAP_LONG_MIN LONG_MIN
1987 # define SLAP_LONG long
1988 #endif /* HAVE_STRTOLL ... */
1996 struct berval *value,
1997 void *assertedValue )
1999 SLAP_LONG lValue, lAssertedValue;
2001 /* safe to assume integers are NUL terminated? */
2002 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2003 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
2004 return LDAP_CONSTRAINT_VIOLATION;
2007 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
2008 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
2009 && errno == ERANGE )
2011 return LDAP_CONSTRAINT_VIOLATION;
2014 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2015 return LDAP_SUCCESS;
2024 struct berval *value,
2025 void *assertedValue )
2027 SLAP_LONG lValue, lAssertedValue;
2029 /* safe to assume integers are NUL terminated? */
2030 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2031 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2034 return LDAP_CONSTRAINT_VIOLATION;
2037 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2039 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
2040 && errno == ERANGE )
2042 return LDAP_CONSTRAINT_VIOLATION;
2045 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2046 return LDAP_SUCCESS;
2050 serialNumberAndIssuerValidate(
2057 struct berval sn, i;
2058 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2060 i.bv_val = strchr( in->bv_val, '$' );
2061 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2063 sn.bv_val = in->bv_val;
2064 sn.bv_len = i.bv_val - in->bv_val;
2067 i.bv_len = in->bv_len - (sn.bv_len + 1);
2069 /* validate serial number (strict for now) */
2070 for( n=0; n < sn.bv_len; n++ ) {
2071 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2072 return LDAP_INVALID_SYNTAX;
2077 rc = dnValidate( NULL, &i );
2078 if( rc ) return LDAP_INVALID_SYNTAX;
2080 return LDAP_SUCCESS;
2084 serialNumberAndIssuerPretty(
2093 struct berval sn, i, newi;
2099 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2100 val->bv_val, 0, 0 );
2102 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2103 val->bv_val, 0, 0 );
2106 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2108 i.bv_val = strchr( val->bv_val, '$' );
2109 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2111 sn.bv_val = val->bv_val;
2112 sn.bv_len = i.bv_val - val->bv_val;
2115 i.bv_len = val->bv_len - (sn.bv_len + 1);
2117 /* eat leading zeros */
2118 for( n=0; n < (sn.bv_len-1); n++ ) {
2119 if( sn.bv_val[n] != '0' ) break;
2124 for( n=0; n < sn.bv_len; n++ ) {
2125 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2126 return LDAP_INVALID_SYNTAX;
2131 rc = dnPretty( syntax, &i, &newi, ctx );
2132 if( rc ) return LDAP_INVALID_SYNTAX;
2134 /* make room from sn + "$" */
2135 out->bv_len = sn.bv_len + newi.bv_len + 1;
2136 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2138 if( out->bv_val == NULL ) {
2139 slap_sl_free( newi.bv_val, ctx );
2143 /* push issuer over */
2144 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2145 /* insert sn and "$" */
2146 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2147 out->bv_val[sn.bv_len] = '$';
2149 out->bv_val[out->bv_len] = '\0';
2152 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2153 out->bv_val, 0, 0 );
2155 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2156 out->bv_val, 0, 0 );
2159 return LDAP_SUCCESS;
2163 * This routine is called by certificateExactNormalize when
2164 * certificateExactNormalize receives a search string instead of
2165 * a certificate. This routine checks if the search value is valid
2166 * and then returns the normalized value
2169 serialNumberAndIssuerNormalize(
2180 struct berval sn, i, newi;
2186 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2187 val->bv_val, 0, 0 );
2189 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2190 val->bv_val, 0, 0 );
2193 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2195 i.bv_val = strchr( val->bv_val, '$' );
2196 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2198 sn.bv_val = val->bv_val;
2199 sn.bv_len = i.bv_val - val->bv_val;
2202 i.bv_len = val->bv_len - (sn.bv_len + 1);
2204 /* eat leading zeros */
2205 for( n=0; n < (sn.bv_len-1); n++ ) {
2206 if( sn.bv_val[n] != '0' ) break;
2211 for( n=0; n < sn.bv_len; n++ ) {
2212 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2213 return LDAP_INVALID_SYNTAX;
2218 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2219 if( rc ) return LDAP_INVALID_SYNTAX;
2221 /* make room from sn + "$" */
2222 out->bv_len = sn.bv_len + newi.bv_len + 1;
2223 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2225 if( out->bv_val == NULL ) {
2226 slap_sl_free( newi.bv_val, ctx );
2230 /* push issuer over */
2231 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2232 /* insert sn and "$" */
2233 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2234 out->bv_val[sn.bv_len] = '$';
2236 out->bv_val[out->bv_len] = '\0';
2239 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2240 out->bv_val, 0, 0 );
2242 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2243 out->bv_val, 0, 0 );
2251 certificateExactNormalize(
2256 struct berval *normalized,
2259 int rc = LDAP_INVALID_SYNTAX;
2261 char *serial = NULL;
2262 ber_len_t seriallen;
2263 struct berval issuer_dn = BER_BVNULL;
2264 X509_NAME *name = NULL;
2265 ASN1_INTEGER *sn = NULL;
2268 if( val->bv_len == 0 ) goto done;
2270 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2271 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2274 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2276 p = (unsigned char *)val->bv_val;
2277 xcert = d2i_X509( NULL, &p, val->bv_len);
2278 if( xcert == NULL ) goto done;
2280 sn=X509_get_serialNumber(xcert);
2281 if ( sn == NULL ) goto done;
2282 serial=i2s_ASN1_INTEGER(0, sn );
2283 if( serial == NULL ) goto done;
2284 seriallen=strlen(serial);
2286 name=X509_get_issuer_name(xcert);
2287 if( name == NULL ) goto done;
2288 rc = dnX509normalize( name, &issuer_dn );
2289 if( rc != LDAP_SUCCESS ) goto done;
2291 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2292 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2293 p = (unsigned char *)normalized->bv_val;
2294 AC_MEMCPY(p, serial, seriallen);
2297 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2298 p += issuer_dn.bv_len;
2302 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2303 normalized->bv_val, 0, 0 );
2305 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2306 normalized->bv_val, NULL, NULL );
2310 if (xcert) X509_free(xcert);
2311 if (serial) ch_free(serial);
2312 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2316 #endif /* HAVE_TLS */
2319 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2320 /* slight optimization - does not need the start parameter */
2321 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2326 check_time_syntax (struct berval *val,
2329 struct berval *fraction)
2332 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2333 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2334 * GeneralizedTime supports leap seconds, UTCTime does not.
2336 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2337 static const int mdays[2][12] = {
2338 /* non-leap years */
2339 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2341 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2344 int part, c, c1, c2, tzoffset, leapyear = 0;
2347 e = p + val->bv_len;
2349 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2350 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2352 for (part = start; part < 7 && p < e; part++) {
2354 if (!ASCII_DIGIT(c1)) {
2359 return LDAP_INVALID_SYNTAX;
2362 if (!ASCII_DIGIT(c)) {
2363 return LDAP_INVALID_SYNTAX;
2365 c += c1 * 10 - '0' * 11;
2366 if ((part | 1) == 3) {
2369 return LDAP_INVALID_SYNTAX;
2372 if (c >= ceiling[part]) {
2373 if (! (c == 60 && part == 6 && start == 0))
2374 return LDAP_INVALID_SYNTAX;
2378 if (part < 5 + start) {
2379 return LDAP_INVALID_SYNTAX;
2381 for (; part < 9; part++) {
2385 /* leapyear check for the Gregorian calendar (year>1581) */
2386 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2391 if (parts[3] >= mdays[leapyear][parts[2]]) {
2392 return LDAP_INVALID_SYNTAX;
2396 fraction->bv_val = p;
2397 fraction->bv_len = 0;
2398 if (p < e && (*p == '.' || *p == ',')) {
2400 while (++p < e && ASCII_DIGIT(*p))
2402 if (p - fraction->bv_val == 1) {
2403 return LDAP_INVALID_SYNTAX;
2405 for (end_num = p; end_num[-1] == '0'; --end_num)
2407 c = end_num - fraction->bv_val;
2409 fraction->bv_len = c;
2415 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2421 return LDAP_INVALID_SYNTAX;
2427 for (part = 7; part < 9 && p < e; part++) {
2429 if (!ASCII_DIGIT(c1)) {
2434 return LDAP_INVALID_SYNTAX;
2437 if (!ASCII_DIGIT(c2)) {
2438 return LDAP_INVALID_SYNTAX;
2440 parts[part] = c1 * 10 + c2 - '0' * 11;
2441 if (parts[part] >= ceiling[part]) {
2442 return LDAP_INVALID_SYNTAX;
2445 if (part < 8 + start) {
2446 return LDAP_INVALID_SYNTAX;
2449 if (tzoffset == '-') {
2450 /* negative offset to UTC, ie west of Greenwich */
2451 parts[4] += parts[7];
2452 parts[5] += parts[8];
2453 /* offset is just hhmm, no seconds */
2454 for (part = 6; --part >= 0; ) {
2458 c = mdays[leapyear][parts[2]];
2460 if (parts[part] >= c) {
2462 return LDAP_INVALID_SYNTAX;
2467 } else if (part != 5) {
2472 /* positive offset to UTC, ie east of Greenwich */
2473 parts[4] -= parts[7];
2474 parts[5] -= parts[8];
2475 for (part = 6; --part >= 0; ) {
2476 if (parts[part] < 0) {
2478 return LDAP_INVALID_SYNTAX;
2483 /* make first arg to % non-negative */
2484 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2489 } else if (part != 5) {
2496 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2499 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2506 struct berval *normalized )
2510 rc = check_time_syntax(val, 1, parts, NULL);
2511 if (rc != LDAP_SUCCESS) {
2515 normalized->bv_val = ch_malloc( 14 );
2516 if ( normalized->bv_val == NULL ) {
2517 return LBER_ERROR_MEMORY;
2520 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2521 parts[1], parts[2] + 1, parts[3] + 1,
2522 parts[4], parts[5], parts[6] );
2523 normalized->bv_len = 13;
2525 return LDAP_SUCCESS;
2535 return check_time_syntax(in, 1, parts, NULL);
2538 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2541 generalizedTimeValidate(
2546 struct berval fraction;
2547 return check_time_syntax(in, 0, parts, &fraction);
2551 generalizedTimeNormalize(
2556 struct berval *normalized,
2561 struct berval fraction;
2563 rc = check_time_syntax(val, 0, parts, &fraction);
2564 if (rc != LDAP_SUCCESS) {
2568 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2569 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2570 if ( normalized->bv_val == NULL ) {
2571 return LBER_ERROR_MEMORY;
2574 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2575 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2576 parts[4], parts[5], parts[6] );
2577 if ( fraction.bv_len ) {
2578 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2579 fraction.bv_val, fraction.bv_len );
2580 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2582 strcpy( normalized->bv_val + len-1, "Z" );
2583 normalized->bv_len = len;
2585 return LDAP_SUCCESS;
2589 generalizedTimeOrderingMatch(
2594 struct berval *value,
2595 void *assertedValue )
2597 struct berval *asserted = (struct berval *) assertedValue;
2598 ber_len_t v_len = value->bv_len;
2599 ber_len_t av_len = asserted->bv_len;
2601 /* ignore trailing 'Z' when comparing */
2602 int match = memcmp( value->bv_val, asserted->bv_val,
2603 (v_len < av_len ? v_len : av_len) - 1 );
2604 if ( match == 0 ) match = v_len - av_len;
2607 return LDAP_SUCCESS;
2611 deliveryMethodValidate(
2613 struct berval *val )
2616 #define LENOF(s) (sizeof(s)-1)
2617 struct berval tmp = *val;
2619 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2620 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2621 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2624 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2626 switch( tmp.bv_val[0] ) {
2629 if(( tmp.bv_len >= LENOF("any") ) &&
2630 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2632 tmp.bv_len -= LENOF("any");
2633 tmp.bv_val += LENOF("any");
2636 return LDAP_INVALID_SYNTAX;
2640 if(( tmp.bv_len >= LENOF("mhs") ) &&
2641 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2643 tmp.bv_len -= LENOF("mhs");
2644 tmp.bv_val += LENOF("mhs");
2647 return LDAP_INVALID_SYNTAX;
2651 if(( tmp.bv_len >= LENOF("physical") ) &&
2652 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2654 tmp.bv_len -= LENOF("physical");
2655 tmp.bv_val += LENOF("physical");
2658 return LDAP_INVALID_SYNTAX;
2661 case 'T': /* telex or teletex or telephone */
2662 if(( tmp.bv_len >= LENOF("telex") ) &&
2663 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2665 tmp.bv_len -= LENOF("telex");
2666 tmp.bv_val += LENOF("telex");
2669 if(( tmp.bv_len >= LENOF("teletex") ) &&
2670 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2672 tmp.bv_len -= LENOF("teletex");
2673 tmp.bv_val += LENOF("teletex");
2676 if(( tmp.bv_len >= LENOF("telephone") ) &&
2677 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2679 tmp.bv_len -= LENOF("telephone");
2680 tmp.bv_val += LENOF("telephone");
2683 return LDAP_INVALID_SYNTAX;
2686 case 'G': /* g3fax or g4fax */
2687 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2688 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2689 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2691 tmp.bv_len -= LENOF("g3fax");
2692 tmp.bv_val += LENOF("g3fax");
2695 return LDAP_INVALID_SYNTAX;
2699 if(( tmp.bv_len >= LENOF("ia5") ) &&
2700 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2702 tmp.bv_len -= LENOF("ia5");
2703 tmp.bv_val += LENOF("ia5");
2706 return LDAP_INVALID_SYNTAX;
2710 if(( tmp.bv_len >= LENOF("videotex") ) &&
2711 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2713 tmp.bv_len -= LENOF("videotex");
2714 tmp.bv_val += LENOF("videotex");
2717 return LDAP_INVALID_SYNTAX;
2720 return LDAP_INVALID_SYNTAX;
2723 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2725 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2729 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2733 return LDAP_INVALID_SYNTAX;
2735 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2744 nisNetgroupTripleValidate(
2746 struct berval *val )
2751 if ( val->bv_len == 0 ) {
2752 return LDAP_INVALID_SYNTAX;
2755 p = (char *)val->bv_val;
2756 e = p + val->bv_len;
2758 if ( *p != '(' /*')'*/ ) {
2759 return LDAP_INVALID_SYNTAX;
2762 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2766 return LDAP_INVALID_SYNTAX;
2769 } else if ( !AD_CHAR( *p ) ) {
2770 return LDAP_INVALID_SYNTAX;
2774 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2775 return LDAP_INVALID_SYNTAX;
2781 return LDAP_INVALID_SYNTAX;
2784 return LDAP_SUCCESS;
2788 bootParameterValidate(
2790 struct berval *val )
2794 if ( val->bv_len == 0 ) {
2795 return LDAP_INVALID_SYNTAX;
2798 p = (char *)val->bv_val;
2799 e = p + val->bv_len;
2802 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2803 if ( !AD_CHAR( *p ) ) {
2804 return LDAP_INVALID_SYNTAX;
2809 return LDAP_INVALID_SYNTAX;
2813 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2814 if ( !AD_CHAR( *p ) ) {
2815 return LDAP_INVALID_SYNTAX;
2820 return LDAP_INVALID_SYNTAX;
2824 for ( p++; p < e; p++ ) {
2825 if ( !SLAP_PRINTABLE( *p ) ) {
2826 return LDAP_INVALID_SYNTAX;
2830 return LDAP_SUCCESS;
2834 firstComponentNormalize(
2839 struct berval *normalized,
2846 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2847 ber_dupbv_x( normalized, val, ctx );
2848 return LDAP_SUCCESS;
2851 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2853 if( val->bv_val[0] != '(' /*')'*/ &&
2854 val->bv_val[0] != '{' /*'}'*/ )
2856 return LDAP_INVALID_SYNTAX;
2859 /* trim leading white space */
2861 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2867 /* grab next word */
2868 comp.bv_val = &val->bv_val[len];
2869 len = val->bv_len - len;
2871 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2877 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2878 rc = numericoidValidate( NULL, &comp );
2879 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2880 rc = integerValidate( NULL, &comp );
2882 rc = LDAP_INVALID_SYNTAX;
2886 if( rc == LDAP_SUCCESS ) {
2887 ber_dupbv_x( normalized, &comp, ctx );
2894 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2895 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2897 static slap_syntax_defs_rec syntax_defs[] = {
2898 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2899 X_BINARY X_NOT_H_R ")",
2900 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2901 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2903 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2905 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2907 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2908 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2910 SLAP_SYNTAX_BER, berValidate, NULL},
2911 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2912 0, bitStringValidate, NULL },
2913 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2914 0, booleanValidate, NULL},
2915 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2916 X_BINARY X_NOT_H_R ")",
2917 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2918 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2919 X_BINARY X_NOT_H_R ")",
2920 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2921 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2922 X_BINARY X_NOT_H_R ")",
2923 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2924 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2925 0, countryStringValidate, NULL},
2926 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2927 0, dnValidate, dnPretty},
2928 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2930 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2931 0, deliveryMethodValidate, NULL},
2932 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2933 0, UTF8StringValidate, NULL},
2934 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2936 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2938 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2940 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2942 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2944 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2945 0, printablesStringValidate, NULL},
2946 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2947 SLAP_SYNTAX_BLOB, NULL, NULL},
2948 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2949 0, generalizedTimeValidate, NULL},
2950 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2952 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2953 0, IA5StringValidate, NULL},
2954 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2955 0, integerValidate, NULL},
2956 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2957 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2958 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2960 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2962 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2964 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2966 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2968 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2969 0, nameUIDValidate, nameUIDPretty },
2970 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2972 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2973 0, numericStringValidate, NULL},
2974 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2976 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2977 0, numericoidValidate, NULL},
2978 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2979 0, IA5StringValidate, NULL},
2980 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2981 0, blobValidate, NULL},
2982 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2983 0, UTF8StringValidate, NULL},
2984 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2986 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2988 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2989 0, printableStringValidate, NULL},
2990 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2991 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2992 0, subtreeSpecificationValidate, NULL},
2993 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2994 X_BINARY X_NOT_H_R ")",
2995 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2996 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2997 0, printableStringValidate, NULL},
2998 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3000 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3001 0, printablesStringValidate, NULL},
3002 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3003 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3004 0, utcTimeValidate, NULL},
3006 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3008 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3010 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3012 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3014 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3017 /* RFC 2307 NIS Syntaxes */
3018 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3019 0, nisNetgroupTripleValidate, NULL},
3020 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3021 0, bootParameterValidate, NULL},
3023 /* From PKIX *//* This OID is not published yet. */
3024 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3026 serialNumberAndIssuerValidate,
3027 serialNumberAndIssuerPretty},
3029 #ifdef SLAPD_ACI_ENABLED
3030 /* OpenLDAP Experimental Syntaxes */
3031 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3033 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3037 #ifdef SLAPD_AUTHPASSWD
3038 /* needs updating */
3039 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3040 SLAP_SYNTAX_HIDE, NULL, NULL},
3043 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3044 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3046 /* OpenLDAP Void Syntax */
3047 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3048 SLAP_SYNTAX_HIDE, inValidate, NULL},
3049 {NULL, 0, NULL, NULL}
3052 char *certificateExactMatchSyntaxes[] = {
3053 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3056 char *directoryStringSyntaxes[] = {
3057 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3060 char *integerFirstComponentMatchSyntaxes[] = {
3061 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3062 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3065 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3066 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3067 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3068 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3069 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3070 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3071 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3072 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3073 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3078 * Other matching rules in X.520 that we do not use (yet):
3080 * 2.5.13.25 uTCTimeMatch
3081 * 2.5.13.26 uTCTimeOrderingMatch
3082 * 2.5.13.31* directoryStringFirstComponentMatch
3083 * 2.5.13.32* wordMatch
3084 * 2.5.13.33* keywordMatch
3085 * 2.5.13.36 certificatePairExactMatch
3086 * 2.5.13.37 certificatePairMatch
3087 * 2.5.13.38 certificateListExactMatch
3088 * 2.5.13.39 certificateListMatch
3089 * 2.5.13.40 algorithmIdentifierMatch
3090 * 2.5.13.41* storedPrefixMatch
3091 * 2.5.13.42 attributeCertificateMatch
3092 * 2.5.13.43 readerAndKeyIDMatch
3093 * 2.5.13.44 attributeIntegrityMatch
3095 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3097 static slap_mrule_defs_rec mrule_defs[] = {
3099 * EQUALITY matching rules must be listed after associated APPROX
3100 * matching rules. So, we list all APPROX matching rules first.
3102 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3103 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3104 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3105 NULL, NULL, directoryStringApproxMatch,
3106 directoryStringApproxIndexer, directoryStringApproxFilter,
3109 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3110 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3111 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3112 NULL, NULL, IA5StringApproxMatch,
3113 IA5StringApproxIndexer, IA5StringApproxFilter,
3117 * Other matching rules
3120 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3121 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3122 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3123 NULL, NULL, octetStringMatch,
3124 octetStringIndexer, octetStringFilter,
3127 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3128 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3129 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3130 NULL, dnNormalize, dnMatch,
3131 octetStringIndexer, octetStringFilter,
3134 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3135 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3136 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3137 NULL, UTF8StringNormalize, octetStringMatch,
3138 octetStringIndexer, octetStringFilter,
3139 directoryStringApproxMatchOID },
3141 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3142 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3143 SLAP_MR_ORDERING, directoryStringSyntaxes,
3144 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3146 "caseIgnoreMatch" },
3148 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3149 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3150 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3151 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3152 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3153 "caseIgnoreMatch" },
3155 {"( 2.5.13.5 NAME 'caseExactMatch' "
3156 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3157 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3158 NULL, UTF8StringNormalize, octetStringMatch,
3159 octetStringIndexer, octetStringFilter,
3160 directoryStringApproxMatchOID },
3162 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3163 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3164 SLAP_MR_ORDERING, directoryStringSyntaxes,
3165 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3169 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3170 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3171 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3172 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3173 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3176 {"( 2.5.13.8 NAME 'numericStringMatch' "
3177 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3178 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3179 NULL, numericStringNormalize, octetStringMatch,
3180 octetStringIndexer, octetStringFilter,
3183 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3184 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3185 SLAP_MR_ORDERING, NULL,
3186 NULL, numericStringNormalize, octetStringOrderingMatch,
3188 "numericStringMatch" },
3190 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3191 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3192 SLAP_MR_SUBSTR, NULL,
3193 NULL, numericStringNormalize, octetStringSubstringsMatch,
3194 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3195 "numericStringMatch" },
3197 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3198 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3199 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3200 NULL, NULL, NULL, NULL, NULL, NULL },
3202 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3203 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3204 SLAP_MR_SUBSTR, NULL,
3205 NULL, NULL, NULL, NULL, NULL,
3206 "caseIgnoreListMatch" },
3208 {"( 2.5.13.13 NAME 'booleanMatch' "
3209 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3210 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3211 NULL, NULL, booleanMatch,
3212 octetStringIndexer, octetStringFilter,
3215 {"( 2.5.13.14 NAME 'integerMatch' "
3216 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3217 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3218 NULL, NULL, integerMatch,
3219 octetStringIndexer, octetStringFilter,
3222 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3223 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3224 SLAP_MR_ORDERING, NULL,
3225 NULL, NULL, integerMatch,
3229 {"( 2.5.13.16 NAME 'bitStringMatch' "
3230 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3231 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3232 NULL, NULL, octetStringMatch,
3233 octetStringIndexer, octetStringFilter,
3236 {"( 2.5.13.17 NAME 'octetStringMatch' "
3237 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3238 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3239 NULL, NULL, octetStringMatch,
3240 octetStringIndexer, octetStringFilter,
3243 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3244 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3245 SLAP_MR_ORDERING, NULL,
3246 NULL, NULL, octetStringOrderingMatch,
3248 "octetStringMatch" },
3250 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3251 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3252 SLAP_MR_SUBSTR, NULL,
3253 NULL, NULL, octetStringSubstringsMatch,
3254 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3255 "octetStringMatch" },
3257 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3258 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3259 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3261 telephoneNumberNormalize, octetStringMatch,
3262 octetStringIndexer, octetStringFilter,
3265 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3266 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3267 SLAP_MR_SUBSTR, NULL,
3268 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3269 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3270 "telephoneNumberMatch" },
3272 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3273 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3274 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3275 NULL, NULL, NULL, NULL, NULL, NULL },
3277 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3278 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3279 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3280 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3284 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3285 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3286 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3287 NULL, NULL, NULL, NULL, NULL, NULL },
3289 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3290 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3291 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3292 NULL, generalizedTimeNormalize, octetStringMatch,
3296 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3297 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3298 SLAP_MR_ORDERING, NULL,
3299 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3301 "generalizedTimeMatch" },
3303 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3304 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3305 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3306 integerFirstComponentMatchSyntaxes,
3307 NULL, firstComponentNormalize, integerMatch,
3308 octetStringIndexer, octetStringFilter,
3311 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3312 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3313 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3314 objectIdentifierFirstComponentMatchSyntaxes,
3315 NULL, firstComponentNormalize, octetStringMatch,
3316 octetStringIndexer, octetStringFilter,
3319 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3320 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3321 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3323 NULL, certificateExactNormalize, octetStringMatch,
3324 octetStringIndexer, octetStringFilter,
3326 NULL, NULL, NULL, NULL, NULL,
3330 {"( 2.5.13.35 NAME 'certificateMatch' "
3331 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3332 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3334 NULL, NULL, octetStringMatch,
3335 octetStringIndexer, octetStringFilter,
3337 NULL, NULL, NULL, NULL, NULL,
3341 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3342 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3343 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3344 NULL, IA5StringNormalize, octetStringMatch,
3345 octetStringIndexer, octetStringFilter,
3346 IA5StringApproxMatchOID },
3348 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3349 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3350 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3351 NULL, IA5StringNormalize, octetStringMatch,
3352 octetStringIndexer, octetStringFilter,
3353 IA5StringApproxMatchOID },
3355 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3356 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3357 SLAP_MR_SUBSTR, NULL,
3358 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3359 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3360 "caseIgnoreIA5Match" },
3362 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3363 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3364 SLAP_MR_SUBSTR, NULL,
3365 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3366 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3367 "caseExactIA5Match" },
3369 #ifdef SLAPD_AUTHPASSWD
3370 /* needs updating */
3371 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3372 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3373 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3374 NULL, NULL, authPasswordMatch,
3379 #ifdef SLAPD_ACI_ENABLED
3380 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3381 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3382 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3383 NULL, NULL, OpenLDAPaciMatch,
3388 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3389 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3391 NULL, NULL, integerBitAndMatch,
3395 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3396 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3398 NULL, NULL, integerBitOrMatch,
3402 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3403 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3404 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3405 NULL, UUIDNormalize, octetStringMatch,
3406 octetStringIndexer, octetStringFilter,
3409 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3410 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3411 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3412 NULL, UUIDNormalize, octetStringOrderingMatch,
3413 octetStringIndexer, octetStringFilter,
3416 {NULL, SLAP_MR_NONE, NULL,
3417 NULL, NULL, NULL, NULL, NULL,
3422 slap_schema_init( void )
3427 /* we should only be called once (from main) */
3428 assert( schema_init_done == 0 );
3430 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3431 res = register_syntax( &syntax_defs[i] );
3434 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3435 syntax_defs[i].sd_desc );
3440 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3441 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3442 mrule_defs[i].mrd_compat_syntaxes == NULL )
3445 "slap_schema_init: Ignoring unusable matching rule %s\n",
3446 mrule_defs[i].mrd_desc );
3450 res = register_matching_rule( &mrule_defs[i] );
3454 "slap_schema_init: Error registering matching rule %s\n",
3455 mrule_defs[i].mrd_desc );
3460 res = slap_schema_load();
3461 schema_init_done = 1;
3466 schema_destroy( void )