1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
31 #include "ldap_utf8.h"
34 #include <openssl/x509.h>
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/crypto.h>
38 #include <openssl/pem.h>
39 #include <openssl/bio.h>
40 #include <openssl/asn1.h>
41 #include <openssl/x509v3.h>
42 #include <openssl/ssl.h>
45 #include "lutil_hash.h"
46 #define HASH_BYTES LUTIL_HASH_BYTES
47 #define HASH_CONTEXT lutil_HASH_CTX
48 #define HASH_Init(c) lutil_HASHInit(c)
49 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
50 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
52 #define OpenLDAPaciMatch NULL
54 /* approx matching rules */
55 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
56 #define directoryStringApproxMatch approxMatch
57 #define directoryStringApproxIndexer approxIndexer
58 #define directoryStringApproxFilter approxFilter
59 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
60 #define IA5StringApproxMatch approxMatch
61 #define IA5StringApproxIndexer approxIndexer
62 #define IA5StringApproxFilter approxFilter
69 /* no value allowed */
70 return LDAP_INVALID_SYNTAX;
78 /* any value allowed */
82 #define berValidate blobValidate
89 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
90 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
97 static int certificateValidate( Syntax *syntax, struct berval *in )
100 unsigned char *p = (unsigned char *)in->bv_val;
102 xcert = d2i_X509(NULL, &p, in->bv_len);
103 if ( !xcert ) return LDAP_INVALID_SYNTAX;
108 #define certificateValidate sequenceValidate
117 struct berval *value,
118 void *assertedValue )
120 struct berval *asserted = (struct berval *) assertedValue;
121 int match = value->bv_len - asserted->bv_len;
124 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
132 octetStringOrderingMatch(
137 struct berval *value,
138 void *assertedValue )
140 struct berval *asserted = (struct berval *) assertedValue;
141 ber_len_t v_len = value->bv_len;
142 ber_len_t av_len = asserted->bv_len;
144 int match = memcmp( value->bv_val, asserted->bv_val,
145 (v_len < av_len ? v_len : av_len) );
147 if( match == 0 ) match = v_len - av_len;
153 /* Index generation function */
154 int octetStringIndexer(
159 struct berval *prefix,
167 HASH_CONTEXT HASHcontext;
168 unsigned char HASHdigest[HASH_BYTES];
169 struct berval digest;
170 digest.bv_val = (char *)HASHdigest;
171 digest.bv_len = sizeof(HASHdigest);
173 for( i=0; values[i].bv_val != NULL; i++ ) {
174 /* just count them */
177 /* we should have at least one value at this point */
180 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
182 slen = syntax->ssyn_oidlen;
183 mlen = mr->smr_oidlen;
185 for( i=0; values[i].bv_val != NULL; i++ ) {
186 HASH_Init( &HASHcontext );
187 if( prefix != NULL && prefix->bv_len > 0 ) {
188 HASH_Update( &HASHcontext,
189 (unsigned char *)prefix->bv_val,
192 HASH_Update( &HASHcontext,
193 (unsigned char *)syntax->ssyn_oid, slen );
194 HASH_Update( &HASHcontext,
195 (unsigned char *)mr->smr_oid, mlen );
196 HASH_Update( &HASHcontext,
197 (unsigned char *)values[i].bv_val, values[i].bv_len );
198 HASH_Final( HASHdigest, &HASHcontext );
200 ber_dupbv_x( &keys[i], &digest, ctx );
203 keys[i].bv_val = NULL;
211 /* Index generation function */
212 int octetStringFilter(
217 struct berval *prefix,
218 void * assertedValue,
224 HASH_CONTEXT HASHcontext;
225 unsigned char HASHdigest[HASH_BYTES];
226 struct berval *value = (struct berval *) assertedValue;
227 struct berval digest;
228 digest.bv_val = (char *)HASHdigest;
229 digest.bv_len = sizeof(HASHdigest);
231 slen = syntax->ssyn_oidlen;
232 mlen = mr->smr_oidlen;
234 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
236 HASH_Init( &HASHcontext );
237 if( prefix != NULL && prefix->bv_len > 0 ) {
238 HASH_Update( &HASHcontext,
239 (unsigned char *)prefix->bv_val, prefix->bv_len );
241 HASH_Update( &HASHcontext,
242 (unsigned char *)syntax->ssyn_oid, slen );
243 HASH_Update( &HASHcontext,
244 (unsigned char *)mr->smr_oid, mlen );
245 HASH_Update( &HASHcontext,
246 (unsigned char *)value->bv_val, value->bv_len );
247 HASH_Final( HASHdigest, &HASHcontext );
249 ber_dupbv_x( keys, &digest, ctx );
250 keys[1].bv_val = NULL;
259 octetStringSubstringsMatch(
264 struct berval *value,
265 void *assertedValue )
268 SubstringsAssertion *sub = assertedValue;
269 struct berval left = *value;
273 /* Add up asserted input length */
274 if( sub->sa_initial.bv_val ) {
275 inlen += sub->sa_initial.bv_len;
278 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
279 inlen += sub->sa_any[i].bv_len;
282 if( sub->sa_final.bv_val ) {
283 inlen += sub->sa_final.bv_len;
286 if( sub->sa_initial.bv_val ) {
287 if( inlen > left.bv_len ) {
292 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
293 sub->sa_initial.bv_len );
299 left.bv_val += sub->sa_initial.bv_len;
300 left.bv_len -= sub->sa_initial.bv_len;
301 inlen -= sub->sa_initial.bv_len;
304 if( sub->sa_final.bv_val ) {
305 if( inlen > left.bv_len ) {
310 match = memcmp( sub->sa_final.bv_val,
311 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
312 sub->sa_final.bv_len );
318 left.bv_len -= sub->sa_final.bv_len;
319 inlen -= sub->sa_final.bv_len;
323 for(i=0; sub->sa_any[i].bv_val; i++) {
328 if( inlen > left.bv_len ) {
329 /* not enough length */
334 if( sub->sa_any[i].bv_len == 0 ) {
338 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
345 idx = p - left.bv_val;
347 if( idx >= left.bv_len ) {
348 /* this shouldn't happen */
355 if( sub->sa_any[i].bv_len > left.bv_len ) {
356 /* not enough left */
361 match = memcmp( left.bv_val,
362 sub->sa_any[i].bv_val,
363 sub->sa_any[i].bv_len );
371 left.bv_val += sub->sa_any[i].bv_len;
372 left.bv_len -= sub->sa_any[i].bv_len;
373 inlen -= sub->sa_any[i].bv_len;
382 /* Substrings Index generation function */
384 octetStringSubstringsIndexer(
389 struct berval *prefix,
394 ber_len_t i, j, nkeys;
398 HASH_CONTEXT HASHcontext;
399 unsigned char HASHdigest[HASH_BYTES];
400 struct berval digest;
401 digest.bv_val = (char *)HASHdigest;
402 digest.bv_len = sizeof(HASHdigest);
406 for( i=0; values[i].bv_val != NULL; i++ ) {
407 /* count number of indices to generate */
408 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
412 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
413 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
414 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
415 (SLAP_INDEX_SUBSTR_MINLEN - 1);
417 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
421 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
422 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
423 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
427 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
428 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
429 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
430 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
432 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
438 /* no keys to generate */
443 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
445 slen = syntax->ssyn_oidlen;
446 mlen = mr->smr_oidlen;
449 for( i=0; values[i].bv_val != NULL; i++ ) {
452 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
454 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
455 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
457 char pre = SLAP_INDEX_SUBSTR_PREFIX;
458 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
460 for( j=0; j<max; j++ ) {
461 HASH_Init( &HASHcontext );
462 if( prefix != NULL && prefix->bv_len > 0 ) {
463 HASH_Update( &HASHcontext,
464 (unsigned char *)prefix->bv_val, prefix->bv_len );
467 HASH_Update( &HASHcontext,
468 (unsigned char *)&pre, sizeof( pre ) );
469 HASH_Update( &HASHcontext,
470 (unsigned char *)syntax->ssyn_oid, slen );
471 HASH_Update( &HASHcontext,
472 (unsigned char *)mr->smr_oid, mlen );
473 HASH_Update( &HASHcontext,
474 (unsigned char *)&values[i].bv_val[j],
475 SLAP_INDEX_SUBSTR_MAXLEN );
476 HASH_Final( HASHdigest, &HASHcontext );
478 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
482 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
483 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
485 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
488 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
489 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
490 HASH_Init( &HASHcontext );
491 if( prefix != NULL && prefix->bv_len > 0 ) {
492 HASH_Update( &HASHcontext,
493 (unsigned char *)prefix->bv_val, prefix->bv_len );
495 HASH_Update( &HASHcontext,
496 (unsigned char *)&pre, sizeof( pre ) );
497 HASH_Update( &HASHcontext,
498 (unsigned char *)syntax->ssyn_oid, slen );
499 HASH_Update( &HASHcontext,
500 (unsigned char *)mr->smr_oid, mlen );
501 HASH_Update( &HASHcontext,
502 (unsigned char *)values[i].bv_val, j );
503 HASH_Final( HASHdigest, &HASHcontext );
505 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
508 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
509 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
510 HASH_Init( &HASHcontext );
511 if( prefix != NULL && prefix->bv_len > 0 ) {
512 HASH_Update( &HASHcontext,
513 (unsigned char *)prefix->bv_val, prefix->bv_len );
515 HASH_Update( &HASHcontext,
516 (unsigned char *)&pre, sizeof( pre ) );
517 HASH_Update( &HASHcontext,
518 (unsigned char *)syntax->ssyn_oid, slen );
519 HASH_Update( &HASHcontext,
520 (unsigned char *)mr->smr_oid, mlen );
521 HASH_Update( &HASHcontext,
522 (unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
523 HASH_Final( HASHdigest, &HASHcontext );
525 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
533 keys[nkeys].bv_val = NULL;
544 octetStringSubstringsFilter (
549 struct berval *prefix,
550 void * assertedValue,
554 SubstringsAssertion *sa;
557 size_t slen, mlen, klen;
559 HASH_CONTEXT HASHcontext;
560 unsigned char HASHdigest[HASH_BYTES];
561 struct berval *value;
562 struct berval digest;
564 sa = (SubstringsAssertion *) assertedValue;
566 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
567 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
572 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
574 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
575 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
576 /* don't bother accounting for stepping */
577 nkeys += sa->sa_any[i].bv_len -
578 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
583 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
584 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
594 digest.bv_val = (char *)HASHdigest;
595 digest.bv_len = sizeof(HASHdigest);
597 slen = syntax->ssyn_oidlen;
598 mlen = mr->smr_oidlen;
600 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
603 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
604 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
606 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
607 value = &sa->sa_initial;
609 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
610 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
612 HASH_Init( &HASHcontext );
613 if( prefix != NULL && prefix->bv_len > 0 ) {
614 HASH_Update( &HASHcontext,
615 (unsigned char *)prefix->bv_val, prefix->bv_len );
617 HASH_Update( &HASHcontext,
618 (unsigned char *)&pre, sizeof( pre ) );
619 HASH_Update( &HASHcontext,
620 (unsigned char *)syntax->ssyn_oid, slen );
621 HASH_Update( &HASHcontext,
622 (unsigned char *)mr->smr_oid, mlen );
623 HASH_Update( &HASHcontext,
624 (unsigned char *)value->bv_val, klen );
625 HASH_Final( HASHdigest, &HASHcontext );
627 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
630 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
632 pre = SLAP_INDEX_SUBSTR_PREFIX;
633 klen = SLAP_INDEX_SUBSTR_MAXLEN;
635 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
636 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
640 value = &sa->sa_any[i];
643 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
644 j += SLAP_INDEX_SUBSTR_STEP )
646 HASH_Init( &HASHcontext );
647 if( prefix != NULL && prefix->bv_len > 0 ) {
648 HASH_Update( &HASHcontext,
649 (unsigned char *)prefix->bv_val, prefix->bv_len );
651 HASH_Update( &HASHcontext,
652 (unsigned char *)&pre, sizeof( pre ) );
653 HASH_Update( &HASHcontext,
654 (unsigned char *)syntax->ssyn_oid, slen );
655 HASH_Update( &HASHcontext,
656 (unsigned char *)mr->smr_oid, mlen );
657 HASH_Update( &HASHcontext,
658 (unsigned char *)&value->bv_val[j], klen );
659 HASH_Final( HASHdigest, &HASHcontext );
661 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
666 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
667 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
669 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
670 value = &sa->sa_final;
672 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
673 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
675 HASH_Init( &HASHcontext );
676 if( prefix != NULL && prefix->bv_len > 0 ) {
677 HASH_Update( &HASHcontext,
678 (unsigned char *)prefix->bv_val, prefix->bv_len );
680 HASH_Update( &HASHcontext,
681 (unsigned char *)&pre, sizeof( pre ) );
682 HASH_Update( &HASHcontext,
683 (unsigned char *)syntax->ssyn_oid, slen );
684 HASH_Update( &HASHcontext,
685 (unsigned char *)mr->smr_oid, mlen );
686 HASH_Update( &HASHcontext,
687 (unsigned char *)&value->bv_val[value->bv_len-klen], klen );
688 HASH_Final( HASHdigest, &HASHcontext );
690 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
694 keys[nkeys].bv_val = NULL;
711 /* very unforgiving validation, requires no normalization
712 * before simplistic matching
714 if( in->bv_len < 3 ) {
715 return LDAP_INVALID_SYNTAX;
719 * RFC 2252 section 6.3 Bit String
720 * bitstring = "'" *binary-digit "'B"
721 * binary-digit = "0" / "1"
722 * example: '0101111101'B
725 if( in->bv_val[0] != '\'' ||
726 in->bv_val[in->bv_len-2] != '\'' ||
727 in->bv_val[in->bv_len-1] != 'B' )
729 return LDAP_INVALID_SYNTAX;
732 for( i=in->bv_len-3; i>0; i-- ) {
733 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
734 return LDAP_INVALID_SYNTAX;
749 if( in->bv_len == 0 ) return LDAP_SUCCESS;
751 ber_dupbv( &dn, in );
752 if( !dn.bv_val ) return LDAP_OTHER;
754 if( dn.bv_val[dn.bv_len-1] == 'B'
755 && dn.bv_val[dn.bv_len-2] == '\'' )
757 /* assume presence of optional UID */
760 for(i=dn.bv_len-3; i>1; i--) {
761 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
765 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
766 ber_memfree( dn.bv_val );
767 return LDAP_INVALID_SYNTAX;
770 /* trim the UID to allow use of dnValidate */
771 dn.bv_val[i-1] = '\0';
775 rc = dnValidate( NULL, &dn );
777 ber_memfree( dn.bv_val );
793 LDAP_LOG( OPERATION, ARGS, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
795 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
798 if( val->bv_len == 0 ) {
799 ber_dupbv_x( out, val, ctx );
801 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
802 return LDAP_INVALID_SYNTAX;
806 struct berval dnval = *val;
807 struct berval uidval = { 0, NULL };
809 if( val->bv_val[val->bv_len-1] == 'B'
810 && val->bv_val[val->bv_len-2] == '\'' )
812 uidval.bv_val=strrchr( val->bv_val, '#' );
813 if( uidval.bv_val ) {
814 dnval.bv_len = uidval.bv_val - dnval.bv_val;
815 uidval.bv_len = val->bv_len - dnval.bv_len;
822 rc = dnPretty( syntax, &dnval, out, ctx );
823 if( rc != LDAP_SUCCESS ) return rc;
825 if( uidval.bv_val ) {
826 char *tmp = sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx );
829 ber_memfree_x( out->bv_val, ctx );
833 out->bv_val[out->bv_len++] = '#';
835 got1 = uidval.bv_len < sizeof("'0'B");
836 for(i=0; i<uidval.bv_len; i++) {
837 c = uidval.bv_val[i];
840 if( got1 ) out->bv_val[out->bv_len++] = c;
845 out->bv_val[out->bv_len++] = c;
849 out->bv_val[out->bv_len] = '\0';
854 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
856 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
863 uniqueMemberNormalize(
868 struct berval *normalized,
874 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
876 ber_dupbv( &out, val );
877 if( out.bv_len != 0 ) {
878 struct berval uid = { 0, NULL };
880 if( out.bv_val[out.bv_len-1] == 'B'
881 && out.bv_val[out.bv_len-2] == '\'' )
883 /* assume presence of optional UID */
884 uid.bv_val = strrchr( out.bv_val, '#' );
886 if( uid.bv_val == NULL ) {
888 return LDAP_INVALID_SYNTAX;
891 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
892 out.bv_len -= uid.bv_len--;
894 /* temporarily trim the UID */
895 *(uid.bv_val++) = '\0';
898 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
900 if( rc != LDAP_SUCCESS ) {
902 return LDAP_INVALID_SYNTAX;
906 normalized->bv_val = ch_realloc( normalized->bv_val,
907 normalized->bv_len + uid.bv_len + sizeof("#") );
909 /* insert the separator */
910 normalized->bv_val[normalized->bv_len++] = '#';
913 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
914 uid.bv_val, uid.bv_len );
915 normalized->bv_len += uid.bv_len;
918 normalized->bv_val[normalized->bv_len] = '\0';
933 struct berval *value,
934 void *assertedValue )
937 struct berval *asserted = (struct berval *) assertedValue;
938 struct berval assertedDN = { 0, NULL };
939 struct berval assertedUID = { 0, NULL };
940 struct berval valueDN = { 0, NULL };
941 struct berval valueUID = { 0, NULL };
943 if( asserted->bv_len != 0 ) {
944 assertedDN = *asserted;
946 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
947 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
949 /* assume presence of optional UID */
950 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
952 if( assertedUID.bv_val == NULL ) {
953 return LDAP_INVALID_SYNTAX;
956 assertedUID.bv_len = assertedDN.bv_len -
957 (assertedUID.bv_val - assertedDN.bv_val);
958 assertedDN.bv_len -= assertedUID.bv_len--;
960 /* trim the separator */
961 assertedUID.bv_val++;
965 if( value->bv_len != 0 ) {
968 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
969 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
971 /* assume presence of optional UID */
972 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
974 if( valueUID.bv_val == NULL ) {
975 return LDAP_INVALID_SYNTAX;
978 valueUID.bv_len = valueDN.bv_len -
979 (assertedUID.bv_val - assertedDN.bv_val);
980 valueDN.bv_len -= valueUID.bv_len--;
982 /* trim the separator */
987 if( valueUID.bv_len && assertedUID.bv_len ) {
988 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
995 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
999 * Handling boolean syntax and matching is quite rigid.
1000 * A more flexible approach would be to allow a variety
1001 * of strings to be normalized and prettied into TRUE
1009 /* very unforgiving validation, requires no normalization
1010 * before simplistic matching
1013 if( in->bv_len == 4 ) {
1014 if( bvmatch( in, &slap_true_bv ) ) {
1015 return LDAP_SUCCESS;
1017 } else if( in->bv_len == 5 ) {
1018 if( bvmatch( in, &slap_false_bv ) ) {
1019 return LDAP_SUCCESS;
1023 return LDAP_INVALID_SYNTAX;
1032 struct berval *value,
1033 void *assertedValue )
1035 /* simplistic matching allowed by rigid validation */
1036 struct berval *asserted = (struct berval *) assertedValue;
1037 *matchp = value->bv_len != asserted->bv_len;
1038 return LDAP_SUCCESS;
1041 /*-------------------------------------------------------------------
1042 LDAP/X.500 string syntax / matching rules have a few oddities. This
1043 comment attempts to detail how slapd(8) treats them.
1046 StringSyntax X.500 LDAP Matching/Comments
1047 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1048 PrintableString subset subset i/e + ignore insignificant spaces
1049 PrintableString subset subset i/e + ignore insignificant spaces
1050 NumericString subset subset ignore all spaces
1051 IA5String ASCII ASCII i/e + ignore insignificant spaces
1052 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1054 TelephoneNumber subset subset i + ignore all spaces and "-"
1056 See draft-ietf-ldapbis-strpro for details (once published).
1060 In X.500(93), a directory string can be either a PrintableString,
1061 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1062 In later versions, more CHOICEs were added. In all cases the string
1065 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1066 A directory string cannot be zero length.
1068 For matching, there are both case ignore and exact rules. Both
1069 also require that "insignificant" spaces be ignored.
1070 spaces before the first non-space are ignored;
1071 spaces after the last non-space are ignored;
1072 spaces after a space are ignored.
1073 Note: by these rules (and as clarified in X.520), a string of only
1074 spaces is to be treated as if held one space, not empty (which
1075 would be a syntax error).
1078 In ASN.1, numeric string is just a string of digits and spaces
1079 and could be empty. However, in X.500, all attribute values of
1080 numeric string carry a non-empty constraint. For example:
1082 internationalISDNNumber ATTRIBUTE ::= {
1083 WITH SYNTAX InternationalISDNNumber
1084 EQUALITY MATCHING RULE numericStringMatch
1085 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1086 ID id-at-internationalISDNNumber }
1087 InternationalISDNNumber ::=
1088 NumericString (SIZE(1..ub-international-isdn-number))
1090 Unforunately, some assertion values are don't carry the same
1091 constraint (but its unclear how such an assertion could ever
1092 be true). In LDAP, there is one syntax (numericString) not two
1093 (numericString with constraint, numericString without constraint).
1094 This should be treated as numericString with non-empty constraint.
1095 Note that while someone may have no ISDN number, there are no ISDN
1096 numbers which are zero length.
1098 In matching, spaces are ignored.
1101 In ASN.1, Printable string is just a string of printable characters
1102 and can be empty. In X.500, semantics much like NumericString (see
1103 serialNumber for a like example) excepting uses insignificant space
1104 handling instead of ignore all spaces.
1107 Basically same as PrintableString. There are no examples in X.500,
1108 but same logic applies. So we require them to be non-empty as
1111 -------------------------------------------------------------------*/
1120 unsigned char *u = (unsigned char *)in->bv_val;
1122 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1123 /* directory strings cannot be empty */
1124 return LDAP_INVALID_SYNTAX;
1127 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1128 /* get the length indicated by the first byte */
1129 len = LDAP_UTF8_CHARLEN2( u, len );
1131 /* very basic checks */
1134 if( (u[5] & 0xC0) != 0x80 ) {
1135 return LDAP_INVALID_SYNTAX;
1138 if( (u[4] & 0xC0) != 0x80 ) {
1139 return LDAP_INVALID_SYNTAX;
1142 if( (u[3] & 0xC0) != 0x80 ) {
1143 return LDAP_INVALID_SYNTAX;
1146 if( (u[2] & 0xC0 )!= 0x80 ) {
1147 return LDAP_INVALID_SYNTAX;
1150 if( (u[1] & 0xC0) != 0x80 ) {
1151 return LDAP_INVALID_SYNTAX;
1154 /* CHARLEN already validated it */
1157 return LDAP_INVALID_SYNTAX;
1160 /* make sure len corresponds with the offset
1161 to the next character */
1162 if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
1166 return LDAP_INVALID_SYNTAX;
1169 return LDAP_SUCCESS;
1173 UTF8StringNormalize(
1178 struct berval *normalized,
1181 struct berval tmp, nvalue;
1185 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1187 if( val->bv_val == NULL ) {
1188 /* assume we're dealing with a syntax (e.g., UTF8String)
1189 * which allows empty strings
1191 normalized->bv_len = 0;
1192 normalized->bv_val = NULL;
1193 return LDAP_SUCCESS;
1196 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1197 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1198 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1199 ? LDAP_UTF8_APPROX : 0;
1201 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1206 /* collapse spaces (in place) */
1208 nvalue.bv_val = tmp.bv_val;
1210 wasspace=1; /* trim leading spaces */
1211 for( i=0; i<tmp.bv_len; i++) {
1212 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1213 if( wasspace++ == 0 ) {
1214 /* trim repeated spaces */
1215 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1219 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1223 if( nvalue.bv_len ) {
1225 /* last character was a space, trim it */
1228 nvalue.bv_val[nvalue.bv_len] = '\0';
1231 /* string of all spaces is treated as one space */
1232 nvalue.bv_val[0] = ' ';
1233 nvalue.bv_val[1] = '\0';
1237 *normalized = nvalue;
1238 return LDAP_SUCCESS;
1241 #if defined(SLAPD_APPROX_INITIALS)
1242 # define SLAPD_APPROX_DELIMITER "._ "
1243 # define SLAPD_APPROX_WORDLEN 2
1245 # define SLAPD_APPROX_DELIMITER " "
1246 # define SLAPD_APPROX_WORDLEN 1
1255 struct berval *value,
1256 void *assertedValue )
1258 struct berval *nval, *assertv;
1259 char *val, **values, **words, *c;
1260 int i, count, len, nextchunk=0, nextavail=0;
1262 /* Yes, this is necessary */
1263 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1264 if( nval == NULL ) {
1266 return LDAP_SUCCESS;
1269 /* Yes, this is necessary */
1270 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1271 NULL, LDAP_UTF8_APPROX, NULL );
1272 if( assertv == NULL ) {
1275 return LDAP_SUCCESS;
1278 /* Isolate how many words there are */
1279 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1280 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1281 if ( c == NULL ) break;
1286 /* Get a phonetic copy of each word */
1287 words = (char **)ch_malloc( count * sizeof(char *) );
1288 values = (char **)ch_malloc( count * sizeof(char *) );
1289 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1291 values[i] = phonetic(c);
1294 /* Work through the asserted value's words, to see if at least some
1295 of the words are there, in the same order. */
1297 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1298 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1303 #if defined(SLAPD_APPROX_INITIALS)
1304 else if( len == 1 ) {
1305 /* Single letter words need to at least match one word's initial */
1306 for( i=nextavail; i<count; i++ )
1307 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1314 /* Isolate the next word in the asserted value and phonetic it */
1315 assertv->bv_val[nextchunk+len] = '\0';
1316 val = phonetic( assertv->bv_val + nextchunk );
1318 /* See if this phonetic chunk is in the remaining words of *value */
1319 for( i=nextavail; i<count; i++ ){
1320 if( !strcmp( val, values[i] ) ){
1328 /* This chunk in the asserted value was NOT within the *value. */
1334 /* Go on to the next word in the asserted value */
1338 /* If some of the words were seen, call it a match */
1339 if( nextavail > 0 ) {
1346 /* Cleanup allocs */
1347 ber_bvfree( assertv );
1348 for( i=0; i<count; i++ ) {
1349 ch_free( values[i] );
1355 return LDAP_SUCCESS;
1364 struct berval *prefix,
1370 int i,j, len, wordcount, keycount=0;
1371 struct berval *newkeys;
1372 BerVarray keys=NULL;
1374 for( j=0; values[j].bv_val != NULL; j++ ) {
1375 struct berval val = { 0, NULL };
1376 /* Yes, this is necessary */
1377 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1378 assert( val.bv_val != NULL );
1380 /* Isolate how many words there are. There will be a key for each */
1381 for( wordcount = 0, c = val.bv_val; *c; c++) {
1382 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1383 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1385 if (*c == '\0') break;
1389 /* Allocate/increase storage to account for new keys */
1390 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1391 * sizeof(struct berval) );
1392 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1393 if( keys ) ch_free( keys );
1396 /* Get a phonetic copy of each word */
1397 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1399 if( len < SLAPD_APPROX_WORDLEN ) continue;
1400 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1405 ber_memfree( val.bv_val );
1407 keys[keycount].bv_val = NULL;
1410 return LDAP_SUCCESS;
1419 struct berval *prefix,
1420 void * assertedValue,
1429 /* Yes, this is necessary */
1430 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1431 NULL, LDAP_UTF8_APPROX, NULL );
1432 if( val == NULL || val->bv_val == NULL ) {
1433 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1434 keys[0].bv_val = NULL;
1437 return LDAP_SUCCESS;
1440 /* Isolate how many words there are. There will be a key for each */
1441 for( count = 0,c = val->bv_val; *c; c++) {
1442 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1443 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1445 if (*c == '\0') break;
1449 /* Allocate storage for new keys */
1450 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1452 /* Get a phonetic copy of each word */
1453 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1455 if( len < SLAPD_APPROX_WORDLEN ) continue;
1456 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1462 keys[count].bv_val = NULL;
1465 return LDAP_SUCCESS;
1468 /* Remove all spaces and '-' characters */
1470 telephoneNumberNormalize(
1475 struct berval *normalized,
1480 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1482 /* validator should have refused an empty string */
1483 assert( val->bv_len );
1485 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1487 for( p = val->bv_val; *p; p++ ) {
1488 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1494 normalized->bv_len = q - normalized->bv_val;
1496 if( normalized->bv_len == 0 ) {
1497 sl_free( normalized->bv_val, ctx );
1498 normalized->bv_val = NULL;
1499 return LDAP_INVALID_SYNTAX;
1502 return LDAP_SUCCESS;
1510 struct berval val = *in;
1512 if( val.bv_len == 0 ) {
1513 /* disallow empty strings */
1514 return LDAP_INVALID_SYNTAX;
1517 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1518 if ( val.bv_len == 1 ) {
1519 return LDAP_SUCCESS;
1522 if ( val.bv_val[0] == '0' ) {
1529 while ( OID_LEADCHAR( val.bv_val[0] )) {
1533 if ( val.bv_len == 0 ) {
1534 return LDAP_SUCCESS;
1538 if( !OID_SEPARATOR( val.bv_val[0] )) {
1546 return LDAP_INVALID_SYNTAX;
1555 struct berval val = *in;
1557 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1559 if ( val.bv_val[0] == '-' ) {
1563 if( val.bv_len == 0 ) { /* bare "-" */
1564 return LDAP_INVALID_SYNTAX;
1567 if( val.bv_val[0] == '0' ) { /* "-0" */
1568 return LDAP_INVALID_SYNTAX;
1571 } else if ( val.bv_val[0] == '0' ) {
1572 if( val.bv_len > 1 ) { /* "0<more>" */
1573 return LDAP_INVALID_SYNTAX;
1576 return LDAP_SUCCESS;
1579 for( i=0; i < val.bv_len; i++ ) {
1580 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1581 return LDAP_INVALID_SYNTAX;
1585 return LDAP_SUCCESS;
1594 struct berval *value,
1595 void *assertedValue )
1597 struct berval *asserted = (struct berval *) assertedValue;
1598 int vsign = 1, asign = 1; /* default sign = '+' */
1603 if( v.bv_val[0] == '-' ) {
1609 if( v.bv_len == 0 ) vsign = 0;
1612 if( a.bv_val[0] == '-' ) {
1618 if( a.bv_len == 0 ) vsign = 0;
1620 match = vsign - asign;
1622 match = ( v.bv_len != a.bv_len
1623 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1624 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1625 if( vsign < 0 ) match = -match;
1629 return LDAP_SUCCESS;
1633 countryStringValidate(
1635 struct berval *val )
1637 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1639 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1640 return LDAP_INVALID_SYNTAX;
1642 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1643 return LDAP_INVALID_SYNTAX;
1646 return LDAP_SUCCESS;
1650 printableStringValidate(
1652 struct berval *val )
1656 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1658 for(i=0; i < val->bv_len; i++) {
1659 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1660 return LDAP_INVALID_SYNTAX;
1664 return LDAP_SUCCESS;
1668 printablesStringValidate(
1670 struct berval *val )
1674 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1676 for(i=0,len=0; i < val->bv_len; i++) {
1677 int c = val->bv_val[i];
1681 return LDAP_INVALID_SYNTAX;
1685 } else if ( SLAP_PRINTABLE(c) ) {
1688 return LDAP_INVALID_SYNTAX;
1693 return LDAP_INVALID_SYNTAX;
1696 return LDAP_SUCCESS;
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( !LDAP_ASCII(val->bv_val[i]) ) {
1710 return LDAP_INVALID_SYNTAX;
1714 return LDAP_SUCCESS;
1723 struct berval *normalized,
1727 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1729 assert( val->bv_len );
1731 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1735 /* Ignore initial whitespace */
1736 while ( ASCII_SPACE( *p ) ) p++;
1738 normalized->bv_val = ber_strdup_x( p, ctx );
1739 p = q = normalized->bv_val;
1742 if ( ASCII_SPACE( *p ) ) {
1745 /* Ignore the extra whitespace */
1746 while ( ASCII_SPACE( *p ) ) {
1750 } else if ( casefold ) {
1751 /* Most IA5 rules require casefolding */
1752 *q++ = TOLOWER(*p++);
1759 assert( normalized->bv_val <= p );
1763 * If the string ended in space, backup the pointer one
1764 * position. One is enough because the above loop collapsed
1765 * all whitespace to a single space.
1767 if ( ASCII_SPACE( q[-1] ) ) --q;
1769 /* null terminate */
1772 normalized->bv_len = q - normalized->bv_val;
1773 if( normalized->bv_len == 0 ) {
1774 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1775 normalized->bv_val[0] = ' ';
1776 normalized->bv_val[1] = '\0';
1777 normalized->bv_len = 1;
1780 return LDAP_SUCCESS;
1789 if( in->bv_len != 36 ) {
1791 return LDAP_INVALID_SYNTAX;
1794 for( i=0; i<36; i++ ) {
1800 if( in->bv_val[i] != '-' ) {
1801 return LDAP_INVALID_SYNTAX;
1805 if( !ASCII_HEX( in->bv_val[i]) ) {
1806 return LDAP_INVALID_SYNTAX;
1811 return LDAP_SUCCESS;
1820 struct berval *normalized,
1823 unsigned char octet = '\0';
1826 normalized->bv_len = 16;
1827 normalized->bv_val = sl_malloc( normalized->bv_len+1, ctx );
1829 for( i=0, j=0; i<36; i++ ) {
1830 unsigned char nibble;
1831 if( val->bv_val[i] == '-' ) {
1834 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1835 nibble = val->bv_val[i] - '0';
1837 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1838 nibble = val->bv_val[i] - ('a'-10);
1840 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1841 nibble = val->bv_val[i] - ('A'-10);
1844 sl_free( normalized->bv_val, ctx );
1845 return LDAP_INVALID_SYNTAX;
1850 normalized->bv_val[j>>1] = octet;
1852 octet = nibble << 4;
1857 normalized->bv_val[normalized->bv_len] = 0;
1858 return LDAP_SUCCESS;
1864 numericStringValidate(
1870 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1872 for(i=0; i < in->bv_len; i++) {
1873 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1874 return LDAP_INVALID_SYNTAX;
1878 return LDAP_SUCCESS;
1882 numericStringNormalize(
1887 struct berval *normalized,
1890 /* removal all spaces */
1893 assert( val->bv_len );
1895 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1898 q = normalized->bv_val;
1901 if ( ASCII_SPACE( *p ) ) {
1902 /* Ignore whitespace */
1909 /* we should have copied no more then is in val */
1910 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1912 /* null terminate */
1915 normalized->bv_len = q - normalized->bv_val;
1917 if( normalized->bv_len == 0 ) {
1918 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1919 normalized->bv_val[0] = ' ';
1920 normalized->bv_val[1] = '\0';
1921 normalized->bv_len = 1;
1924 return LDAP_SUCCESS;
1928 * Integer conversion macros that will use the largest available
1931 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1932 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1933 # define SLAP_LONG_MAX LLONG_MAX
1934 # define SLAP_LONG_MIN LLONG_MIN
1935 # define SLAP_LONG long long
1937 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1938 # define SLAP_LONG_MAX LONG_MAX
1939 # define SLAP_LONG_MIN LONG_MIN
1940 # define SLAP_LONG long
1941 #endif /* HAVE_STRTOLL ... */
1949 struct berval *value,
1950 void *assertedValue )
1952 SLAP_LONG lValue, lAssertedValue;
1954 /* safe to assume integers are NUL terminated? */
1955 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1956 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
1957 return LDAP_CONSTRAINT_VIOLATION;
1960 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1961 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1962 && errno == ERANGE )
1964 return LDAP_CONSTRAINT_VIOLATION;
1967 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1968 return LDAP_SUCCESS;
1977 struct berval *value,
1978 void *assertedValue )
1980 SLAP_LONG lValue, lAssertedValue;
1982 /* safe to assume integers are NUL terminated? */
1983 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1984 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && errno == ERANGE ) {
1985 return LDAP_CONSTRAINT_VIOLATION;
1988 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1989 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1990 && errno == ERANGE )
1992 return LDAP_CONSTRAINT_VIOLATION;
1995 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1996 return LDAP_SUCCESS;
2000 serialNumberAndIssuerValidate(
2007 struct berval sn, i;
2008 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2010 i.bv_val = strchr( in->bv_val, '$' );
2011 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2013 sn.bv_val = in->bv_val;
2014 sn.bv_len = i.bv_val - in->bv_val;
2017 i.bv_len = in->bv_len - (sn.bv_len + 1);
2019 /* validate serial number (strict for now) */
2020 for( n=0; n < sn.bv_len; n++ ) {
2021 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2022 return LDAP_INVALID_SYNTAX;
2027 rc = dnValidate( NULL, &i );
2028 if( rc ) return LDAP_INVALID_SYNTAX;
2030 return LDAP_SUCCESS;
2034 serialNumberAndIssuerPretty(
2043 struct berval sn, i, newi;
2049 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2050 val->bv_val, 0, 0 );
2052 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2053 val->bv_val, 0, 0 );
2056 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2058 i.bv_val = strchr( val->bv_val, '$' );
2059 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2061 sn.bv_val = val->bv_val;
2062 sn.bv_len = i.bv_val - val->bv_val;
2065 i.bv_len = val->bv_len - (sn.bv_len + 1);
2067 /* eat leading zeros */
2068 for( n=0; n < (sn.bv_len-1); n++ ) {
2069 if( sn.bv_val[n] != '0' ) break;
2074 for( n=0; n < sn.bv_len; n++ ) {
2075 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2076 return LDAP_INVALID_SYNTAX;
2081 rc = dnPretty( syntax, &i, &newi, ctx );
2082 if( rc ) return LDAP_INVALID_SYNTAX;
2084 /* make room from sn + "$" */
2085 out->bv_len = sn.bv_len + newi.bv_len + 1;
2086 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2088 if( out->bv_val == NULL ) {
2089 sl_free( newi.bv_val, ctx );
2093 /* push issuer over */
2094 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2095 /* insert sn and "$" */
2096 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2097 out->bv_val[sn.bv_len] = '$';
2099 out->bv_val[out->bv_len] = '\0';
2102 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2103 out->bv_val, 0, 0 );
2105 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2106 out->bv_val, 0, 0 );
2109 return LDAP_SUCCESS;
2113 * This routine is called by certificateExactNormalize when
2114 * certificateExactNormalize receives a search string instead of
2115 * a certificate. This routine checks if the search value is valid
2116 * and then returns the normalized value
2119 serialNumberAndIssuerNormalize(
2130 struct berval sn, i, newi;
2136 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2137 val->bv_val, 0, 0 );
2139 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2140 val->bv_val, 0, 0 );
2143 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2145 i.bv_val = strchr( val->bv_val, '$' );
2146 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2148 sn.bv_val = val->bv_val;
2149 sn.bv_len = i.bv_val - val->bv_val;
2152 i.bv_len = val->bv_len - (sn.bv_len + 1);
2154 /* eat leading zeros */
2155 for( n=0; n < (sn.bv_len-1); n++ ) {
2156 if( sn.bv_val[n] != '0' ) break;
2161 for( n=0; n < sn.bv_len; n++ ) {
2162 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2163 return LDAP_INVALID_SYNTAX;
2168 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2169 if( rc ) return LDAP_INVALID_SYNTAX;
2171 /* make room from sn + "$" */
2172 out->bv_len = sn.bv_len + newi.bv_len + 1;
2173 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2175 if( out->bv_val == NULL ) {
2176 sl_free( newi.bv_val, ctx );
2180 /* push issuer over */
2181 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2182 /* insert sn and "$" */
2183 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2184 out->bv_val[sn.bv_len] = '$';
2186 out->bv_val[out->bv_len] = '\0';
2189 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2190 out->bv_val, 0, 0 );
2192 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2193 out->bv_val, 0, 0 );
2201 certificateExactNormalize(
2206 struct berval *normalized,
2209 int rc = LDAP_INVALID_SYNTAX;
2211 char *serial = NULL;
2212 ber_len_t seriallen;
2213 struct berval issuer_dn = { 0, NULL };
2214 X509_NAME *name = NULL;
2215 ASN1_INTEGER *sn = NULL;
2218 if( val->bv_len == 0 ) goto done;
2220 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2221 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2224 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2226 p = (unsigned char *)val->bv_val;
2227 xcert = d2i_X509( NULL, &p, val->bv_len);
2228 if( xcert == NULL ) goto done;
2230 sn=X509_get_serialNumber(xcert);
2231 if ( sn == NULL ) goto done;
2232 serial=i2s_ASN1_INTEGER(0, sn );
2233 if( serial == NULL ) goto done;
2234 seriallen=strlen(serial);
2236 name=X509_get_issuer_name(xcert);
2237 if( name == NULL ) goto done;
2238 rc = dnX509normalize( name, &issuer_dn );
2239 if( rc != LDAP_SUCCESS ) goto done;
2241 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2242 normalized->bv_val = ch_malloc(normalized->bv_len+1);
2243 p = (unsigned char *)normalized->bv_val;
2244 AC_MEMCPY(p, serial, seriallen);
2247 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2248 p += issuer_dn.bv_len;
2252 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2253 normalized->bv_val, 0, 0 );
2255 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2256 normalized->bv_val, NULL, NULL );
2260 if (xcert) X509_free(xcert);
2261 if (serial) ch_free(serial);
2262 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2266 #endif /* HAVE_TLS */
2269 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2270 /* slight optimization - does not need the start parameter */
2271 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2276 check_time_syntax (struct berval *val,
2279 struct berval *fraction)
2282 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2283 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2284 * GeneralizedTime supports leap seconds, UTCTime does not.
2286 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2287 static const int mdays[2][12] = {
2288 /* non-leap years */
2289 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2291 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2294 int part, c, c1, c2, tzoffset, leapyear = 0;
2297 e = p + val->bv_len;
2299 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2300 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2302 for (part = start; part < 7 && p < e; part++) {
2304 if (!ASCII_DIGIT(c1)) {
2309 return LDAP_INVALID_SYNTAX;
2312 if (!ASCII_DIGIT(c)) {
2313 return LDAP_INVALID_SYNTAX;
2315 c += c1 * 10 - '0' * 11;
2316 if ((part | 1) == 3) {
2319 return LDAP_INVALID_SYNTAX;
2322 if (c >= ceiling[part]) {
2323 if (! (c == 60 && part == 6 && start == 0))
2324 return LDAP_INVALID_SYNTAX;
2328 if (part < 5 + start) {
2329 return LDAP_INVALID_SYNTAX;
2331 for (; part < 9; part++) {
2335 /* leapyear check for the Gregorian calendar (year>1581) */
2336 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2341 if (parts[3] >= mdays[leapyear][parts[2]]) {
2342 return LDAP_INVALID_SYNTAX;
2346 fraction->bv_val = p;
2347 fraction->bv_len = 0;
2348 if (p < e && (*p == '.' || *p == ',')) {
2350 while (++p < e && ASCII_DIGIT(*p))
2352 if (p - fraction->bv_val == 1) {
2353 return LDAP_INVALID_SYNTAX;
2355 for (end_num = p; end_num[-1] == '0'; --end_num)
2357 c = end_num - fraction->bv_val;
2359 fraction->bv_len = c;
2365 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2371 return LDAP_INVALID_SYNTAX;
2377 for (part = 7; part < 9 && p < e; part++) {
2379 if (!ASCII_DIGIT(c1)) {
2384 return LDAP_INVALID_SYNTAX;
2387 if (!ASCII_DIGIT(c2)) {
2388 return LDAP_INVALID_SYNTAX;
2390 parts[part] = c1 * 10 + c2 - '0' * 11;
2391 if (parts[part] >= ceiling[part]) {
2392 return LDAP_INVALID_SYNTAX;
2395 if (part < 8 + start) {
2396 return LDAP_INVALID_SYNTAX;
2399 if (tzoffset == '-') {
2400 /* negative offset to UTC, ie west of Greenwich */
2401 parts[4] += parts[7];
2402 parts[5] += parts[8];
2403 /* offset is just hhmm, no seconds */
2404 for (part = 6; --part >= 0; ) {
2408 c = mdays[leapyear][parts[2]];
2410 if (parts[part] >= c) {
2412 return LDAP_INVALID_SYNTAX;
2417 } else if (part != 5) {
2422 /* positive offset to UTC, ie east of Greenwich */
2423 parts[4] -= parts[7];
2424 parts[5] -= parts[8];
2425 for (part = 6; --part >= 0; ) {
2426 if (parts[part] < 0) {
2428 return LDAP_INVALID_SYNTAX;
2433 /* make first arg to % non-negative */
2434 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2439 } else if (part != 5) {
2446 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2449 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2456 struct berval *normalized )
2460 rc = check_time_syntax(val, 1, parts, NULL);
2461 if (rc != LDAP_SUCCESS) {
2465 normalized->bv_val = ch_malloc( 14 );
2466 if ( normalized->bv_val == NULL ) {
2467 return LBER_ERROR_MEMORY;
2470 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2471 parts[1], parts[2] + 1, parts[3] + 1,
2472 parts[4], parts[5], parts[6] );
2473 normalized->bv_len = 13;
2475 return LDAP_SUCCESS;
2485 return check_time_syntax(in, 1, parts, NULL);
2488 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2491 generalizedTimeValidate(
2496 struct berval fraction;
2497 return check_time_syntax(in, 0, parts, &fraction);
2501 generalizedTimeNormalize(
2506 struct berval *normalized,
2511 struct berval fraction;
2513 rc = check_time_syntax(val, 0, parts, &fraction);
2514 if (rc != LDAP_SUCCESS) {
2518 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2519 normalized->bv_val = sl_malloc( len + 1, ctx );
2520 if ( normalized->bv_val == NULL ) {
2521 return LBER_ERROR_MEMORY;
2524 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2525 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2526 parts[4], parts[5], parts[6] );
2527 if ( fraction.bv_len ) {
2528 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2529 fraction.bv_val, fraction.bv_len );
2530 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2532 strcpy( normalized->bv_val + len-1, "Z" );
2533 normalized->bv_len = len;
2535 return LDAP_SUCCESS;
2539 generalizedTimeOrderingMatch(
2544 struct berval *value,
2545 void *assertedValue )
2547 struct berval *asserted = (struct berval *) assertedValue;
2548 ber_len_t v_len = value->bv_len;
2549 ber_len_t av_len = asserted->bv_len;
2551 /* ignore trailing 'Z' when comparing */
2552 int match = memcmp( value->bv_val, asserted->bv_val,
2553 (v_len < av_len ? v_len : av_len) - 1 );
2554 if ( match == 0 ) match = v_len - av_len;
2557 return LDAP_SUCCESS;
2561 nisNetgroupTripleValidate(
2563 struct berval *val )
2568 if ( val->bv_len == 0 ) {
2569 return LDAP_INVALID_SYNTAX;
2572 p = (char *)val->bv_val;
2573 e = p + val->bv_len;
2575 if ( *p != '(' /*')'*/ ) {
2576 return LDAP_INVALID_SYNTAX;
2579 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2583 return LDAP_INVALID_SYNTAX;
2586 } else if ( !AD_CHAR( *p ) ) {
2587 return LDAP_INVALID_SYNTAX;
2591 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2592 return LDAP_INVALID_SYNTAX;
2598 return LDAP_INVALID_SYNTAX;
2601 return LDAP_SUCCESS;
2605 bootParameterValidate(
2607 struct berval *val )
2611 if ( val->bv_len == 0 ) {
2612 return LDAP_INVALID_SYNTAX;
2615 p = (char *)val->bv_val;
2616 e = p + val->bv_len;
2619 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2620 if ( !AD_CHAR( *p ) ) {
2621 return LDAP_INVALID_SYNTAX;
2626 return LDAP_INVALID_SYNTAX;
2630 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2631 if ( !AD_CHAR( *p ) ) {
2632 return LDAP_INVALID_SYNTAX;
2637 return LDAP_INVALID_SYNTAX;
2641 for ( p++; p < e; p++ ) {
2642 if ( !SLAP_PRINTABLE( *p ) ) {
2643 return LDAP_INVALID_SYNTAX;
2647 return LDAP_SUCCESS;
2651 firstComponentNormalize(
2656 struct berval *normalized,
2663 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2665 if( val->bv_val[0] != '(' /*')'*/ &&
2666 val->bv_val[0] != '{' /*'}'*/ )
2668 return LDAP_INVALID_SYNTAX;
2671 /* trim leading white space */
2673 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2679 /* grab next word */
2680 oid.bv_val = &val->bv_val[len];
2681 len = val->bv_len - len;
2683 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2689 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2690 rc = numericoidValidate( NULL, &oid );
2691 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2692 rc = integerValidate( NULL, &oid );
2694 rc = LDAP_INVALID_SYNTAX;
2698 if( rc == LDAP_SUCCESS ) {
2699 ber_dupbv_x( normalized, &oid, ctx );
2706 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2707 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2709 static slap_syntax_defs_rec syntax_defs[] = {
2710 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2711 X_BINARY X_NOT_H_R ")",
2712 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2713 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2715 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2717 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2719 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2720 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2722 SLAP_SYNTAX_BER, berValidate, NULL},
2723 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2724 0, bitStringValidate, NULL },
2725 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2726 0, booleanValidate, NULL},
2727 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2728 X_BINARY X_NOT_H_R ")",
2729 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2730 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2731 X_BINARY X_NOT_H_R ")",
2732 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2733 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2734 X_BINARY X_NOT_H_R ")",
2735 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2736 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2737 0, countryStringValidate, NULL},
2738 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2739 0, dnValidate, dnPretty},
2740 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2742 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2744 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2745 0, UTF8StringValidate, NULL},
2746 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2748 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2750 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2752 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2754 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2756 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2757 0, printablesStringValidate, NULL},
2758 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2759 SLAP_SYNTAX_BLOB, NULL, NULL},
2760 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2761 0, generalizedTimeValidate, NULL},
2762 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2764 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2765 0, IA5StringValidate, NULL},
2766 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2767 0, integerValidate, NULL},
2768 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2769 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2770 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2772 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2774 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2776 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2778 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2780 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2781 0, nameUIDValidate, nameUIDPretty },
2782 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2784 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2785 0, numericStringValidate, NULL},
2786 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2788 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2789 0, numericoidValidate, NULL},
2790 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2791 0, IA5StringValidate, NULL},
2792 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2793 0, blobValidate, NULL},
2794 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2795 0, UTF8StringValidate, NULL},
2796 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2798 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2800 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2801 0, printableStringValidate, NULL},
2802 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2803 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2804 0, subtreeSpecificationValidate, NULL},
2805 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2806 X_BINARY X_NOT_H_R ")",
2807 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2808 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2809 0, printableStringValidate, NULL},
2810 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2812 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2813 0, printablesStringValidate, NULL},
2814 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2815 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2816 0, utcTimeValidate, NULL},
2818 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2820 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2822 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2824 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2826 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2829 /* RFC 2307 NIS Syntaxes */
2830 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2831 0, nisNetgroupTripleValidate, NULL},
2832 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2833 0, bootParameterValidate, NULL},
2835 /* From PKIX *//* This OID is not published yet. */
2836 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
2838 serialNumberAndIssuerValidate,
2839 serialNumberAndIssuerPretty},
2841 #ifdef SLAPD_ACI_ENABLED
2842 /* OpenLDAP Experimental Syntaxes */
2843 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2845 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2849 #ifdef SLAPD_AUTHPASSWD
2850 /* needs updating */
2851 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2852 SLAP_SYNTAX_HIDE, NULL, NULL},
2855 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
2856 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
2858 /* OpenLDAP Void Syntax */
2859 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2860 SLAP_SYNTAX_HIDE, inValidate, NULL},
2861 {NULL, 0, NULL, NULL}
2864 char *certificateExactMatchSyntaxes[] = {
2865 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2868 char *directoryStringSyntaxes[] = {
2869 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2872 char *integerFirstComponentMatchSyntaxes[] = {
2873 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2874 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2877 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2878 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2879 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2880 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2881 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2882 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2883 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2884 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2885 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2890 * Other matching rules in X.520 that we do not use (yet):
2892 * 2.5.13.9 numericStringOrderingMatch
2893 * 2.5.13.25 uTCTimeMatch
2894 * 2.5.13.26 uTCTimeOrderingMatch
2895 * 2.5.13.31 directoryStringFirstComponentMatch
2896 * 2.5.13.32 wordMatch
2897 * 2.5.13.33 keywordMatch
2898 * 2.5.13.36 certificatePairExactMatch
2899 * 2.5.13.37 certificatePairMatch
2900 * 2.5.13.38 certificateListExactMatch
2901 * 2.5.13.39 certificateListMatch
2902 * 2.5.13.40 algorithmIdentifierMatch
2903 * 2.5.13.41 storedPrefixMatch
2904 * 2.5.13.42 attributeCertificateMatch
2905 * 2.5.13.43 readerAndKeyIDMatch
2906 * 2.5.13.44 attributeIntegrityMatch
2908 static slap_mrule_defs_rec mrule_defs[] = {
2910 * EQUALITY matching rules must be listed after associated APPROX
2911 * matching rules. So, we list all APPROX matching rules first.
2913 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2915 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2916 NULL, NULL, directoryStringApproxMatch,
2917 directoryStringApproxIndexer, directoryStringApproxFilter,
2920 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2922 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2923 NULL, NULL, IA5StringApproxMatch,
2924 IA5StringApproxIndexer, IA5StringApproxFilter,
2928 * Other matching rules
2931 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2932 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2933 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2934 NULL, NULL, octetStringMatch,
2935 octetStringIndexer, octetStringFilter,
2938 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2939 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2940 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2941 NULL, dnNormalize, dnMatch,
2942 octetStringIndexer, octetStringFilter,
2945 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2946 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2947 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2948 NULL, UTF8StringNormalize, octetStringMatch,
2949 octetStringIndexer, octetStringFilter,
2950 directoryStringApproxMatchOID },
2952 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2953 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2954 SLAP_MR_ORDERING, directoryStringSyntaxes,
2955 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2957 "caseIgnoreMatch" },
2959 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2960 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2961 SLAP_MR_SUBSTR, NULL,
2962 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2963 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2964 "caseIgnoreMatch" },
2966 {"( 2.5.13.5 NAME 'caseExactMatch' "
2967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2968 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2969 NULL, UTF8StringNormalize, octetStringMatch,
2970 octetStringIndexer, octetStringFilter,
2971 directoryStringApproxMatchOID },
2973 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2974 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2975 SLAP_MR_ORDERING, directoryStringSyntaxes,
2976 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2980 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2981 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2982 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2983 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2984 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2987 {"( 2.5.13.8 NAME 'numericStringMatch' "
2988 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2989 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2990 NULL, numericStringNormalize, octetStringSubstringsMatch,
2991 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2994 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2995 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2996 SLAP_MR_SUBSTR, NULL,
2997 NULL, numericStringNormalize, octetStringSubstringsMatch,
2998 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2999 "numericStringMatch" },
3001 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3002 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3003 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3004 NULL, NULL, NULL, NULL, NULL, NULL },
3006 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3008 SLAP_MR_SUBSTR, NULL,
3009 NULL, NULL, NULL, NULL, NULL,
3010 "caseIgnoreListMatch" },
3012 {"( 2.5.13.13 NAME 'booleanMatch' "
3013 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3014 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3015 NULL, NULL, booleanMatch,
3016 octetStringIndexer, octetStringFilter,
3019 {"( 2.5.13.14 NAME 'integerMatch' "
3020 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3021 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3022 NULL, NULL, integerMatch,
3023 octetStringIndexer, octetStringFilter,
3026 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3027 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3028 SLAP_MR_ORDERING, NULL,
3029 NULL, NULL, integerMatch,
3033 {"( 2.5.13.16 NAME 'bitStringMatch' "
3034 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3035 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3036 NULL, NULL, octetStringMatch,
3037 octetStringIndexer, octetStringFilter,
3040 {"( 2.5.13.17 NAME 'octetStringMatch' "
3041 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3042 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3043 NULL, NULL, octetStringMatch,
3044 octetStringIndexer, octetStringFilter,
3047 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3049 SLAP_MR_ORDERING, NULL,
3050 NULL, NULL, octetStringOrderingMatch,
3052 "octetStringMatch" },
3054 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3055 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3056 SLAP_MR_SUBSTR, NULL,
3057 NULL, NULL, octetStringSubstringsMatch,
3058 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3059 "octetStringMatch" },
3061 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3062 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3063 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3065 telephoneNumberNormalize, octetStringMatch,
3066 octetStringIndexer, octetStringFilter,
3069 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3070 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3071 SLAP_MR_SUBSTR, NULL,
3072 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3073 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3074 "telephoneNumberMatch" },
3076 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3077 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3078 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3079 NULL, NULL, NULL, NULL, NULL, NULL },
3081 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3082 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3083 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3084 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3088 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3089 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3090 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3091 NULL, NULL, NULL, NULL, NULL, NULL },
3093 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3094 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3095 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3096 NULL, generalizedTimeNormalize, octetStringMatch,
3100 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3101 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3102 SLAP_MR_ORDERING, NULL,
3103 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3105 "generalizedTimeMatch" },
3107 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3108 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3109 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3110 integerFirstComponentMatchSyntaxes,
3111 NULL, firstComponentNormalize, integerMatch,
3112 octetStringIndexer, octetStringFilter,
3115 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3116 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3117 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3118 objectIdentifierFirstComponentMatchSyntaxes,
3119 NULL, firstComponentNormalize, octetStringMatch,
3120 octetStringIndexer, octetStringFilter,
3123 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3124 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3125 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3127 NULL, certificateExactNormalize, octetStringMatch,
3128 octetStringIndexer, octetStringFilter,
3130 NULL, NULL, NULL, NULL, NULL,
3134 {"( 2.5.13.35 NAME 'certificateMatch' "
3135 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3136 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3138 NULL, NULL, octetStringMatch,
3139 octetStringIndexer, octetStringFilter,
3141 NULL, NULL, NULL, NULL, NULL,
3145 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3146 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3147 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3148 NULL, IA5StringNormalize, octetStringMatch,
3149 octetStringIndexer, octetStringFilter,
3150 IA5StringApproxMatchOID },
3152 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3153 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3154 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3155 NULL, IA5StringNormalize, octetStringMatch,
3156 octetStringIndexer, octetStringFilter,
3157 IA5StringApproxMatchOID },
3159 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3160 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3161 SLAP_MR_SUBSTR, NULL,
3162 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3163 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3164 "caseIgnoreIA5Match" },
3166 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3167 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3168 SLAP_MR_SUBSTR, NULL,
3169 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3170 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3171 "caseExactIA5Match" },
3173 #ifdef SLAPD_AUTHPASSWD
3174 /* needs updating */
3175 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3176 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3177 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3178 NULL, NULL, authPasswordMatch,
3183 #ifdef SLAPD_ACI_ENABLED
3184 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3185 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3186 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3187 NULL, NULL, OpenLDAPaciMatch,
3192 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3193 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3195 NULL, NULL, integerBitAndMatch,
3199 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3200 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3202 NULL, NULL, integerBitOrMatch,
3206 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3207 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3208 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3209 NULL, UUIDNormalize, octetStringMatch,
3210 octetStringIndexer, octetStringFilter,
3213 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3214 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3215 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3216 NULL, UUIDNormalize, octetStringOrderingMatch,
3217 octetStringIndexer, octetStringFilter,
3220 {NULL, SLAP_MR_NONE, NULL,
3221 NULL, NULL, NULL, NULL, NULL,
3226 slap_schema_init( void )
3231 /* we should only be called once (from main) */
3232 assert( schema_init_done == 0 );
3234 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3235 res = register_syntax( &syntax_defs[i] );
3238 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3239 syntax_defs[i].sd_desc );
3244 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3245 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3246 mrule_defs[i].mrd_compat_syntaxes == NULL )
3249 "slap_schema_init: Ignoring unusable matching rule %s\n",
3250 mrule_defs[i].mrd_desc );
3254 res = register_matching_rule( &mrule_defs[i] );
3258 "slap_schema_init: Error registering matching rule %s\n",
3259 mrule_defs[i].mrd_desc );
3264 res = slap_schema_load();
3265 schema_init_done = 1;
3270 schema_destroy( void )