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;
1779 if( in->bv_len != 36 ) {
1781 return LDAP_INVALID_SYNTAX;
1784 for( i=0; i<36; i++ ) {
1790 if( in->bv_val[i] != '-' ) {
1791 return LDAP_INVALID_SYNTAX;
1795 if( !ASCII_HEX( in->bv_val[i]) ) {
1796 return LDAP_INVALID_SYNTAX;
1801 return LDAP_SUCCESS;
1810 struct berval *normalized,
1813 unsigned char octet;
1816 normalized->bv_len = 16;
1817 normalized->bv_val = sl_malloc( normalized->bv_len+1, ctx );
1819 for( i=0, j=0; i<36; i++ ) {
1820 unsigned char nibble;
1821 if( val->bv_val[i] == '-' ) {
1824 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1825 nibble = val->bv_val[i] - '0';
1827 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1828 nibble = val->bv_val[i] - ('a'-10);
1830 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1831 nibble = val->bv_val[i] - ('A'-10);
1834 sl_free( normalized->bv_val, ctx );
1835 return LDAP_INVALID_SYNTAX;
1840 normalized->bv_val[j>>1] = octet;
1842 octet = nibble << 4;
1847 normalized->bv_val[normalized->bv_len] = 0;
1848 return LDAP_SUCCESS;
1854 numericStringValidate(
1860 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1862 for(i=0; i < in->bv_len; i++) {
1863 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1864 return LDAP_INVALID_SYNTAX;
1868 return LDAP_SUCCESS;
1872 numericStringNormalize(
1877 struct berval *normalized,
1880 /* removal all spaces */
1883 assert( val->bv_len );
1885 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1888 q = normalized->bv_val;
1891 if ( ASCII_SPACE( *p ) ) {
1892 /* Ignore whitespace */
1899 /* we should have copied no more then is in val */
1900 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1902 /* null terminate */
1905 normalized->bv_len = q - normalized->bv_val;
1907 if( normalized->bv_len == 0 ) {
1908 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1909 normalized->bv_val[0] = ' ';
1910 normalized->bv_val[1] = '\0';
1911 normalized->bv_len = 1;
1914 return LDAP_SUCCESS;
1918 * Integer conversion macros that will use the largest available
1921 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1922 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1923 # define SLAP_LONG_MAX LLONG_MAX
1924 # define SLAP_LONG_MIN LLONG_MIN
1925 # define SLAP_LONG long long
1927 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1928 # define SLAP_LONG_MAX LONG_MAX
1929 # define SLAP_LONG_MIN LONG_MIN
1930 # define SLAP_LONG long
1931 #endif /* HAVE_STRTOLL ... */
1939 struct berval *value,
1940 void *assertedValue )
1942 SLAP_LONG lValue, lAssertedValue;
1944 /* safe to assume integers are NUL terminated? */
1945 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1946 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
1947 return LDAP_CONSTRAINT_VIOLATION;
1950 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1951 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1952 && errno == ERANGE )
1954 return LDAP_CONSTRAINT_VIOLATION;
1957 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1958 return LDAP_SUCCESS;
1967 struct berval *value,
1968 void *assertedValue )
1970 SLAP_LONG lValue, lAssertedValue;
1972 /* safe to assume integers are NUL terminated? */
1973 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1974 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && errno == ERANGE ) {
1975 return LDAP_CONSTRAINT_VIOLATION;
1978 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1979 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1980 && errno == ERANGE )
1982 return LDAP_CONSTRAINT_VIOLATION;
1985 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1986 return LDAP_SUCCESS;
1990 serialNumberAndIssuerValidate(
1997 struct berval sn, i;
1998 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2000 i.bv_val = strchr( in->bv_val, '$' );
2001 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2003 sn.bv_val = in->bv_val;
2004 sn.bv_len = i.bv_val - in->bv_val;
2007 i.bv_len = in->bv_len - (sn.bv_len + 1);
2009 /* validate serial number (strict for now) */
2010 for( n=0; n < sn.bv_len; n++ ) {
2011 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2012 return LDAP_INVALID_SYNTAX;
2017 rc = dnValidate( NULL, &i );
2018 if( rc ) return LDAP_INVALID_SYNTAX;
2020 return LDAP_SUCCESS;
2024 serialNumberAndIssuerPretty(
2033 struct berval sn, i, newi;
2039 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2040 val->bv_val, 0, 0 );
2042 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2043 val->bv_val, 0, 0 );
2046 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2048 i.bv_val = strchr( val->bv_val, '$' );
2049 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2051 sn.bv_val = val->bv_val;
2052 sn.bv_len = i.bv_val - val->bv_val;
2055 i.bv_len = val->bv_len - (sn.bv_len + 1);
2057 /* eat leading zeros */
2058 for( n=0; n < (sn.bv_len-1); n++ ) {
2059 if( sn.bv_val[n] != '0' ) break;
2064 for( n=0; n < sn.bv_len; n++ ) {
2065 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2066 return LDAP_INVALID_SYNTAX;
2071 rc = dnPretty( syntax, &i, &newi, ctx );
2072 if( rc ) return LDAP_INVALID_SYNTAX;
2074 /* make room from sn + "$" */
2075 out->bv_len = sn.bv_len + newi.bv_len + 1;
2076 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2078 if( out->bv_val == NULL ) {
2079 sl_free( newi.bv_val, ctx );
2083 /* push issuer over */
2084 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2085 /* insert sn and "$" */
2086 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2087 out->bv_val[sn.bv_len] = '$';
2089 out->bv_val[out->bv_len] = '\0';
2092 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2093 out->bv_val, 0, 0 );
2095 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2096 out->bv_val, 0, 0 );
2099 return LDAP_SUCCESS;
2103 * This routine is called by certificateExactNormalize when
2104 * certificateExactNormalize receives a search string instead of
2105 * a certificate. This routine checks if the search value is valid
2106 * and then returns the normalized value
2109 serialNumberAndIssuerNormalize(
2120 struct berval sn, i, newi;
2126 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2127 val->bv_val, 0, 0 );
2129 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2130 val->bv_val, 0, 0 );
2133 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2135 i.bv_val = strchr( val->bv_val, '$' );
2136 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2138 sn.bv_val = val->bv_val;
2139 sn.bv_len = i.bv_val - val->bv_val;
2142 i.bv_len = val->bv_len - (sn.bv_len + 1);
2144 /* eat leading zeros */
2145 for( n=0; n < (sn.bv_len-1); n++ ) {
2146 if( sn.bv_val[n] != '0' ) break;
2151 for( n=0; n < sn.bv_len; n++ ) {
2152 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2153 return LDAP_INVALID_SYNTAX;
2158 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2159 if( rc ) return LDAP_INVALID_SYNTAX;
2161 /* make room from sn + "$" */
2162 out->bv_len = sn.bv_len + newi.bv_len + 1;
2163 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2165 if( out->bv_val == NULL ) {
2166 sl_free( newi.bv_val, ctx );
2170 /* push issuer over */
2171 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2172 /* insert sn and "$" */
2173 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2174 out->bv_val[sn.bv_len] = '$';
2176 out->bv_val[out->bv_len] = '\0';
2179 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2180 out->bv_val, 0, 0 );
2182 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2183 out->bv_val, 0, 0 );
2191 certificateExactNormalize(
2196 struct berval *normalized,
2199 int rc = LDAP_INVALID_SYNTAX;
2201 char *serial = NULL;
2202 ber_len_t seriallen;
2203 struct berval issuer_dn = { 0, NULL };
2204 X509_NAME *name = NULL;
2205 ASN1_INTEGER *sn = NULL;
2208 if( val->bv_len == 0 ) goto done;
2210 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2211 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2214 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2217 xcert = d2i_X509( NULL, &p, val->bv_len);
2218 if( xcert == NULL ) goto done;
2220 sn=X509_get_serialNumber(xcert);
2221 if ( sn == NULL ) goto done;
2222 serial=i2s_ASN1_INTEGER(0, sn );
2223 if( serial == NULL ) goto done;
2224 seriallen=strlen(serial);
2226 name=X509_get_issuer_name(xcert);
2227 if( name == NULL ) goto done;
2228 rc = dnX509normalize( name, &issuer_dn );
2229 if( rc != LDAP_SUCCESS ) goto done;
2231 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2232 p = normalized->bv_val = ch_malloc(normalized->bv_len+1);
2233 AC_MEMCPY(p, serial, seriallen);
2236 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2237 p += issuer_dn.bv_len;
2241 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2242 normalized->bv_val, 0, 0 );
2244 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2245 normalized->bv_val, NULL, NULL );
2249 if (xcert) X509_free(xcert);
2250 if (serial) ch_free(serial);
2251 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2255 #endif /* HAVE_TLS */
2258 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2259 /* slight optimization - does not need the start parameter */
2260 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2265 check_time_syntax (struct berval *val,
2268 struct berval *fraction)
2271 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2272 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2273 * GeneralizedTime supports leap seconds, UTCTime does not.
2275 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2276 static const int mdays[2][12] = {
2277 /* non-leap years */
2278 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2280 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2283 int part, c, c1, c2, tzoffset, leapyear = 0;
2286 e = p + val->bv_len;
2288 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2289 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2291 for (part = start; part < 7 && p < e; part++) {
2293 if (!ASCII_DIGIT(c1)) {
2298 return LDAP_INVALID_SYNTAX;
2301 if (!ASCII_DIGIT(c)) {
2302 return LDAP_INVALID_SYNTAX;
2304 c += c1 * 10 - '0' * 11;
2305 if ((part | 1) == 3) {
2308 return LDAP_INVALID_SYNTAX;
2311 if (c >= ceiling[part]) {
2312 if (! (c == 60 && part == 6 && start == 0))
2313 return LDAP_INVALID_SYNTAX;
2317 if (part < 5 + start) {
2318 return LDAP_INVALID_SYNTAX;
2320 for (; part < 9; part++) {
2324 /* leapyear check for the Gregorian calendar (year>1581) */
2325 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2330 if (parts[3] >= mdays[leapyear][parts[2]]) {
2331 return LDAP_INVALID_SYNTAX;
2335 fraction->bv_val = p;
2336 fraction->bv_len = 0;
2337 if (p < e && (*p == '.' || *p == ',')) {
2339 while (++p < e && ASCII_DIGIT(*p))
2341 if (p - fraction->bv_val == 1) {
2342 return LDAP_INVALID_SYNTAX;
2344 for (end_num = p; end_num[-1] == '0'; --end_num)
2346 c = end_num - fraction->bv_val;
2348 fraction->bv_len = c;
2354 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2360 return LDAP_INVALID_SYNTAX;
2366 for (part = 7; part < 9 && p < e; part++) {
2368 if (!ASCII_DIGIT(c1)) {
2373 return LDAP_INVALID_SYNTAX;
2376 if (!ASCII_DIGIT(c2)) {
2377 return LDAP_INVALID_SYNTAX;
2379 parts[part] = c1 * 10 + c2 - '0' * 11;
2380 if (parts[part] >= ceiling[part]) {
2381 return LDAP_INVALID_SYNTAX;
2384 if (part < 8 + start) {
2385 return LDAP_INVALID_SYNTAX;
2388 if (tzoffset == '-') {
2389 /* negative offset to UTC, ie west of Greenwich */
2390 parts[4] += parts[7];
2391 parts[5] += parts[8];
2392 /* offset is just hhmm, no seconds */
2393 for (part = 6; --part >= 0; ) {
2397 c = mdays[leapyear][parts[2]];
2399 if (parts[part] >= c) {
2401 return LDAP_INVALID_SYNTAX;
2406 } else if (part != 5) {
2411 /* positive offset to UTC, ie east of Greenwich */
2412 parts[4] -= parts[7];
2413 parts[5] -= parts[8];
2414 for (part = 6; --part >= 0; ) {
2415 if (parts[part] < 0) {
2417 return LDAP_INVALID_SYNTAX;
2422 /* make first arg to % non-negative */
2423 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2428 } else if (part != 5) {
2435 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2438 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2445 struct berval *normalized )
2449 rc = check_time_syntax(val, 1, parts, NULL);
2450 if (rc != LDAP_SUCCESS) {
2454 normalized->bv_val = ch_malloc( 14 );
2455 if ( normalized->bv_val == NULL ) {
2456 return LBER_ERROR_MEMORY;
2459 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2460 parts[1], parts[2] + 1, parts[3] + 1,
2461 parts[4], parts[5], parts[6] );
2462 normalized->bv_len = 13;
2464 return LDAP_SUCCESS;
2474 return check_time_syntax(in, 1, parts, NULL);
2477 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2480 generalizedTimeValidate(
2485 struct berval fraction;
2486 return check_time_syntax(in, 0, parts, &fraction);
2490 generalizedTimeNormalize(
2495 struct berval *normalized,
2500 struct berval fraction;
2502 rc = check_time_syntax(val, 0, parts, &fraction);
2503 if (rc != LDAP_SUCCESS) {
2507 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2508 normalized->bv_val = sl_malloc( len + 1, ctx );
2509 if ( normalized->bv_val == NULL ) {
2510 return LBER_ERROR_MEMORY;
2513 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2514 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2515 parts[4], parts[5], parts[6] );
2516 if ( fraction.bv_len ) {
2517 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2518 fraction.bv_val, fraction.bv_len );
2519 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2521 strcpy( normalized->bv_val + len-1, "Z" );
2522 normalized->bv_len = len;
2524 return LDAP_SUCCESS;
2528 generalizedTimeOrderingMatch(
2533 struct berval *value,
2534 void *assertedValue )
2536 struct berval *asserted = (struct berval *) assertedValue;
2537 ber_len_t v_len = value->bv_len;
2538 ber_len_t av_len = asserted->bv_len;
2540 /* ignore trailing 'Z' when comparing */
2541 int match = memcmp( value->bv_val, asserted->bv_val,
2542 (v_len < av_len ? v_len : av_len) - 1 );
2543 if ( match == 0 ) match = v_len - av_len;
2546 return LDAP_SUCCESS;
2550 nisNetgroupTripleValidate(
2552 struct berval *val )
2557 if ( val->bv_len == 0 ) {
2558 return LDAP_INVALID_SYNTAX;
2561 p = (char *)val->bv_val;
2562 e = p + val->bv_len;
2564 if ( *p != '(' /*')'*/ ) {
2565 return LDAP_INVALID_SYNTAX;
2568 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2572 return LDAP_INVALID_SYNTAX;
2575 } else if ( !AD_CHAR( *p ) ) {
2576 return LDAP_INVALID_SYNTAX;
2580 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2581 return LDAP_INVALID_SYNTAX;
2587 return LDAP_INVALID_SYNTAX;
2590 return LDAP_SUCCESS;
2594 bootParameterValidate(
2596 struct berval *val )
2600 if ( val->bv_len == 0 ) {
2601 return LDAP_INVALID_SYNTAX;
2604 p = (char *)val->bv_val;
2605 e = p + val->bv_len;
2608 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2609 if ( !AD_CHAR( *p ) ) {
2610 return LDAP_INVALID_SYNTAX;
2615 return LDAP_INVALID_SYNTAX;
2619 for ( p++; ( 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++ ) {
2631 if ( !SLAP_PRINTABLE( *p ) ) {
2632 return LDAP_INVALID_SYNTAX;
2636 return LDAP_SUCCESS;
2640 firstComponentNormalize(
2645 struct berval *normalized,
2652 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2654 if( val->bv_val[0] != '(' /*')'*/ &&
2655 val->bv_val[0] != '{' /*'}'*/ )
2657 return LDAP_INVALID_SYNTAX;
2660 /* trim leading white space */
2662 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2668 /* grab next word */
2669 oid.bv_val = &val->bv_val[len];
2670 len = val->bv_len - len;
2672 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2678 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2679 rc = numericoidValidate( NULL, &oid );
2680 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2681 rc = integerValidate( NULL, &oid );
2683 rc = LDAP_INVALID_SYNTAX;
2687 if( rc == LDAP_SUCCESS ) {
2688 ber_dupbv_x( normalized, &oid, ctx );
2695 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2696 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2698 static slap_syntax_defs_rec syntax_defs[] = {
2699 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2700 X_BINARY X_NOT_H_R ")",
2701 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2702 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2704 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2706 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2708 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2709 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2711 SLAP_SYNTAX_BER, berValidate, NULL},
2712 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2713 0, bitStringValidate, NULL },
2714 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2715 0, booleanValidate, NULL},
2716 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2717 X_BINARY X_NOT_H_R ")",
2718 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2719 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2720 X_BINARY X_NOT_H_R ")",
2721 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2722 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2723 X_BINARY X_NOT_H_R ")",
2724 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2725 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2726 0, countryStringValidate, NULL},
2727 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2728 0, dnValidate, dnPretty},
2729 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2731 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2733 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2734 0, UTF8StringValidate, NULL},
2735 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2737 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2739 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2741 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2743 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2745 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2746 0, printablesStringValidate, NULL},
2747 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2748 SLAP_SYNTAX_BLOB, NULL, NULL},
2749 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2750 0, generalizedTimeValidate, NULL},
2751 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2753 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2754 0, IA5StringValidate, NULL},
2755 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2756 0, integerValidate, NULL},
2757 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2758 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2759 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2761 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2763 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2765 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2767 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2769 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2770 0, nameUIDValidate, nameUIDPretty },
2771 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2773 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2774 0, numericStringValidate, NULL},
2775 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2777 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2778 0, numericoidValidate, NULL},
2779 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2780 0, IA5StringValidate, NULL},
2781 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2782 0, blobValidate, NULL},
2783 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2784 0, UTF8StringValidate, NULL},
2785 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2787 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2789 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2790 0, printableStringValidate, NULL},
2791 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2792 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2793 0, subtreeSpecificationValidate, NULL},
2794 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2795 X_BINARY X_NOT_H_R ")",
2796 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2797 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2798 0, printableStringValidate, NULL},
2799 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2801 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2802 0, printablesStringValidate, NULL},
2803 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2804 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2805 0, utcTimeValidate, NULL},
2807 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2809 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2811 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2813 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2815 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2818 /* RFC 2307 NIS Syntaxes */
2819 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2820 0, nisNetgroupTripleValidate, NULL},
2821 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2822 0, bootParameterValidate, NULL},
2824 /* From PKIX *//* This OID is not published yet. */
2825 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
2827 serialNumberAndIssuerValidate,
2828 serialNumberAndIssuerPretty},
2830 #ifdef SLAPD_ACI_ENABLED
2831 /* OpenLDAP Experimental Syntaxes */
2832 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2834 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2838 #ifdef SLAPD_AUTHPASSWD
2839 /* needs updating */
2840 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2841 SLAP_SYNTAX_HIDE, NULL, NULL},
2844 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
2845 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
2847 /* OpenLDAP Void Syntax */
2848 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2849 SLAP_SYNTAX_HIDE, inValidate, NULL},
2850 {NULL, 0, NULL, NULL}
2853 char *certificateExactMatchSyntaxes[] = {
2854 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2857 char *directoryStringSyntaxes[] = {
2858 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2861 char *integerFirstComponentMatchSyntaxes[] = {
2862 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2863 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2866 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2867 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2868 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2869 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2870 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2871 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2872 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2873 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2874 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2879 * Other matching rules in X.520 that we do not use (yet):
2881 * 2.5.13.9 numericStringOrderingMatch
2882 * 2.5.13.25 uTCTimeMatch
2883 * 2.5.13.26 uTCTimeOrderingMatch
2884 * 2.5.13.31 directoryStringFirstComponentMatch
2885 * 2.5.13.32 wordMatch
2886 * 2.5.13.33 keywordMatch
2887 * 2.5.13.36 certificatePairExactMatch
2888 * 2.5.13.37 certificatePairMatch
2889 * 2.5.13.38 certificateListExactMatch
2890 * 2.5.13.39 certificateListMatch
2891 * 2.5.13.40 algorithmIdentifierMatch
2892 * 2.5.13.41 storedPrefixMatch
2893 * 2.5.13.42 attributeCertificateMatch
2894 * 2.5.13.43 readerAndKeyIDMatch
2895 * 2.5.13.44 attributeIntegrityMatch
2897 static slap_mrule_defs_rec mrule_defs[] = {
2899 * EQUALITY matching rules must be listed after associated APPROX
2900 * matching rules. So, we list all APPROX matching rules first.
2902 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2903 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2904 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2905 NULL, NULL, directoryStringApproxMatch,
2906 directoryStringApproxIndexer, directoryStringApproxFilter,
2909 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2910 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2911 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2912 NULL, NULL, IA5StringApproxMatch,
2913 IA5StringApproxIndexer, IA5StringApproxFilter,
2917 * Other matching rules
2920 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2922 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2923 NULL, NULL, octetStringMatch,
2924 octetStringIndexer, octetStringFilter,
2927 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2928 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2929 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2930 NULL, dnNormalize, dnMatch,
2931 octetStringIndexer, octetStringFilter,
2934 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2935 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2936 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2937 NULL, UTF8StringNormalize, octetStringMatch,
2938 octetStringIndexer, octetStringFilter,
2939 directoryStringApproxMatchOID },
2941 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2942 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2943 SLAP_MR_ORDERING, directoryStringSyntaxes,
2944 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2946 "caseIgnoreMatch" },
2948 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2949 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2950 SLAP_MR_SUBSTR, NULL,
2951 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2952 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2953 "caseIgnoreMatch" },
2955 {"( 2.5.13.5 NAME 'caseExactMatch' "
2956 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2957 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2958 NULL, UTF8StringNormalize, octetStringMatch,
2959 octetStringIndexer, octetStringFilter,
2960 directoryStringApproxMatchOID },
2962 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2963 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2964 SLAP_MR_ORDERING, directoryStringSyntaxes,
2965 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2969 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2970 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2971 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2972 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2973 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2976 {"( 2.5.13.8 NAME 'numericStringMatch' "
2977 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2978 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2979 NULL, numericStringNormalize, octetStringSubstringsMatch,
2980 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2983 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2984 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2985 SLAP_MR_SUBSTR, NULL,
2986 NULL, numericStringNormalize, octetStringSubstringsMatch,
2987 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2988 "numericStringMatch" },
2990 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2991 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2992 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2993 NULL, NULL, NULL, NULL, NULL, NULL },
2995 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2996 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2997 SLAP_MR_SUBSTR, NULL,
2998 NULL, NULL, NULL, NULL, NULL,
2999 "caseIgnoreListMatch" },
3001 {"( 2.5.13.13 NAME 'booleanMatch' "
3002 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3003 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3004 NULL, NULL, booleanMatch,
3005 octetStringIndexer, octetStringFilter,
3008 {"( 2.5.13.14 NAME 'integerMatch' "
3009 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3010 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3011 NULL, NULL, integerMatch,
3012 octetStringIndexer, octetStringFilter,
3015 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3016 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3017 SLAP_MR_ORDERING, NULL,
3018 NULL, NULL, integerMatch,
3022 {"( 2.5.13.16 NAME 'bitStringMatch' "
3023 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3024 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3025 NULL, NULL, octetStringMatch,
3026 octetStringIndexer, octetStringFilter,
3029 {"( 2.5.13.17 NAME 'octetStringMatch' "
3030 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3031 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3032 NULL, NULL, octetStringMatch,
3033 octetStringIndexer, octetStringFilter,
3036 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3037 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3038 SLAP_MR_ORDERING, NULL,
3039 NULL, NULL, octetStringOrderingMatch,
3041 "octetStringMatch" },
3043 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3044 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3045 SLAP_MR_SUBSTR, NULL,
3046 NULL, NULL, octetStringSubstringsMatch,
3047 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3048 "octetStringMatch" },
3050 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3051 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3052 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3054 telephoneNumberNormalize, octetStringMatch,
3055 octetStringIndexer, octetStringFilter,
3058 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3059 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3060 SLAP_MR_SUBSTR, NULL,
3061 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3062 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3063 "telephoneNumberMatch" },
3065 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3066 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3067 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3068 NULL, NULL, NULL, NULL, NULL, NULL },
3070 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3071 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3072 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3073 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3077 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3078 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3079 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3080 NULL, NULL, NULL, NULL, NULL, NULL },
3082 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3083 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3084 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3085 NULL, generalizedTimeNormalize, octetStringMatch,
3089 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3090 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3091 SLAP_MR_ORDERING, NULL,
3092 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3094 "generalizedTimeMatch" },
3096 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3097 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3098 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3099 integerFirstComponentMatchSyntaxes,
3100 NULL, firstComponentNormalize, integerMatch,
3101 octetStringIndexer, octetStringFilter,
3104 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3105 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3106 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3107 objectIdentifierFirstComponentMatchSyntaxes,
3108 NULL, firstComponentNormalize, octetStringMatch,
3109 octetStringIndexer, octetStringFilter,
3112 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3113 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3114 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3116 NULL, certificateExactNormalize, octetStringMatch,
3117 octetStringIndexer, octetStringFilter,
3119 NULL, NULL, NULL, NULL, NULL,
3123 {"( 2.5.13.35 NAME 'certificateMatch' "
3124 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3125 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3127 NULL, NULL, octetStringMatch,
3128 octetStringIndexer, octetStringFilter,
3130 NULL, NULL, NULL, NULL, NULL,
3134 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3135 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3136 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3137 NULL, IA5StringNormalize, octetStringMatch,
3138 octetStringIndexer, octetStringFilter,
3139 IA5StringApproxMatchOID },
3141 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3142 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3143 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3144 NULL, IA5StringNormalize, octetStringMatch,
3145 octetStringIndexer, octetStringFilter,
3146 IA5StringApproxMatchOID },
3148 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3149 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3150 SLAP_MR_SUBSTR, NULL,
3151 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3152 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3153 "caseIgnoreIA5Match" },
3155 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3156 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3157 SLAP_MR_SUBSTR, NULL,
3158 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3159 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3160 "caseExactIA5Match" },
3162 #ifdef SLAPD_AUTHPASSWD
3163 /* needs updating */
3164 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3165 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3166 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3167 NULL, NULL, authPasswordMatch,
3172 #ifdef SLAPD_ACI_ENABLED
3173 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3174 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3175 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3176 NULL, NULL, OpenLDAPaciMatch,
3181 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3182 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3184 NULL, NULL, integerBitAndMatch,
3188 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3189 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3191 NULL, NULL, integerBitOrMatch,
3195 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3196 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3197 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3198 NULL, UUIDNormalize, octetStringMatch,
3199 octetStringIndexer, octetStringFilter,
3202 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3203 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3204 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3205 NULL, UUIDNormalize, octetStringOrderingMatch,
3206 octetStringIndexer, octetStringFilter,
3209 {NULL, SLAP_MR_NONE, NULL,
3210 NULL, NULL, NULL, NULL, NULL,
3215 slap_schema_init( void )
3220 /* we should only be called once (from main) */
3221 assert( schema_init_done == 0 );
3223 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3224 res = register_syntax( &syntax_defs[i] );
3227 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3228 syntax_defs[i].sd_desc );
3233 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3234 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3235 mrule_defs[i].mrd_compat_syntaxes == NULL )
3238 "slap_schema_init: Ignoring unusable matching rule %s\n",
3239 mrule_defs[i].mrd_desc );
3243 res = register_matching_rule( &mrule_defs[i] );
3247 "slap_schema_init: Error registering matching rule %s\n",
3248 mrule_defs[i].mrd_desc );
3253 res = slap_schema_load();
3254 schema_init_done = 1;
3259 schema_destroy( void )