1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
15 #include <ac/string.h>
16 #include <ac/socket.h>
22 #include "ldap_utf8.h"
25 #include <openssl/x509.h>
26 #include <openssl/err.h>
27 #include <openssl/rsa.h>
28 #include <openssl/crypto.h>
29 #include <openssl/pem.h>
30 #include <openssl/bio.h>
31 #include <openssl/asn1.h>
32 #include <openssl/x509v3.h>
33 #include <openssl/ssl.h>
36 #include "lutil_hash.h"
37 #define HASH_BYTES LUTIL_HASH_BYTES
38 #define HASH_CONTEXT lutil_HASH_CTX
39 #define HASH_Init(c) lutil_HASHInit(c)
40 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
41 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
43 #define OpenLDAPaciMatch NULL
45 /* approx matching rules */
46 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
47 #define directoryStringApproxMatch approxMatch
48 #define directoryStringApproxIndexer approxIndexer
49 #define directoryStringApproxFilter approxFilter
50 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
51 #define IA5StringApproxMatch approxMatch
52 #define IA5StringApproxIndexer approxIndexer
53 #define IA5StringApproxFilter approxFilter
60 /* no value allowed */
61 return LDAP_INVALID_SYNTAX;
69 /* any value allowed */
73 #define berValidate blobValidate
80 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
81 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
88 static int certificateValidate( Syntax *syntax, struct berval *in )
91 unsigned char *p = in->bv_val;
93 xcert = d2i_X509(NULL, &p, in->bv_len);
94 if ( !xcert ) return LDAP_INVALID_SYNTAX;
99 #define certificateValidate sequenceValidate
108 struct berval *value,
109 void *assertedValue )
111 struct berval *asserted = (struct berval *) assertedValue;
112 int match = value->bv_len - asserted->bv_len;
115 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
123 octetStringOrderingMatch(
128 struct berval *value,
129 void *assertedValue )
131 struct berval *asserted = (struct berval *) assertedValue;
132 ber_len_t v_len = value->bv_len;
133 ber_len_t av_len = asserted->bv_len;
135 int match = memcmp( value->bv_val, asserted->bv_val,
136 (v_len < av_len ? v_len : av_len) );
138 if( match == 0 ) match = v_len - av_len;
144 /* Index generation function */
145 int octetStringIndexer(
150 struct berval *prefix,
158 HASH_CONTEXT HASHcontext;
159 unsigned char HASHdigest[HASH_BYTES];
160 struct berval digest;
161 digest.bv_val = HASHdigest;
162 digest.bv_len = sizeof(HASHdigest);
164 for( i=0; values[i].bv_val != NULL; i++ ) {
165 /* just count them */
168 /* we should have at least one value at this point */
171 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
173 slen = syntax->ssyn_oidlen;
174 mlen = mr->smr_oidlen;
176 for( i=0; values[i].bv_val != NULL; i++ ) {
177 HASH_Init( &HASHcontext );
178 if( prefix != NULL && prefix->bv_len > 0 ) {
179 HASH_Update( &HASHcontext,
180 prefix->bv_val, prefix->bv_len );
182 HASH_Update( &HASHcontext,
183 syntax->ssyn_oid, slen );
184 HASH_Update( &HASHcontext,
186 HASH_Update( &HASHcontext,
187 values[i].bv_val, values[i].bv_len );
188 HASH_Final( HASHdigest, &HASHcontext );
190 ber_dupbv_x( &keys[i], &digest, ctx );
193 keys[i].bv_val = NULL;
201 /* Index generation function */
202 int octetStringFilter(
207 struct berval *prefix,
208 void * assertedValue,
214 HASH_CONTEXT HASHcontext;
215 unsigned char HASHdigest[HASH_BYTES];
216 struct berval *value = (struct berval *) assertedValue;
217 struct berval digest;
218 digest.bv_val = HASHdigest;
219 digest.bv_len = sizeof(HASHdigest);
221 slen = syntax->ssyn_oidlen;
222 mlen = mr->smr_oidlen;
224 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
226 HASH_Init( &HASHcontext );
227 if( prefix != NULL && prefix->bv_len > 0 ) {
228 HASH_Update( &HASHcontext,
229 prefix->bv_val, prefix->bv_len );
231 HASH_Update( &HASHcontext,
232 syntax->ssyn_oid, slen );
233 HASH_Update( &HASHcontext,
235 HASH_Update( &HASHcontext,
236 value->bv_val, value->bv_len );
237 HASH_Final( HASHdigest, &HASHcontext );
239 ber_dupbv_x( keys, &digest, ctx );
240 keys[1].bv_val = NULL;
249 octetStringSubstringsMatch(
254 struct berval *value,
255 void *assertedValue )
258 SubstringsAssertion *sub = assertedValue;
259 struct berval left = *value;
263 /* Add up asserted input length */
264 if( sub->sa_initial.bv_val ) {
265 inlen += sub->sa_initial.bv_len;
268 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
269 inlen += sub->sa_any[i].bv_len;
272 if( sub->sa_final.bv_val ) {
273 inlen += sub->sa_final.bv_len;
276 if( sub->sa_initial.bv_val ) {
277 if( inlen > left.bv_len ) {
282 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
283 sub->sa_initial.bv_len );
289 left.bv_val += sub->sa_initial.bv_len;
290 left.bv_len -= sub->sa_initial.bv_len;
291 inlen -= sub->sa_initial.bv_len;
294 if( sub->sa_final.bv_val ) {
295 if( inlen > left.bv_len ) {
300 match = memcmp( sub->sa_final.bv_val,
301 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
302 sub->sa_final.bv_len );
308 left.bv_len -= sub->sa_final.bv_len;
309 inlen -= sub->sa_final.bv_len;
313 for(i=0; sub->sa_any[i].bv_val; i++) {
318 if( inlen > left.bv_len ) {
319 /* not enough length */
324 if( sub->sa_any[i].bv_len == 0 ) {
328 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
335 idx = p - left.bv_val;
337 if( idx >= left.bv_len ) {
338 /* this shouldn't happen */
345 if( sub->sa_any[i].bv_len > left.bv_len ) {
346 /* not enough left */
351 match = memcmp( left.bv_val,
352 sub->sa_any[i].bv_val,
353 sub->sa_any[i].bv_len );
361 left.bv_val += sub->sa_any[i].bv_len;
362 left.bv_len -= sub->sa_any[i].bv_len;
363 inlen -= sub->sa_any[i].bv_len;
372 /* Substrings Index generation function */
374 octetStringSubstringsIndexer(
379 struct berval *prefix,
384 ber_len_t i, j, nkeys;
388 HASH_CONTEXT HASHcontext;
389 unsigned char HASHdigest[HASH_BYTES];
390 struct berval digest;
391 digest.bv_val = HASHdigest;
392 digest.bv_len = sizeof(HASHdigest);
396 for( i=0; values[i].bv_val != NULL; i++ ) {
397 /* count number of indices to generate */
398 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
402 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
403 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
404 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
405 (SLAP_INDEX_SUBSTR_MINLEN - 1);
407 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
411 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
412 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
413 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
417 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
418 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
419 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
420 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
422 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
428 /* no keys to generate */
433 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
435 slen = syntax->ssyn_oidlen;
436 mlen = mr->smr_oidlen;
439 for( i=0; values[i].bv_val != NULL; i++ ) {
442 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
444 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
445 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
447 char pre = SLAP_INDEX_SUBSTR_PREFIX;
448 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
450 for( j=0; j<max; j++ ) {
451 HASH_Init( &HASHcontext );
452 if( prefix != NULL && prefix->bv_len > 0 ) {
453 HASH_Update( &HASHcontext,
454 prefix->bv_val, prefix->bv_len );
457 HASH_Update( &HASHcontext,
458 &pre, sizeof( pre ) );
459 HASH_Update( &HASHcontext,
460 syntax->ssyn_oid, slen );
461 HASH_Update( &HASHcontext,
463 HASH_Update( &HASHcontext,
464 &values[i].bv_val[j],
465 SLAP_INDEX_SUBSTR_MAXLEN );
466 HASH_Final( HASHdigest, &HASHcontext );
468 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
472 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
473 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
475 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
478 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
479 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
480 HASH_Init( &HASHcontext );
481 if( prefix != NULL && prefix->bv_len > 0 ) {
482 HASH_Update( &HASHcontext,
483 prefix->bv_val, prefix->bv_len );
485 HASH_Update( &HASHcontext,
486 &pre, sizeof( pre ) );
487 HASH_Update( &HASHcontext,
488 syntax->ssyn_oid, slen );
489 HASH_Update( &HASHcontext,
491 HASH_Update( &HASHcontext,
492 values[i].bv_val, j );
493 HASH_Final( HASHdigest, &HASHcontext );
495 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
498 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
499 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
500 HASH_Init( &HASHcontext );
501 if( prefix != NULL && prefix->bv_len > 0 ) {
502 HASH_Update( &HASHcontext,
503 prefix->bv_val, prefix->bv_len );
505 HASH_Update( &HASHcontext,
506 &pre, sizeof( pre ) );
507 HASH_Update( &HASHcontext,
508 syntax->ssyn_oid, slen );
509 HASH_Update( &HASHcontext,
511 HASH_Update( &HASHcontext,
512 &values[i].bv_val[values[i].bv_len-j], j );
513 HASH_Final( HASHdigest, &HASHcontext );
515 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
523 keys[nkeys].bv_val = NULL;
534 octetStringSubstringsFilter (
539 struct berval *prefix,
540 void * assertedValue,
544 SubstringsAssertion *sa;
547 size_t slen, mlen, klen;
549 HASH_CONTEXT HASHcontext;
550 unsigned char HASHdigest[HASH_BYTES];
551 struct berval *value;
552 struct berval digest;
554 sa = (SubstringsAssertion *) assertedValue;
556 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
557 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
562 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
564 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
565 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
566 /* don't bother accounting for stepping */
567 nkeys += sa->sa_any[i].bv_len -
568 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
573 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
574 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
584 digest.bv_val = HASHdigest;
585 digest.bv_len = sizeof(HASHdigest);
587 slen = syntax->ssyn_oidlen;
588 mlen = mr->smr_oidlen;
590 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
593 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
594 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
596 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
597 value = &sa->sa_initial;
599 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
600 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
602 HASH_Init( &HASHcontext );
603 if( prefix != NULL && prefix->bv_len > 0 ) {
604 HASH_Update( &HASHcontext,
605 prefix->bv_val, prefix->bv_len );
607 HASH_Update( &HASHcontext,
608 &pre, sizeof( pre ) );
609 HASH_Update( &HASHcontext,
610 syntax->ssyn_oid, slen );
611 HASH_Update( &HASHcontext,
613 HASH_Update( &HASHcontext,
614 value->bv_val, klen );
615 HASH_Final( HASHdigest, &HASHcontext );
617 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
620 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
622 pre = SLAP_INDEX_SUBSTR_PREFIX;
623 klen = SLAP_INDEX_SUBSTR_MAXLEN;
625 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
626 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
630 value = &sa->sa_any[i];
633 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
634 j += SLAP_INDEX_SUBSTR_STEP )
636 HASH_Init( &HASHcontext );
637 if( prefix != NULL && prefix->bv_len > 0 ) {
638 HASH_Update( &HASHcontext,
639 prefix->bv_val, prefix->bv_len );
641 HASH_Update( &HASHcontext,
642 &pre, sizeof( pre ) );
643 HASH_Update( &HASHcontext,
644 syntax->ssyn_oid, slen );
645 HASH_Update( &HASHcontext,
647 HASH_Update( &HASHcontext,
648 &value->bv_val[j], klen );
649 HASH_Final( HASHdigest, &HASHcontext );
651 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
656 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
657 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
659 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
660 value = &sa->sa_final;
662 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
663 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
665 HASH_Init( &HASHcontext );
666 if( prefix != NULL && prefix->bv_len > 0 ) {
667 HASH_Update( &HASHcontext,
668 prefix->bv_val, prefix->bv_len );
670 HASH_Update( &HASHcontext,
671 &pre, sizeof( pre ) );
672 HASH_Update( &HASHcontext,
673 syntax->ssyn_oid, slen );
674 HASH_Update( &HASHcontext,
676 HASH_Update( &HASHcontext,
677 &value->bv_val[value->bv_len-klen], klen );
678 HASH_Final( HASHdigest, &HASHcontext );
680 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
684 keys[nkeys].bv_val = NULL;
701 /* very unforgiving validation, requires no normalization
702 * before simplistic matching
704 if( in->bv_len < 3 ) {
705 return LDAP_INVALID_SYNTAX;
709 * RFC 2252 section 6.3 Bit String
710 * bitstring = "'" *binary-digit "'B"
711 * binary-digit = "0" / "1"
712 * example: '0101111101'B
715 if( in->bv_val[0] != '\'' ||
716 in->bv_val[in->bv_len-2] != '\'' ||
717 in->bv_val[in->bv_len-1] != 'B' )
719 return LDAP_INVALID_SYNTAX;
722 for( i=in->bv_len-3; i>0; i-- ) {
723 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
724 return LDAP_INVALID_SYNTAX;
739 if( in->bv_len == 0 ) return LDAP_SUCCESS;
741 ber_dupbv( &dn, in );
742 if( !dn.bv_val ) return LDAP_OTHER;
744 if( dn.bv_val[dn.bv_len-1] == 'B'
745 && dn.bv_val[dn.bv_len-2] == '\'' )
747 /* assume presence of optional UID */
750 for(i=dn.bv_len-3; i>1; i--) {
751 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
755 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
756 ber_memfree( dn.bv_val );
757 return LDAP_INVALID_SYNTAX;
760 /* trim the UID to allow use of dnValidate */
761 dn.bv_val[i-1] = '\0';
765 rc = dnValidate( NULL, &dn );
767 ber_memfree( dn.bv_val );
783 LDAP_LOG( OPERATION, ARGS, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
785 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
788 if( val->bv_len == 0 ) {
789 ber_dupbv_x( out, val, ctx );
791 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
792 return LDAP_INVALID_SYNTAX;
796 struct berval dnval = *val;
797 struct berval uidval = { 0, NULL };
799 if( val->bv_val[val->bv_len-1] == 'B'
800 && val->bv_val[val->bv_len-2] == '\'' )
802 uidval.bv_val=strrchr( val->bv_val, '#' );
803 if( uidval.bv_val ) {
804 dnval.bv_len = uidval.bv_val - dnval.bv_val;
805 uidval.bv_len = val->bv_len - dnval.bv_len;
812 rc = dnPretty( syntax, &dnval, out, ctx );
813 if( rc != LDAP_SUCCESS ) return rc;
815 if( uidval.bv_val ) {
816 char *tmp = sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx );
819 ber_memfree_x( out->bv_val, ctx );
823 out->bv_val[out->bv_len++] = '#';
825 got1 = uidval.bv_len < sizeof("'0'B");
826 for(i=0; i<uidval.bv_len; i++) {
827 c = uidval.bv_val[i];
830 if( got1 ) out->bv_val[out->bv_len++] = c;
835 out->bv_val[out->bv_len++] = c;
839 out->bv_val[out->bv_len] = '\0';
844 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
846 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
853 uniqueMemberNormalize(
858 struct berval *normalized,
864 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
866 ber_dupbv( &out, val );
867 if( out.bv_len != 0 ) {
868 struct berval uid = { 0, NULL };
870 if( out.bv_val[out.bv_len-1] == 'B'
871 && out.bv_val[out.bv_len-2] == '\'' )
873 /* assume presence of optional UID */
874 uid.bv_val = strrchr( out.bv_val, '#' );
876 if( uid.bv_val == NULL ) {
878 return LDAP_INVALID_SYNTAX;
881 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
882 out.bv_len -= uid.bv_len--;
884 /* temporarily trim the UID */
885 *(uid.bv_val++) = '\0';
888 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
890 if( rc != LDAP_SUCCESS ) {
892 return LDAP_INVALID_SYNTAX;
896 normalized->bv_val = ch_realloc( normalized->bv_val,
897 normalized->bv_len + uid.bv_len + sizeof("#") );
899 /* insert the separator */
900 normalized->bv_val[normalized->bv_len++] = '#';
903 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
904 uid.bv_val, uid.bv_len );
905 normalized->bv_len += uid.bv_len;
908 normalized->bv_val[normalized->bv_len] = '\0';
923 struct berval *value,
924 void *assertedValue )
927 struct berval *asserted = (struct berval *) assertedValue;
928 struct berval assertedDN = { 0, NULL };
929 struct berval assertedUID = { 0, NULL };
930 struct berval valueDN = { 0, NULL };
931 struct berval valueUID = { 0, NULL };
933 if( asserted->bv_len != 0 ) {
934 assertedDN = *asserted;
936 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
937 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
939 /* assume presence of optional UID */
940 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
942 if( assertedUID.bv_val == NULL ) {
943 return LDAP_INVALID_SYNTAX;
946 assertedUID.bv_len = assertedDN.bv_len -
947 (assertedUID.bv_val - assertedDN.bv_val);
948 assertedDN.bv_len -= assertedUID.bv_len--;
950 /* trim the separator */
951 assertedUID.bv_val++;
955 if( value->bv_len != 0 ) {
958 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
959 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
961 /* assume presence of optional UID */
962 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
964 if( valueUID.bv_val == NULL ) {
965 return LDAP_INVALID_SYNTAX;
968 valueUID.bv_len = valueDN.bv_len -
969 (assertedUID.bv_val - assertedDN.bv_val);
970 valueDN.bv_len -= valueUID.bv_len--;
972 /* trim the separator */
977 if( valueUID.bv_len && assertedUID.bv_len ) {
978 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
985 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
989 * Handling boolean syntax and matching is quite rigid.
990 * A more flexible approach would be to allow a variety
991 * of strings to be normalized and prettied into TRUE
999 /* very unforgiving validation, requires no normalization
1000 * before simplistic matching
1003 if( in->bv_len == 4 ) {
1004 if( bvmatch( in, &slap_true_bv ) ) {
1005 return LDAP_SUCCESS;
1007 } else if( in->bv_len == 5 ) {
1008 if( bvmatch( in, &slap_false_bv ) ) {
1009 return LDAP_SUCCESS;
1013 return LDAP_INVALID_SYNTAX;
1022 struct berval *value,
1023 void *assertedValue )
1025 /* simplistic matching allowed by rigid validation */
1026 struct berval *asserted = (struct berval *) assertedValue;
1027 *matchp = value->bv_len != asserted->bv_len;
1028 return LDAP_SUCCESS;
1031 /*-------------------------------------------------------------------
1032 LDAP/X.500 string syntax / matching rules have a few oddities. This
1033 comment attempts to detail how slapd(8) treats them.
1036 StringSyntax X.500 LDAP Matching/Comments
1037 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1038 PrintableString subset subset i/e + ignore insignificant spaces
1039 PrintableString subset subset i/e + ignore insignificant spaces
1040 NumericString subset subset ignore all spaces
1041 IA5String ASCII ASCII i/e + ignore insignificant spaces
1042 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1044 TelephoneNumber subset subset i + ignore all spaces and "-"
1046 See draft-ietf-ldapbis-strpro for details (once published).
1050 In X.500(93), a directory string can be either a PrintableString,
1051 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1052 In later versions, more CHOICEs were added. In all cases the string
1055 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1056 A directory string cannot be zero length.
1058 For matching, there are both case ignore and exact rules. Both
1059 also require that "insignificant" spaces be ignored.
1060 spaces before the first non-space are ignored;
1061 spaces after the last non-space are ignored;
1062 spaces after a space are ignored.
1063 Note: by these rules (and as clarified in X.520), a string of only
1064 spaces is to be treated as if held one space, not empty (which
1065 would be a syntax error).
1068 In ASN.1, numeric string is just a string of digits and spaces
1069 and could be empty. However, in X.500, all attribute values of
1070 numeric string carry a non-empty constraint. For example:
1072 internationalISDNNumber ATTRIBUTE ::= {
1073 WITH SYNTAX InternationalISDNNumber
1074 EQUALITY MATCHING RULE numericStringMatch
1075 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1076 ID id-at-internationalISDNNumber }
1077 InternationalISDNNumber ::=
1078 NumericString (SIZE(1..ub-international-isdn-number))
1080 Unforunately, some assertion values are don't carry the same
1081 constraint (but its unclear how such an assertion could ever
1082 be true). In LDAP, there is one syntax (numericString) not two
1083 (numericString with constraint, numericString without constraint).
1084 This should be treated as numericString with non-empty constraint.
1085 Note that while someone may have no ISDN number, there are no ISDN
1086 numbers which are zero length.
1088 In matching, spaces are ignored.
1091 In ASN.1, Printable string is just a string of printable characters
1092 and can be empty. In X.500, semantics much like NumericString (see
1093 serialNumber for a like example) excepting uses insignificant space
1094 handling instead of ignore all spaces.
1097 Basically same as PrintableString. There are no examples in X.500,
1098 but same logic applies. So we require them to be non-empty as
1101 -------------------------------------------------------------------*/
1110 unsigned char *u = in->bv_val;
1112 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1113 /* directory strings cannot be empty */
1114 return LDAP_INVALID_SYNTAX;
1117 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1118 /* get the length indicated by the first byte */
1119 len = LDAP_UTF8_CHARLEN2( u, len );
1121 /* very basic checks */
1124 if( (u[5] & 0xC0) != 0x80 ) {
1125 return LDAP_INVALID_SYNTAX;
1128 if( (u[4] & 0xC0) != 0x80 ) {
1129 return LDAP_INVALID_SYNTAX;
1132 if( (u[3] & 0xC0) != 0x80 ) {
1133 return LDAP_INVALID_SYNTAX;
1136 if( (u[2] & 0xC0 )!= 0x80 ) {
1137 return LDAP_INVALID_SYNTAX;
1140 if( (u[1] & 0xC0) != 0x80 ) {
1141 return LDAP_INVALID_SYNTAX;
1144 /* CHARLEN already validated it */
1147 return LDAP_INVALID_SYNTAX;
1150 /* make sure len corresponds with the offset
1151 to the next character */
1152 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
1156 return LDAP_INVALID_SYNTAX;
1159 return LDAP_SUCCESS;
1163 UTF8StringNormalize(
1168 struct berval *normalized,
1171 struct berval tmp, nvalue;
1175 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1177 if( val->bv_val == NULL ) {
1178 /* assume we're dealing with a syntax (e.g., UTF8String)
1179 * which allows empty strings
1181 normalized->bv_len = 0;
1182 normalized->bv_val = NULL;
1183 return LDAP_SUCCESS;
1186 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1187 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1188 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1189 ? LDAP_UTF8_APPROX : 0;
1191 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1196 /* collapse spaces (in place) */
1198 nvalue.bv_val = tmp.bv_val;
1200 wasspace=1; /* trim leading spaces */
1201 for( i=0; i<tmp.bv_len; i++) {
1202 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1203 if( wasspace++ == 0 ) {
1204 /* trim repeated spaces */
1205 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1209 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1213 if( nvalue.bv_len ) {
1215 /* last character was a space, trim it */
1218 nvalue.bv_val[nvalue.bv_len] = '\0';
1221 /* string of all spaces is treated as one space */
1222 nvalue.bv_val[0] = ' ';
1223 nvalue.bv_val[1] = '\0';
1227 *normalized = nvalue;
1228 return LDAP_SUCCESS;
1231 #if defined(SLAPD_APPROX_INITIALS)
1232 # define SLAPD_APPROX_DELIMITER "._ "
1233 # define SLAPD_APPROX_WORDLEN 2
1235 # define SLAPD_APPROX_DELIMITER " "
1236 # define SLAPD_APPROX_WORDLEN 1
1245 struct berval *value,
1246 void *assertedValue )
1248 struct berval *nval, *assertv;
1249 char *val, **values, **words, *c;
1250 int i, count, len, nextchunk=0, nextavail=0;
1252 /* Yes, this is necessary */
1253 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1254 if( nval == NULL ) {
1256 return LDAP_SUCCESS;
1259 /* Yes, this is necessary */
1260 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1261 NULL, LDAP_UTF8_APPROX, NULL );
1262 if( assertv == NULL ) {
1265 return LDAP_SUCCESS;
1268 /* Isolate how many words there are */
1269 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1270 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1271 if ( c == NULL ) break;
1276 /* Get a phonetic copy of each word */
1277 words = (char **)ch_malloc( count * sizeof(char *) );
1278 values = (char **)ch_malloc( count * sizeof(char *) );
1279 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1281 values[i] = phonetic(c);
1284 /* Work through the asserted value's words, to see if at least some
1285 of the words are there, in the same order. */
1287 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1288 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1293 #if defined(SLAPD_APPROX_INITIALS)
1294 else if( len == 1 ) {
1295 /* Single letter words need to at least match one word's initial */
1296 for( i=nextavail; i<count; i++ )
1297 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1304 /* Isolate the next word in the asserted value and phonetic it */
1305 assertv->bv_val[nextchunk+len] = '\0';
1306 val = phonetic( assertv->bv_val + nextchunk );
1308 /* See if this phonetic chunk is in the remaining words of *value */
1309 for( i=nextavail; i<count; i++ ){
1310 if( !strcmp( val, values[i] ) ){
1318 /* This chunk in the asserted value was NOT within the *value. */
1324 /* Go on to the next word in the asserted value */
1328 /* If some of the words were seen, call it a match */
1329 if( nextavail > 0 ) {
1336 /* Cleanup allocs */
1337 ber_bvfree( assertv );
1338 for( i=0; i<count; i++ ) {
1339 ch_free( values[i] );
1345 return LDAP_SUCCESS;
1354 struct berval *prefix,
1360 int i,j, len, wordcount, keycount=0;
1361 struct berval *newkeys;
1362 BerVarray keys=NULL;
1364 for( j=0; values[j].bv_val != NULL; j++ ) {
1365 struct berval val = { 0, NULL };
1366 /* Yes, this is necessary */
1367 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1368 assert( val.bv_val != NULL );
1370 /* Isolate how many words there are. There will be a key for each */
1371 for( wordcount = 0, c = val.bv_val; *c; c++) {
1372 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1373 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1375 if (*c == '\0') break;
1379 /* Allocate/increase storage to account for new keys */
1380 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1381 * sizeof(struct berval) );
1382 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1383 if( keys ) ch_free( keys );
1386 /* Get a phonetic copy of each word */
1387 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1389 if( len < SLAPD_APPROX_WORDLEN ) continue;
1390 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1395 ber_memfree( val.bv_val );
1397 keys[keycount].bv_val = NULL;
1400 return LDAP_SUCCESS;
1409 struct berval *prefix,
1410 void * assertedValue,
1419 /* Yes, this is necessary */
1420 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1421 NULL, LDAP_UTF8_APPROX, NULL );
1422 if( val == NULL || val->bv_val == NULL ) {
1423 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1424 keys[0].bv_val = NULL;
1427 return LDAP_SUCCESS;
1430 /* Isolate how many words there are. There will be a key for each */
1431 for( count = 0,c = val->bv_val; *c; c++) {
1432 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1433 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1435 if (*c == '\0') break;
1439 /* Allocate storage for new keys */
1440 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1442 /* Get a phonetic copy of each word */
1443 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1445 if( len < SLAPD_APPROX_WORDLEN ) continue;
1446 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1452 keys[count].bv_val = NULL;
1455 return LDAP_SUCCESS;
1458 /* Remove all spaces and '-' characters */
1460 telephoneNumberNormalize(
1465 struct berval *normalized,
1470 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1472 /* validator should have refused an empty string */
1473 assert( val->bv_len );
1475 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1477 for( p = val->bv_val; *p; p++ ) {
1478 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1484 normalized->bv_len = q - normalized->bv_val;
1486 if( normalized->bv_len == 0 ) {
1487 sl_free( normalized->bv_val, ctx );
1488 normalized->bv_val = NULL;
1489 return LDAP_INVALID_SYNTAX;
1492 return LDAP_SUCCESS;
1500 struct berval val = *in;
1502 if( val.bv_len == 0 ) {
1503 /* disallow empty strings */
1504 return LDAP_INVALID_SYNTAX;
1507 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1508 if ( val.bv_len == 1 ) {
1509 return LDAP_SUCCESS;
1512 if ( val.bv_val[0] == '0' ) {
1519 while ( OID_LEADCHAR( val.bv_val[0] )) {
1523 if ( val.bv_len == 0 ) {
1524 return LDAP_SUCCESS;
1528 if( !OID_SEPARATOR( val.bv_val[0] )) {
1536 return LDAP_INVALID_SYNTAX;
1545 struct berval val = *in;
1547 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1549 if ( val.bv_val[0] == '-' ) {
1553 if( val.bv_len == 0 ) { /* bare "-" */
1554 return LDAP_INVALID_SYNTAX;
1557 if( val.bv_val[0] == '0' ) { /* "-0" */
1558 return LDAP_INVALID_SYNTAX;
1561 } else if ( val.bv_val[0] == '0' ) {
1562 if( val.bv_len > 1 ) { /* "0<more>" */
1563 return LDAP_INVALID_SYNTAX;
1566 return LDAP_SUCCESS;
1569 for( i=0; i < val.bv_len; i++ ) {
1570 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1571 return LDAP_INVALID_SYNTAX;
1575 return LDAP_SUCCESS;
1584 struct berval *value,
1585 void *assertedValue )
1587 struct berval *asserted = (struct berval *) assertedValue;
1588 int vsign = 1, asign = 1; /* default sign = '+' */
1593 if( v.bv_val[0] == '-' ) {
1599 if( v.bv_len == 0 ) vsign = 0;
1602 if( a.bv_val[0] == '-' ) {
1608 if( a.bv_len == 0 ) vsign = 0;
1610 match = vsign - asign;
1612 match = ( v.bv_len != a.bv_len
1613 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1614 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1615 if( vsign < 0 ) match = -match;
1619 return LDAP_SUCCESS;
1623 countryStringValidate(
1625 struct berval *val )
1627 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1629 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1630 return LDAP_INVALID_SYNTAX;
1632 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1633 return LDAP_INVALID_SYNTAX;
1636 return LDAP_SUCCESS;
1640 printableStringValidate(
1642 struct berval *val )
1646 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1648 for(i=0; i < val->bv_len; i++) {
1649 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1650 return LDAP_INVALID_SYNTAX;
1654 return LDAP_SUCCESS;
1658 printablesStringValidate(
1660 struct berval *val )
1664 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1666 for(i=0,len=0; i < val->bv_len; i++) {
1667 int c = val->bv_val[i];
1671 return LDAP_INVALID_SYNTAX;
1675 } else if ( SLAP_PRINTABLE(c) ) {
1678 return LDAP_INVALID_SYNTAX;
1683 return LDAP_INVALID_SYNTAX;
1686 return LDAP_SUCCESS;
1692 struct berval *val )
1696 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1698 for(i=0; i < val->bv_len; i++) {
1699 if( !LDAP_ASCII(val->bv_val[i]) ) {
1700 return LDAP_INVALID_SYNTAX;
1704 return LDAP_SUCCESS;
1713 struct berval *normalized,
1717 int casefold = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1719 assert( val->bv_len );
1721 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1725 /* Ignore initial whitespace */
1726 while ( ASCII_SPACE( *p ) ) p++;
1728 normalized->bv_val = ber_strdup_x( p, ctx );
1729 p = q = normalized->bv_val;
1732 if ( ASCII_SPACE( *p ) ) {
1735 /* Ignore the extra whitespace */
1736 while ( ASCII_SPACE( *p ) ) {
1740 } else if ( casefold ) {
1741 /* Most IA5 rules require casefolding */
1742 *q++ = TOLOWER(*p++);
1749 assert( normalized->bv_val <= p );
1753 * If the string ended in space, backup the pointer one
1754 * position. One is enough because the above loop collapsed
1755 * all whitespace to a single space.
1757 if ( ASCII_SPACE( q[-1] ) ) --q;
1759 /* null terminate */
1762 normalized->bv_len = q - normalized->bv_val;
1763 if( normalized->bv_len == 0 ) {
1764 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1765 normalized->bv_val[0] = ' ';
1766 normalized->bv_val[1] = '\0';
1767 normalized->bv_len = 1;
1770 return LDAP_SUCCESS;
1774 numericStringValidate(
1780 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1782 for(i=0; i < in->bv_len; i++) {
1783 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1784 return LDAP_INVALID_SYNTAX;
1788 return LDAP_SUCCESS;
1792 numericStringNormalize(
1797 struct berval *normalized,
1800 /* removal all spaces */
1803 assert( val->bv_len );
1805 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1808 q = normalized->bv_val;
1811 if ( ASCII_SPACE( *p ) ) {
1812 /* Ignore whitespace */
1819 /* we should have copied no more then is in val */
1820 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1822 /* null terminate */
1825 normalized->bv_len = q - normalized->bv_val;
1827 if( normalized->bv_len == 0 ) {
1828 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1829 normalized->bv_val[0] = ' ';
1830 normalized->bv_val[1] = '\0';
1831 normalized->bv_len = 1;
1834 return LDAP_SUCCESS;
1838 * Integer conversion macros that will use the largest available
1841 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1842 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1843 # define SLAP_LONG_MAX LLONG_MAX
1844 # define SLAP_LONG_MIN LLONG_MIN
1845 # define SLAP_LONG long long
1847 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1848 # define SLAP_LONG_MAX LONG_MAX
1849 # define SLAP_LONG_MIN LONG_MIN
1850 # define SLAP_LONG long
1851 #endif /* HAVE_STRTOLL ... */
1859 struct berval *value,
1860 void *assertedValue )
1862 SLAP_LONG lValue, lAssertedValue;
1864 /* safe to assume integers are NUL terminated? */
1865 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1866 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
1867 return LDAP_CONSTRAINT_VIOLATION;
1870 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1871 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1872 && errno == ERANGE )
1874 return LDAP_CONSTRAINT_VIOLATION;
1877 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1878 return LDAP_SUCCESS;
1887 struct berval *value,
1888 void *assertedValue )
1890 SLAP_LONG lValue, lAssertedValue;
1892 /* safe to assume integers are NUL terminated? */
1893 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1894 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && errno == ERANGE ) {
1895 return LDAP_CONSTRAINT_VIOLATION;
1898 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1899 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1900 && errno == ERANGE )
1902 return LDAP_CONSTRAINT_VIOLATION;
1905 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1906 return LDAP_SUCCESS;
1910 serialNumberAndIssuerValidate(
1917 struct berval sn, i;
1918 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
1920 i.bv_val = strchr( in->bv_val, '$' );
1921 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
1923 sn.bv_val = in->bv_val;
1924 sn.bv_len = i.bv_val - in->bv_val;
1927 i.bv_len = in->bv_len - (sn.bv_len + 1);
1929 /* validate serial number (strict for now) */
1930 for( n=0; n < sn.bv_len; n++ ) {
1931 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
1932 return LDAP_INVALID_SYNTAX;
1937 rc = dnValidate( NULL, &i );
1938 if( rc ) return LDAP_INVALID_SYNTAX;
1940 return LDAP_SUCCESS;
1944 serialNumberAndIssuerPretty(
1953 struct berval sn, i, newi;
1959 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
1960 val->bv_val, 0, 0 );
1962 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
1963 val->bv_val, 0, 0 );
1966 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
1968 i.bv_val = strchr( val->bv_val, '$' );
1969 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
1971 sn.bv_val = val->bv_val;
1972 sn.bv_len = i.bv_val - val->bv_val;
1975 i.bv_len = val->bv_len - (sn.bv_len + 1);
1977 /* eat leading zeros */
1978 for( n=0; n < (sn.bv_len-1); n++ ) {
1979 if( sn.bv_val[n] != '0' ) break;
1984 for( n=0; n < sn.bv_len; n++ ) {
1985 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
1986 return LDAP_INVALID_SYNTAX;
1991 rc = dnPretty( syntax, &i, &newi, ctx );
1992 if( rc ) return LDAP_INVALID_SYNTAX;
1994 /* make room from sn + "$" */
1995 out->bv_len = sn.bv_len + newi.bv_len + 1;
1996 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
1998 if( out->bv_val == NULL ) {
1999 sl_free( newi.bv_val, ctx );
2003 /* push issuer over */
2004 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2005 /* insert sn and "$" */
2006 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2007 out->bv_val[sn.bv_len] = '$';
2009 out->bv_val[out->bv_len] = '\0';
2012 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2013 out->bv_val, 0, 0 );
2015 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2016 out->bv_val, 0, 0 );
2019 return LDAP_SUCCESS;
2023 * This routine is called by certificateExactNormalize when
2024 * certificateExactNormalize receives a search string instead of
2025 * a certificate. This routine checks if the search value is valid
2026 * and then returns the normalized value
2029 serialNumberAndIssuerNormalize(
2040 struct berval sn, i, newi;
2046 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2047 val->bv_val, 0, 0 );
2049 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2050 val->bv_val, 0, 0 );
2053 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2055 i.bv_val = strchr( val->bv_val, '$' );
2056 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2058 sn.bv_val = val->bv_val;
2059 sn.bv_len = i.bv_val - val->bv_val;
2062 i.bv_len = val->bv_len - (sn.bv_len + 1);
2064 /* eat leading zeros */
2065 for( n=0; n < (sn.bv_len-1); n++ ) {
2066 if( sn.bv_val[n] != '0' ) break;
2071 for( n=0; n < sn.bv_len; n++ ) {
2072 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2073 return LDAP_INVALID_SYNTAX;
2078 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2079 if( rc ) return LDAP_INVALID_SYNTAX;
2081 /* make room from sn + "$" */
2082 out->bv_len = sn.bv_len + newi.bv_len + 1;
2083 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2085 if( out->bv_val == NULL ) {
2086 sl_free( newi.bv_val, ctx );
2090 /* push issuer over */
2091 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2092 /* insert sn and "$" */
2093 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2094 out->bv_val[sn.bv_len] = '$';
2096 out->bv_val[out->bv_len] = '\0';
2099 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2100 out->bv_val, 0, 0 );
2102 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2103 out->bv_val, 0, 0 );
2111 certificateExactNormalize(
2116 struct berval *normalized,
2119 int rc = LDAP_INVALID_SYNTAX;
2121 char *serial = NULL;
2122 ber_len_t seriallen;
2123 struct berval issuer_dn = { 0, NULL };
2124 X509_NAME *name = NULL;
2125 ASN1_INTEGER *sn = NULL;
2128 if( val->bv_len == 0 ) goto done;
2130 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2131 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2134 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2137 xcert = d2i_X509( NULL, &p, val->bv_len);
2138 if( xcert == NULL ) goto done;
2140 sn=X509_get_serialNumber(xcert);
2141 if ( sn == NULL ) goto done;
2142 serial=i2s_ASN1_INTEGER(0, sn );
2143 if( serial == NULL ) goto done;
2144 seriallen=strlen(serial);
2146 name=X509_get_issuer_name(xcert);
2147 if( name == NULL ) goto done;
2148 rc = dnX509normalize( name, &issuer_dn );
2149 if( rc != LDAP_SUCCESS ) goto done;
2151 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2152 p = normalized->bv_val = ch_malloc(normalized->bv_len+1);
2153 AC_MEMCPY(p, serial, seriallen);
2156 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2157 p += issuer_dn.bv_len;
2161 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2162 normalized->bv_val, 0, 0 );
2164 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2165 normalized->bv_val, NULL, NULL );
2169 if (xcert) X509_free(xcert);
2170 if (serial) ch_free(serial);
2171 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2175 #endif /* HAVE_TLS */
2178 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2179 /* slight optimization - does not need the start parameter */
2180 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2185 check_time_syntax (struct berval *val,
2188 struct berval *fraction)
2191 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2192 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2193 * GeneralizedTime supports leap seconds, UTCTime does not.
2195 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2196 static const int mdays[2][12] = {
2197 /* non-leap years */
2198 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2200 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2203 int part, c, c1, c2, tzoffset, leapyear = 0;
2206 e = p + val->bv_len;
2208 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2209 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2211 for (part = start; part < 7 && p < e; part++) {
2213 if (!ASCII_DIGIT(c1)) {
2218 return LDAP_INVALID_SYNTAX;
2221 if (!ASCII_DIGIT(c)) {
2222 return LDAP_INVALID_SYNTAX;
2224 c += c1 * 10 - '0' * 11;
2225 if ((part | 1) == 3) {
2228 return LDAP_INVALID_SYNTAX;
2231 if (c >= ceiling[part]) {
2232 if (! (c == 60 && part == 6 && start == 0))
2233 return LDAP_INVALID_SYNTAX;
2237 if (part < 5 + start) {
2238 return LDAP_INVALID_SYNTAX;
2240 for (; part < 9; part++) {
2244 /* leapyear check for the Gregorian calendar (year>1581) */
2245 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2250 if (parts[3] >= mdays[leapyear][parts[2]]) {
2251 return LDAP_INVALID_SYNTAX;
2255 fraction->bv_val = p;
2256 fraction->bv_len = 0;
2257 if (p < e && (*p == '.' || *p == ',')) {
2259 while (++p < e && ASCII_DIGIT(*p))
2261 if (p - fraction->bv_val == 1) {
2262 return LDAP_INVALID_SYNTAX;
2264 for (end_num = p; end_num[-1] == '0'; --end_num)
2266 c = end_num - fraction->bv_val;
2268 fraction->bv_len = c;
2274 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2280 return LDAP_INVALID_SYNTAX;
2286 for (part = 7; part < 9 && p < e; part++) {
2288 if (!ASCII_DIGIT(c1)) {
2293 return LDAP_INVALID_SYNTAX;
2296 if (!ASCII_DIGIT(c2)) {
2297 return LDAP_INVALID_SYNTAX;
2299 parts[part] = c1 * 10 + c2 - '0' * 11;
2300 if (parts[part] >= ceiling[part]) {
2301 return LDAP_INVALID_SYNTAX;
2304 if (part < 8 + start) {
2305 return LDAP_INVALID_SYNTAX;
2308 if (tzoffset == '-') {
2309 /* negative offset to UTC, ie west of Greenwich */
2310 parts[4] += parts[7];
2311 parts[5] += parts[8];
2312 /* offset is just hhmm, no seconds */
2313 for (part = 6; --part >= 0; ) {
2317 c = mdays[leapyear][parts[2]];
2319 if (parts[part] >= c) {
2321 return LDAP_INVALID_SYNTAX;
2326 } else if (part != 5) {
2331 /* positive offset to UTC, ie east of Greenwich */
2332 parts[4] -= parts[7];
2333 parts[5] -= parts[8];
2334 for (part = 6; --part >= 0; ) {
2335 if (parts[part] < 0) {
2337 return LDAP_INVALID_SYNTAX;
2342 /* make first arg to % non-negative */
2343 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2348 } else if (part != 5) {
2355 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2358 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2365 struct berval *normalized )
2369 rc = check_time_syntax(val, 1, parts, NULL);
2370 if (rc != LDAP_SUCCESS) {
2374 normalized->bv_val = ch_malloc( 14 );
2375 if ( normalized->bv_val == NULL ) {
2376 return LBER_ERROR_MEMORY;
2379 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2380 parts[1], parts[2] + 1, parts[3] + 1,
2381 parts[4], parts[5], parts[6] );
2382 normalized->bv_len = 13;
2384 return LDAP_SUCCESS;
2394 return check_time_syntax(in, 1, parts, NULL);
2397 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2400 generalizedTimeValidate(
2405 struct berval fraction;
2406 return check_time_syntax(in, 0, parts, &fraction);
2410 generalizedTimeNormalize(
2415 struct berval *normalized,
2420 struct berval fraction;
2422 rc = check_time_syntax(val, 0, parts, &fraction);
2423 if (rc != LDAP_SUCCESS) {
2427 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2428 normalized->bv_val = sl_malloc( len + 1, ctx );
2429 if ( normalized->bv_val == NULL ) {
2430 return LBER_ERROR_MEMORY;
2433 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2434 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2435 parts[4], parts[5], parts[6] );
2436 if ( fraction.bv_len ) {
2437 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2438 fraction.bv_val, fraction.bv_len );
2439 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2441 strcpy( normalized->bv_val + len-1, "Z" );
2442 normalized->bv_len = len;
2444 return LDAP_SUCCESS;
2448 generalizedTimeOrderingMatch(
2453 struct berval *value,
2454 void *assertedValue )
2456 struct berval *asserted = (struct berval *) assertedValue;
2457 ber_len_t v_len = value->bv_len;
2458 ber_len_t av_len = asserted->bv_len;
2460 /* ignore trailing 'Z' when comparing */
2461 int match = memcmp( value->bv_val, asserted->bv_val,
2462 (v_len < av_len ? v_len : av_len) - 1 );
2463 if ( match == 0 ) match = v_len - av_len;
2466 return LDAP_SUCCESS;
2470 nisNetgroupTripleValidate(
2472 struct berval *val )
2477 if ( val->bv_len == 0 ) {
2478 return LDAP_INVALID_SYNTAX;
2481 p = (char *)val->bv_val;
2482 e = p + val->bv_len;
2484 if ( *p != '(' /*')'*/ ) {
2485 return LDAP_INVALID_SYNTAX;
2488 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2492 return LDAP_INVALID_SYNTAX;
2495 } else if ( !AD_CHAR( *p ) ) {
2496 return LDAP_INVALID_SYNTAX;
2500 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2501 return LDAP_INVALID_SYNTAX;
2507 return LDAP_INVALID_SYNTAX;
2510 return LDAP_SUCCESS;
2514 bootParameterValidate(
2516 struct berval *val )
2520 if ( val->bv_len == 0 ) {
2521 return LDAP_INVALID_SYNTAX;
2524 p = (char *)val->bv_val;
2525 e = p + val->bv_len;
2528 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2529 if ( !AD_CHAR( *p ) ) {
2530 return LDAP_INVALID_SYNTAX;
2535 return LDAP_INVALID_SYNTAX;
2539 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2540 if ( !AD_CHAR( *p ) ) {
2541 return LDAP_INVALID_SYNTAX;
2546 return LDAP_INVALID_SYNTAX;
2550 for ( p++; p < e; p++ ) {
2551 if ( !SLAP_PRINTABLE( *p ) ) {
2552 return LDAP_INVALID_SYNTAX;
2556 return LDAP_SUCCESS;
2560 firstComponentNormalize(
2565 struct berval *normalized,
2572 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2574 if( val->bv_val[0] != '(' /*')'*/ &&
2575 val->bv_val[0] != '{' /*'}'*/ )
2577 return LDAP_INVALID_SYNTAX;
2580 /* trim leading white space */
2582 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2588 /* grab next word */
2589 oid.bv_val = &val->bv_val[len];
2590 len = val->bv_len - len;
2592 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2598 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2599 rc = numericoidValidate( NULL, &oid );
2600 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2601 rc = integerValidate( NULL, &oid );
2603 rc = LDAP_INVALID_SYNTAX;
2607 if( rc == LDAP_SUCCESS ) {
2608 ber_dupbv_x( normalized, &oid, ctx );
2615 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2616 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2618 static slap_syntax_defs_rec syntax_defs[] = {
2619 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2620 X_BINARY X_NOT_H_R ")",
2621 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2622 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2624 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2626 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2628 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2629 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2631 SLAP_SYNTAX_BER, berValidate, NULL},
2632 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2633 0, bitStringValidate, NULL },
2634 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2635 0, booleanValidate, NULL},
2636 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2637 X_BINARY X_NOT_H_R ")",
2638 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2639 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2640 X_BINARY X_NOT_H_R ")",
2641 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2642 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2643 X_BINARY X_NOT_H_R ")",
2644 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2645 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2646 0, countryStringValidate, NULL},
2647 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2648 0, dnValidate, dnPretty},
2649 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2651 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2653 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2654 0, UTF8StringValidate, NULL},
2655 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2657 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2659 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2661 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2663 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2665 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2666 0, printablesStringValidate, NULL},
2667 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2668 SLAP_SYNTAX_BLOB, NULL, NULL},
2669 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2670 0, generalizedTimeValidate, NULL},
2671 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2673 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2674 0, IA5StringValidate, NULL},
2675 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2676 0, integerValidate, NULL},
2677 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2678 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2679 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2681 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2683 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2685 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2687 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2689 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2690 0, nameUIDValidate, nameUIDPretty },
2691 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2693 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2694 0, numericStringValidate, NULL},
2695 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2697 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2698 0, numericoidValidate, NULL},
2699 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2700 0, IA5StringValidate, NULL},
2701 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2702 0, blobValidate, NULL},
2703 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2704 0, UTF8StringValidate, NULL},
2705 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2707 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2709 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2710 0, printableStringValidate, NULL},
2711 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2712 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2713 0, subtreeSpecificationValidate, NULL},
2714 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2715 X_BINARY X_NOT_H_R ")",
2716 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2717 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2718 0, printableStringValidate, NULL},
2719 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2721 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2722 0, printablesStringValidate, NULL},
2723 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2724 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2725 0, utcTimeValidate, NULL},
2727 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2729 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2731 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2733 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2735 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2738 /* RFC 2307 NIS Syntaxes */
2739 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2740 0, nisNetgroupTripleValidate, NULL},
2741 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2742 0, bootParameterValidate, NULL},
2744 /* From PKIX *//* This OID is not published yet. */
2745 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
2747 serialNumberAndIssuerValidate,
2748 serialNumberAndIssuerPretty},
2750 #ifdef SLAPD_ACI_ENABLED
2751 /* OpenLDAP Experimental Syntaxes */
2752 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2754 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2758 #ifdef SLAPD_AUTHPASSWD
2759 /* needs updating */
2760 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2761 SLAP_SYNTAX_HIDE, NULL, NULL},
2764 /* OpenLDAP Void Syntax */
2765 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2766 SLAP_SYNTAX_HIDE, inValidate, NULL},
2767 {NULL, 0, NULL, NULL}
2770 char *certificateExactMatchSyntaxes[] = {
2771 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2774 char *directoryStringSyntaxes[] = {
2775 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2778 char *integerFirstComponentMatchSyntaxes[] = {
2779 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2780 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2783 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2784 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2785 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2786 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2787 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2788 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2789 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2790 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2791 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2796 * Other matching rules in X.520 that we do not use (yet):
2798 * 2.5.13.9 numericStringOrderingMatch
2799 * 2.5.13.25 uTCTimeMatch
2800 * 2.5.13.26 uTCTimeOrderingMatch
2801 * 2.5.13.31 directoryStringFirstComponentMatch
2802 * 2.5.13.32 wordMatch
2803 * 2.5.13.33 keywordMatch
2804 * 2.5.13.36 certificatePairExactMatch
2805 * 2.5.13.37 certificatePairMatch
2806 * 2.5.13.38 certificateListExactMatch
2807 * 2.5.13.39 certificateListMatch
2808 * 2.5.13.40 algorithmIdentifierMatch
2809 * 2.5.13.41 storedPrefixMatch
2810 * 2.5.13.42 attributeCertificateMatch
2811 * 2.5.13.43 readerAndKeyIDMatch
2812 * 2.5.13.44 attributeIntegrityMatch
2814 static slap_mrule_defs_rec mrule_defs[] = {
2816 * EQUALITY matching rules must be listed after associated APPROX
2817 * matching rules. So, we list all APPROX matching rules first.
2819 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2820 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2821 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2822 NULL, NULL, directoryStringApproxMatch,
2823 directoryStringApproxIndexer, directoryStringApproxFilter,
2826 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2827 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2828 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2829 NULL, NULL, IA5StringApproxMatch,
2830 IA5StringApproxIndexer, IA5StringApproxFilter,
2834 * Other matching rules
2837 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2838 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2839 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2840 NULL, NULL, octetStringMatch,
2841 octetStringIndexer, octetStringFilter,
2844 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2845 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2846 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2847 NULL, dnNormalize, dnMatch,
2848 octetStringIndexer, octetStringFilter,
2851 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2852 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2853 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2854 NULL, UTF8StringNormalize, octetStringMatch,
2855 octetStringIndexer, octetStringFilter,
2856 directoryStringApproxMatchOID },
2858 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2859 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2860 SLAP_MR_ORDERING, directoryStringSyntaxes,
2861 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2863 "caseIgnoreMatch" },
2865 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2866 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2867 SLAP_MR_SUBSTR, NULL,
2868 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2869 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2870 "caseIgnoreMatch" },
2872 {"( 2.5.13.5 NAME 'caseExactMatch' "
2873 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2874 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2875 NULL, UTF8StringNormalize, octetStringMatch,
2876 octetStringIndexer, octetStringFilter,
2877 directoryStringApproxMatchOID },
2879 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2880 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2881 SLAP_MR_ORDERING, directoryStringSyntaxes,
2882 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2886 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2887 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2888 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2889 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2890 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2893 {"( 2.5.13.8 NAME 'numericStringMatch' "
2894 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2895 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2896 NULL, numericStringNormalize, octetStringSubstringsMatch,
2897 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2900 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2901 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2902 SLAP_MR_SUBSTR, NULL,
2903 NULL, numericStringNormalize, octetStringSubstringsMatch,
2904 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2905 "numericStringMatch" },
2907 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2908 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2909 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2910 NULL, NULL, NULL, NULL, NULL, NULL },
2912 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2913 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2914 SLAP_MR_SUBSTR, NULL,
2915 NULL, NULL, NULL, NULL, NULL,
2916 "caseIgnoreListMatch" },
2918 {"( 2.5.13.13 NAME 'booleanMatch' "
2919 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2920 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2921 NULL, NULL, booleanMatch,
2922 octetStringIndexer, octetStringFilter,
2925 {"( 2.5.13.14 NAME 'integerMatch' "
2926 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2927 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2928 NULL, NULL, integerMatch,
2929 octetStringIndexer, octetStringFilter,
2932 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2933 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2934 SLAP_MR_ORDERING, NULL,
2935 NULL, NULL, integerMatch,
2939 {"( 2.5.13.16 NAME 'bitStringMatch' "
2940 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2941 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2942 NULL, NULL, octetStringMatch,
2943 octetStringIndexer, octetStringFilter,
2946 {"( 2.5.13.17 NAME 'octetStringMatch' "
2947 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2948 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2949 NULL, NULL, octetStringMatch,
2950 octetStringIndexer, octetStringFilter,
2953 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2954 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2955 SLAP_MR_ORDERING, NULL,
2956 NULL, NULL, octetStringOrderingMatch,
2958 "octetStringMatch" },
2960 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2961 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2962 SLAP_MR_SUBSTR, NULL,
2963 NULL, NULL, octetStringSubstringsMatch,
2964 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2965 "octetStringMatch" },
2967 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2968 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2969 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2971 telephoneNumberNormalize, octetStringMatch,
2972 octetStringIndexer, octetStringFilter,
2975 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2976 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2977 SLAP_MR_SUBSTR, NULL,
2978 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2979 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2980 "telephoneNumberMatch" },
2982 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2983 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2984 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2985 NULL, NULL, NULL, NULL, NULL, NULL },
2987 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2988 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2989 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2990 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2994 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2995 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2996 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2997 NULL, NULL, NULL, NULL, NULL, NULL },
2999 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3001 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3002 NULL, generalizedTimeNormalize, octetStringMatch,
3006 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3008 SLAP_MR_ORDERING, NULL,
3009 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3011 "generalizedTimeMatch" },
3013 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3015 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3016 integerFirstComponentMatchSyntaxes,
3017 NULL, firstComponentNormalize, integerMatch,
3018 octetStringIndexer, octetStringFilter,
3021 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3022 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3023 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3024 objectIdentifierFirstComponentMatchSyntaxes,
3025 NULL, firstComponentNormalize, octetStringMatch,
3026 octetStringIndexer, octetStringFilter,
3029 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3030 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3031 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3033 NULL, certificateExactNormalize, octetStringMatch,
3034 octetStringIndexer, octetStringFilter,
3036 NULL, NULL, NULL, NULL, NULL,
3040 {"( 2.5.13.35 NAME 'certificateMatch' "
3041 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3042 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3044 NULL, NULL, octetStringMatch,
3045 octetStringIndexer, octetStringFilter,
3047 NULL, NULL, NULL, NULL, NULL,
3051 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3052 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3053 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3054 NULL, IA5StringNormalize, octetStringMatch,
3055 octetStringIndexer, octetStringFilter,
3056 IA5StringApproxMatchOID },
3058 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3059 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3060 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3061 NULL, IA5StringNormalize, octetStringMatch,
3062 octetStringIndexer, octetStringFilter,
3063 IA5StringApproxMatchOID },
3065 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3066 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3067 SLAP_MR_SUBSTR, NULL,
3068 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3069 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3070 "caseIgnoreIA5Match" },
3072 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3073 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3074 SLAP_MR_SUBSTR, NULL,
3075 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3076 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3077 "caseExactIA5Match" },
3079 #ifdef SLAPD_AUTHPASSWD
3080 /* needs updating */
3081 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3082 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3083 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3084 NULL, NULL, authPasswordMatch,
3089 #ifdef SLAPD_ACI_ENABLED
3090 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3091 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3092 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3093 NULL, NULL, OpenLDAPaciMatch,
3098 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3099 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3101 NULL, NULL, integerBitAndMatch,
3105 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3106 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3108 NULL, NULL, integerBitOrMatch,
3112 {NULL, SLAP_MR_NONE, NULL,
3113 NULL, NULL, NULL, NULL, NULL,
3118 slap_schema_init( void )
3123 /* we should only be called once (from main) */
3124 assert( schema_init_done == 0 );
3126 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3127 res = register_syntax( &syntax_defs[i] );
3130 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3131 syntax_defs[i].sd_desc );
3136 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3137 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3138 mrule_defs[i].mrd_compat_syntaxes == NULL )
3141 "slap_schema_init: Ignoring unusable matching rule %s\n",
3142 mrule_defs[i].mrd_desc );
3146 res = register_matching_rule( &mrule_defs[i] );
3150 "slap_schema_init: Error registering matching rule %s\n",
3151 mrule_defs[i].mrd_desc );
3156 res = slap_schema_load();
3157 schema_init_done = 1;
3162 schema_destroy( void )