1 /* schema_init.c - init builtin schema */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2003 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
25 #include <ac/socket.h>
31 #include "ldap_utf8.h"
34 #include <openssl/x509.h>
35 #include <openssl/err.h>
36 #include <openssl/rsa.h>
37 #include <openssl/crypto.h>
38 #include <openssl/pem.h>
39 #include <openssl/bio.h>
40 #include <openssl/asn1.h>
41 #include <openssl/x509v3.h>
42 #include <openssl/ssl.h>
45 #include "lutil_hash.h"
46 #define HASH_BYTES LUTIL_HASH_BYTES
47 #define HASH_CONTEXT lutil_HASH_CTX
48 #define HASH_Init(c) lutil_HASHInit(c)
49 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
50 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
52 #define OpenLDAPaciMatch NULL
54 /* approx matching rules */
55 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
56 #define directoryStringApproxMatch approxMatch
57 #define directoryStringApproxIndexer approxIndexer
58 #define directoryStringApproxFilter approxFilter
59 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
60 #define IA5StringApproxMatch approxMatch
61 #define IA5StringApproxIndexer approxIndexer
62 #define IA5StringApproxFilter approxFilter
69 /* no value allowed */
70 return LDAP_INVALID_SYNTAX;
78 /* any value allowed */
82 #define berValidate blobValidate
89 if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
90 if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
97 static int certificateValidate( Syntax *syntax, struct berval *in )
100 unsigned char *p = in->bv_val;
102 xcert = d2i_X509(NULL, &p, in->bv_len);
103 if ( !xcert ) return LDAP_INVALID_SYNTAX;
108 #define certificateValidate sequenceValidate
117 struct berval *value,
118 void *assertedValue )
120 struct berval *asserted = (struct berval *) assertedValue;
121 int match = value->bv_len - asserted->bv_len;
124 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
132 octetStringOrderingMatch(
137 struct berval *value,
138 void *assertedValue )
140 struct berval *asserted = (struct berval *) assertedValue;
141 ber_len_t v_len = value->bv_len;
142 ber_len_t av_len = asserted->bv_len;
144 int match = memcmp( value->bv_val, asserted->bv_val,
145 (v_len < av_len ? v_len : av_len) );
147 if( match == 0 ) match = v_len - av_len;
153 /* Index generation function */
154 int octetStringIndexer(
159 struct berval *prefix,
167 HASH_CONTEXT HASHcontext;
168 unsigned char HASHdigest[HASH_BYTES];
169 struct berval digest;
170 digest.bv_val = HASHdigest;
171 digest.bv_len = sizeof(HASHdigest);
173 for( i=0; values[i].bv_val != NULL; i++ ) {
174 /* just count them */
177 /* we should have at least one value at this point */
180 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
182 slen = syntax->ssyn_oidlen;
183 mlen = mr->smr_oidlen;
185 for( i=0; values[i].bv_val != NULL; i++ ) {
186 HASH_Init( &HASHcontext );
187 if( prefix != NULL && prefix->bv_len > 0 ) {
188 HASH_Update( &HASHcontext,
189 prefix->bv_val, prefix->bv_len );
191 HASH_Update( &HASHcontext,
192 syntax->ssyn_oid, slen );
193 HASH_Update( &HASHcontext,
195 HASH_Update( &HASHcontext,
196 values[i].bv_val, values[i].bv_len );
197 HASH_Final( HASHdigest, &HASHcontext );
199 ber_dupbv_x( &keys[i], &digest, ctx );
202 keys[i].bv_val = NULL;
210 /* Index generation function */
211 int octetStringFilter(
216 struct berval *prefix,
217 void * assertedValue,
223 HASH_CONTEXT HASHcontext;
224 unsigned char HASHdigest[HASH_BYTES];
225 struct berval *value = (struct berval *) assertedValue;
226 struct berval digest;
227 digest.bv_val = HASHdigest;
228 digest.bv_len = sizeof(HASHdigest);
230 slen = syntax->ssyn_oidlen;
231 mlen = mr->smr_oidlen;
233 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
235 HASH_Init( &HASHcontext );
236 if( prefix != NULL && prefix->bv_len > 0 ) {
237 HASH_Update( &HASHcontext,
238 prefix->bv_val, prefix->bv_len );
240 HASH_Update( &HASHcontext,
241 syntax->ssyn_oid, slen );
242 HASH_Update( &HASHcontext,
244 HASH_Update( &HASHcontext,
245 value->bv_val, value->bv_len );
246 HASH_Final( HASHdigest, &HASHcontext );
248 ber_dupbv_x( keys, &digest, ctx );
249 keys[1].bv_val = NULL;
258 octetStringSubstringsMatch(
263 struct berval *value,
264 void *assertedValue )
267 SubstringsAssertion *sub = assertedValue;
268 struct berval left = *value;
272 /* Add up asserted input length */
273 if( sub->sa_initial.bv_val ) {
274 inlen += sub->sa_initial.bv_len;
277 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
278 inlen += sub->sa_any[i].bv_len;
281 if( sub->sa_final.bv_val ) {
282 inlen += sub->sa_final.bv_len;
285 if( sub->sa_initial.bv_val ) {
286 if( inlen > left.bv_len ) {
291 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
292 sub->sa_initial.bv_len );
298 left.bv_val += sub->sa_initial.bv_len;
299 left.bv_len -= sub->sa_initial.bv_len;
300 inlen -= sub->sa_initial.bv_len;
303 if( sub->sa_final.bv_val ) {
304 if( inlen > left.bv_len ) {
309 match = memcmp( sub->sa_final.bv_val,
310 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
311 sub->sa_final.bv_len );
317 left.bv_len -= sub->sa_final.bv_len;
318 inlen -= sub->sa_final.bv_len;
322 for(i=0; sub->sa_any[i].bv_val; i++) {
327 if( inlen > left.bv_len ) {
328 /* not enough length */
333 if( sub->sa_any[i].bv_len == 0 ) {
337 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
344 idx = p - left.bv_val;
346 if( idx >= left.bv_len ) {
347 /* this shouldn't happen */
354 if( sub->sa_any[i].bv_len > left.bv_len ) {
355 /* not enough left */
360 match = memcmp( left.bv_val,
361 sub->sa_any[i].bv_val,
362 sub->sa_any[i].bv_len );
370 left.bv_val += sub->sa_any[i].bv_len;
371 left.bv_len -= sub->sa_any[i].bv_len;
372 inlen -= sub->sa_any[i].bv_len;
381 /* Substrings Index generation function */
383 octetStringSubstringsIndexer(
388 struct berval *prefix,
393 ber_len_t i, j, nkeys;
397 HASH_CONTEXT HASHcontext;
398 unsigned char HASHdigest[HASH_BYTES];
399 struct berval digest;
400 digest.bv_val = HASHdigest;
401 digest.bv_len = sizeof(HASHdigest);
405 for( i=0; values[i].bv_val != NULL; i++ ) {
406 /* count number of indices to generate */
407 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
411 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
412 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
413 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
414 (SLAP_INDEX_SUBSTR_MINLEN - 1);
416 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
420 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
421 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
422 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
426 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
427 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
428 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
429 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
431 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
437 /* no keys to generate */
442 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
444 slen = syntax->ssyn_oidlen;
445 mlen = mr->smr_oidlen;
448 for( i=0; values[i].bv_val != NULL; i++ ) {
451 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
453 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
454 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
456 char pre = SLAP_INDEX_SUBSTR_PREFIX;
457 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
459 for( j=0; j<max; j++ ) {
460 HASH_Init( &HASHcontext );
461 if( prefix != NULL && prefix->bv_len > 0 ) {
462 HASH_Update( &HASHcontext,
463 prefix->bv_val, prefix->bv_len );
466 HASH_Update( &HASHcontext,
467 &pre, sizeof( pre ) );
468 HASH_Update( &HASHcontext,
469 syntax->ssyn_oid, slen );
470 HASH_Update( &HASHcontext,
472 HASH_Update( &HASHcontext,
473 &values[i].bv_val[j],
474 SLAP_INDEX_SUBSTR_MAXLEN );
475 HASH_Final( HASHdigest, &HASHcontext );
477 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
481 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
482 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
484 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
487 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
488 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
489 HASH_Init( &HASHcontext );
490 if( prefix != NULL && prefix->bv_len > 0 ) {
491 HASH_Update( &HASHcontext,
492 prefix->bv_val, prefix->bv_len );
494 HASH_Update( &HASHcontext,
495 &pre, sizeof( pre ) );
496 HASH_Update( &HASHcontext,
497 syntax->ssyn_oid, slen );
498 HASH_Update( &HASHcontext,
500 HASH_Update( &HASHcontext,
501 values[i].bv_val, j );
502 HASH_Final( HASHdigest, &HASHcontext );
504 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
507 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
508 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
509 HASH_Init( &HASHcontext );
510 if( prefix != NULL && prefix->bv_len > 0 ) {
511 HASH_Update( &HASHcontext,
512 prefix->bv_val, prefix->bv_len );
514 HASH_Update( &HASHcontext,
515 &pre, sizeof( pre ) );
516 HASH_Update( &HASHcontext,
517 syntax->ssyn_oid, slen );
518 HASH_Update( &HASHcontext,
520 HASH_Update( &HASHcontext,
521 &values[i].bv_val[values[i].bv_len-j], j );
522 HASH_Final( HASHdigest, &HASHcontext );
524 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
532 keys[nkeys].bv_val = NULL;
543 octetStringSubstringsFilter (
548 struct berval *prefix,
549 void * assertedValue,
553 SubstringsAssertion *sa;
556 size_t slen, mlen, klen;
558 HASH_CONTEXT HASHcontext;
559 unsigned char HASHdigest[HASH_BYTES];
560 struct berval *value;
561 struct berval digest;
563 sa = (SubstringsAssertion *) assertedValue;
565 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
566 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
571 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
573 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
574 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
575 /* don't bother accounting for stepping */
576 nkeys += sa->sa_any[i].bv_len -
577 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
582 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
583 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
593 digest.bv_val = HASHdigest;
594 digest.bv_len = sizeof(HASHdigest);
596 slen = syntax->ssyn_oidlen;
597 mlen = mr->smr_oidlen;
599 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
602 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
603 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
605 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
606 value = &sa->sa_initial;
608 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
609 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
611 HASH_Init( &HASHcontext );
612 if( prefix != NULL && prefix->bv_len > 0 ) {
613 HASH_Update( &HASHcontext,
614 prefix->bv_val, prefix->bv_len );
616 HASH_Update( &HASHcontext,
617 &pre, sizeof( pre ) );
618 HASH_Update( &HASHcontext,
619 syntax->ssyn_oid, slen );
620 HASH_Update( &HASHcontext,
622 HASH_Update( &HASHcontext,
623 value->bv_val, klen );
624 HASH_Final( HASHdigest, &HASHcontext );
626 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
629 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
631 pre = SLAP_INDEX_SUBSTR_PREFIX;
632 klen = SLAP_INDEX_SUBSTR_MAXLEN;
634 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
635 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
639 value = &sa->sa_any[i];
642 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
643 j += SLAP_INDEX_SUBSTR_STEP )
645 HASH_Init( &HASHcontext );
646 if( prefix != NULL && prefix->bv_len > 0 ) {
647 HASH_Update( &HASHcontext,
648 prefix->bv_val, prefix->bv_len );
650 HASH_Update( &HASHcontext,
651 &pre, sizeof( pre ) );
652 HASH_Update( &HASHcontext,
653 syntax->ssyn_oid, slen );
654 HASH_Update( &HASHcontext,
656 HASH_Update( &HASHcontext,
657 &value->bv_val[j], klen );
658 HASH_Final( HASHdigest, &HASHcontext );
660 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
665 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
666 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
668 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
669 value = &sa->sa_final;
671 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
672 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
674 HASH_Init( &HASHcontext );
675 if( prefix != NULL && prefix->bv_len > 0 ) {
676 HASH_Update( &HASHcontext,
677 prefix->bv_val, prefix->bv_len );
679 HASH_Update( &HASHcontext,
680 &pre, sizeof( pre ) );
681 HASH_Update( &HASHcontext,
682 syntax->ssyn_oid, slen );
683 HASH_Update( &HASHcontext,
685 HASH_Update( &HASHcontext,
686 &value->bv_val[value->bv_len-klen], klen );
687 HASH_Final( HASHdigest, &HASHcontext );
689 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
693 keys[nkeys].bv_val = NULL;
710 /* very unforgiving validation, requires no normalization
711 * before simplistic matching
713 if( in->bv_len < 3 ) {
714 return LDAP_INVALID_SYNTAX;
718 * RFC 2252 section 6.3 Bit String
719 * bitstring = "'" *binary-digit "'B"
720 * binary-digit = "0" / "1"
721 * example: '0101111101'B
724 if( in->bv_val[0] != '\'' ||
725 in->bv_val[in->bv_len-2] != '\'' ||
726 in->bv_val[in->bv_len-1] != 'B' )
728 return LDAP_INVALID_SYNTAX;
731 for( i=in->bv_len-3; i>0; i-- ) {
732 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
733 return LDAP_INVALID_SYNTAX;
748 if( in->bv_len == 0 ) return LDAP_SUCCESS;
750 ber_dupbv( &dn, in );
751 if( !dn.bv_val ) return LDAP_OTHER;
753 if( dn.bv_val[dn.bv_len-1] == 'B'
754 && dn.bv_val[dn.bv_len-2] == '\'' )
756 /* assume presence of optional UID */
759 for(i=dn.bv_len-3; i>1; i--) {
760 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
764 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
765 ber_memfree( dn.bv_val );
766 return LDAP_INVALID_SYNTAX;
769 /* trim the UID to allow use of dnValidate */
770 dn.bv_val[i-1] = '\0';
774 rc = dnValidate( NULL, &dn );
776 ber_memfree( dn.bv_val );
792 LDAP_LOG( OPERATION, ARGS, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
794 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
797 if( val->bv_len == 0 ) {
798 ber_dupbv_x( out, val, ctx );
800 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
801 return LDAP_INVALID_SYNTAX;
805 struct berval dnval = *val;
806 struct berval uidval = { 0, NULL };
808 if( val->bv_val[val->bv_len-1] == 'B'
809 && val->bv_val[val->bv_len-2] == '\'' )
811 uidval.bv_val=strrchr( val->bv_val, '#' );
812 if( uidval.bv_val ) {
813 dnval.bv_len = uidval.bv_val - dnval.bv_val;
814 uidval.bv_len = val->bv_len - dnval.bv_len;
821 rc = dnPretty( syntax, &dnval, out, ctx );
822 if( rc != LDAP_SUCCESS ) return rc;
824 if( uidval.bv_val ) {
825 char *tmp = sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx );
828 ber_memfree_x( out->bv_val, ctx );
832 out->bv_val[out->bv_len++] = '#';
834 got1 = uidval.bv_len < sizeof("'0'B");
835 for(i=0; i<uidval.bv_len; i++) {
836 c = uidval.bv_val[i];
839 if( got1 ) out->bv_val[out->bv_len++] = c;
844 out->bv_val[out->bv_len++] = c;
848 out->bv_val[out->bv_len] = '\0';
853 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
855 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
862 uniqueMemberNormalize(
867 struct berval *normalized,
873 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
875 ber_dupbv( &out, val );
876 if( out.bv_len != 0 ) {
877 struct berval uid = { 0, NULL };
879 if( out.bv_val[out.bv_len-1] == 'B'
880 && out.bv_val[out.bv_len-2] == '\'' )
882 /* assume presence of optional UID */
883 uid.bv_val = strrchr( out.bv_val, '#' );
885 if( uid.bv_val == NULL ) {
887 return LDAP_INVALID_SYNTAX;
890 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
891 out.bv_len -= uid.bv_len--;
893 /* temporarily trim the UID */
894 *(uid.bv_val++) = '\0';
897 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
899 if( rc != LDAP_SUCCESS ) {
901 return LDAP_INVALID_SYNTAX;
905 normalized->bv_val = ch_realloc( normalized->bv_val,
906 normalized->bv_len + uid.bv_len + sizeof("#") );
908 /* insert the separator */
909 normalized->bv_val[normalized->bv_len++] = '#';
912 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
913 uid.bv_val, uid.bv_len );
914 normalized->bv_len += uid.bv_len;
917 normalized->bv_val[normalized->bv_len] = '\0';
932 struct berval *value,
933 void *assertedValue )
936 struct berval *asserted = (struct berval *) assertedValue;
937 struct berval assertedDN = { 0, NULL };
938 struct berval assertedUID = { 0, NULL };
939 struct berval valueDN = { 0, NULL };
940 struct berval valueUID = { 0, NULL };
942 if( asserted->bv_len != 0 ) {
943 assertedDN = *asserted;
945 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
946 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
948 /* assume presence of optional UID */
949 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
951 if( assertedUID.bv_val == NULL ) {
952 return LDAP_INVALID_SYNTAX;
955 assertedUID.bv_len = assertedDN.bv_len -
956 (assertedUID.bv_val - assertedDN.bv_val);
957 assertedDN.bv_len -= assertedUID.bv_len--;
959 /* trim the separator */
960 assertedUID.bv_val++;
964 if( value->bv_len != 0 ) {
967 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
968 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
970 /* assume presence of optional UID */
971 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
973 if( valueUID.bv_val == NULL ) {
974 return LDAP_INVALID_SYNTAX;
977 valueUID.bv_len = valueDN.bv_len -
978 (assertedUID.bv_val - assertedDN.bv_val);
979 valueDN.bv_len -= valueUID.bv_len--;
981 /* trim the separator */
986 if( valueUID.bv_len && assertedUID.bv_len ) {
987 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
994 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
998 * Handling boolean syntax and matching is quite rigid.
999 * A more flexible approach would be to allow a variety
1000 * of strings to be normalized and prettied into TRUE
1008 /* very unforgiving validation, requires no normalization
1009 * before simplistic matching
1012 if( in->bv_len == 4 ) {
1013 if( bvmatch( in, &slap_true_bv ) ) {
1014 return LDAP_SUCCESS;
1016 } else if( in->bv_len == 5 ) {
1017 if( bvmatch( in, &slap_false_bv ) ) {
1018 return LDAP_SUCCESS;
1022 return LDAP_INVALID_SYNTAX;
1031 struct berval *value,
1032 void *assertedValue )
1034 /* simplistic matching allowed by rigid validation */
1035 struct berval *asserted = (struct berval *) assertedValue;
1036 *matchp = value->bv_len != asserted->bv_len;
1037 return LDAP_SUCCESS;
1040 /*-------------------------------------------------------------------
1041 LDAP/X.500 string syntax / matching rules have a few oddities. This
1042 comment attempts to detail how slapd(8) treats them.
1045 StringSyntax X.500 LDAP Matching/Comments
1046 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
1047 PrintableString subset subset i/e + ignore insignificant spaces
1048 PrintableString subset subset i/e + ignore insignificant spaces
1049 NumericString subset subset ignore all spaces
1050 IA5String ASCII ASCII i/e + ignore insignificant spaces
1051 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1053 TelephoneNumber subset subset i + ignore all spaces and "-"
1055 See draft-ietf-ldapbis-strpro for details (once published).
1059 In X.500(93), a directory string can be either a PrintableString,
1060 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1061 In later versions, more CHOICEs were added. In all cases the string
1064 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1065 A directory string cannot be zero length.
1067 For matching, there are both case ignore and exact rules. Both
1068 also require that "insignificant" spaces be ignored.
1069 spaces before the first non-space are ignored;
1070 spaces after the last non-space are ignored;
1071 spaces after a space are ignored.
1072 Note: by these rules (and as clarified in X.520), a string of only
1073 spaces is to be treated as if held one space, not empty (which
1074 would be a syntax error).
1077 In ASN.1, numeric string is just a string of digits and spaces
1078 and could be empty. However, in X.500, all attribute values of
1079 numeric string carry a non-empty constraint. For example:
1081 internationalISDNNumber ATTRIBUTE ::= {
1082 WITH SYNTAX InternationalISDNNumber
1083 EQUALITY MATCHING RULE numericStringMatch
1084 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1085 ID id-at-internationalISDNNumber }
1086 InternationalISDNNumber ::=
1087 NumericString (SIZE(1..ub-international-isdn-number))
1089 Unforunately, some assertion values are don't carry the same
1090 constraint (but its unclear how such an assertion could ever
1091 be true). In LDAP, there is one syntax (numericString) not two
1092 (numericString with constraint, numericString without constraint).
1093 This should be treated as numericString with non-empty constraint.
1094 Note that while someone may have no ISDN number, there are no ISDN
1095 numbers which are zero length.
1097 In matching, spaces are ignored.
1100 In ASN.1, Printable string is just a string of printable characters
1101 and can be empty. In X.500, semantics much like NumericString (see
1102 serialNumber for a like example) excepting uses insignificant space
1103 handling instead of ignore all spaces.
1106 Basically same as PrintableString. There are no examples in X.500,
1107 but same logic applies. So we require them to be non-empty as
1110 -------------------------------------------------------------------*/
1119 unsigned char *u = in->bv_val;
1121 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1122 /* directory strings cannot be empty */
1123 return LDAP_INVALID_SYNTAX;
1126 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1127 /* get the length indicated by the first byte */
1128 len = LDAP_UTF8_CHARLEN2( u, len );
1130 /* very basic checks */
1133 if( (u[5] & 0xC0) != 0x80 ) {
1134 return LDAP_INVALID_SYNTAX;
1137 if( (u[4] & 0xC0) != 0x80 ) {
1138 return LDAP_INVALID_SYNTAX;
1141 if( (u[3] & 0xC0) != 0x80 ) {
1142 return LDAP_INVALID_SYNTAX;
1145 if( (u[2] & 0xC0 )!= 0x80 ) {
1146 return LDAP_INVALID_SYNTAX;
1149 if( (u[1] & 0xC0) != 0x80 ) {
1150 return LDAP_INVALID_SYNTAX;
1153 /* CHARLEN already validated it */
1156 return LDAP_INVALID_SYNTAX;
1159 /* make sure len corresponds with the offset
1160 to the next character */
1161 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
1165 return LDAP_INVALID_SYNTAX;
1168 return LDAP_SUCCESS;
1172 UTF8StringNormalize(
1177 struct berval *normalized,
1180 struct berval tmp, nvalue;
1184 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1186 if( val->bv_val == NULL ) {
1187 /* assume we're dealing with a syntax (e.g., UTF8String)
1188 * which allows empty strings
1190 normalized->bv_len = 0;
1191 normalized->bv_val = NULL;
1192 return LDAP_SUCCESS;
1195 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1196 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1197 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1198 ? LDAP_UTF8_APPROX : 0;
1200 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1205 /* collapse spaces (in place) */
1207 nvalue.bv_val = tmp.bv_val;
1209 wasspace=1; /* trim leading spaces */
1210 for( i=0; i<tmp.bv_len; i++) {
1211 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1212 if( wasspace++ == 0 ) {
1213 /* trim repeated spaces */
1214 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1218 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1222 if( nvalue.bv_len ) {
1224 /* last character was a space, trim it */
1227 nvalue.bv_val[nvalue.bv_len] = '\0';
1230 /* string of all spaces is treated as one space */
1231 nvalue.bv_val[0] = ' ';
1232 nvalue.bv_val[1] = '\0';
1236 *normalized = nvalue;
1237 return LDAP_SUCCESS;
1240 #if defined(SLAPD_APPROX_INITIALS)
1241 # define SLAPD_APPROX_DELIMITER "._ "
1242 # define SLAPD_APPROX_WORDLEN 2
1244 # define SLAPD_APPROX_DELIMITER " "
1245 # define SLAPD_APPROX_WORDLEN 1
1254 struct berval *value,
1255 void *assertedValue )
1257 struct berval *nval, *assertv;
1258 char *val, **values, **words, *c;
1259 int i, count, len, nextchunk=0, nextavail=0;
1261 /* Yes, this is necessary */
1262 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1263 if( nval == NULL ) {
1265 return LDAP_SUCCESS;
1268 /* Yes, this is necessary */
1269 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1270 NULL, LDAP_UTF8_APPROX, NULL );
1271 if( assertv == NULL ) {
1274 return LDAP_SUCCESS;
1277 /* Isolate how many words there are */
1278 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1279 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1280 if ( c == NULL ) break;
1285 /* Get a phonetic copy of each word */
1286 words = (char **)ch_malloc( count * sizeof(char *) );
1287 values = (char **)ch_malloc( count * sizeof(char *) );
1288 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1290 values[i] = phonetic(c);
1293 /* Work through the asserted value's words, to see if at least some
1294 of the words are there, in the same order. */
1296 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1297 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1302 #if defined(SLAPD_APPROX_INITIALS)
1303 else if( len == 1 ) {
1304 /* Single letter words need to at least match one word's initial */
1305 for( i=nextavail; i<count; i++ )
1306 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1313 /* Isolate the next word in the asserted value and phonetic it */
1314 assertv->bv_val[nextchunk+len] = '\0';
1315 val = phonetic( assertv->bv_val + nextchunk );
1317 /* See if this phonetic chunk is in the remaining words of *value */
1318 for( i=nextavail; i<count; i++ ){
1319 if( !strcmp( val, values[i] ) ){
1327 /* This chunk in the asserted value was NOT within the *value. */
1333 /* Go on to the next word in the asserted value */
1337 /* If some of the words were seen, call it a match */
1338 if( nextavail > 0 ) {
1345 /* Cleanup allocs */
1346 ber_bvfree( assertv );
1347 for( i=0; i<count; i++ ) {
1348 ch_free( values[i] );
1354 return LDAP_SUCCESS;
1363 struct berval *prefix,
1369 int i,j, len, wordcount, keycount=0;
1370 struct berval *newkeys;
1371 BerVarray keys=NULL;
1373 for( j=0; values[j].bv_val != NULL; j++ ) {
1374 struct berval val = { 0, NULL };
1375 /* Yes, this is necessary */
1376 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1377 assert( val.bv_val != NULL );
1379 /* Isolate how many words there are. There will be a key for each */
1380 for( wordcount = 0, c = val.bv_val; *c; c++) {
1381 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1382 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1384 if (*c == '\0') break;
1388 /* Allocate/increase storage to account for new keys */
1389 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1390 * sizeof(struct berval) );
1391 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1392 if( keys ) ch_free( keys );
1395 /* Get a phonetic copy of each word */
1396 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1398 if( len < SLAPD_APPROX_WORDLEN ) continue;
1399 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1404 ber_memfree( val.bv_val );
1406 keys[keycount].bv_val = NULL;
1409 return LDAP_SUCCESS;
1418 struct berval *prefix,
1419 void * assertedValue,
1428 /* Yes, this is necessary */
1429 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1430 NULL, LDAP_UTF8_APPROX, NULL );
1431 if( val == NULL || val->bv_val == NULL ) {
1432 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1433 keys[0].bv_val = NULL;
1436 return LDAP_SUCCESS;
1439 /* Isolate how many words there are. There will be a key for each */
1440 for( count = 0,c = val->bv_val; *c; c++) {
1441 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1442 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1444 if (*c == '\0') break;
1448 /* Allocate storage for new keys */
1449 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1451 /* Get a phonetic copy of each word */
1452 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1454 if( len < SLAPD_APPROX_WORDLEN ) continue;
1455 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1461 keys[count].bv_val = NULL;
1464 return LDAP_SUCCESS;
1467 /* Remove all spaces and '-' characters */
1469 telephoneNumberNormalize(
1474 struct berval *normalized,
1479 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ));
1481 /* validator should have refused an empty string */
1482 assert( val->bv_len );
1484 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1486 for( p = val->bv_val; *p; p++ ) {
1487 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1493 normalized->bv_len = q - normalized->bv_val;
1495 if( normalized->bv_len == 0 ) {
1496 sl_free( normalized->bv_val, ctx );
1497 normalized->bv_val = NULL;
1498 return LDAP_INVALID_SYNTAX;
1501 return LDAP_SUCCESS;
1509 struct berval val = *in;
1511 if( val.bv_len == 0 ) {
1512 /* disallow empty strings */
1513 return LDAP_INVALID_SYNTAX;
1516 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1517 if ( val.bv_len == 1 ) {
1518 return LDAP_SUCCESS;
1521 if ( val.bv_val[0] == '0' ) {
1528 while ( OID_LEADCHAR( val.bv_val[0] )) {
1532 if ( val.bv_len == 0 ) {
1533 return LDAP_SUCCESS;
1537 if( !OID_SEPARATOR( val.bv_val[0] )) {
1545 return LDAP_INVALID_SYNTAX;
1554 struct berval val = *in;
1556 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1558 if ( val.bv_val[0] == '-' ) {
1562 if( val.bv_len == 0 ) { /* bare "-" */
1563 return LDAP_INVALID_SYNTAX;
1566 if( val.bv_val[0] == '0' ) { /* "-0" */
1567 return LDAP_INVALID_SYNTAX;
1570 } else if ( val.bv_val[0] == '0' ) {
1571 if( val.bv_len > 1 ) { /* "0<more>" */
1572 return LDAP_INVALID_SYNTAX;
1575 return LDAP_SUCCESS;
1578 for( i=0; i < val.bv_len; i++ ) {
1579 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1580 return LDAP_INVALID_SYNTAX;
1584 return LDAP_SUCCESS;
1593 struct berval *value,
1594 void *assertedValue )
1596 struct berval *asserted = (struct berval *) assertedValue;
1597 int vsign = 1, asign = 1; /* default sign = '+' */
1602 if( v.bv_val[0] == '-' ) {
1608 if( v.bv_len == 0 ) vsign = 0;
1611 if( a.bv_val[0] == '-' ) {
1617 if( a.bv_len == 0 ) vsign = 0;
1619 match = vsign - asign;
1621 match = ( v.bv_len != a.bv_len
1622 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1623 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1624 if( vsign < 0 ) match = -match;
1628 return LDAP_SUCCESS;
1632 countryStringValidate(
1634 struct berval *val )
1636 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1638 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1639 return LDAP_INVALID_SYNTAX;
1641 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1642 return LDAP_INVALID_SYNTAX;
1645 return LDAP_SUCCESS;
1649 printableStringValidate(
1651 struct berval *val )
1655 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1657 for(i=0; i < val->bv_len; i++) {
1658 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1659 return LDAP_INVALID_SYNTAX;
1663 return LDAP_SUCCESS;
1667 printablesStringValidate(
1669 struct berval *val )
1673 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1675 for(i=0,len=0; i < val->bv_len; i++) {
1676 int c = val->bv_val[i];
1680 return LDAP_INVALID_SYNTAX;
1684 } else if ( SLAP_PRINTABLE(c) ) {
1687 return LDAP_INVALID_SYNTAX;
1692 return LDAP_INVALID_SYNTAX;
1695 return LDAP_SUCCESS;
1701 struct berval *val )
1705 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1707 for(i=0; i < val->bv_len; i++) {
1708 if( !LDAP_ASCII(val->bv_val[i]) ) {
1709 return LDAP_INVALID_SYNTAX;
1713 return LDAP_SUCCESS;
1722 struct berval *normalized,
1726 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1728 assert( val->bv_len );
1730 assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ));
1734 /* Ignore initial whitespace */
1735 while ( ASCII_SPACE( *p ) ) p++;
1737 normalized->bv_val = ber_strdup_x( p, ctx );
1738 p = q = normalized->bv_val;
1741 if ( ASCII_SPACE( *p ) ) {
1744 /* Ignore the extra whitespace */
1745 while ( ASCII_SPACE( *p ) ) {
1749 } else if ( casefold ) {
1750 /* Most IA5 rules require casefolding */
1751 *q++ = TOLOWER(*p++);
1758 assert( normalized->bv_val <= p );
1762 * If the string ended in space, backup the pointer one
1763 * position. One is enough because the above loop collapsed
1764 * all whitespace to a single space.
1766 if ( ASCII_SPACE( q[-1] ) ) --q;
1768 /* null terminate */
1771 normalized->bv_len = q - normalized->bv_val;
1772 if( normalized->bv_len == 0 ) {
1773 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1774 normalized->bv_val[0] = ' ';
1775 normalized->bv_val[1] = '\0';
1776 normalized->bv_len = 1;
1779 return LDAP_SUCCESS;
1788 if( in->bv_len != 36 ) {
1790 return LDAP_INVALID_SYNTAX;
1793 for( i=0; i<36; i++ ) {
1799 if( in->bv_val[i] != '-' ) {
1800 return LDAP_INVALID_SYNTAX;
1804 if( !ASCII_HEX( in->bv_val[i]) ) {
1805 return LDAP_INVALID_SYNTAX;
1810 return LDAP_SUCCESS;
1819 struct berval *normalized,
1822 unsigned char octet;
1825 normalized->bv_len = 16;
1826 normalized->bv_val = sl_malloc( normalized->bv_len+1, ctx );
1828 for( i=0, j=0; i<36; i++ ) {
1829 unsigned char nibble;
1830 if( val->bv_val[i] == '-' ) {
1833 } else if( ASCII_DIGIT( val->bv_val[i] ) ) {
1834 nibble = val->bv_val[i] - '0';
1836 } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
1837 nibble = val->bv_val[i] - ('a'-10);
1839 } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
1840 nibble = val->bv_val[i] - ('A'-10);
1843 sl_free( normalized->bv_val, ctx );
1844 return LDAP_INVALID_SYNTAX;
1849 normalized->bv_val[j>>1] = octet;
1851 octet = nibble << 4;
1856 normalized->bv_val[normalized->bv_len] = 0;
1857 return LDAP_SUCCESS;
1863 numericStringValidate(
1869 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1871 for(i=0; i < in->bv_len; i++) {
1872 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1873 return LDAP_INVALID_SYNTAX;
1877 return LDAP_SUCCESS;
1881 numericStringNormalize(
1886 struct berval *normalized,
1889 /* removal all spaces */
1892 assert( val->bv_len );
1894 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1897 q = normalized->bv_val;
1900 if ( ASCII_SPACE( *p ) ) {
1901 /* Ignore whitespace */
1908 /* we should have copied no more then is in val */
1909 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1911 /* null terminate */
1914 normalized->bv_len = q - normalized->bv_val;
1916 if( normalized->bv_len == 0 ) {
1917 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1918 normalized->bv_val[0] = ' ';
1919 normalized->bv_val[1] = '\0';
1920 normalized->bv_len = 1;
1923 return LDAP_SUCCESS;
1927 * Integer conversion macros that will use the largest available
1930 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1931 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1932 # define SLAP_LONG_MAX LLONG_MAX
1933 # define SLAP_LONG_MIN LLONG_MIN
1934 # define SLAP_LONG long long
1936 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1937 # define SLAP_LONG_MAX LONG_MAX
1938 # define SLAP_LONG_MIN LONG_MIN
1939 # define SLAP_LONG long
1940 #endif /* HAVE_STRTOLL ... */
1948 struct berval *value,
1949 void *assertedValue )
1951 SLAP_LONG lValue, lAssertedValue;
1953 /* safe to assume integers are NUL terminated? */
1954 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1955 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
1956 return LDAP_CONSTRAINT_VIOLATION;
1959 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1960 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1961 && errno == ERANGE )
1963 return LDAP_CONSTRAINT_VIOLATION;
1966 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1967 return LDAP_SUCCESS;
1976 struct berval *value,
1977 void *assertedValue )
1979 SLAP_LONG lValue, lAssertedValue;
1981 /* safe to assume integers are NUL terminated? */
1982 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1983 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && errno == ERANGE ) {
1984 return LDAP_CONSTRAINT_VIOLATION;
1987 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1988 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1989 && errno == ERANGE )
1991 return LDAP_CONSTRAINT_VIOLATION;
1994 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1995 return LDAP_SUCCESS;
1999 serialNumberAndIssuerValidate(
2006 struct berval sn, i;
2007 if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2009 i.bv_val = strchr( in->bv_val, '$' );
2010 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2012 sn.bv_val = in->bv_val;
2013 sn.bv_len = i.bv_val - in->bv_val;
2016 i.bv_len = in->bv_len - (sn.bv_len + 1);
2018 /* validate serial number (strict for now) */
2019 for( n=0; n < sn.bv_len; n++ ) {
2020 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2021 return LDAP_INVALID_SYNTAX;
2026 rc = dnValidate( NULL, &i );
2027 if( rc ) return LDAP_INVALID_SYNTAX;
2029 return LDAP_SUCCESS;
2033 serialNumberAndIssuerPretty(
2042 struct berval sn, i, newi;
2048 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n",
2049 val->bv_val, 0, 0 );
2051 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
2052 val->bv_val, 0, 0 );
2055 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2057 i.bv_val = strchr( val->bv_val, '$' );
2058 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2060 sn.bv_val = val->bv_val;
2061 sn.bv_len = i.bv_val - val->bv_val;
2064 i.bv_len = val->bv_len - (sn.bv_len + 1);
2066 /* eat leading zeros */
2067 for( n=0; n < (sn.bv_len-1); n++ ) {
2068 if( sn.bv_val[n] != '0' ) break;
2073 for( n=0; n < sn.bv_len; n++ ) {
2074 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2075 return LDAP_INVALID_SYNTAX;
2080 rc = dnPretty( syntax, &i, &newi, ctx );
2081 if( rc ) return LDAP_INVALID_SYNTAX;
2083 /* make room from sn + "$" */
2084 out->bv_len = sn.bv_len + newi.bv_len + 1;
2085 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2087 if( out->bv_val == NULL ) {
2088 sl_free( newi.bv_val, ctx );
2092 /* push issuer over */
2093 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2094 /* insert sn and "$" */
2095 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2096 out->bv_val[sn.bv_len] = '$';
2098 out->bv_val[out->bv_len] = '\0';
2101 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n",
2102 out->bv_val, 0, 0 );
2104 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n",
2105 out->bv_val, 0, 0 );
2108 return LDAP_SUCCESS;
2112 * This routine is called by certificateExactNormalize when
2113 * certificateExactNormalize receives a search string instead of
2114 * a certificate. This routine checks if the search value is valid
2115 * and then returns the normalized value
2118 serialNumberAndIssuerNormalize(
2129 struct berval sn, i, newi;
2135 LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2136 val->bv_val, 0, 0 );
2138 Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
2139 val->bv_val, 0, 0 );
2142 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2144 i.bv_val = strchr( val->bv_val, '$' );
2145 if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX;
2147 sn.bv_val = val->bv_val;
2148 sn.bv_len = i.bv_val - val->bv_val;
2151 i.bv_len = val->bv_len - (sn.bv_len + 1);
2153 /* eat leading zeros */
2154 for( n=0; n < (sn.bv_len-1); n++ ) {
2155 if( sn.bv_val[n] != '0' ) break;
2160 for( n=0; n < sn.bv_len; n++ ) {
2161 if( !ASCII_DIGIT(sn.bv_val[n]) ) {
2162 return LDAP_INVALID_SYNTAX;
2167 rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx );
2168 if( rc ) return LDAP_INVALID_SYNTAX;
2170 /* make room from sn + "$" */
2171 out->bv_len = sn.bv_len + newi.bv_len + 1;
2172 out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx );
2174 if( out->bv_val == NULL ) {
2175 sl_free( newi.bv_val, ctx );
2179 /* push issuer over */
2180 AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len );
2181 /* insert sn and "$" */
2182 AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len );
2183 out->bv_val[sn.bv_len] = '$';
2185 out->bv_val[out->bv_len] = '\0';
2188 LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2189 out->bv_val, 0, 0 );
2191 Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n",
2192 out->bv_val, 0, 0 );
2200 certificateExactNormalize(
2205 struct berval *normalized,
2208 int rc = LDAP_INVALID_SYNTAX;
2210 char *serial = NULL;
2211 ber_len_t seriallen;
2212 struct berval issuer_dn = { 0, NULL };
2213 X509_NAME *name = NULL;
2214 ASN1_INTEGER *sn = NULL;
2217 if( val->bv_len == 0 ) goto done;
2219 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
2220 return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx);
2223 assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) );
2226 xcert = d2i_X509( NULL, &p, val->bv_len);
2227 if( xcert == NULL ) goto done;
2229 sn=X509_get_serialNumber(xcert);
2230 if ( sn == NULL ) goto done;
2231 serial=i2s_ASN1_INTEGER(0, sn );
2232 if( serial == NULL ) goto done;
2233 seriallen=strlen(serial);
2235 name=X509_get_issuer_name(xcert);
2236 if( name == NULL ) goto done;
2237 rc = dnX509normalize( name, &issuer_dn );
2238 if( rc != LDAP_SUCCESS ) goto done;
2240 normalized->bv_len = seriallen + issuer_dn.bv_len + 1;
2241 p = normalized->bv_val = ch_malloc(normalized->bv_len+1);
2242 AC_MEMCPY(p, serial, seriallen);
2245 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2246 p += issuer_dn.bv_len;
2250 LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n",
2251 normalized->bv_val, 0, 0 );
2253 Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n",
2254 normalized->bv_val, NULL, NULL );
2258 if (xcert) X509_free(xcert);
2259 if (serial) ch_free(serial);
2260 if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val);
2264 #endif /* HAVE_TLS */
2267 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2268 /* slight optimization - does not need the start parameter */
2269 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2274 check_time_syntax (struct berval *val,
2277 struct berval *fraction)
2280 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2281 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2282 * GeneralizedTime supports leap seconds, UTCTime does not.
2284 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2285 static const int mdays[2][12] = {
2286 /* non-leap years */
2287 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2289 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2292 int part, c, c1, c2, tzoffset, leapyear = 0;
2295 e = p + val->bv_len;
2297 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2298 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2300 for (part = start; part < 7 && p < e; part++) {
2302 if (!ASCII_DIGIT(c1)) {
2307 return LDAP_INVALID_SYNTAX;
2310 if (!ASCII_DIGIT(c)) {
2311 return LDAP_INVALID_SYNTAX;
2313 c += c1 * 10 - '0' * 11;
2314 if ((part | 1) == 3) {
2317 return LDAP_INVALID_SYNTAX;
2320 if (c >= ceiling[part]) {
2321 if (! (c == 60 && part == 6 && start == 0))
2322 return LDAP_INVALID_SYNTAX;
2326 if (part < 5 + start) {
2327 return LDAP_INVALID_SYNTAX;
2329 for (; part < 9; part++) {
2333 /* leapyear check for the Gregorian calendar (year>1581) */
2334 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2339 if (parts[3] >= mdays[leapyear][parts[2]]) {
2340 return LDAP_INVALID_SYNTAX;
2344 fraction->bv_val = p;
2345 fraction->bv_len = 0;
2346 if (p < e && (*p == '.' || *p == ',')) {
2348 while (++p < e && ASCII_DIGIT(*p))
2350 if (p - fraction->bv_val == 1) {
2351 return LDAP_INVALID_SYNTAX;
2353 for (end_num = p; end_num[-1] == '0'; --end_num)
2355 c = end_num - fraction->bv_val;
2357 fraction->bv_len = c;
2363 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2369 return LDAP_INVALID_SYNTAX;
2375 for (part = 7; part < 9 && p < e; part++) {
2377 if (!ASCII_DIGIT(c1)) {
2382 return LDAP_INVALID_SYNTAX;
2385 if (!ASCII_DIGIT(c2)) {
2386 return LDAP_INVALID_SYNTAX;
2388 parts[part] = c1 * 10 + c2 - '0' * 11;
2389 if (parts[part] >= ceiling[part]) {
2390 return LDAP_INVALID_SYNTAX;
2393 if (part < 8 + start) {
2394 return LDAP_INVALID_SYNTAX;
2397 if (tzoffset == '-') {
2398 /* negative offset to UTC, ie west of Greenwich */
2399 parts[4] += parts[7];
2400 parts[5] += parts[8];
2401 /* offset is just hhmm, no seconds */
2402 for (part = 6; --part >= 0; ) {
2406 c = mdays[leapyear][parts[2]];
2408 if (parts[part] >= c) {
2410 return LDAP_INVALID_SYNTAX;
2415 } else if (part != 5) {
2420 /* positive offset to UTC, ie east of Greenwich */
2421 parts[4] -= parts[7];
2422 parts[5] -= parts[8];
2423 for (part = 6; --part >= 0; ) {
2424 if (parts[part] < 0) {
2426 return LDAP_INVALID_SYNTAX;
2431 /* make first arg to % non-negative */
2432 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2437 } else if (part != 5) {
2444 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2447 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2454 struct berval *normalized )
2458 rc = check_time_syntax(val, 1, parts, NULL);
2459 if (rc != LDAP_SUCCESS) {
2463 normalized->bv_val = ch_malloc( 14 );
2464 if ( normalized->bv_val == NULL ) {
2465 return LBER_ERROR_MEMORY;
2468 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2469 parts[1], parts[2] + 1, parts[3] + 1,
2470 parts[4], parts[5], parts[6] );
2471 normalized->bv_len = 13;
2473 return LDAP_SUCCESS;
2483 return check_time_syntax(in, 1, parts, NULL);
2486 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2489 generalizedTimeValidate(
2494 struct berval fraction;
2495 return check_time_syntax(in, 0, parts, &fraction);
2499 generalizedTimeNormalize(
2504 struct berval *normalized,
2509 struct berval fraction;
2511 rc = check_time_syntax(val, 0, parts, &fraction);
2512 if (rc != LDAP_SUCCESS) {
2516 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2517 normalized->bv_val = sl_malloc( len + 1, ctx );
2518 if ( normalized->bv_val == NULL ) {
2519 return LBER_ERROR_MEMORY;
2522 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2523 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2524 parts[4], parts[5], parts[6] );
2525 if ( fraction.bv_len ) {
2526 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2527 fraction.bv_val, fraction.bv_len );
2528 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2530 strcpy( normalized->bv_val + len-1, "Z" );
2531 normalized->bv_len = len;
2533 return LDAP_SUCCESS;
2537 generalizedTimeOrderingMatch(
2542 struct berval *value,
2543 void *assertedValue )
2545 struct berval *asserted = (struct berval *) assertedValue;
2546 ber_len_t v_len = value->bv_len;
2547 ber_len_t av_len = asserted->bv_len;
2549 /* ignore trailing 'Z' when comparing */
2550 int match = memcmp( value->bv_val, asserted->bv_val,
2551 (v_len < av_len ? v_len : av_len) - 1 );
2552 if ( match == 0 ) match = v_len - av_len;
2555 return LDAP_SUCCESS;
2559 nisNetgroupTripleValidate(
2561 struct berval *val )
2566 if ( val->bv_len == 0 ) {
2567 return LDAP_INVALID_SYNTAX;
2570 p = (char *)val->bv_val;
2571 e = p + val->bv_len;
2573 if ( *p != '(' /*')'*/ ) {
2574 return LDAP_INVALID_SYNTAX;
2577 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2581 return LDAP_INVALID_SYNTAX;
2584 } else if ( !AD_CHAR( *p ) ) {
2585 return LDAP_INVALID_SYNTAX;
2589 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2590 return LDAP_INVALID_SYNTAX;
2596 return LDAP_INVALID_SYNTAX;
2599 return LDAP_SUCCESS;
2603 bootParameterValidate(
2605 struct berval *val )
2609 if ( val->bv_len == 0 ) {
2610 return LDAP_INVALID_SYNTAX;
2613 p = (char *)val->bv_val;
2614 e = p + val->bv_len;
2617 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2618 if ( !AD_CHAR( *p ) ) {
2619 return LDAP_INVALID_SYNTAX;
2624 return LDAP_INVALID_SYNTAX;
2628 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2629 if ( !AD_CHAR( *p ) ) {
2630 return LDAP_INVALID_SYNTAX;
2635 return LDAP_INVALID_SYNTAX;
2639 for ( p++; p < e; p++ ) {
2640 if ( !SLAP_PRINTABLE( *p ) ) {
2641 return LDAP_INVALID_SYNTAX;
2645 return LDAP_SUCCESS;
2649 firstComponentNormalize(
2654 struct berval *normalized,
2661 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2663 if( val->bv_val[0] != '(' /*')'*/ &&
2664 val->bv_val[0] != '{' /*'}'*/ )
2666 return LDAP_INVALID_SYNTAX;
2669 /* trim leading white space */
2671 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2677 /* grab next word */
2678 oid.bv_val = &val->bv_val[len];
2679 len = val->bv_len - len;
2681 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2687 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2688 rc = numericoidValidate( NULL, &oid );
2689 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2690 rc = integerValidate( NULL, &oid );
2692 rc = LDAP_INVALID_SYNTAX;
2696 if( rc == LDAP_SUCCESS ) {
2697 ber_dupbv_x( normalized, &oid, ctx );
2704 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2705 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2707 static slap_syntax_defs_rec syntax_defs[] = {
2708 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2709 X_BINARY X_NOT_H_R ")",
2710 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2711 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2713 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2715 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2717 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2718 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2720 SLAP_SYNTAX_BER, berValidate, NULL},
2721 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2722 0, bitStringValidate, NULL },
2723 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2724 0, booleanValidate, NULL},
2725 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2726 X_BINARY X_NOT_H_R ")",
2727 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL},
2728 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2729 X_BINARY X_NOT_H_R ")",
2730 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2731 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2732 X_BINARY X_NOT_H_R ")",
2733 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL},
2734 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2735 0, countryStringValidate, NULL},
2736 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2737 0, dnValidate, dnPretty},
2738 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2740 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2742 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2743 0, UTF8StringValidate, NULL},
2744 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2746 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2748 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2750 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2752 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2754 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2755 0, printablesStringValidate, NULL},
2756 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2757 SLAP_SYNTAX_BLOB, NULL, NULL},
2758 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2759 0, generalizedTimeValidate, NULL},
2760 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2762 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2763 0, IA5StringValidate, NULL},
2764 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2765 0, integerValidate, NULL},
2766 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2767 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2768 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2770 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2772 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2774 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2776 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2778 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2779 0, nameUIDValidate, nameUIDPretty },
2780 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2782 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2783 0, numericStringValidate, NULL},
2784 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2786 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2787 0, numericoidValidate, NULL},
2788 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2789 0, IA5StringValidate, NULL},
2790 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2791 0, blobValidate, NULL},
2792 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2793 0, UTF8StringValidate, NULL},
2794 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2796 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2798 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2799 0, printableStringValidate, NULL},
2800 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2801 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2802 0, subtreeSpecificationValidate, NULL},
2803 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2804 X_BINARY X_NOT_H_R ")",
2805 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2806 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2807 0, printableStringValidate, NULL},
2808 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2810 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2811 0, printablesStringValidate, NULL},
2812 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2813 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2814 0, utcTimeValidate, NULL},
2816 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2818 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2820 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2822 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2824 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2827 /* RFC 2307 NIS Syntaxes */
2828 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2829 0, nisNetgroupTripleValidate, NULL},
2830 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2831 0, bootParameterValidate, NULL},
2833 /* From PKIX *//* This OID is not published yet. */
2834 {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )",
2836 serialNumberAndIssuerValidate,
2837 serialNumberAndIssuerPretty},
2839 #ifdef SLAPD_ACI_ENABLED
2840 /* OpenLDAP Experimental Syntaxes */
2841 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2843 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2847 #ifdef SLAPD_AUTHPASSWD
2848 /* needs updating */
2849 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2850 SLAP_SYNTAX_HIDE, NULL, NULL},
2853 {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )",
2854 SLAP_SYNTAX_HIDE, UUIDValidate, NULL},
2856 /* OpenLDAP Void Syntax */
2857 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2858 SLAP_SYNTAX_HIDE, inValidate, NULL},
2859 {NULL, 0, NULL, NULL}
2862 char *certificateExactMatchSyntaxes[] = {
2863 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2866 char *directoryStringSyntaxes[] = {
2867 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2870 char *integerFirstComponentMatchSyntaxes[] = {
2871 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2872 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2875 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2876 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2877 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2878 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2879 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2880 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2881 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2882 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2883 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2888 * Other matching rules in X.520 that we do not use (yet):
2890 * 2.5.13.9 numericStringOrderingMatch
2891 * 2.5.13.25 uTCTimeMatch
2892 * 2.5.13.26 uTCTimeOrderingMatch
2893 * 2.5.13.31 directoryStringFirstComponentMatch
2894 * 2.5.13.32 wordMatch
2895 * 2.5.13.33 keywordMatch
2896 * 2.5.13.36 certificatePairExactMatch
2897 * 2.5.13.37 certificatePairMatch
2898 * 2.5.13.38 certificateListExactMatch
2899 * 2.5.13.39 certificateListMatch
2900 * 2.5.13.40 algorithmIdentifierMatch
2901 * 2.5.13.41 storedPrefixMatch
2902 * 2.5.13.42 attributeCertificateMatch
2903 * 2.5.13.43 readerAndKeyIDMatch
2904 * 2.5.13.44 attributeIntegrityMatch
2906 static slap_mrule_defs_rec mrule_defs[] = {
2908 * EQUALITY matching rules must be listed after associated APPROX
2909 * matching rules. So, we list all APPROX matching rules first.
2911 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2912 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2913 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2914 NULL, NULL, directoryStringApproxMatch,
2915 directoryStringApproxIndexer, directoryStringApproxFilter,
2918 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2919 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2920 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2921 NULL, NULL, IA5StringApproxMatch,
2922 IA5StringApproxIndexer, IA5StringApproxFilter,
2926 * Other matching rules
2929 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2930 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2931 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2932 NULL, NULL, octetStringMatch,
2933 octetStringIndexer, octetStringFilter,
2936 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2937 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2938 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2939 NULL, dnNormalize, dnMatch,
2940 octetStringIndexer, octetStringFilter,
2943 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2944 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2945 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2946 NULL, UTF8StringNormalize, octetStringMatch,
2947 octetStringIndexer, octetStringFilter,
2948 directoryStringApproxMatchOID },
2950 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2951 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2952 SLAP_MR_ORDERING, directoryStringSyntaxes,
2953 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2955 "caseIgnoreMatch" },
2957 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2958 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2959 SLAP_MR_SUBSTR, NULL,
2960 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2961 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2962 "caseIgnoreMatch" },
2964 {"( 2.5.13.5 NAME 'caseExactMatch' "
2965 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2966 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2967 NULL, UTF8StringNormalize, octetStringMatch,
2968 octetStringIndexer, octetStringFilter,
2969 directoryStringApproxMatchOID },
2971 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2973 SLAP_MR_ORDERING, directoryStringSyntaxes,
2974 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2978 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2980 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2981 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2982 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2985 {"( 2.5.13.8 NAME 'numericStringMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2987 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2988 NULL, numericStringNormalize, octetStringSubstringsMatch,
2989 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2992 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2994 SLAP_MR_SUBSTR, NULL,
2995 NULL, numericStringNormalize, octetStringSubstringsMatch,
2996 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2997 "numericStringMatch" },
2999 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3001 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3002 NULL, NULL, NULL, NULL, NULL, NULL },
3004 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3005 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3006 SLAP_MR_SUBSTR, NULL,
3007 NULL, NULL, NULL, NULL, NULL,
3008 "caseIgnoreListMatch" },
3010 {"( 2.5.13.13 NAME 'booleanMatch' "
3011 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3012 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3013 NULL, NULL, booleanMatch,
3014 octetStringIndexer, octetStringFilter,
3017 {"( 2.5.13.14 NAME 'integerMatch' "
3018 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3019 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3020 NULL, NULL, integerMatch,
3021 octetStringIndexer, octetStringFilter,
3024 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3025 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3026 SLAP_MR_ORDERING, NULL,
3027 NULL, NULL, integerMatch,
3031 {"( 2.5.13.16 NAME 'bitStringMatch' "
3032 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3033 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3034 NULL, NULL, octetStringMatch,
3035 octetStringIndexer, octetStringFilter,
3038 {"( 2.5.13.17 NAME 'octetStringMatch' "
3039 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3040 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3041 NULL, NULL, octetStringMatch,
3042 octetStringIndexer, octetStringFilter,
3045 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3046 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3047 SLAP_MR_ORDERING, NULL,
3048 NULL, NULL, octetStringOrderingMatch,
3050 "octetStringMatch" },
3052 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3054 SLAP_MR_SUBSTR, NULL,
3055 NULL, NULL, octetStringSubstringsMatch,
3056 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3057 "octetStringMatch" },
3059 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3061 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3063 telephoneNumberNormalize, octetStringMatch,
3064 octetStringIndexer, octetStringFilter,
3067 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3068 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3069 SLAP_MR_SUBSTR, NULL,
3070 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3071 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3072 "telephoneNumberMatch" },
3074 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3075 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3076 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3077 NULL, NULL, NULL, NULL, NULL, NULL },
3079 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3080 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3081 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3082 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3086 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3087 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3088 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3089 NULL, NULL, NULL, NULL, NULL, NULL },
3091 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3092 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3093 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3094 NULL, generalizedTimeNormalize, octetStringMatch,
3098 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3099 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3100 SLAP_MR_ORDERING, NULL,
3101 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
3103 "generalizedTimeMatch" },
3105 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3106 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3107 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3108 integerFirstComponentMatchSyntaxes,
3109 NULL, firstComponentNormalize, integerMatch,
3110 octetStringIndexer, octetStringFilter,
3113 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3115 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3116 objectIdentifierFirstComponentMatchSyntaxes,
3117 NULL, firstComponentNormalize, octetStringMatch,
3118 octetStringIndexer, octetStringFilter,
3121 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3122 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3123 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3125 NULL, certificateExactNormalize, octetStringMatch,
3126 octetStringIndexer, octetStringFilter,
3128 NULL, NULL, NULL, NULL, NULL,
3132 {"( 2.5.13.35 NAME 'certificateMatch' "
3133 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )",
3134 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3136 NULL, NULL, octetStringMatch,
3137 octetStringIndexer, octetStringFilter,
3139 NULL, NULL, NULL, NULL, NULL,
3143 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3144 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3145 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3146 NULL, IA5StringNormalize, octetStringMatch,
3147 octetStringIndexer, octetStringFilter,
3148 IA5StringApproxMatchOID },
3150 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3151 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3152 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3153 NULL, IA5StringNormalize, octetStringMatch,
3154 octetStringIndexer, octetStringFilter,
3155 IA5StringApproxMatchOID },
3157 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3158 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3159 SLAP_MR_SUBSTR, NULL,
3160 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3161 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3162 "caseIgnoreIA5Match" },
3164 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3165 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3166 SLAP_MR_SUBSTR, NULL,
3167 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3168 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3169 "caseExactIA5Match" },
3171 #ifdef SLAPD_AUTHPASSWD
3172 /* needs updating */
3173 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3174 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3175 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3176 NULL, NULL, authPasswordMatch,
3181 #ifdef SLAPD_ACI_ENABLED
3182 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3183 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3184 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3185 NULL, NULL, OpenLDAPaciMatch,
3190 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3191 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3193 NULL, NULL, integerBitAndMatch,
3197 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3198 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3200 NULL, NULL, integerBitOrMatch,
3204 {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' "
3205 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3206 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3207 NULL, UUIDNormalize, octetStringMatch,
3208 octetStringIndexer, octetStringFilter,
3211 {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' "
3212 "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )",
3213 SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL,
3214 NULL, UUIDNormalize, octetStringOrderingMatch,
3215 octetStringIndexer, octetStringFilter,
3218 {NULL, SLAP_MR_NONE, NULL,
3219 NULL, NULL, NULL, NULL, NULL,
3224 slap_schema_init( void )
3229 /* we should only be called once (from main) */
3230 assert( schema_init_done == 0 );
3232 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3233 res = register_syntax( &syntax_defs[i] );
3236 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3237 syntax_defs[i].sd_desc );
3242 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3243 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3244 mrule_defs[i].mrd_compat_syntaxes == NULL )
3247 "slap_schema_init: Ignoring unusable matching rule %s\n",
3248 mrule_defs[i].mrd_desc );
3252 res = register_matching_rule( &mrule_defs[i] );
3256 "slap_schema_init: Error registering matching rule %s\n",
3257 mrule_defs[i].mrd_desc );
3262 res = slap_schema_load();
3263 schema_init_done = 1;
3268 schema_destroy( void )