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 ber_dupbv( &out, val );
865 if( out.bv_len != 0 ) {
866 struct berval uid = { 0, NULL };
868 if( out.bv_val[out.bv_len-1] == 'B'
869 && out.bv_val[out.bv_len-2] == '\'' )
871 /* assume presence of optional UID */
872 uid.bv_val = strrchr( out.bv_val, '#' );
874 if( uid.bv_val == NULL ) {
876 return LDAP_INVALID_SYNTAX;
879 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
880 out.bv_len -= uid.bv_len--;
882 /* temporarily trim the UID */
883 *(uid.bv_val++) = '\0';
886 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
888 if( rc != LDAP_SUCCESS ) {
890 return LDAP_INVALID_SYNTAX;
894 normalized->bv_val = ch_realloc( normalized->bv_val,
895 normalized->bv_len + uid.bv_len + sizeof("#") );
897 /* insert the separator */
898 normalized->bv_val[normalized->bv_len++] = '#';
901 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
902 uid.bv_val, uid.bv_len );
903 normalized->bv_len += uid.bv_len;
906 normalized->bv_val[normalized->bv_len] = '\0';
921 struct berval *value,
922 void *assertedValue )
925 struct berval *asserted = (struct berval *) assertedValue;
926 struct berval assertedDN = { 0, NULL };
927 struct berval assertedUID = { 0, NULL };
928 struct berval valueDN = { 0, NULL };
929 struct berval valueUID = { 0, NULL };
931 if( asserted->bv_len != 0 ) {
932 assertedDN = *asserted;
934 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
935 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
937 /* assume presence of optional UID */
938 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
940 if( assertedUID.bv_val == NULL ) {
941 return LDAP_INVALID_SYNTAX;
944 assertedUID.bv_len = assertedDN.bv_len -
945 (assertedUID.bv_val - assertedDN.bv_val);
946 assertedDN.bv_len -= assertedUID.bv_len--;
948 /* trim the separator */
949 assertedUID.bv_val++;
953 if( value->bv_len != 0 ) {
956 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
957 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
959 /* assume presence of optional UID */
960 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
962 if( valueUID.bv_val == NULL ) {
963 return LDAP_INVALID_SYNTAX;
966 valueUID.bv_len = valueDN.bv_len -
967 (assertedUID.bv_val - assertedDN.bv_val);
968 valueDN.bv_len -= valueUID.bv_len--;
970 /* trim the separator */
975 if( valueUID.bv_len && assertedUID.bv_len ) {
976 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
983 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
987 * Handling boolean syntax and matching is quite rigid.
988 * A more flexible approach would be to allow a variety
989 * of strings to be normalized and prettied into TRUE
997 /* very unforgiving validation, requires no normalization
998 * before simplistic matching
1001 if( in->bv_len == 4 ) {
1002 if( bvmatch( in, &slap_true_bv ) ) {
1003 return LDAP_SUCCESS;
1005 } else if( in->bv_len == 5 ) {
1006 if( bvmatch( in, &slap_false_bv ) ) {
1007 return LDAP_SUCCESS;
1011 return LDAP_INVALID_SYNTAX;
1020 struct berval *value,
1021 void *assertedValue )
1023 /* simplistic matching allowed by rigid validation */
1024 struct berval *asserted = (struct berval *) assertedValue;
1025 *matchp = value->bv_len != asserted->bv_len;
1026 return LDAP_SUCCESS;
1029 /*-------------------------------------------------------------------
1030 LDAP/X.500 string syntax / matching rules have a few oddities. This
1031 comment attempts to detail how slapd(8) treats them.
1034 StringSyntax X.500 LDAP Matching/Comments
1035 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1036 PrintableString subset subset i/e + ignore insignificant spaces
1037 PrintableString subset subset i/e + ignore insignificant spaces
1038 NumericString subset subset ignore all spaces
1039 IA5String ASCII ASCII i/e + ignore insignificant spaces
1040 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1042 TelephoneNumber subset subset i + ignore all spaces and "-"
1044 See draft-ietf-ldapbis-strpro for details (once published).
1048 In X.500(93), a directory string can be either a PrintableString,
1049 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1050 In later versions, more CHOICEs were added. In all cases the string
1053 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1054 A directory string cannot be zero length.
1056 For matching, there are both case ignore and exact rules. Both
1057 also require that "insignificant" spaces be ignored.
1058 spaces before the first non-space are ignored;
1059 spaces after the last non-space are ignored;
1060 spaces after a space are ignored.
1061 Note: by these rules (and as clarified in X.520), a string of only
1062 spaces is to be treated as if held one space, not empty (which
1063 would be a syntax error).
1066 In ASN.1, numeric string is just a string of digits and spaces
1067 and could be empty. However, in X.500, all attribute values of
1068 numeric string carry a non-empty constraint. For example:
1070 internationalISDNNumber ATTRIBUTE ::= {
1071 WITH SYNTAX InternationalISDNNumber
1072 EQUALITY MATCHING RULE numericStringMatch
1073 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1074 ID id-at-internationalISDNNumber }
1075 InternationalISDNNumber ::=
1076 NumericString (SIZE(1..ub-international-isdn-number))
1078 Unforunately, some assertion values are don't carry the same
1079 constraint (but its unclear how such an assertion could ever
1080 be true). In LDAP, there is one syntax (numericString) not two
1081 (numericString with constraint, numericString without constraint).
1082 This should be treated as numericString with non-empty constraint.
1083 Note that while someone may have no ISDN number, there are no ISDN
1084 numbers which are zero length.
1086 In matching, spaces are ignored.
1089 In ASN.1, Printable string is just a string of printable characters
1090 and can be empty. In X.500, semantics much like NumericString (see
1091 serialNumber for a like example) excepting uses insignificant space
1092 handling instead of ignore all spaces.
1095 Basically same as PrintableString. There are no examples in X.500,
1096 but same logic applies. So we require them to be non-empty as
1099 -------------------------------------------------------------------*/
1108 unsigned char *u = in->bv_val;
1110 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1111 /* directory strings cannot be empty */
1112 return LDAP_INVALID_SYNTAX;
1115 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1116 /* get the length indicated by the first byte */
1117 len = LDAP_UTF8_CHARLEN2( u, len );
1119 /* very basic checks */
1122 if( (u[5] & 0xC0) != 0x80 ) {
1123 return LDAP_INVALID_SYNTAX;
1126 if( (u[4] & 0xC0) != 0x80 ) {
1127 return LDAP_INVALID_SYNTAX;
1130 if( (u[3] & 0xC0) != 0x80 ) {
1131 return LDAP_INVALID_SYNTAX;
1134 if( (u[2] & 0xC0 )!= 0x80 ) {
1135 return LDAP_INVALID_SYNTAX;
1138 if( (u[1] & 0xC0) != 0x80 ) {
1139 return LDAP_INVALID_SYNTAX;
1142 /* CHARLEN already validated it */
1145 return LDAP_INVALID_SYNTAX;
1148 /* make sure len corresponds with the offset
1149 to the next character */
1150 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
1154 return LDAP_INVALID_SYNTAX;
1157 return LDAP_SUCCESS;
1161 UTF8StringNormalize(
1166 struct berval *normalized,
1169 struct berval tmp, nvalue;
1173 if( val->bv_val == NULL ) {
1174 /* assume we're dealing with a syntax (e.g., UTF8String)
1175 * which allows empty strings
1177 normalized->bv_len = 0;
1178 normalized->bv_val = NULL;
1179 return LDAP_SUCCESS;
1182 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1183 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1184 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1185 ? LDAP_UTF8_APPROX : 0;
1187 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1192 /* collapse spaces (in place) */
1194 nvalue.bv_val = tmp.bv_val;
1196 wasspace=1; /* trim leading spaces */
1197 for( i=0; i<tmp.bv_len; i++) {
1198 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1199 if( wasspace++ == 0 ) {
1200 /* trim repeated spaces */
1201 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1205 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1209 if( nvalue.bv_len ) {
1211 /* last character was a space, trim it */
1214 nvalue.bv_val[nvalue.bv_len] = '\0';
1217 /* string of all spaces is treated as one space */
1218 nvalue.bv_val[0] = ' ';
1219 nvalue.bv_val[1] = '\0';
1223 *normalized = nvalue;
1224 return LDAP_SUCCESS;
1227 #if defined(SLAPD_APPROX_INITIALS)
1228 # define SLAPD_APPROX_DELIMITER "._ "
1229 # define SLAPD_APPROX_WORDLEN 2
1231 # define SLAPD_APPROX_DELIMITER " "
1232 # define SLAPD_APPROX_WORDLEN 1
1241 struct berval *value,
1242 void *assertedValue )
1244 struct berval *nval, *assertv;
1245 char *val, **values, **words, *c;
1246 int i, count, len, nextchunk=0, nextavail=0;
1248 /* Yes, this is necessary */
1249 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1250 if( nval == NULL ) {
1252 return LDAP_SUCCESS;
1255 /* Yes, this is necessary */
1256 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1257 NULL, LDAP_UTF8_APPROX, NULL );
1258 if( assertv == NULL ) {
1261 return LDAP_SUCCESS;
1264 /* Isolate how many words there are */
1265 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1266 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1267 if ( c == NULL ) break;
1272 /* Get a phonetic copy of each word */
1273 words = (char **)ch_malloc( count * sizeof(char *) );
1274 values = (char **)ch_malloc( count * sizeof(char *) );
1275 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1277 values[i] = phonetic(c);
1280 /* Work through the asserted value's words, to see if at least some
1281 of the words are there, in the same order. */
1283 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1284 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1289 #if defined(SLAPD_APPROX_INITIALS)
1290 else if( len == 1 ) {
1291 /* Single letter words need to at least match one word's initial */
1292 for( i=nextavail; i<count; i++ )
1293 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1300 /* Isolate the next word in the asserted value and phonetic it */
1301 assertv->bv_val[nextchunk+len] = '\0';
1302 val = phonetic( assertv->bv_val + nextchunk );
1304 /* See if this phonetic chunk is in the remaining words of *value */
1305 for( i=nextavail; i<count; i++ ){
1306 if( !strcmp( val, values[i] ) ){
1314 /* This chunk in the asserted value was NOT within the *value. */
1320 /* Go on to the next word in the asserted value */
1324 /* If some of the words were seen, call it a match */
1325 if( nextavail > 0 ) {
1332 /* Cleanup allocs */
1333 ber_bvfree( assertv );
1334 for( i=0; i<count; i++ ) {
1335 ch_free( values[i] );
1341 return LDAP_SUCCESS;
1350 struct berval *prefix,
1356 int i,j, len, wordcount, keycount=0;
1357 struct berval *newkeys;
1358 BerVarray keys=NULL;
1360 for( j=0; values[j].bv_val != NULL; j++ ) {
1361 struct berval val = { 0, NULL };
1362 /* Yes, this is necessary */
1363 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1364 assert( val.bv_val != NULL );
1366 /* Isolate how many words there are. There will be a key for each */
1367 for( wordcount = 0, c = val.bv_val; *c; c++) {
1368 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1369 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1371 if (*c == '\0') break;
1375 /* Allocate/increase storage to account for new keys */
1376 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1377 * sizeof(struct berval) );
1378 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1379 if( keys ) ch_free( keys );
1382 /* Get a phonetic copy of each word */
1383 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1385 if( len < SLAPD_APPROX_WORDLEN ) continue;
1386 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1391 ber_memfree( val.bv_val );
1393 keys[keycount].bv_val = NULL;
1396 return LDAP_SUCCESS;
1405 struct berval *prefix,
1406 void * assertedValue,
1415 /* Yes, this is necessary */
1416 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1417 NULL, LDAP_UTF8_APPROX, NULL );
1418 if( val == NULL || val->bv_val == NULL ) {
1419 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1420 keys[0].bv_val = NULL;
1423 return LDAP_SUCCESS;
1426 /* Isolate how many words there are. There will be a key for each */
1427 for( count = 0,c = val->bv_val; *c; c++) {
1428 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1429 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1431 if (*c == '\0') break;
1435 /* Allocate storage for new keys */
1436 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1438 /* Get a phonetic copy of each word */
1439 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1441 if( len < SLAPD_APPROX_WORDLEN ) continue;
1442 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1448 keys[count].bv_val = NULL;
1451 return LDAP_SUCCESS;
1454 /* Remove all spaces and '-' characters */
1456 telephoneNumberNormalize(
1461 struct berval *normalized,
1466 /* validator should have refused an empty string */
1467 assert( val->bv_len );
1469 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1471 for( p = val->bv_val; *p; p++ ) {
1472 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1478 normalized->bv_len = q - normalized->bv_val;
1480 if( normalized->bv_len == 0 ) {
1481 sl_free( normalized->bv_val, ctx );
1482 normalized->bv_val = NULL;
1483 return LDAP_INVALID_SYNTAX;
1486 return LDAP_SUCCESS;
1494 struct berval val = *in;
1496 if( val.bv_len == 0 ) {
1497 /* disallow empty strings */
1498 return LDAP_INVALID_SYNTAX;
1501 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1502 if ( val.bv_len == 1 ) {
1503 return LDAP_SUCCESS;
1506 if ( val.bv_val[0] == '0' ) {
1513 while ( OID_LEADCHAR( val.bv_val[0] )) {
1517 if ( val.bv_len == 0 ) {
1518 return LDAP_SUCCESS;
1522 if( !OID_SEPARATOR( val.bv_val[0] )) {
1530 return LDAP_INVALID_SYNTAX;
1539 struct berval val = *in;
1541 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1543 if ( val.bv_val[0] == '-' ) {
1547 if( val.bv_len == 0 ) { /* bare "-" */
1548 return LDAP_INVALID_SYNTAX;
1551 if( val.bv_val[0] == '0' ) { /* "-0" */
1552 return LDAP_INVALID_SYNTAX;
1555 } else if ( val.bv_val[0] == '0' ) {
1556 if( val.bv_len > 1 ) { /* "0<more>" */
1557 return LDAP_INVALID_SYNTAX;
1560 return LDAP_SUCCESS;
1563 for( i=0; i < val.bv_len; i++ ) {
1564 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1565 return LDAP_INVALID_SYNTAX;
1569 return LDAP_SUCCESS;
1578 struct berval *value,
1579 void *assertedValue )
1581 struct berval *asserted = (struct berval *) assertedValue;
1582 int vsign = 1, asign = 1; /* default sign = '+' */
1587 if( v.bv_val[0] == '-' ) {
1593 if( v.bv_len == 0 ) vsign = 0;
1596 if( a.bv_val[0] == '-' ) {
1602 if( a.bv_len == 0 ) vsign = 0;
1604 match = vsign - asign;
1606 match = ( v.bv_len != a.bv_len
1607 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1608 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1609 if( vsign < 0 ) match = -match;
1613 return LDAP_SUCCESS;
1617 countryStringValidate(
1619 struct berval *val )
1621 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1623 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1624 return LDAP_INVALID_SYNTAX;
1626 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1627 return LDAP_INVALID_SYNTAX;
1630 return LDAP_SUCCESS;
1634 printableStringValidate(
1636 struct berval *val )
1640 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1642 for(i=0; i < val->bv_len; i++) {
1643 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1644 return LDAP_INVALID_SYNTAX;
1648 return LDAP_SUCCESS;
1652 printablesStringValidate(
1654 struct berval *val )
1658 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1660 for(i=0,len=0; i < val->bv_len; i++) {
1661 int c = val->bv_val[i];
1665 return LDAP_INVALID_SYNTAX;
1669 } else if ( SLAP_PRINTABLE(c) ) {
1672 return LDAP_INVALID_SYNTAX;
1677 return LDAP_INVALID_SYNTAX;
1680 return LDAP_SUCCESS;
1686 struct berval *val )
1690 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1692 for(i=0; i < val->bv_len; i++) {
1693 if( !LDAP_ASCII(val->bv_val[i]) ) {
1694 return LDAP_INVALID_SYNTAX;
1698 return LDAP_SUCCESS;
1707 struct berval *normalized,
1711 int casefold = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1713 assert( val->bv_len );
1717 /* Ignore initial whitespace */
1718 while ( ASCII_SPACE( *p ) ) p++;
1720 normalized->bv_val = ber_strdup_x( p, ctx );
1721 p = q = normalized->bv_val;
1724 if ( ASCII_SPACE( *p ) ) {
1727 /* Ignore the extra whitespace */
1728 while ( ASCII_SPACE( *p ) ) {
1732 } else if ( casefold ) {
1733 /* Most IA5 rules require casefolding */
1734 *q++ = TOLOWER(*p++);
1741 assert( normalized->bv_val <= p );
1745 * If the string ended in space, backup the pointer one
1746 * position. One is enough because the above loop collapsed
1747 * all whitespace to a single space.
1749 if ( ASCII_SPACE( q[-1] ) ) --q;
1751 /* null terminate */
1754 normalized->bv_len = q - normalized->bv_val;
1755 if( normalized->bv_len == 0 ) {
1756 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1757 normalized->bv_val[0] = ' ';
1758 normalized->bv_val[1] = '\0';
1759 normalized->bv_len = 1;
1762 return LDAP_SUCCESS;
1766 numericStringValidate(
1772 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1774 for(i=0; i < in->bv_len; i++) {
1775 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1776 return LDAP_INVALID_SYNTAX;
1780 return LDAP_SUCCESS;
1784 numericStringNormalize(
1789 struct berval *normalized,
1792 /* removal all spaces */
1795 assert( val->bv_len );
1797 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1800 q = normalized->bv_val;
1803 if ( ASCII_SPACE( *p ) ) {
1804 /* Ignore whitespace */
1811 /* we should have copied no more then is in val */
1812 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1814 /* null terminate */
1817 normalized->bv_len = q - normalized->bv_val;
1819 if( normalized->bv_len == 0 ) {
1820 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1821 normalized->bv_val[0] = ' ';
1822 normalized->bv_val[1] = '\0';
1823 normalized->bv_len = 1;
1826 return LDAP_SUCCESS;
1830 * Integer conversion macros that will use the largest available
1833 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1834 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1835 # define SLAP_LONG_MAX LLONG_MAX
1836 # define SLAP_LONG_MIN LLONG_MIN
1837 # define SLAP_LONG long long
1839 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1840 # define SLAP_LONG_MAX LONG_MAX
1841 # define SLAP_LONG_MIN LONG_MIN
1842 # define SLAP_LONG long
1843 #endif /* HAVE_STRTOLL ... */
1851 struct berval *value,
1852 void *assertedValue )
1854 SLAP_LONG lValue, lAssertedValue;
1856 /* safe to assume integers are NUL terminated? */
1857 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1858 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
1859 return LDAP_CONSTRAINT_VIOLATION;
1862 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1863 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1864 && errno == ERANGE )
1866 return LDAP_CONSTRAINT_VIOLATION;
1869 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1870 return LDAP_SUCCESS;
1879 struct berval *value,
1880 void *assertedValue )
1882 SLAP_LONG lValue, lAssertedValue;
1884 /* safe to assume integers are NUL terminated? */
1885 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1886 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && errno == ERANGE ) {
1887 return LDAP_CONSTRAINT_VIOLATION;
1890 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1891 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1892 && errno == ERANGE )
1894 return LDAP_CONSTRAINT_VIOLATION;
1897 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1898 return LDAP_SUCCESS;
1902 serialNumberAndIssuerValidate(
1909 struct berval sn, i;
1910 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
1912 i.bv_val = strchr( in->bv_val, '$' );
1913 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
1915 sn.bv_val = in->bv_val;
1916 sn.bv_len = i.bv_val - in->bv_val;
1919 i.bv_len = in->bv_len - (sn.bv_len + 1);
1921 /* validate serial number (strict for now) */
1922 for( n=0; n < sn.bv_len; n++ ) {
1923 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
1924 return LDAP_INVALID_SYNTAX;
1929 rc = dnValidate( NULL, &i );
1930 if( rc ) return LDAP_INVALID_SYNTAX;
1932 return LDAP_SUCCESS;
1936 serialNumberAndIssuerPretty(
1945 struct berval sn, i, newi;
1951 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
1952 val->bv_val, 0, 0 );
1954 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
1955 val->bv_val, 0, 0 );
1958 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
1960 i.bv_val = strchr( val->bv_val, '$' );
1961 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
1963 sn.bv_val = val->bv_val;
1964 sn.bv_len = i.bv_val - val->bv_val;
1967 i.bv_len = val->bv_len - (sn.bv_len + 1);
1969 /* eat leading zeros */
1970 for( n=0; n < (sn.bv_len-1); n++ ) {
1971 if( sn.bv_val[n] != '0' ) break;
1976 for( n=0; n < sn.bv_len; n++ ) {
1977 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
1978 return LDAP_INVALID_SYNTAX;
1983 rc = dnPretty( syntax, &i, &newi, ctx );
1984 if( rc ) return LDAP_INVALID_SYNTAX;
1986 /* make room from sn + "$" */
1987 out->bv_len = sn.bv_len + newi.bv_len + 1;
1988 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
1990 if( out->bv_val == NULL ) {
1991 sl_free( newi.bv_val, ctx );
1995 /* push issuer over */
1996 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
1997 /* insert sn and "$" */
1998 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
1999 out->bv_val[sn.bv_len] = '$';
2001 out->bv_val[out->bv_len] = '\0';
2004 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2005 out->bv_val, 0, 0 );
2007 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2008 out->bv_val, 0, 0 );
2011 return LDAP_SUCCESS;
2015 * This routine is called by certificateExactNormalize when
2016 * certificateExactNormalize receives a search string instead of
2017 * a certificate. This routine checks if the search value is valid
2018 * and then returns the normalized value
2021 serialNumberAndIssuerNormalize(
2032 struct berval sn, i, newi;
2038 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2039 val->bv_val, 0, 0 );
2041 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2042 val->bv_val, 0, 0 );
2045 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2047 i.bv_val = strchr( val->bv_val, '$' );
2048 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2050 sn.bv_val = val->bv_val;
2051 sn.bv_len = i.bv_val - val->bv_val;
2054 i.bv_len = val->bv_len - (sn.bv_len + 1);
2056 /* eat leading zeros */
2057 for( n=0; n < (sn.bv_len-1); n++ ) {
2058 if( sn.bv_val[n] != '0' ) break;
2063 for( n=0; n < sn.bv_len; n++ ) {
2064 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2065 return LDAP_INVALID_SYNTAX;
2070 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2071 if( rc ) return LDAP_INVALID_SYNTAX;
2073 /* make room from sn + "$" */
2074 out->bv_len = sn.bv_len + newi.bv_len + 1;
2075 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2077 if( out->bv_val == NULL ) {
2078 sl_free( newi.bv_val, ctx );
2082 /* push issuer over */
2083 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2084 /* insert sn and "$" */
2085 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2086 out->bv_val[sn.bv_len] = '$';
2088 out->bv_val[out->bv_len] = '\0';
2091 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2092 out->bv_val, 0, 0 );
2094 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2095 out->bv_val, 0, 0 );
2103 certificateExactNormalize(
2108 struct berval *normalized,
2111 int rc = LDAP_INVALID_SYNTAX;
2113 char *serial = NULL;
2114 ber_len_t seriallen;
2115 struct berval issuer_dn = { 0, NULL };
2116 X509_NAME *name = NULL;
2117 ASN1_INTEGER *sn = NULL;
2120 if( val->bv_len == 0 ) goto done;
2122 if( val->bv_val[0] != LBER_SEQUENCE ) {
2123 /* assume serialNumberAndIssuer */
2124 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,NULL);
2128 xcert = d2i_X509( NULL, &p, val->bv_len);
2129 if( xcert == NULL ) goto done;
2131 sn=X509_get_serialNumber(xcert);
2132 if ( sn == NULL ) goto done;
2133 serial=i2s_ASN1_INTEGER(0, sn );
2134 if( serial == NULL ) goto done;
2135 seriallen=strlen(serial);
2137 name=X509_get_issuer_name(xcert);
2138 if( name == NULL ) goto done;
2139 rc = dnX509normalize( name, &issuer_dn );
2140 if( rc != LDAP_SUCCESS ) goto done;
2142 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2143 p = normalized->bv_val = ch_malloc(normalized->bv_len+1);
2144 AC_MEMCPY(p, serial, seriallen);
2147 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2148 p += issuer_dn.bv_len;
2152 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2153 normalized->bv_val, 0, 0 );
2155 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2156 normalized->bv_val, NULL, NULL );
2160 if (xcert) X509_free(xcert);
2161 if (serial) ch_free(serial);
2162 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2166 #endif /* HAVE_TLS */
2169 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2170 /* slight optimization - does not need the start parameter */
2171 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2176 check_time_syntax (struct berval *val,
2179 struct berval *fraction)
2182 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2183 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2184 * GeneralizedTime supports leap seconds, UTCTime does not.
2186 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2187 static const int mdays[2][12] = {
2188 /* non-leap years */
2189 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2191 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2194 int part, c, c1, c2, tzoffset, leapyear = 0;
2197 e = p + val->bv_len;
2199 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2200 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2202 for (part = start; part < 7 && p < e; part++) {
2204 if (!ASCII_DIGIT(c1)) {
2209 return LDAP_INVALID_SYNTAX;
2212 if (!ASCII_DIGIT(c)) {
2213 return LDAP_INVALID_SYNTAX;
2215 c += c1 * 10 - '0' * 11;
2216 if ((part | 1) == 3) {
2219 return LDAP_INVALID_SYNTAX;
2222 if (c >= ceiling[part]) {
2223 if (! (c == 60 && part == 6 && start == 0))
2224 return LDAP_INVALID_SYNTAX;
2228 if (part < 5 + start) {
2229 return LDAP_INVALID_SYNTAX;
2231 for (; part < 9; part++) {
2235 /* leapyear check for the Gregorian calendar (year>1581) */
2236 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2241 if (parts[3] >= mdays[leapyear][parts[2]]) {
2242 return LDAP_INVALID_SYNTAX;
2246 fraction->bv_val = p;
2247 fraction->bv_len = 0;
2248 if (p < e && (*p == '.' || *p == ',')) {
2250 while (++p < e && ASCII_DIGIT(*p))
2252 if (p - fraction->bv_val == 1) {
2253 return LDAP_INVALID_SYNTAX;
2255 for (end_num = p; end_num[-1] == '0'; --end_num)
2257 c = end_num - fraction->bv_val;
2259 fraction->bv_len = c;
2265 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2271 return LDAP_INVALID_SYNTAX;
2277 for (part = 7; part < 9 && p < e; part++) {
2279 if (!ASCII_DIGIT(c1)) {
2284 return LDAP_INVALID_SYNTAX;
2287 if (!ASCII_DIGIT(c2)) {
2288 return LDAP_INVALID_SYNTAX;
2290 parts[part] = c1 * 10 + c2 - '0' * 11;
2291 if (parts[part] >= ceiling[part]) {
2292 return LDAP_INVALID_SYNTAX;
2295 if (part < 8 + start) {
2296 return LDAP_INVALID_SYNTAX;
2299 if (tzoffset == '-') {
2300 /* negative offset to UTC, ie west of Greenwich */
2301 parts[4] += parts[7];
2302 parts[5] += parts[8];
2303 /* offset is just hhmm, no seconds */
2304 for (part = 6; --part >= 0; ) {
2308 c = mdays[leapyear][parts[2]];
2310 if (parts[part] >= c) {
2312 return LDAP_INVALID_SYNTAX;
2317 } else if (part != 5) {
2322 /* positive offset to UTC, ie east of Greenwich */
2323 parts[4] -= parts[7];
2324 parts[5] -= parts[8];
2325 for (part = 6; --part >= 0; ) {
2326 if (parts[part] < 0) {
2328 return LDAP_INVALID_SYNTAX;
2333 /* make first arg to % non-negative */
2334 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2339 } else if (part != 5) {
2346 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2349 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2356 struct berval *normalized )
2360 rc = check_time_syntax(val, 1, parts, NULL);
2361 if (rc != LDAP_SUCCESS) {
2365 normalized->bv_val = ch_malloc( 14 );
2366 if ( normalized->bv_val == NULL ) {
2367 return LBER_ERROR_MEMORY;
2370 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2371 parts[1], parts[2] + 1, parts[3] + 1,
2372 parts[4], parts[5], parts[6] );
2373 normalized->bv_len = 13;
2375 return LDAP_SUCCESS;
2385 return check_time_syntax(in, 1, parts, NULL);
2388 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2391 generalizedTimeValidate(
2396 struct berval fraction;
2397 return check_time_syntax(in, 0, parts, &fraction);
2401 generalizedTimeNormalize(
2406 struct berval *normalized,
2411 struct berval fraction;
2413 rc = check_time_syntax(val, 0, parts, &fraction);
2414 if (rc != LDAP_SUCCESS) {
2418 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2419 normalized->bv_val = sl_malloc( len + 1, ctx );
2420 if ( normalized->bv_val == NULL ) {
2421 return LBER_ERROR_MEMORY;
2424 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2425 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2426 parts[4], parts[5], parts[6] );
2427 if ( fraction.bv_len ) {
2428 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2429 fraction.bv_val, fraction.bv_len );
2430 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2432 strcpy( normalized->bv_val + len-1, "Z" );
2433 normalized->bv_len = len;
2435 return LDAP_SUCCESS;
2439 generalizedTimeOrderingMatch(
2444 struct berval *value,
2445 void *assertedValue )
2447 struct berval *asserted = (struct berval *) assertedValue;
2448 ber_len_t v_len = value->bv_len;
2449 ber_len_t av_len = asserted->bv_len;
2451 /* ignore trailing 'Z' when comparing */
2452 int match = memcmp( value->bv_val, asserted->bv_val,
2453 (v_len < av_len ? v_len : av_len) - 1 );
2454 if ( match == 0 ) match = v_len - av_len;
2457 return LDAP_SUCCESS;
2461 nisNetgroupTripleValidate(
2463 struct berval *val )
2468 if ( val->bv_len == 0 ) {
2469 return LDAP_INVALID_SYNTAX;
2472 p = (char *)val->bv_val;
2473 e = p + val->bv_len;
2475 if ( *p != '(' /*')'*/ ) {
2476 return LDAP_INVALID_SYNTAX;
2479 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2483 return LDAP_INVALID_SYNTAX;
2486 } else if ( !AD_CHAR( *p ) ) {
2487 return LDAP_INVALID_SYNTAX;
2491 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2492 return LDAP_INVALID_SYNTAX;
2498 return LDAP_INVALID_SYNTAX;
2501 return LDAP_SUCCESS;
2505 bootParameterValidate(
2507 struct berval *val )
2511 if ( val->bv_len == 0 ) {
2512 return LDAP_INVALID_SYNTAX;
2515 p = (char *)val->bv_val;
2516 e = p + val->bv_len;
2519 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2520 if ( !AD_CHAR( *p ) ) {
2521 return LDAP_INVALID_SYNTAX;
2526 return LDAP_INVALID_SYNTAX;
2530 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2531 if ( !AD_CHAR( *p ) ) {
2532 return LDAP_INVALID_SYNTAX;
2537 return LDAP_INVALID_SYNTAX;
2541 for ( p++; p < e; p++ ) {
2542 if ( !SLAP_PRINTABLE( *p ) ) {
2543 return LDAP_INVALID_SYNTAX;
2547 return LDAP_SUCCESS;
2551 firstComponentNormalize(
2556 struct berval *normalized,
2563 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2565 if( val->bv_val[0] != '(' /*')'*/ &&
2566 val->bv_val[0] != '{' /*'}'*/ )
2568 return LDAP_INVALID_SYNTAX;
2571 /* trim leading white space */
2573 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2579 /* grab next word */
2580 oid.bv_val = &val->bv_val[len];
2581 len = val->bv_len - len;
2583 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2589 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2590 rc = numericoidValidate( NULL, &oid );
2591 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2592 rc = integerValidate( NULL, &oid );
2594 rc = LDAP_INVALID_SYNTAX;
2598 if( rc == LDAP_SUCCESS ) {
2599 ber_dupbv_x( normalized, &oid, ctx );
2606 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2607 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2609 static slap_syntax_defs_rec syntax_defs[] = {
2610 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2611 X_BINARY X_NOT_H_R ")",
2612 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2613 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2615 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2617 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2619 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2620 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2622 SLAP_SYNTAX_BER, berValidate, NULL},
2623 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2624 0, bitStringValidate, NULL },
2625 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2626 0, booleanValidate, NULL},
2627 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2628 X_BINARY X_NOT_H_R ")",
2629 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2630 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2631 X_BINARY X_NOT_H_R ")",
2632 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2633 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2634 X_BINARY X_NOT_H_R ")",
2635 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2636 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2637 0, countryStringValidate, NULL},
2638 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2639 0, dnValidate, dnPretty},
2640 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2642 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2644 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2645 0, UTF8StringValidate, NULL},
2646 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2648 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2650 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2652 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2654 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2656 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2657 0, printablesStringValidate, NULL},
2658 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2659 SLAP_SYNTAX_BLOB, NULL, NULL},
2660 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2661 0, generalizedTimeValidate, NULL},
2662 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2664 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2665 0, IA5StringValidate, NULL},
2666 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2667 0, integerValidate, NULL},
2668 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2669 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2670 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2672 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2674 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2676 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2678 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2680 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2681 0, nameUIDValidate, nameUIDPretty },
2682 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2684 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2685 0, numericStringValidate, NULL},
2686 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2688 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2689 0, numericoidValidate, NULL},
2690 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2691 0, IA5StringValidate, NULL},
2692 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2693 0, blobValidate, NULL},
2694 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2695 0, UTF8StringValidate, NULL},
2696 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2698 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2700 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2701 0, printableStringValidate, NULL},
2702 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2703 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2704 0, subtreeSpecificationValidate, NULL},
2705 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2706 X_BINARY X_NOT_H_R ")",
2707 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2708 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2709 0, printableStringValidate, NULL},
2710 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2712 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2713 0, printablesStringValidate, NULL},
2714 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2715 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2716 0, utcTimeValidate, NULL},
2718 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2720 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2722 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2724 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2726 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2729 /* RFC 2307 NIS Syntaxes */
2730 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2731 0, nisNetgroupTripleValidate, NULL},
2732 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2733 0, bootParameterValidate, NULL},
2735 /* From PKIX *//* This OID is not published yet. */
2736 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
2738 serialNumberAndIssuerValidate,
2739 serialNumberAndIssuerPretty},
2741 #ifdef SLAPD_ACI_ENABLED
2742 /* OpenLDAP Experimental Syntaxes */
2743 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2745 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2749 #ifdef SLAPD_AUTHPASSWD
2750 /* needs updating */
2751 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2752 SLAP_SYNTAX_HIDE, NULL, NULL},
2755 /* OpenLDAP Void Syntax */
2756 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2757 SLAP_SYNTAX_HIDE, inValidate, NULL},
2758 {NULL, 0, NULL, NULL}
2761 char *certificateExactMatchSyntaxes[] = {
2762 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2765 char *directoryStringSyntaxes[] = {
2766 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2769 char *integerFirstComponentMatchSyntaxes[] = {
2770 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2771 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2774 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2775 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2776 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2777 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2778 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2779 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2780 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2781 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2782 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2787 * Other matching rules in X.520 that we do not use (yet):
2789 * 2.5.13.9 numericStringOrderingMatch
2790 * 2.5.13.25 uTCTimeMatch
2791 * 2.5.13.26 uTCTimeOrderingMatch
2792 * 2.5.13.31 directoryStringFirstComponentMatch
2793 * 2.5.13.32 wordMatch
2794 * 2.5.13.33 keywordMatch
2795 * 2.5.13.36 certificatePairExactMatch
2796 * 2.5.13.37 certificatePairMatch
2797 * 2.5.13.38 certificateListExactMatch
2798 * 2.5.13.39 certificateListMatch
2799 * 2.5.13.40 algorithmIdentifierMatch
2800 * 2.5.13.41 storedPrefixMatch
2801 * 2.5.13.42 attributeCertificateMatch
2802 * 2.5.13.43 readerAndKeyIDMatch
2803 * 2.5.13.44 attributeIntegrityMatch
2805 static slap_mrule_defs_rec mrule_defs[] = {
2807 * EQUALITY matching rules must be listed after associated APPROX
2808 * matching rules. So, we list all APPROX matching rules first.
2810 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2811 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2812 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2813 NULL, NULL, directoryStringApproxMatch,
2814 directoryStringApproxIndexer, directoryStringApproxFilter,
2817 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2818 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2819 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2820 NULL, NULL, IA5StringApproxMatch,
2821 IA5StringApproxIndexer, IA5StringApproxFilter,
2825 * Other matching rules
2828 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2829 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2830 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2831 NULL, NULL, octetStringMatch,
2832 octetStringIndexer, octetStringFilter,
2835 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2836 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2837 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2838 NULL, dnNormalize, dnMatch,
2839 octetStringIndexer, octetStringFilter,
2842 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2843 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2844 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2845 NULL, UTF8StringNormalize, octetStringMatch,
2846 octetStringIndexer, octetStringFilter,
2847 directoryStringApproxMatchOID },
2849 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2850 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2851 SLAP_MR_ORDERING, directoryStringSyntaxes,
2852 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2854 "caseIgnoreMatch" },
2856 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2857 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2858 SLAP_MR_SUBSTR, NULL,
2859 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2860 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2861 "caseIgnoreMatch" },
2863 {"( 2.5.13.5 NAME 'caseExactMatch' "
2864 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2865 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2866 NULL, UTF8StringNormalize, octetStringMatch,
2867 octetStringIndexer, octetStringFilter,
2868 directoryStringApproxMatchOID },
2870 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2871 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2872 SLAP_MR_ORDERING, directoryStringSyntaxes,
2873 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2877 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2878 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2879 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2880 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2881 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2884 {"( 2.5.13.8 NAME 'numericStringMatch' "
2885 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2886 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2887 NULL, numericStringNormalize, octetStringSubstringsMatch,
2888 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2891 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2893 SLAP_MR_SUBSTR, NULL,
2894 NULL, numericStringNormalize, octetStringSubstringsMatch,
2895 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2896 "numericStringMatch" },
2898 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2899 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2900 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2901 NULL, NULL, NULL, NULL, NULL, NULL },
2903 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2904 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2905 SLAP_MR_SUBSTR, NULL,
2906 NULL, NULL, NULL, NULL, NULL,
2907 "caseIgnoreListMatch" },
2909 {"( 2.5.13.13 NAME 'booleanMatch' "
2910 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2911 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2912 NULL, NULL, booleanMatch,
2913 octetStringIndexer, octetStringFilter,
2916 {"( 2.5.13.14 NAME 'integerMatch' "
2917 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2918 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2919 NULL, NULL, integerMatch,
2920 octetStringIndexer, octetStringFilter,
2923 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2924 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2925 SLAP_MR_ORDERING, NULL,
2926 NULL, NULL, integerMatch,
2930 {"( 2.5.13.16 NAME 'bitStringMatch' "
2931 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2932 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2933 NULL, NULL, octetStringMatch,
2934 octetStringIndexer, octetStringFilter,
2937 {"( 2.5.13.17 NAME 'octetStringMatch' "
2938 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2939 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2940 NULL, NULL, octetStringMatch,
2941 octetStringIndexer, octetStringFilter,
2944 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2945 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2946 SLAP_MR_ORDERING, NULL,
2947 NULL, NULL, octetStringOrderingMatch,
2949 "octetStringMatch" },
2951 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2952 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2953 SLAP_MR_SUBSTR, NULL,
2954 NULL, NULL, octetStringSubstringsMatch,
2955 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2956 "octetStringMatch" },
2958 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2959 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2960 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2962 telephoneNumberNormalize, octetStringMatch,
2963 octetStringIndexer, octetStringFilter,
2966 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2968 SLAP_MR_SUBSTR, NULL,
2969 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2970 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2971 "telephoneNumberMatch" },
2973 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2974 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2975 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2976 NULL, NULL, NULL, NULL, NULL, NULL },
2978 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2980 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2981 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2985 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2987 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2988 NULL, NULL, NULL, NULL, NULL, NULL },
2990 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2991 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2992 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2993 NULL, generalizedTimeNormalize, octetStringMatch,
2997 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2998 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2999 SLAP_MR_ORDERING, NULL,
3000 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3002 "generalizedTimeMatch" },
3004 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3005 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3006 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3007 integerFirstComponentMatchSyntaxes,
3008 NULL, firstComponentNormalize, integerMatch,
3009 octetStringIndexer, octetStringFilter,
3012 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3013 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3014 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3015 objectIdentifierFirstComponentMatchSyntaxes,
3016 NULL, firstComponentNormalize, octetStringMatch,
3017 octetStringIndexer, octetStringFilter,
3020 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3021 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3022 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3024 NULL, certificateExactNormalize, octetStringMatch,
3025 octetStringIndexer, octetStringFilter,
3027 NULL, NULL, NULL, NULL, NULL,
3031 {"( 2.5.13.35 NAME 'certificateMatch' "
3032 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3033 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3035 NULL, NULL, octetStringMatch,
3036 octetStringIndexer, octetStringFilter,
3038 NULL, NULL, NULL, NULL, NULL,
3042 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3043 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3044 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3045 NULL, IA5StringNormalize, octetStringMatch,
3046 octetStringIndexer, octetStringFilter,
3047 IA5StringApproxMatchOID },
3049 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3050 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3051 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3052 NULL, IA5StringNormalize, octetStringMatch,
3053 octetStringIndexer, octetStringFilter,
3054 IA5StringApproxMatchOID },
3056 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3057 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3058 SLAP_MR_SUBSTR, NULL,
3059 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3060 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3061 "caseIgnoreIA5Match" },
3063 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3064 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3065 SLAP_MR_SUBSTR, NULL,
3066 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3067 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3068 "caseExactIA5Match" },
3070 #ifdef SLAPD_AUTHPASSWD
3071 /* needs updating */
3072 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3073 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3074 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3075 NULL, NULL, authPasswordMatch,
3080 #ifdef SLAPD_ACI_ENABLED
3081 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3082 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3083 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3084 NULL, NULL, OpenLDAPaciMatch,
3089 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3090 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3092 NULL, NULL, integerBitAndMatch,
3096 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3097 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3099 NULL, NULL, integerBitOrMatch,
3103 {NULL, SLAP_MR_NONE, NULL,
3104 NULL, NULL, NULL, NULL, NULL,
3109 slap_schema_init( void )
3114 /* we should only be called once (from main) */
3115 assert( schema_init_done == 0 );
3117 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3118 res = register_syntax( &syntax_defs[i] );
3121 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3122 syntax_defs[i].sd_desc );
3127 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3128 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3129 mrule_defs[i].mrd_compat_syntaxes == NULL )
3132 "slap_schema_init: Ignoring unusable matching rule %s\n",
3133 mrule_defs[i].mrd_desc );
3137 res = register_matching_rule( &mrule_defs[i] );
3141 "slap_schema_init: Error registering matching rule %s\n",
3142 mrule_defs[i].mrd_desc );
3147 res = slap_schema_load();
3148 schema_init_done = 1;
3153 schema_destroy( void )