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,
846 ber_memfree_x( out->bv_val, ctx );
850 out->bv_val[out->bv_len++] = '#';
851 out->bv_val[out->bv_len++] = '\'';
853 got1 = uidval.bv_len < sizeof("'0'B");
854 for( i = 1; i < uidval.bv_len - 2; i++ ) {
855 c = uidval.bv_val[i];
858 if( got1 ) out->bv_val[out->bv_len++] = c;
862 out->bv_val[out->bv_len++] = c;
865 return LDAP_INVALID_SYNTAX;
869 out->bv_val[out->bv_len++] = '\'';
870 out->bv_val[out->bv_len++] = 'B';
871 out->bv_val[out->bv_len] = '\0';
876 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
878 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
885 uniqueMemberNormalize(
890 struct berval *normalized,
896 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
898 ber_dupbv_x( &out, val, ctx );
899 if ( BER_BVISEMPTY( &out ) ) {
903 struct berval uid = BER_BVNULL;
905 if( out.bv_val[out.bv_len-1] == 'B'
906 && out.bv_val[out.bv_len-2] == '\'' )
908 /* assume presence of optional UID */
909 uid.bv_val = strrchr( out.bv_val, '#' );
911 /* if no '#', or '#' before the beginning
912 * of the string, or preceded
913 * by an escape char '\\'...
914 * (a string of "#'<UID>'B" should be valid,
915 * since the empty "" DN is legal) */
916 if( uid.bv_val == NULL
917 || uid.bv_val < out.bv_val
918 || ( uid.bv_val > out.bv_val && uid.bv_val[-1] == '\\' ) )
920 slap_sl_free( out.bv_val, ctx );
921 return LDAP_INVALID_SYNTAX;
924 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
925 out.bv_len -= uid.bv_len--;
927 /* temporarily trim the UID */
928 *(uid.bv_val++) = '\0';
931 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
933 if( rc != LDAP_SUCCESS ) {
934 slap_sl_free( out.bv_val, ctx );
935 return LDAP_INVALID_SYNTAX;
939 normalized->bv_val = ch_realloc( normalized->bv_val,
940 normalized->bv_len + uid.bv_len
941 + STRLENOF("#") + 1 );
943 /* insert the separator */
944 normalized->bv_val[normalized->bv_len++] = '#';
947 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
948 uid.bv_val, uid.bv_len );
949 normalized->bv_len += uid.bv_len;
952 normalized->bv_val[normalized->bv_len] = '\0';
955 slap_sl_free( out.bv_val, ctx );
967 struct berval *value,
968 void *assertedValue )
971 struct berval *asserted = (struct berval *) assertedValue;
972 struct berval assertedDN = BER_BVNULL;
973 struct berval assertedUID = BER_BVNULL;
974 struct berval valueDN = BER_BVNULL;
975 struct berval valueUID = BER_BVNULL;
977 if( asserted->bv_len != 0 ) {
978 assertedDN = *asserted;
980 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
981 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
983 /* assume presence of optional UID */
984 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
986 if( assertedUID.bv_val == NULL ||
987 assertedUID.bv_val < assertedDN.bv_val ||
988 ( assertedUID.bv_val > assertedDN.bv_val &&
989 assertedUID.bv_val[-1] == '\\' ))
991 return LDAP_INVALID_SYNTAX;
994 assertedUID.bv_len = assertedDN.bv_len -
995 (assertedUID.bv_val - assertedDN.bv_val);
996 assertedDN.bv_len -= assertedUID.bv_len;
998 /* trim the separator */
999 assertedUID.bv_len--;
1000 assertedUID.bv_val++;
1004 if( value->bv_len != 0 ) {
1007 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
1008 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
1010 /* assume presence of optional UID */
1011 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
1013 if( valueUID.bv_val == NULL ||
1014 valueUID.bv_val < valueDN.bv_val ||
1015 ( valueUID.bv_val > valueDN.bv_val &&
1016 valueUID.bv_val[-1] == '\\' ) )
1018 return LDAP_INVALID_SYNTAX;
1021 valueUID.bv_len = valueDN.bv_len -
1022 (valueUID.bv_val - valueDN.bv_val);
1023 valueDN.bv_len -= valueUID.bv_len;
1025 /* trim the separator */
1031 if( valueUID.bv_len && assertedUID.bv_len ) {
1032 match = valueUID.bv_len - assertedUID.bv_len;
1035 return LDAP_SUCCESS;
1038 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
1041 return LDAP_SUCCESS;
1045 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
1049 * Handling boolean syntax and matching is quite rigid.
1050 * A more flexible approach would be to allow a variety
1051 * of strings to be normalized and prettied into TRUE
1059 /* very unforgiving validation, requires no normalization
1060 * before simplistic matching
1063 if( in->bv_len == 4 ) {
1064 if( bvmatch( in, &slap_true_bv ) ) {
1065 return LDAP_SUCCESS;
1067 } else if( in->bv_len == 5 ) {
1068 if( bvmatch( in, &slap_false_bv ) ) {
1069 return LDAP_SUCCESS;
1073 return LDAP_INVALID_SYNTAX;
1082 struct berval *value,
1083 void *assertedValue )
1085 /* simplistic matching allowed by rigid validation */
1086 struct berval *asserted = (struct berval *) assertedValue;
1087 *matchp = value->bv_len != asserted->bv_len;
1088 return LDAP_SUCCESS;
1091 /*-------------------------------------------------------------------
1092 LDAP/X.500 string syntax / matching rules have a few oddities. This
1093 comment attempts to detail how slapd(8) treats them.
1096 StringSyntax X.500 LDAP Matching/Comments
1097 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1098 PrintableString subset subset i/e + ignore insignificant spaces
1099 PrintableString subset subset i/e + ignore insignificant spaces
1100 NumericString subset subset ignore all spaces
1101 IA5String ASCII ASCII i/e + ignore insignificant spaces
1102 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1104 TelephoneNumber subset subset i + ignore all spaces and "-"
1106 See draft-ietf-ldapbis-strpro for details (once published).
1110 In X.500(93), a directory string can be either a PrintableString,
1111 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1112 In later versions, more CHOICEs were added. In all cases the string
1115 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1116 A directory string cannot be zero length.
1118 For matching, there are both case ignore and exact rules. Both
1119 also require that "insignificant" spaces be ignored.
1120 spaces before the first non-space are ignored;
1121 spaces after the last non-space are ignored;
1122 spaces after a space are ignored.
1123 Note: by these rules (and as clarified in X.520), a string of only
1124 spaces is to be treated as if held one space, not empty (which
1125 would be a syntax error).
1128 In ASN.1, numeric string is just a string of digits and spaces
1129 and could be empty. However, in X.500, all attribute values of
1130 numeric string carry a non-empty constraint. For example:
1132 internationalISDNNumber ATTRIBUTE ::= {
1133 WITH SYNTAX InternationalISDNNumber
1134 EQUALITY MATCHING RULE numericStringMatch
1135 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1136 ID id-at-internationalISDNNumber }
1137 InternationalISDNNumber ::=
1138 NumericString (SIZE(1..ub-international-isdn-number))
1140 Unforunately, some assertion values are don't carry the same
1141 constraint (but its unclear how such an assertion could ever
1142 be true). In LDAP, there is one syntax (numericString) not two
1143 (numericString with constraint, numericString without constraint).
1144 This should be treated as numericString with non-empty constraint.
1145 Note that while someone may have no ISDN number, there are no ISDN
1146 numbers which are zero length.
1148 In matching, spaces are ignored.
1151 In ASN.1, Printable string is just a string of printable characters
1152 and can be empty. In X.500, semantics much like NumericString (see
1153 serialNumber for a like example) excepting uses insignificant space
1154 handling instead of ignore all spaces.
1157 Basically same as PrintableString. There are no examples in X.500,
1158 but same logic applies. So we require them to be non-empty as
1161 -------------------------------------------------------------------*/
1170 unsigned char *u = (unsigned char *)in->bv_val;
1172 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1173 /* directory strings cannot be empty */
1174 return LDAP_INVALID_SYNTAX;
1177 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1178 /* get the length indicated by the first byte */
1179 len = LDAP_UTF8_CHARLEN2( u, len );
1181 /* very basic checks */
1184 if( (u[5] & 0xC0) != 0x80 ) {
1185 return LDAP_INVALID_SYNTAX;
1188 if( (u[4] & 0xC0) != 0x80 ) {
1189 return LDAP_INVALID_SYNTAX;
1192 if( (u[3] & 0xC0) != 0x80 ) {
1193 return LDAP_INVALID_SYNTAX;
1196 if( (u[2] & 0xC0 )!= 0x80 ) {
1197 return LDAP_INVALID_SYNTAX;
1200 if( (u[1] & 0xC0) != 0x80 ) {
1201 return LDAP_INVALID_SYNTAX;
1204 /* CHARLEN already validated it */
1207 return LDAP_INVALID_SYNTAX;
1210 /* make sure len corresponds with the offset
1211 to the next character */
1212 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1216 return LDAP_INVALID_SYNTAX;
1219 return LDAP_SUCCESS;
1223 UTF8StringNormalize(
1228 struct berval *normalized,
1231 struct berval tmp, nvalue;
1235 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1237 if( val->bv_val == NULL ) {
1238 /* assume we're dealing with a syntax (e.g., UTF8String)
1239 * which allows empty strings
1241 normalized->bv_len = 0;
1242 normalized->bv_val = NULL;
1243 return LDAP_SUCCESS;
1246 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1247 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1248 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1249 ? LDAP_UTF8_APPROX : 0;
1251 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1256 /* collapse spaces (in place) */
1258 nvalue.bv_val = tmp.bv_val;
1260 wasspace=1; /* trim leading spaces */
1261 for( i=0; i<tmp.bv_len; i++) {
1262 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1263 if( wasspace++ == 0 ) {
1264 /* trim repeated spaces */
1265 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1269 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1273 if( nvalue.bv_len ) {
1275 /* last character was a space, trim it */
1278 nvalue.bv_val[nvalue.bv_len] = '\0';
1281 /* string of all spaces is treated as one space */
1282 nvalue.bv_val[0] = ' ';
1283 nvalue.bv_val[1] = '\0';
1287 *normalized = nvalue;
1288 return LDAP_SUCCESS;
1291 #if defined(SLAPD_APPROX_INITIALS)
1292 # define SLAPD_APPROX_DELIMITER "._ "
1293 # define SLAPD_APPROX_WORDLEN 2
1295 # define SLAPD_APPROX_DELIMITER " "
1296 # define SLAPD_APPROX_WORDLEN 1
1305 struct berval *value,
1306 void *assertedValue )
1308 struct berval *nval, *assertv;
1309 char *val, **values, **words, *c;
1310 int i, count, len, nextchunk=0, nextavail=0;
1312 /* Yes, this is necessary */
1313 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1314 if( nval == NULL ) {
1316 return LDAP_SUCCESS;
1319 /* Yes, this is necessary */
1320 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1321 NULL, LDAP_UTF8_APPROX, NULL );
1322 if( assertv == NULL ) {
1325 return LDAP_SUCCESS;
1328 /* Isolate how many words there are */
1329 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1330 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1331 if ( c == NULL ) break;
1336 /* Get a phonetic copy of each word */
1337 words = (char **)ch_malloc( count * sizeof(char *) );
1338 values = (char **)ch_malloc( count * sizeof(char *) );
1339 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1341 values[i] = phonetic(c);
1344 /* Work through the asserted value's words, to see if at least some
1345 of the words are there, in the same order. */
1347 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1348 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1353 #if defined(SLAPD_APPROX_INITIALS)
1354 else if( len == 1 ) {
1355 /* Single letter words need to at least match one word's initial */
1356 for( i=nextavail; i<count; i++ )
1357 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1364 /* Isolate the next word in the asserted value and phonetic it */
1365 assertv->bv_val[nextchunk+len] = '\0';
1366 val = phonetic( assertv->bv_val + nextchunk );
1368 /* See if this phonetic chunk is in the remaining words of *value */
1369 for( i=nextavail; i<count; i++ ){
1370 if( !strcmp( val, values[i] ) ){
1378 /* This chunk in the asserted value was NOT within the *value. */
1384 /* Go on to the next word in the asserted value */
1388 /* If some of the words were seen, call it a match */
1389 if( nextavail > 0 ) {
1396 /* Cleanup allocs */
1397 ber_bvfree( assertv );
1398 for( i=0; i<count; i++ ) {
1399 ch_free( values[i] );
1405 return LDAP_SUCCESS;
1414 struct berval *prefix,
1420 int i,j, len, wordcount, keycount=0;
1421 struct berval *newkeys;
1422 BerVarray keys=NULL;
1424 for( j=0; values[j].bv_val != NULL; j++ ) {
1425 struct berval val = BER_BVNULL;
1426 /* Yes, this is necessary */
1427 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1428 assert( val.bv_val != NULL );
1430 /* Isolate how many words there are. There will be a key for each */
1431 for( wordcount = 0, c = val.bv_val; *c; c++) {
1432 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1433 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1435 if (*c == '\0') break;
1439 /* Allocate/increase storage to account for new keys */
1440 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1441 * sizeof(struct berval) );
1442 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1443 if( keys ) ch_free( keys );
1446 /* Get a phonetic copy of each word */
1447 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1449 if( len < SLAPD_APPROX_WORDLEN ) continue;
1450 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1455 ber_memfree( val.bv_val );
1457 keys[keycount].bv_val = NULL;
1460 return LDAP_SUCCESS;
1469 struct berval *prefix,
1470 void * assertedValue,
1479 /* Yes, this is necessary */
1480 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1481 NULL, LDAP_UTF8_APPROX, NULL );
1482 if( val == NULL || val->bv_val == NULL ) {
1483 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1484 keys[0].bv_val = NULL;
1487 return LDAP_SUCCESS;
1490 /* Isolate how many words there are. There will be a key for each */
1491 for( count = 0,c = val->bv_val; *c; c++) {
1492 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1493 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1495 if (*c == '\0') break;
1499 /* Allocate storage for new keys */
1500 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1502 /* Get a phonetic copy of each word */
1503 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1505 if( len < SLAPD_APPROX_WORDLEN ) continue;
1506 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1512 keys[count].bv_val = NULL;
1515 return LDAP_SUCCESS;
1518 /* Remove all spaces and '-' characters */
1520 telephoneNumberNormalize(
1525 struct berval *normalized,
1530 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1532 /* validator should have refused an empty string */
1533 assert( val->bv_len );
1535 q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1537 for( p = val->bv_val; *p; p++ ) {
1538 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1544 normalized->bv_len = q - normalized->bv_val;
1546 if( normalized->bv_len == 0 ) {
1547 slap_sl_free( normalized->bv_val, ctx );
1548 normalized->bv_val = NULL;
1549 return LDAP_INVALID_SYNTAX;
1552 return LDAP_SUCCESS;
1560 struct berval val = *in;
1562 if( val.bv_len == 0 ) {
1563 /* disallow empty strings */
1564 return LDAP_INVALID_SYNTAX;
1567 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1568 if ( val.bv_len == 1 ) {
1569 return LDAP_SUCCESS;
1572 if ( val.bv_val[0] == '0' ) {
1579 while ( OID_LEADCHAR( val.bv_val[0] )) {
1583 if ( val.bv_len == 0 ) {
1584 return LDAP_SUCCESS;
1588 if( !OID_SEPARATOR( val.bv_val[0] )) {
1596 return LDAP_INVALID_SYNTAX;
1605 struct berval val = *in;
1607 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1609 if ( val.bv_val[0] == '-' ) {
1613 if( val.bv_len == 0 ) { /* bare "-" */
1614 return LDAP_INVALID_SYNTAX;
1617 if( val.bv_val[0] == '0' ) { /* "-0" */
1618 return LDAP_INVALID_SYNTAX;
1621 } else if ( val.bv_val[0] == '0' ) {
1622 if( val.bv_len > 1 ) { /* "0<more>" */
1623 return LDAP_INVALID_SYNTAX;
1626 return LDAP_SUCCESS;
1629 for( i=0; i < val.bv_len; i++ ) {
1630 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1631 return LDAP_INVALID_SYNTAX;
1635 return LDAP_SUCCESS;
1644 struct berval *value,
1645 void *assertedValue )
1647 struct berval *asserted = (struct berval *) assertedValue;
1648 int vsign = 1, asign = 1; /* default sign = '+' */
1653 if( v.bv_val[0] == '-' ) {
1659 if( v.bv_len == 0 ) vsign = 0;
1662 if( a.bv_val[0] == '-' ) {
1668 if( a.bv_len == 0 ) vsign = 0;
1670 match = vsign - asign;
1672 match = ( v.bv_len != a.bv_len
1673 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1674 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1675 if( vsign < 0 ) match = -match;
1679 return LDAP_SUCCESS;
1683 countryStringValidate(
1685 struct berval *val )
1687 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1689 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1690 return LDAP_INVALID_SYNTAX;
1692 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1693 return LDAP_INVALID_SYNTAX;
1696 return LDAP_SUCCESS;
1700 printableStringValidate(
1702 struct berval *val )
1706 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1708 for(i=0; i < val->bv_len; i++) {
1709 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1710 return LDAP_INVALID_SYNTAX;
1714 return LDAP_SUCCESS;
1718 printablesStringValidate(
1720 struct berval *val )
1724 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1726 for(i=0,len=0; i < val->bv_len; i++) {
1727 int c = val->bv_val[i];
1731 return LDAP_INVALID_SYNTAX;
1735 } else if ( SLAP_PRINTABLE(c) ) {
1738 return LDAP_INVALID_SYNTAX;
1743 return LDAP_INVALID_SYNTAX;
1746 return LDAP_SUCCESS;
1752 struct berval *val )
1756 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1758 for(i=0; i < val->bv_len; i++) {
1759 if( !LDAP_ASCII(val->bv_val[i]) ) {
1760 return LDAP_INVALID_SYNTAX;
1764 return LDAP_SUCCESS;
1773 struct berval *normalized,
1777 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1779 assert( val->bv_len );
1781 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1785 /* Ignore initial whitespace */
1786 while ( ASCII_SPACE( *p ) ) p++;
1788 normalized->bv_val = ber_strdup_x( p, ctx );
1789 p = q = normalized->bv_val;
1792 if ( ASCII_SPACE( *p ) ) {
1795 /* Ignore the extra whitespace */
1796 while ( ASCII_SPACE( *p ) ) {
1800 } else if ( casefold ) {
1801 /* Most IA5 rules require casefolding */
1802 *q++ = TOLOWER(*p); p++;
1809 assert( normalized->bv_val <= p );
1813 * If the string ended in space, backup the pointer one
1814 * position. One is enough because the above loop collapsed
1815 * all whitespace to a single space.
1817 if ( ASCII_SPACE( q[-1] ) ) --q;
1819 /* null terminate */
1822 normalized->bv_len = q - normalized->bv_val;
1823 if( normalized->bv_len == 0 ) {
1824 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1825 normalized->bv_val[0] = ' ';
1826 normalized->bv_val[1] = '\0';
1827 normalized->bv_len = 1;
1830 return LDAP_SUCCESS;
1839 if( in->bv_len != 36 ) {
1841 return LDAP_INVALID_SYNTAX;
1844 for( i=0; i<36; i++ ) {
1850 if( in->bv_val[i] != '-' ) {
1851 return LDAP_INVALID_SYNTAX;
1855 if( !ASCII_HEX( in->bv_val[i]) ) {
1856 return LDAP_INVALID_SYNTAX;
1861 return LDAP_SUCCESS;
1870 struct berval *normalized,
1873 unsigned char octet = '\0';
1876 normalized->bv_len = 16;
1877 normalized->bv_val = slap_sl_malloc( normalized->bv_len+1, ctx );
1879 for( i=0, j=0; i<36; i++ ) {
1880 unsigned char nibble;
1881 if( val->bv_val[i] == '-' ) {
1884 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1885 nibble = val->bv_val[i] - '0';
1887 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1888 nibble = val->bv_val[i] - ('a'-10);
1890 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1891 nibble = val->bv_val[i] - ('A'-10);
1894 slap_sl_free( normalized->bv_val, ctx );
1895 return LDAP_INVALID_SYNTAX;
1900 normalized->bv_val[j>>1] = octet;
1902 octet = nibble << 4;
1907 normalized->bv_val[normalized->bv_len] = 0;
1908 return LDAP_SUCCESS;
1914 numericStringValidate(
1920 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1922 for(i=0; i < in->bv_len; i++) {
1923 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1924 return LDAP_INVALID_SYNTAX;
1928 return LDAP_SUCCESS;
1932 numericStringNormalize(
1937 struct berval *normalized,
1940 /* removal all spaces */
1943 assert( val->bv_len );
1945 normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
1948 q = normalized->bv_val;
1951 if ( ASCII_SPACE( *p ) ) {
1952 /* Ignore whitespace */
1959 /* we should have copied no more then is in val */
1960 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1962 /* null terminate */
1965 normalized->bv_len = q - normalized->bv_val;
1967 if( normalized->bv_len == 0 ) {
1968 normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
1969 normalized->bv_val[0] = ' ';
1970 normalized->bv_val[1] = '\0';
1971 normalized->bv_len = 1;
1974 return LDAP_SUCCESS;
1978 * Integer conversion macros that will use the largest available
1981 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \
1982 && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1983 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1984 # define SLAP_LONG_MAX LLONG_MAX
1985 # define SLAP_LONG_MIN LLONG_MIN
1986 # define SLAP_LONG long long
1988 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1989 # define SLAP_LONG_MAX LONG_MAX
1990 # define SLAP_LONG_MIN LONG_MIN
1991 # define SLAP_LONG long
1992 #endif /* HAVE_STRTOLL ... */
2000 struct berval *value,
2001 void *assertedValue )
2003 SLAP_LONG lValue, lAssertedValue;
2005 /* safe to assume integers are NUL terminated? */
2006 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2007 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) &&
2010 return LDAP_CONSTRAINT_VIOLATION;
2013 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
2015 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2018 return LDAP_CONSTRAINT_VIOLATION;
2021 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2022 return LDAP_SUCCESS;
2031 struct berval *value,
2032 void *assertedValue )
2034 SLAP_LONG lValue, lAssertedValue;
2036 /* safe to assume integers are NUL terminated? */
2037 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
2038 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) &&
2041 return LDAP_CONSTRAINT_VIOLATION;
2044 lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
2046 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) &&
2049 return LDAP_CONSTRAINT_VIOLATION;
2052 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2053 return LDAP_SUCCESS;
2057 serialNumberAndIssuerValidate(
2064 struct berval sn, i;
2065 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2067 i.bv_val = strchr( in->bv_val, '$' );
2068 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2070 sn.bv_val = in->bv_val;
2071 sn.bv_len = i.bv_val - in->bv_val;
2074 i.bv_len = in->bv_len - (sn.bv_len + 1);
2076 /* validate serial number (strict for now) */
2077 for( n=0; n < sn.bv_len; n++ ) {
2078 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2082 rc = dnValidate( NULL, &i );
2083 if( rc ) return LDAP_INVALID_SYNTAX;
2085 return LDAP_SUCCESS;
2089 serialNumberAndIssuerPretty(
2098 struct berval sn, i, newi;
2104 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2105 val->bv_val, 0, 0 );
2107 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2108 val->bv_val, 0, 0 );
2111 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2113 i.bv_val = strchr( val->bv_val, '$' );
2114 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2116 sn.bv_val = val->bv_val;
2117 sn.bv_len = i.bv_val - val->bv_val;
2120 i.bv_len = val->bv_len - (sn.bv_len + 1);
2122 /* eat leading zeros */
2123 for( n=0; n < (sn.bv_len-1); n++ ) {
2124 if( sn.bv_val[n] != '0' ) break;
2129 for( n=0; n < sn.bv_len; n++ ) {
2130 if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX;
2134 rc = dnPretty( syntax, &i, &newi, ctx );
2135 if( rc ) return LDAP_INVALID_SYNTAX;
2137 /* make room from sn + "$" */
2138 out->bv_len = sn.bv_len + newi.bv_len + 1;
2139 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2141 if( out->bv_val == NULL ) {
2142 slap_sl_free( newi.bv_val, ctx );
2146 /* push issuer over */
2147 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2148 /* insert sn and "$" */
2149 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2150 out->bv_val[sn.bv_len] = '$';
2152 out->bv_val[out->bv_len] = '\0';
2155 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2156 out->bv_val, 0, 0 );
2158 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2159 out->bv_val, 0, 0 );
2162 return LDAP_SUCCESS;
2166 * This routine is called by certificateExactNormalize when
2167 * certificateExactNormalize receives a search string instead of
2168 * a certificate. This routine checks if the search value is valid
2169 * and then returns the normalized value
2172 serialNumberAndIssuerNormalize(
2183 struct berval sn, i, newi;
2189 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2190 val->bv_val, 0, 0 );
2192 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2193 val->bv_val, 0, 0 );
2196 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2198 i.bv_val = strchr( val->bv_val, '$' );
2199 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2201 sn.bv_val = val->bv_val;
2202 sn.bv_len = i.bv_val - val->bv_val;
2205 i.bv_len = val->bv_len - (sn.bv_len + 1);
2207 /* eat leading zeros */
2208 for( n=0; n < (sn.bv_len-1); n++ ) {
2209 if( sn.bv_val[n] != '0' ) break;
2214 for( n=0; n < sn.bv_len; n++ ) {
2215 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2216 return LDAP_INVALID_SYNTAX;
2221 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2222 if( rc ) return LDAP_INVALID_SYNTAX;
2224 /* make room from sn + "$" */
2225 out->bv_len = sn.bv_len + newi.bv_len + 1;
2226 out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2228 if( out->bv_val == NULL ) {
2229 slap_sl_free( newi.bv_val, ctx );
2233 /* push issuer over */
2234 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2235 /* insert sn and "$" */
2236 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2237 out->bv_val[sn.bv_len] = '$';
2239 out->bv_val[out->bv_len] = '\0';
2242 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2243 out->bv_val, 0, 0 );
2245 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2246 out->bv_val, 0, 0 );
2254 certificateExactNormalize(
2259 struct berval *normalized,
2262 int rc = LDAP_INVALID_SYNTAX;
2264 char *serial = NULL;
2265 ber_len_t seriallen;
2266 struct berval issuer_dn = BER_BVNULL;
2267 X509_NAME *name = NULL;
2268 ASN1_INTEGER *sn = NULL;
2271 if( val->bv_len == 0 ) goto done;
2273 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2274 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2277 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2279 p = (unsigned char *)val->bv_val;
2280 xcert = d2i_X509( NULL, &p, val->bv_len);
2281 if( xcert == NULL ) goto done;
2283 sn=X509_get_serialNumber(xcert);
2284 if ( sn == NULL ) goto done;
2285 serial=i2s_ASN1_INTEGER(0, sn );
2286 if( serial == NULL ) goto done;
2287 seriallen=strlen(serial);
2289 name=X509_get_issuer_name(xcert);
2290 if( name == NULL ) goto done;
2291 rc = dnX509normalize( name, &issuer_dn );
2292 if( rc != LDAP_SUCCESS ) goto done;
2294 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2295 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2296 p = (unsigned char *)normalized->bv_val;
2297 AC_MEMCPY(p, serial, seriallen);
2300 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2301 p += issuer_dn.bv_len;
2305 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2306 normalized->bv_val, 0, 0 );
2308 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2309 normalized->bv_val, NULL, NULL );
2313 if (xcert) X509_free(xcert);
2314 if (serial) ch_free(serial);
2315 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2319 #endif /* HAVE_TLS */
2322 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2323 /* slight optimization - does not need the start parameter */
2324 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2329 check_time_syntax (struct berval *val,
2332 struct berval *fraction)
2335 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2336 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2337 * GeneralizedTime supports leap seconds, UTCTime does not.
2339 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2340 static const int mdays[2][12] = {
2341 /* non-leap years */
2342 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2344 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2347 int part, c, c1, c2, tzoffset, leapyear = 0;
2350 e = p + val->bv_len;
2352 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2353 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2355 for (part = start; part < 7 && p < e; part++) {
2357 if (!ASCII_DIGIT(c1)) {
2362 return LDAP_INVALID_SYNTAX;
2365 if (!ASCII_DIGIT(c)) {
2366 return LDAP_INVALID_SYNTAX;
2368 c += c1 * 10 - '0' * 11;
2369 if ((part | 1) == 3) {
2372 return LDAP_INVALID_SYNTAX;
2375 if (c >= ceiling[part]) {
2376 if (! (c == 60 && part == 6 && start == 0))
2377 return LDAP_INVALID_SYNTAX;
2381 if (part < 5 + start) {
2382 return LDAP_INVALID_SYNTAX;
2384 for (; part < 9; part++) {
2388 /* leapyear check for the Gregorian calendar (year>1581) */
2389 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2394 if (parts[3] >= mdays[leapyear][parts[2]]) {
2395 return LDAP_INVALID_SYNTAX;
2399 fraction->bv_val = p;
2400 fraction->bv_len = 0;
2401 if (p < e && (*p == '.' || *p == ',')) {
2403 while (++p < e && ASCII_DIGIT(*p))
2405 if (p - fraction->bv_val == 1) {
2406 return LDAP_INVALID_SYNTAX;
2408 for (end_num = p; end_num[-1] == '0'; --end_num)
2410 c = end_num - fraction->bv_val;
2412 fraction->bv_len = c;
2418 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2424 return LDAP_INVALID_SYNTAX;
2430 for (part = 7; part < 9 && p < e; part++) {
2432 if (!ASCII_DIGIT(c1)) {
2437 return LDAP_INVALID_SYNTAX;
2440 if (!ASCII_DIGIT(c2)) {
2441 return LDAP_INVALID_SYNTAX;
2443 parts[part] = c1 * 10 + c2 - '0' * 11;
2444 if (parts[part] >= ceiling[part]) {
2445 return LDAP_INVALID_SYNTAX;
2448 if (part < 8 + start) {
2449 return LDAP_INVALID_SYNTAX;
2452 if (tzoffset == '-') {
2453 /* negative offset to UTC, ie west of Greenwich */
2454 parts[4] += parts[7];
2455 parts[5] += parts[8];
2456 /* offset is just hhmm, no seconds */
2457 for (part = 6; --part >= 0; ) {
2461 c = mdays[leapyear][parts[2]];
2463 if (parts[part] >= c) {
2465 return LDAP_INVALID_SYNTAX;
2470 } else if (part != 5) {
2475 /* positive offset to UTC, ie east of Greenwich */
2476 parts[4] -= parts[7];
2477 parts[5] -= parts[8];
2478 for (part = 6; --part >= 0; ) {
2479 if (parts[part] < 0) {
2481 return LDAP_INVALID_SYNTAX;
2486 /* make first arg to % non-negative */
2487 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2492 } else if (part != 5) {
2499 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2502 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2509 struct berval *normalized )
2513 rc = check_time_syntax(val, 1, parts, NULL);
2514 if (rc != LDAP_SUCCESS) {
2518 normalized->bv_val = ch_malloc( 14 );
2519 if ( normalized->bv_val == NULL ) {
2520 return LBER_ERROR_MEMORY;
2523 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2524 parts[1], parts[2] + 1, parts[3] + 1,
2525 parts[4], parts[5], parts[6] );
2526 normalized->bv_len = 13;
2528 return LDAP_SUCCESS;
2538 return check_time_syntax(in, 1, parts, NULL);
2541 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2544 generalizedTimeValidate(
2549 struct berval fraction;
2550 return check_time_syntax(in, 0, parts, &fraction);
2554 generalizedTimeNormalize(
2559 struct berval *normalized,
2564 struct berval fraction;
2566 rc = check_time_syntax(val, 0, parts, &fraction);
2567 if (rc != LDAP_SUCCESS) {
2571 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2572 normalized->bv_val = slap_sl_malloc( len + 1, ctx );
2573 if ( normalized->bv_val == NULL ) {
2574 return LBER_ERROR_MEMORY;
2577 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2578 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2579 parts[4], parts[5], parts[6] );
2580 if ( fraction.bv_len ) {
2581 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2582 fraction.bv_val, fraction.bv_len );
2583 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2585 strcpy( normalized->bv_val + len-1, "Z" );
2586 normalized->bv_len = len;
2588 return LDAP_SUCCESS;
2592 generalizedTimeOrderingMatch(
2597 struct berval *value,
2598 void *assertedValue )
2600 struct berval *asserted = (struct berval *) assertedValue;
2601 ber_len_t v_len = value->bv_len;
2602 ber_len_t av_len = asserted->bv_len;
2604 /* ignore trailing 'Z' when comparing */
2605 int match = memcmp( value->bv_val, asserted->bv_val,
2606 (v_len < av_len ? v_len : av_len) - 1 );
2607 if ( match == 0 ) match = v_len - av_len;
2610 return LDAP_SUCCESS;
2614 deliveryMethodValidate(
2616 struct berval *val )
2619 #define LENOF(s) (sizeof(s)-1)
2620 struct berval tmp = *val;
2622 * DeliveryMethod = pdm *( WSP DOLLAR WSP DeliveryMethod )
2623 * pdm = "any" / "mhs" / "physical" / "telex" / "teletex" /
2624 * "g3fax" / "g4fax" / "ia5" / "videotex" / "telephone"
2627 if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2629 switch( tmp.bv_val[0] ) {
2632 if(( tmp.bv_len >= LENOF("any") ) &&
2633 ( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
2635 tmp.bv_len -= LENOF("any");
2636 tmp.bv_val += LENOF("any");
2639 return LDAP_INVALID_SYNTAX;
2643 if(( tmp.bv_len >= LENOF("mhs") ) &&
2644 ( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
2646 tmp.bv_len -= LENOF("mhs");
2647 tmp.bv_val += LENOF("mhs");
2650 return LDAP_INVALID_SYNTAX;
2654 if(( tmp.bv_len >= LENOF("physical") ) &&
2655 ( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
2657 tmp.bv_len -= LENOF("physical");
2658 tmp.bv_val += LENOF("physical");
2661 return LDAP_INVALID_SYNTAX;
2664 case 'T': /* telex or teletex or telephone */
2665 if(( tmp.bv_len >= LENOF("telex") ) &&
2666 ( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
2668 tmp.bv_len -= LENOF("telex");
2669 tmp.bv_val += LENOF("telex");
2672 if(( tmp.bv_len >= LENOF("teletex") ) &&
2673 ( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
2675 tmp.bv_len -= LENOF("teletex");
2676 tmp.bv_val += LENOF("teletex");
2679 if(( tmp.bv_len >= LENOF("telephone") ) &&
2680 ( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
2682 tmp.bv_len -= LENOF("telephone");
2683 tmp.bv_val += LENOF("telephone");
2686 return LDAP_INVALID_SYNTAX;
2689 case 'G': /* g3fax or g4fax */
2690 if(( tmp.bv_len >= LENOF("g3fax") ) && (
2691 ( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
2692 ( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
2694 tmp.bv_len -= LENOF("g3fax");
2695 tmp.bv_val += LENOF("g3fax");
2698 return LDAP_INVALID_SYNTAX;
2702 if(( tmp.bv_len >= LENOF("ia5") ) &&
2703 ( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
2705 tmp.bv_len -= LENOF("ia5");
2706 tmp.bv_val += LENOF("ia5");
2709 return LDAP_INVALID_SYNTAX;
2713 if(( tmp.bv_len >= LENOF("videotex") ) &&
2714 ( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
2716 tmp.bv_len -= LENOF("videotex");
2717 tmp.bv_val += LENOF("videotex");
2720 return LDAP_INVALID_SYNTAX;
2723 return LDAP_INVALID_SYNTAX;
2726 if( tmp.bv_len == 0 ) return LDAP_SUCCESS;
2728 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2732 if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) {
2736 return LDAP_INVALID_SYNTAX;
2738 while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) {
2747 nisNetgroupTripleValidate(
2749 struct berval *val )
2754 if ( val->bv_len == 0 ) {
2755 return LDAP_INVALID_SYNTAX;
2758 p = (char *)val->bv_val;
2759 e = p + val->bv_len;
2761 if ( *p != '(' /*')'*/ ) {
2762 return LDAP_INVALID_SYNTAX;
2765 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2769 return LDAP_INVALID_SYNTAX;
2772 } else if ( !AD_CHAR( *p ) ) {
2773 return LDAP_INVALID_SYNTAX;
2777 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2778 return LDAP_INVALID_SYNTAX;
2784 return LDAP_INVALID_SYNTAX;
2787 return LDAP_SUCCESS;
2791 bootParameterValidate(
2793 struct berval *val )
2797 if ( val->bv_len == 0 ) {
2798 return LDAP_INVALID_SYNTAX;
2801 p = (char *)val->bv_val;
2802 e = p + val->bv_len;
2805 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2806 if ( !AD_CHAR( *p ) ) {
2807 return LDAP_INVALID_SYNTAX;
2812 return LDAP_INVALID_SYNTAX;
2816 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2817 if ( !AD_CHAR( *p ) ) {
2818 return LDAP_INVALID_SYNTAX;
2823 return LDAP_INVALID_SYNTAX;
2827 for ( p++; p < e; p++ ) {
2828 if ( !SLAP_PRINTABLE( *p ) ) {
2829 return LDAP_INVALID_SYNTAX;
2833 return LDAP_SUCCESS;
2837 firstComponentNormalize(
2842 struct berval *normalized,
2849 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
2850 ber_dupbv_x( normalized, val, ctx );
2851 return LDAP_SUCCESS;
2854 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2856 if( val->bv_val[0] != '(' /*')'*/ &&
2857 val->bv_val[0] != '{' /*'}'*/ )
2859 return LDAP_INVALID_SYNTAX;
2862 /* trim leading white space */
2864 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2870 /* grab next word */
2871 comp.bv_val = &val->bv_val[len];
2872 len = val->bv_len - len;
2874 !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
2880 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2881 rc = numericoidValidate( NULL, &comp );
2882 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2883 rc = integerValidate( NULL, &comp );
2885 rc = LDAP_INVALID_SYNTAX;
2889 if( rc == LDAP_SUCCESS ) {
2890 ber_dupbv_x( normalized, &comp, ctx );
2897 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2898 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2900 static slap_syntax_defs_rec syntax_defs[] = {
2901 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2902 X_BINARY X_NOT_H_R ")",
2903 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2904 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2906 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2908 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2910 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2911 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2913 SLAP_SYNTAX_BER, berValidate, NULL},
2914 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2915 0, bitStringValidate, NULL },
2916 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2917 0, booleanValidate, NULL},
2918 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2919 X_BINARY X_NOT_H_R ")",
2920 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2921 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
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.10 DESC 'Certificate Pair' "
2925 X_BINARY X_NOT_H_R ")",
2926 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2927 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2928 0, countryStringValidate, NULL},
2929 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2930 0, dnValidate, dnPretty},
2931 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2933 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2934 0, deliveryMethodValidate, NULL},
2935 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2936 0, UTF8StringValidate, NULL},
2937 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2939 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2941 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2943 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2945 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2947 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2948 0, printablesStringValidate, NULL},
2949 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2950 SLAP_SYNTAX_BLOB, NULL, NULL},
2951 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2952 0, generalizedTimeValidate, NULL},
2953 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2955 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2956 0, IA5StringValidate, NULL},
2957 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2958 0, integerValidate, NULL},
2959 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2960 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2961 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2963 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2965 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2967 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2969 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2971 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2972 0, nameUIDValidate, nameUIDPretty },
2973 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2975 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2976 0, numericStringValidate, NULL},
2977 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2979 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2980 0, numericoidValidate, NULL},
2981 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2982 0, IA5StringValidate, NULL},
2983 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2984 0, blobValidate, NULL},
2985 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2986 0, UTF8StringValidate, NULL},
2987 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2989 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2991 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2992 0, printableStringValidate, NULL},
2993 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2994 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2995 0, subtreeSpecificationValidate, NULL},
2996 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2997 X_BINARY X_NOT_H_R ")",
2998 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2999 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3000 0, printableStringValidate, NULL},
3001 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3003 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3004 0, printablesStringValidate, NULL},
3005 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3006 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3007 0, utcTimeValidate, NULL},
3009 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3011 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3013 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3015 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3017 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3020 /* RFC 2307 NIS Syntaxes */
3021 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
3022 0, nisNetgroupTripleValidate, NULL},
3023 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
3024 0, bootParameterValidate, NULL},
3026 /* From PKIX *//* This OID is not published yet. */
3027 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
3029 serialNumberAndIssuerValidate,
3030 serialNumberAndIssuerPretty},
3032 #ifdef SLAPD_ACI_ENABLED
3033 /* OpenLDAP Experimental Syntaxes */
3034 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3036 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3040 #ifdef SLAPD_AUTHPASSWD
3041 /* needs updating */
3042 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3043 SLAP_SYNTAX_HIDE, NULL, NULL},
3046 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
3047 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
3049 /* OpenLDAP Void Syntax */
3050 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
3051 SLAP_SYNTAX_HIDE, inValidate, NULL},
3052 {NULL, 0, NULL, NULL}
3055 char *certificateExactMatchSyntaxes[] = {
3056 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
3059 char *directoryStringSyntaxes[] = {
3060 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
3063 char *integerFirstComponentMatchSyntaxes[] = {
3064 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
3065 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
3068 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
3069 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
3070 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
3071 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
3072 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
3073 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
3074 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
3075 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
3076 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
3081 * Other matching rules in X.520 that we do not use (yet):
3083 * 2.5.13.25 uTCTimeMatch
3084 * 2.5.13.26 uTCTimeOrderingMatch
3085 * 2.5.13.31* directoryStringFirstComponentMatch
3086 * 2.5.13.32* wordMatch
3087 * 2.5.13.33* keywordMatch
3088 * 2.5.13.36 certificatePairExactMatch
3089 * 2.5.13.37 certificatePairMatch
3090 * 2.5.13.38 certificateListExactMatch
3091 * 2.5.13.39 certificateListMatch
3092 * 2.5.13.40 algorithmIdentifierMatch
3093 * 2.5.13.41* storedPrefixMatch
3094 * 2.5.13.42 attributeCertificateMatch
3095 * 2.5.13.43 readerAndKeyIDMatch
3096 * 2.5.13.44 attributeIntegrityMatch
3098 * (*) described in RFC 3698 (LDAP: Additional Matching Rules)
3100 static slap_mrule_defs_rec mrule_defs[] = {
3102 * EQUALITY matching rules must be listed after associated APPROX
3103 * matching rules. So, we list all APPROX matching rules first.
3105 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3106 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3107 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3108 NULL, NULL, directoryStringApproxMatch,
3109 directoryStringApproxIndexer, directoryStringApproxFilter,
3112 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3113 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3114 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
3115 NULL, NULL, IA5StringApproxMatch,
3116 IA5StringApproxIndexer, IA5StringApproxFilter,
3120 * Other matching rules
3123 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3124 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3125 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3126 NULL, NULL, octetStringMatch,
3127 octetStringIndexer, octetStringFilter,
3130 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3131 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3132 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3133 NULL, dnNormalize, dnMatch,
3134 octetStringIndexer, octetStringFilter,
3137 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3138 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3139 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3140 NULL, UTF8StringNormalize, octetStringMatch,
3141 octetStringIndexer, octetStringFilter,
3142 directoryStringApproxMatchOID },
3144 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3145 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3146 SLAP_MR_ORDERING, directoryStringSyntaxes,
3147 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3149 "caseIgnoreMatch" },
3151 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3152 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3153 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3154 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3155 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3156 "caseIgnoreMatch" },
3158 {"( 2.5.13.5 NAME 'caseExactMatch' "
3159 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3160 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3161 NULL, UTF8StringNormalize, octetStringMatch,
3162 octetStringIndexer, octetStringFilter,
3163 directoryStringApproxMatchOID },
3165 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3166 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3167 SLAP_MR_ORDERING, directoryStringSyntaxes,
3168 NULL, UTF8StringNormalize, octetStringOrderingMatch,
3172 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3173 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3174 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3175 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
3176 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3179 {"( 2.5.13.8 NAME 'numericStringMatch' "
3180 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3181 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3182 NULL, numericStringNormalize, octetStringMatch,
3183 octetStringIndexer, octetStringFilter,
3186 {"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
3187 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3188 SLAP_MR_ORDERING, NULL,
3189 NULL, numericStringNormalize, octetStringOrderingMatch,
3191 "numericStringMatch" },
3193 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3194 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3195 SLAP_MR_SUBSTR, NULL,
3196 NULL, numericStringNormalize, octetStringSubstringsMatch,
3197 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3198 "numericStringMatch" },
3200 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3201 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3202 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3203 NULL, NULL, NULL, NULL, NULL, NULL },
3205 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3206 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3207 SLAP_MR_SUBSTR, NULL,
3208 NULL, NULL, NULL, NULL, NULL,
3209 "caseIgnoreListMatch" },
3211 {"( 2.5.13.13 NAME 'booleanMatch' "
3212 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3213 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3214 NULL, NULL, booleanMatch,
3215 octetStringIndexer, octetStringFilter,
3218 {"( 2.5.13.14 NAME 'integerMatch' "
3219 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3220 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3221 NULL, NULL, integerMatch,
3222 octetStringIndexer, octetStringFilter,
3225 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3226 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3227 SLAP_MR_ORDERING, NULL,
3228 NULL, NULL, integerMatch,
3232 {"( 2.5.13.16 NAME 'bitStringMatch' "
3233 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3234 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3235 NULL, NULL, octetStringMatch,
3236 octetStringIndexer, octetStringFilter,
3239 {"( 2.5.13.17 NAME 'octetStringMatch' "
3240 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3241 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3242 NULL, NULL, octetStringMatch,
3243 octetStringIndexer, octetStringFilter,
3246 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3247 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3248 SLAP_MR_ORDERING, NULL,
3249 NULL, NULL, octetStringOrderingMatch,
3251 "octetStringMatch" },
3253 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3254 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3255 SLAP_MR_SUBSTR, NULL,
3256 NULL, NULL, octetStringSubstringsMatch,
3257 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3258 "octetStringMatch" },
3260 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3261 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3262 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3264 telephoneNumberNormalize, octetStringMatch,
3265 octetStringIndexer, octetStringFilter,
3268 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3269 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3270 SLAP_MR_SUBSTR, NULL,
3271 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3272 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3273 "telephoneNumberMatch" },
3275 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3276 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3277 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3278 NULL, NULL, NULL, NULL, NULL, NULL },
3280 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3281 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3282 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3283 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3287 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3288 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3289 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3290 NULL, NULL, NULL, NULL, NULL, NULL },
3292 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3293 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3294 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3295 NULL, generalizedTimeNormalize, octetStringMatch,
3299 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3300 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3301 SLAP_MR_ORDERING, NULL,
3302 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3304 "generalizedTimeMatch" },
3306 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3307 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3308 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3309 integerFirstComponentMatchSyntaxes,
3310 NULL, firstComponentNormalize, integerMatch,
3311 octetStringIndexer, octetStringFilter,
3314 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3315 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3316 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3317 objectIdentifierFirstComponentMatchSyntaxes,
3318 NULL, firstComponentNormalize, octetStringMatch,
3319 octetStringIndexer, octetStringFilter,
3322 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3323 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3324 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3326 NULL, certificateExactNormalize, octetStringMatch,
3327 octetStringIndexer, octetStringFilter,
3329 NULL, NULL, NULL, NULL, NULL,
3333 {"( 2.5.13.35 NAME 'certificateMatch' "
3334 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3335 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3337 NULL, NULL, octetStringMatch,
3338 octetStringIndexer, octetStringFilter,
3340 NULL, NULL, NULL, NULL, NULL,
3344 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3345 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3346 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3347 NULL, IA5StringNormalize, octetStringMatch,
3348 octetStringIndexer, octetStringFilter,
3349 IA5StringApproxMatchOID },
3351 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3352 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3353 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3354 NULL, IA5StringNormalize, octetStringMatch,
3355 octetStringIndexer, octetStringFilter,
3356 IA5StringApproxMatchOID },
3358 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3359 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3360 SLAP_MR_SUBSTR, NULL,
3361 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3362 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3363 "caseIgnoreIA5Match" },
3365 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3366 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3367 SLAP_MR_SUBSTR, NULL,
3368 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3369 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3370 "caseExactIA5Match" },
3372 #ifdef SLAPD_AUTHPASSWD
3373 /* needs updating */
3374 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3375 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3376 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3377 NULL, NULL, authPasswordMatch,
3382 #ifdef SLAPD_ACI_ENABLED
3383 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3384 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3385 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3386 NULL, NULL, OpenLDAPaciMatch,
3391 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3392 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3394 NULL, NULL, integerBitAndMatch,
3398 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3399 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3401 NULL, NULL, integerBitOrMatch,
3405 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3406 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3407 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3408 NULL, UUIDNormalize, octetStringMatch,
3409 octetStringIndexer, octetStringFilter,
3412 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3413 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3414 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3415 NULL, UUIDNormalize, octetStringOrderingMatch,
3416 octetStringIndexer, octetStringFilter,
3419 {NULL, SLAP_MR_NONE, NULL,
3420 NULL, NULL, NULL, NULL, NULL,
3425 slap_schema_init( void )
3430 /* we should only be called once (from main) */
3431 assert( schema_init_done == 0 );
3433 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3434 res = register_syntax( &syntax_defs[i] );
3437 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3438 syntax_defs[i].sd_desc );
3443 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3444 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3445 mrule_defs[i].mrd_compat_syntaxes == NULL )
3448 "slap_schema_init: Ignoring unusable matching rule %s\n",
3449 mrule_defs[i].mrd_desc );
3453 res = register_matching_rule( &mrule_defs[i] );
3457 "slap_schema_init: Error registering matching rule %s\n",
3458 mrule_defs[i].mrd_desc );
3463 res = slap_schema_load();
3464 schema_init_done = 1;
3469 schema_destroy( void )