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"
24 #include "lutil_hash.h"
25 #define HASH_BYTES LUTIL_HASH_BYTES
26 #define HASH_CONTEXT lutil_HASH_CTX
27 #define HASH_Init(c) lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
31 #define OpenLDAPaciMatch NULL
33 /* approx matching rules */
34 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
35 #define directoryStringApproxMatch approxMatch
36 #define directoryStringApproxIndexer approxIndexer
37 #define directoryStringApproxFilter approxFilter
38 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
39 #define IA5StringApproxMatch approxMatch
40 #define IA5StringApproxIndexer approxIndexer
41 #define IA5StringApproxFilter approxFilter
48 /* no value allowed */
49 return LDAP_INVALID_SYNTAX;
57 /* any value allowed */
61 #define berValidate blobValidate
72 struct berval *asserted = (struct berval *) assertedValue;
73 int match = value->bv_len - asserted->bv_len;
76 match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
84 octetStringOrderingMatch(
92 struct berval *asserted = (struct berval *) assertedValue;
93 ber_len_t v_len = value->bv_len;
94 ber_len_t av_len = asserted->bv_len;
96 int match = memcmp( value->bv_val, asserted->bv_val,
97 (v_len < av_len ? v_len : av_len) );
99 if( match == 0 ) match = v_len - av_len;
105 /* Index generation function */
106 int octetStringIndexer(
111 struct berval *prefix,
119 HASH_CONTEXT HASHcontext;
120 unsigned char HASHdigest[HASH_BYTES];
121 struct berval digest;
122 digest.bv_val = HASHdigest;
123 digest.bv_len = sizeof(HASHdigest);
125 for( i=0; values[i].bv_val != NULL; i++ ) {
126 /* just count them */
129 /* we should have at least one value at this point */
132 keys = sl_malloc( sizeof( struct berval ) * (i+1), ctx );
134 slen = syntax->ssyn_oidlen;
135 mlen = mr->smr_oidlen;
137 for( i=0; values[i].bv_val != NULL; i++ ) {
138 HASH_Init( &HASHcontext );
139 if( prefix != NULL && prefix->bv_len > 0 ) {
140 HASH_Update( &HASHcontext,
141 prefix->bv_val, prefix->bv_len );
143 HASH_Update( &HASHcontext,
144 syntax->ssyn_oid, slen );
145 HASH_Update( &HASHcontext,
147 HASH_Update( &HASHcontext,
148 values[i].bv_val, values[i].bv_len );
149 HASH_Final( HASHdigest, &HASHcontext );
151 ber_dupbv_x( &keys[i], &digest, ctx );
154 keys[i].bv_val = NULL;
162 /* Index generation function */
163 int octetStringFilter(
168 struct berval *prefix,
169 void * assertedValue,
175 HASH_CONTEXT HASHcontext;
176 unsigned char HASHdigest[HASH_BYTES];
177 struct berval *value = (struct berval *) assertedValue;
178 struct berval digest;
179 digest.bv_val = HASHdigest;
180 digest.bv_len = sizeof(HASHdigest);
182 slen = syntax->ssyn_oidlen;
183 mlen = mr->smr_oidlen;
185 keys = sl_malloc( sizeof( struct berval ) * 2, ctx );
187 HASH_Init( &HASHcontext );
188 if( prefix != NULL && prefix->bv_len > 0 ) {
189 HASH_Update( &HASHcontext,
190 prefix->bv_val, prefix->bv_len );
192 HASH_Update( &HASHcontext,
193 syntax->ssyn_oid, slen );
194 HASH_Update( &HASHcontext,
196 HASH_Update( &HASHcontext,
197 value->bv_val, value->bv_len );
198 HASH_Final( HASHdigest, &HASHcontext );
200 ber_dupbv_x( keys, &digest, ctx );
201 keys[1].bv_val = NULL;
210 octetStringSubstringsMatch(
215 struct berval *value,
216 void *assertedValue )
219 SubstringsAssertion *sub = assertedValue;
220 struct berval left = *value;
224 /* Add up asserted input length */
225 if( sub->sa_initial.bv_val ) {
226 inlen += sub->sa_initial.bv_len;
229 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
230 inlen += sub->sa_any[i].bv_len;
233 if( sub->sa_final.bv_val ) {
234 inlen += sub->sa_final.bv_len;
237 if( sub->sa_initial.bv_val ) {
238 if( inlen > left.bv_len ) {
243 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
244 sub->sa_initial.bv_len );
250 left.bv_val += sub->sa_initial.bv_len;
251 left.bv_len -= sub->sa_initial.bv_len;
252 inlen -= sub->sa_initial.bv_len;
255 if( sub->sa_final.bv_val ) {
256 if( inlen > left.bv_len ) {
261 match = memcmp( sub->sa_final.bv_val,
262 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
263 sub->sa_final.bv_len );
269 left.bv_len -= sub->sa_final.bv_len;
270 inlen -= sub->sa_final.bv_len;
274 for(i=0; sub->sa_any[i].bv_val; i++) {
279 if( inlen > left.bv_len ) {
280 /* not enough length */
285 if( sub->sa_any[i].bv_len == 0 ) {
289 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
296 idx = p - left.bv_val;
298 if( idx >= left.bv_len ) {
299 /* this shouldn't happen */
306 if( sub->sa_any[i].bv_len > left.bv_len ) {
307 /* not enough left */
312 match = memcmp( left.bv_val,
313 sub->sa_any[i].bv_val,
314 sub->sa_any[i].bv_len );
322 left.bv_val += sub->sa_any[i].bv_len;
323 left.bv_len -= sub->sa_any[i].bv_len;
324 inlen -= sub->sa_any[i].bv_len;
333 /* Substrings Index generation function */
335 octetStringSubstringsIndexer(
340 struct berval *prefix,
345 ber_len_t i, j, nkeys;
349 HASH_CONTEXT HASHcontext;
350 unsigned char HASHdigest[HASH_BYTES];
351 struct berval digest;
352 digest.bv_val = HASHdigest;
353 digest.bv_len = sizeof(HASHdigest);
357 for( i=0; values[i].bv_val != NULL; i++ ) {
358 /* count number of indices to generate */
359 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
363 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
364 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
365 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
366 (SLAP_INDEX_SUBSTR_MINLEN - 1);
368 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
372 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
373 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
374 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
378 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
379 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
380 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
381 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
383 nkeys += values[i].bv_len - (SLAP_INDEX_SUBSTR_MINLEN - 1);
389 /* no keys to generate */
394 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
396 slen = syntax->ssyn_oidlen;
397 mlen = mr->smr_oidlen;
400 for( i=0; values[i].bv_val != NULL; i++ ) {
403 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
405 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
406 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
408 char pre = SLAP_INDEX_SUBSTR_PREFIX;
409 max = values[i].bv_len - (SLAP_INDEX_SUBSTR_MAXLEN - 1);
411 for( j=0; j<max; j++ ) {
412 HASH_Init( &HASHcontext );
413 if( prefix != NULL && prefix->bv_len > 0 ) {
414 HASH_Update( &HASHcontext,
415 prefix->bv_val, prefix->bv_len );
418 HASH_Update( &HASHcontext,
419 &pre, sizeof( pre ) );
420 HASH_Update( &HASHcontext,
421 syntax->ssyn_oid, slen );
422 HASH_Update( &HASHcontext,
424 HASH_Update( &HASHcontext,
425 &values[i].bv_val[j],
426 SLAP_INDEX_SUBSTR_MAXLEN );
427 HASH_Final( HASHdigest, &HASHcontext );
429 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
433 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
434 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
436 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
439 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
440 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
441 HASH_Init( &HASHcontext );
442 if( prefix != NULL && prefix->bv_len > 0 ) {
443 HASH_Update( &HASHcontext,
444 prefix->bv_val, prefix->bv_len );
446 HASH_Update( &HASHcontext,
447 &pre, sizeof( pre ) );
448 HASH_Update( &HASHcontext,
449 syntax->ssyn_oid, slen );
450 HASH_Update( &HASHcontext,
452 HASH_Update( &HASHcontext,
453 values[i].bv_val, j );
454 HASH_Final( HASHdigest, &HASHcontext );
456 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
459 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
460 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
461 HASH_Init( &HASHcontext );
462 if( prefix != NULL && prefix->bv_len > 0 ) {
463 HASH_Update( &HASHcontext,
464 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[values[i].bv_len-j], j );
474 HASH_Final( HASHdigest, &HASHcontext );
476 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
484 keys[nkeys].bv_val = NULL;
495 octetStringSubstringsFilter (
500 struct berval *prefix,
501 void * assertedValue,
505 SubstringsAssertion *sa;
508 size_t slen, mlen, klen;
510 HASH_CONTEXT HASHcontext;
511 unsigned char HASHdigest[HASH_BYTES];
512 struct berval *value;
513 struct berval digest;
515 sa = (SubstringsAssertion *) assertedValue;
517 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
518 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
523 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
525 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
526 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
527 /* don't bother accounting for stepping */
528 nkeys += sa->sa_any[i].bv_len -
529 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
534 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
535 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
545 digest.bv_val = HASHdigest;
546 digest.bv_len = sizeof(HASHdigest);
548 slen = syntax->ssyn_oidlen;
549 mlen = mr->smr_oidlen;
551 keys = sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
554 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
555 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
557 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
558 value = &sa->sa_initial;
560 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
561 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
563 HASH_Init( &HASHcontext );
564 if( prefix != NULL && prefix->bv_len > 0 ) {
565 HASH_Update( &HASHcontext,
566 prefix->bv_val, prefix->bv_len );
568 HASH_Update( &HASHcontext,
569 &pre, sizeof( pre ) );
570 HASH_Update( &HASHcontext,
571 syntax->ssyn_oid, slen );
572 HASH_Update( &HASHcontext,
574 HASH_Update( &HASHcontext,
575 value->bv_val, klen );
576 HASH_Final( HASHdigest, &HASHcontext );
578 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
581 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
583 pre = SLAP_INDEX_SUBSTR_PREFIX;
584 klen = SLAP_INDEX_SUBSTR_MAXLEN;
586 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
587 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
591 value = &sa->sa_any[i];
594 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
595 j += SLAP_INDEX_SUBSTR_STEP )
597 HASH_Init( &HASHcontext );
598 if( prefix != NULL && prefix->bv_len > 0 ) {
599 HASH_Update( &HASHcontext,
600 prefix->bv_val, prefix->bv_len );
602 HASH_Update( &HASHcontext,
603 &pre, sizeof( pre ) );
604 HASH_Update( &HASHcontext,
605 syntax->ssyn_oid, slen );
606 HASH_Update( &HASHcontext,
608 HASH_Update( &HASHcontext,
609 &value->bv_val[j], klen );
610 HASH_Final( HASHdigest, &HASHcontext );
612 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
617 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
618 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
620 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
621 value = &sa->sa_final;
623 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
624 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
626 HASH_Init( &HASHcontext );
627 if( prefix != NULL && prefix->bv_len > 0 ) {
628 HASH_Update( &HASHcontext,
629 prefix->bv_val, prefix->bv_len );
631 HASH_Update( &HASHcontext,
632 &pre, sizeof( pre ) );
633 HASH_Update( &HASHcontext,
634 syntax->ssyn_oid, slen );
635 HASH_Update( &HASHcontext,
637 HASH_Update( &HASHcontext,
638 &value->bv_val[value->bv_len-klen], klen );
639 HASH_Final( HASHdigest, &HASHcontext );
641 ber_dupbv_x( &keys[nkeys++], &digest, ctx );
645 keys[nkeys].bv_val = NULL;
662 /* very unforgiving validation, requires no normalization
663 * before simplistic matching
665 if( in->bv_len < 3 ) {
666 return LDAP_INVALID_SYNTAX;
670 * RFC 2252 section 6.3 Bit String
671 * bitstring = "'" *binary-digit "'B"
672 * binary-digit = "0" / "1"
673 * example: '0101111101'B
676 if( in->bv_val[0] != '\'' ||
677 in->bv_val[in->bv_len-2] != '\'' ||
678 in->bv_val[in->bv_len-1] != 'B' )
680 return LDAP_INVALID_SYNTAX;
683 for( i=in->bv_len-3; i>0; i-- ) {
684 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
685 return LDAP_INVALID_SYNTAX;
700 if( in->bv_len == 0 ) return LDAP_SUCCESS;
702 ber_dupbv( &dn, in );
703 if( !dn.bv_val ) return LDAP_OTHER;
705 if( dn.bv_val[dn.bv_len-1] == 'B'
706 && dn.bv_val[dn.bv_len-2] == '\'' )
708 /* assume presence of optional UID */
711 for(i=dn.bv_len-3; i>1; i--) {
712 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
716 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
717 ber_memfree( dn.bv_val );
718 return LDAP_INVALID_SYNTAX;
721 /* trim the UID to allow use of dnValidate */
722 dn.bv_val[i-1] = '\0';
726 rc = dnValidate( NULL, &dn );
728 ber_memfree( dn.bv_val );
744 LDAP_LOG( OPERATION, ARGS, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
746 Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
749 if( val->bv_len == 0 ) {
750 ber_dupbv_x( out, val, ctx );
752 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
753 return LDAP_INVALID_SYNTAX;
757 struct berval dnval = *val;
758 struct berval uidval = { 0, NULL };
760 if( val->bv_val[val->bv_len-1] == 'B'
761 && val->bv_val[val->bv_len-2] == '\'' )
763 uidval.bv_val=strrchr( val->bv_val, '#' );
764 if( uidval.bv_val ) {
765 dnval.bv_len = uidval.bv_val - dnval.bv_val;
766 uidval.bv_len = val->bv_len - dnval.bv_len;
773 rc = dnPretty( syntax, &dnval, out, ctx );
774 if( rc != LDAP_SUCCESS ) return rc;
776 if( uidval.bv_val ) {
777 char *tmp = sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx );
780 ber_memfree_x( out->bv_val, ctx );
784 out->bv_val[out->bv_len++] = '#';
786 got1 = uidval.bv_len < sizeof("'0'B");
787 for(i=0; i<uidval.bv_len; i++) {
788 c = uidval.bv_val[i];
791 if( got1 ) out->bv_val[out->bv_len++] = c;
796 out->bv_val[out->bv_len++] = c;
800 out->bv_val[out->bv_len] = '\0';
805 LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
807 Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
814 uniqueMemberNormalize(
819 struct berval *normalized,
825 ber_dupbv( &out, val );
826 if( out.bv_len != 0 ) {
827 struct berval uid = { 0, NULL };
829 if( out.bv_val[out.bv_len-1] == 'B'
830 && out.bv_val[out.bv_len-2] == '\'' )
832 /* assume presence of optional UID */
833 uid.bv_val = strrchr( out.bv_val, '#' );
835 if( uid.bv_val == NULL ) {
837 return LDAP_INVALID_SYNTAX;
840 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
841 out.bv_len -= uid.bv_len--;
843 /* temporarily trim the UID */
844 *(uid.bv_val++) = '\0';
847 rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
849 if( rc != LDAP_SUCCESS ) {
851 return LDAP_INVALID_SYNTAX;
855 normalized->bv_val = ch_realloc( normalized->bv_val,
856 normalized->bv_len + uid.bv_len + sizeof("#") );
858 /* insert the separator */
859 normalized->bv_val[normalized->bv_len++] = '#';
862 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
863 uid.bv_val, uid.bv_len );
864 normalized->bv_len += uid.bv_len;
867 normalized->bv_val[normalized->bv_len] = '\0';
882 struct berval *value,
883 void *assertedValue )
886 struct berval *asserted = (struct berval *) assertedValue;
887 struct berval assertedDN = { 0, NULL };
888 struct berval assertedUID = { 0, NULL };
889 struct berval valueDN = { 0, NULL };
890 struct berval valueUID = { 0, NULL };
892 if( asserted->bv_len != 0 ) {
893 assertedDN = *asserted;
895 if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B'
896 && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' )
898 /* assume presence of optional UID */
899 assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
901 if( assertedUID.bv_val == NULL ) {
902 return LDAP_INVALID_SYNTAX;
905 assertedUID.bv_len = assertedDN.bv_len -
906 (assertedUID.bv_val - assertedDN.bv_val);
907 assertedDN.bv_len -= assertedUID.bv_len--;
909 /* trim the separator */
910 assertedUID.bv_val++;
914 if( value->bv_len != 0 ) {
917 if( valueDN.bv_val[valueDN.bv_len-1] == 'B'
918 && valueDN.bv_val[valueDN.bv_len-2] == '\'' )
920 /* assume presence of optional UID */
921 valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
923 if( valueUID.bv_val == NULL ) {
924 return LDAP_INVALID_SYNTAX;
927 valueUID.bv_len = valueDN.bv_len -
928 (assertedUID.bv_val - assertedDN.bv_val);
929 valueDN.bv_len -= valueUID.bv_len--;
931 /* trim the separator */
936 if( valueUID.bv_len && assertedUID.bv_len ) {
937 match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
944 return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
948 * Handling boolean syntax and matching is quite rigid.
949 * A more flexible approach would be to allow a variety
950 * of strings to be normalized and prettied into TRUE
958 /* very unforgiving validation, requires no normalization
959 * before simplistic matching
962 if( in->bv_len == 4 ) {
963 if( bvmatch( in, &slap_true_bv ) ) {
966 } else if( in->bv_len == 5 ) {
967 if( bvmatch( in, &slap_false_bv ) ) {
972 return LDAP_INVALID_SYNTAX;
981 struct berval *value,
982 void *assertedValue )
984 /* simplistic matching allowed by rigid validation */
985 struct berval *asserted = (struct berval *) assertedValue;
986 *matchp = value->bv_len != asserted->bv_len;
990 /*-------------------------------------------------------------------
991 LDAP/X.500 string syntax / matching rules have a few oddities. This
992 comment attempts to detail how slapd(8) treats them.
995 StringSyntax X.500 LDAP Matching/Comments
996 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
997 PrintableString subset subset i/e + ignore insignificant spaces
998 PrintableString subset subset i/e + ignore insignificant spaces
999 NumericString subset subset ignore all spaces
1000 IA5String ASCII ASCII i/e + ignore insignificant spaces
1001 TeletexString T.61 T.61 i/e + ignore insignificant spaces
1003 TelephoneNumber subset subset i + ignore all spaces and "-"
1005 See draft-ietf-ldapbis-strpro for details (once published).
1009 In X.500(93), a directory string can be either a PrintableString,
1010 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
1011 In later versions, more CHOICEs were added. In all cases the string
1014 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
1015 A directory string cannot be zero length.
1017 For matching, there are both case ignore and exact rules. Both
1018 also require that "insignificant" spaces be ignored.
1019 spaces before the first non-space are ignored;
1020 spaces after the last non-space are ignored;
1021 spaces after a space are ignored.
1022 Note: by these rules (and as clarified in X.520), a string of only
1023 spaces is to be treated as if held one space, not empty (which
1024 would be a syntax error).
1027 In ASN.1, numeric string is just a string of digits and spaces
1028 and could be empty. However, in X.500, all attribute values of
1029 numeric string carry a non-empty constraint. For example:
1031 internationalISDNNumber ATTRIBUTE ::= {
1032 WITH SYNTAX InternationalISDNNumber
1033 EQUALITY MATCHING RULE numericStringMatch
1034 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
1035 ID id-at-internationalISDNNumber }
1036 InternationalISDNNumber ::=
1037 NumericString (SIZE(1..ub-international-isdn-number))
1039 Unforunately, some assertion values are don't carry the same
1040 constraint (but its unclear how such an assertion could ever
1041 be true). In LDAP, there is one syntax (numericString) not two
1042 (numericString with constraint, numericString without constraint).
1043 This should be treated as numericString with non-empty constraint.
1044 Note that while someone may have no ISDN number, there are no ISDN
1045 numbers which are zero length.
1047 In matching, spaces are ignored.
1050 In ASN.1, Printable string is just a string of printable characters
1051 and can be empty. In X.500, semantics much like NumericString (see
1052 serialNumber for a like example) excepting uses insignificant space
1053 handling instead of ignore all spaces.
1056 Basically same as PrintableString. There are no examples in X.500,
1057 but same logic applies. So we require them to be non-empty as
1060 -------------------------------------------------------------------*/
1069 unsigned char *u = in->bv_val;
1071 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
1072 /* directory strings cannot be empty */
1073 return LDAP_INVALID_SYNTAX;
1076 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
1077 /* get the length indicated by the first byte */
1078 len = LDAP_UTF8_CHARLEN2( u, len );
1080 /* very basic checks */
1083 if( (u[5] & 0xC0) != 0x80 ) {
1084 return LDAP_INVALID_SYNTAX;
1087 if( (u[4] & 0xC0) != 0x80 ) {
1088 return LDAP_INVALID_SYNTAX;
1091 if( (u[3] & 0xC0) != 0x80 ) {
1092 return LDAP_INVALID_SYNTAX;
1095 if( (u[2] & 0xC0 )!= 0x80 ) {
1096 return LDAP_INVALID_SYNTAX;
1099 if( (u[1] & 0xC0) != 0x80 ) {
1100 return LDAP_INVALID_SYNTAX;
1103 /* CHARLEN already validated it */
1106 return LDAP_INVALID_SYNTAX;
1109 /* make sure len corresponds with the offset
1110 to the next character */
1111 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
1115 return LDAP_INVALID_SYNTAX;
1118 return LDAP_SUCCESS;
1122 UTF8StringNormalize(
1127 struct berval *normalized,
1130 struct berval tmp, nvalue;
1134 if( val->bv_val == NULL ) {
1135 /* assume we're dealing with a syntax (e.g., UTF8String)
1136 * which allows empty strings
1138 normalized->bv_len = 0;
1139 normalized->bv_val = NULL;
1140 return LDAP_SUCCESS;
1143 flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
1144 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1145 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1146 ? LDAP_UTF8_APPROX : 0;
1148 val = UTF8bvnormalize( val, &tmp, flags, ctx );
1153 /* collapse spaces (in place) */
1155 nvalue.bv_val = tmp.bv_val;
1157 wasspace=1; /* trim leading spaces */
1158 for( i=0; i<tmp.bv_len; i++) {
1159 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1160 if( wasspace++ == 0 ) {
1161 /* trim repeated spaces */
1162 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1166 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1170 if( nvalue.bv_len ) {
1172 /* last character was a space, trim it */
1175 nvalue.bv_val[nvalue.bv_len] = '\0';
1178 /* string of all spaces is treated as one space */
1179 nvalue.bv_val[0] = ' ';
1180 nvalue.bv_val[1] = '\0';
1184 *normalized = nvalue;
1185 return LDAP_SUCCESS;
1188 #if defined(SLAPD_APPROX_INITIALS)
1189 # define SLAPD_APPROX_DELIMITER "._ "
1190 # define SLAPD_APPROX_WORDLEN 2
1192 # define SLAPD_APPROX_DELIMITER " "
1193 # define SLAPD_APPROX_WORDLEN 1
1202 struct berval *value,
1203 void *assertedValue )
1205 struct berval *nval, *assertv;
1206 char *val, **values, **words, *c;
1207 int i, count, len, nextchunk=0, nextavail=0;
1209 /* Yes, this is necessary */
1210 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
1211 if( nval == NULL ) {
1213 return LDAP_SUCCESS;
1216 /* Yes, this is necessary */
1217 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1218 NULL, LDAP_UTF8_APPROX, NULL );
1219 if( assertv == NULL ) {
1222 return LDAP_SUCCESS;
1225 /* Isolate how many words there are */
1226 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1227 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1228 if ( c == NULL ) break;
1233 /* Get a phonetic copy of each word */
1234 words = (char **)ch_malloc( count * sizeof(char *) );
1235 values = (char **)ch_malloc( count * sizeof(char *) );
1236 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1238 values[i] = phonetic(c);
1241 /* Work through the asserted value's words, to see if at least some
1242 of the words are there, in the same order. */
1244 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1245 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1250 #if defined(SLAPD_APPROX_INITIALS)
1251 else if( len == 1 ) {
1252 /* Single letter words need to at least match one word's initial */
1253 for( i=nextavail; i<count; i++ )
1254 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1261 /* Isolate the next word in the asserted value and phonetic it */
1262 assertv->bv_val[nextchunk+len] = '\0';
1263 val = phonetic( assertv->bv_val + nextchunk );
1265 /* See if this phonetic chunk is in the remaining words of *value */
1266 for( i=nextavail; i<count; i++ ){
1267 if( !strcmp( val, values[i] ) ){
1275 /* This chunk in the asserted value was NOT within the *value. */
1281 /* Go on to the next word in the asserted value */
1285 /* If some of the words were seen, call it a match */
1286 if( nextavail > 0 ) {
1293 /* Cleanup allocs */
1294 ber_bvfree( assertv );
1295 for( i=0; i<count; i++ ) {
1296 ch_free( values[i] );
1302 return LDAP_SUCCESS;
1311 struct berval *prefix,
1317 int i,j, len, wordcount, keycount=0;
1318 struct berval *newkeys;
1319 BerVarray keys=NULL;
1321 for( j=0; values[j].bv_val != NULL; j++ ) {
1322 struct berval val = { 0, NULL };
1323 /* Yes, this is necessary */
1324 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
1325 assert( val.bv_val != NULL );
1327 /* Isolate how many words there are. There will be a key for each */
1328 for( wordcount = 0, c = val.bv_val; *c; c++) {
1329 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1330 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1332 if (*c == '\0') break;
1336 /* Allocate/increase storage to account for new keys */
1337 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1338 * sizeof(struct berval) );
1339 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1340 if( keys ) ch_free( keys );
1343 /* Get a phonetic copy of each word */
1344 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1346 if( len < SLAPD_APPROX_WORDLEN ) continue;
1347 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1352 ber_memfree( val.bv_val );
1354 keys[keycount].bv_val = NULL;
1357 return LDAP_SUCCESS;
1366 struct berval *prefix,
1367 void * assertedValue,
1376 /* Yes, this is necessary */
1377 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1378 NULL, LDAP_UTF8_APPROX, NULL );
1379 if( val == NULL || val->bv_val == NULL ) {
1380 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1381 keys[0].bv_val = NULL;
1384 return LDAP_SUCCESS;
1387 /* Isolate how many words there are. There will be a key for each */
1388 for( count = 0,c = val->bv_val; *c; c++) {
1389 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1390 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1392 if (*c == '\0') break;
1396 /* Allocate storage for new keys */
1397 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1399 /* Get a phonetic copy of each word */
1400 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1402 if( len < SLAPD_APPROX_WORDLEN ) continue;
1403 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1409 keys[count].bv_val = NULL;
1412 return LDAP_SUCCESS;
1415 /* Remove all spaces and '-' characters */
1417 telephoneNumberNormalize(
1422 struct berval *normalized,
1427 /* validator should have refused an empty string */
1428 assert( val->bv_len );
1430 q = normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1432 for( p = val->bv_val; *p; p++ ) {
1433 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1439 normalized->bv_len = q - normalized->bv_val;
1441 if( normalized->bv_len == 0 ) {
1442 sl_free( normalized->bv_val, ctx );
1443 normalized->bv_val = NULL;
1444 return LDAP_INVALID_SYNTAX;
1447 return LDAP_SUCCESS;
1455 struct berval val = *in;
1457 if( val.bv_len == 0 ) {
1458 /* disallow empty strings */
1459 return LDAP_INVALID_SYNTAX;
1462 while( OID_LEADCHAR( val.bv_val[0] ) ) {
1463 if ( val.bv_len == 1 ) {
1464 return LDAP_SUCCESS;
1467 if ( val.bv_val[0] == '0' ) {
1474 while ( OID_LEADCHAR( val.bv_val[0] )) {
1478 if ( val.bv_len == 0 ) {
1479 return LDAP_SUCCESS;
1483 if( !OID_SEPARATOR( val.bv_val[0] )) {
1491 return LDAP_INVALID_SYNTAX;
1500 struct berval val = *in;
1502 if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1504 if ( val.bv_val[0] == '-' ) {
1508 if( val.bv_len == 0 ) { /* bare "-" */
1509 return LDAP_INVALID_SYNTAX;
1512 if( val.bv_val[0] == '0' ) { /* "-0" */
1513 return LDAP_INVALID_SYNTAX;
1516 } else if ( val.bv_val[0] == '0' ) {
1517 if( val.bv_len > 1 ) { /* "0<more>" */
1518 return LDAP_INVALID_SYNTAX;
1521 return LDAP_SUCCESS;
1524 for( i=0; i < val.bv_len; i++ ) {
1525 if( !ASCII_DIGIT(val.bv_val[i]) ) {
1526 return LDAP_INVALID_SYNTAX;
1530 return LDAP_SUCCESS;
1539 struct berval *value,
1540 void *assertedValue )
1542 struct berval *asserted = (struct berval *) assertedValue;
1543 int vsign = 1, asign = 1; /* default sign = '+' */
1548 if( v.bv_val[0] == '-' ) {
1554 if( v.bv_len == 0 ) vsign = 0;
1557 if( a.bv_val[0] == '-' ) {
1563 if( a.bv_len == 0 ) vsign = 0;
1565 match = vsign - asign;
1567 match = ( v.bv_len != a.bv_len
1568 ? ( v.bv_len < a.bv_len ? -1 : 1 )
1569 : memcmp( v.bv_val, a.bv_val, v.bv_len ));
1570 if( vsign < 0 ) match = -match;
1574 return LDAP_SUCCESS;
1578 countryStringValidate(
1580 struct berval *val )
1582 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1584 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1585 return LDAP_INVALID_SYNTAX;
1587 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1588 return LDAP_INVALID_SYNTAX;
1591 return LDAP_SUCCESS;
1595 printableStringValidate(
1597 struct berval *val )
1601 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1603 for(i=0; i < val->bv_len; i++) {
1604 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1605 return LDAP_INVALID_SYNTAX;
1609 return LDAP_SUCCESS;
1613 printablesStringValidate(
1615 struct berval *val )
1619 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1621 for(i=0,len=0; i < val->bv_len; i++) {
1622 int c = val->bv_val[i];
1626 return LDAP_INVALID_SYNTAX;
1630 } else if ( SLAP_PRINTABLE(c) ) {
1633 return LDAP_INVALID_SYNTAX;
1638 return LDAP_INVALID_SYNTAX;
1641 return LDAP_SUCCESS;
1647 struct berval *val )
1651 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1653 for(i=0; i < val->bv_len; i++) {
1654 if( !LDAP_ASCII(val->bv_val[i]) ) {
1655 return LDAP_INVALID_SYNTAX;
1659 return LDAP_SUCCESS;
1668 struct berval *normalized,
1672 int casefold = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1674 assert( val->bv_len );
1678 /* Ignore initial whitespace */
1679 while ( ASCII_SPACE( *p ) ) p++;
1681 normalized->bv_val = ber_strdup_x( p, ctx );
1682 p = q = normalized->bv_val;
1685 if ( ASCII_SPACE( *p ) ) {
1688 /* Ignore the extra whitespace */
1689 while ( ASCII_SPACE( *p ) ) {
1693 } else if ( casefold ) {
1694 /* Most IA5 rules require casefolding */
1695 *q++ = TOLOWER(*p++);
1702 assert( normalized->bv_val <= p );
1706 * If the string ended in space, backup the pointer one
1707 * position. One is enough because the above loop collapsed
1708 * all whitespace to a single space.
1710 if ( ASCII_SPACE( q[-1] ) ) --q;
1712 /* null terminate */
1715 normalized->bv_len = q - normalized->bv_val;
1716 if( normalized->bv_len == 0 ) {
1717 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1718 normalized->bv_val[0] = ' ';
1719 normalized->bv_val[1] = '\0';
1720 normalized->bv_len = 1;
1723 return LDAP_SUCCESS;
1727 numericStringValidate(
1733 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1735 for(i=0; i < in->bv_len; i++) {
1736 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1737 return LDAP_INVALID_SYNTAX;
1741 return LDAP_SUCCESS;
1745 numericStringNormalize(
1750 struct berval *normalized,
1753 /* removal all spaces */
1756 assert( val->bv_len );
1758 normalized->bv_val = sl_malloc( val->bv_len + 1, ctx );
1761 q = normalized->bv_val;
1764 if ( ASCII_SPACE( *p ) ) {
1765 /* Ignore whitespace */
1772 /* we should have copied no more then is in val */
1773 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1775 /* null terminate */
1778 normalized->bv_len = q - normalized->bv_val;
1780 if( normalized->bv_len == 0 ) {
1781 normalized->bv_val = sl_realloc( normalized->bv_val, 2, ctx );
1782 normalized->bv_val[0] = ' ';
1783 normalized->bv_val[1] = '\0';
1784 normalized->bv_len = 1;
1787 return LDAP_SUCCESS;
1791 * Integer conversion macros that will use the largest available
1794 #if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG)
1795 # define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
1796 # define SLAP_LONG_MAX LLONG_MAX
1797 # define SLAP_LONG_MIN LLONG_MIN
1798 # define SLAP_LONG long long
1800 # define SLAP_STRTOL(n,e,b) strtol(n,e,b)
1801 # define SLAP_LONG_MAX LONG_MAX
1802 # define SLAP_LONG_MIN LONG_MIN
1803 # define SLAP_LONG long
1804 #endif /* HAVE_STRTOLL ... */
1812 struct berval *value,
1813 void *assertedValue )
1815 SLAP_LONG lValue, lAssertedValue;
1817 /* safe to assume integers are NUL terminated? */
1818 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1819 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) {
1820 return LDAP_CONSTRAINT_VIOLATION;
1823 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1824 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1825 && errno == ERANGE )
1827 return LDAP_CONSTRAINT_VIOLATION;
1830 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1831 return LDAP_SUCCESS;
1840 struct berval *value,
1841 void *assertedValue )
1843 SLAP_LONG lValue, lAssertedValue;
1845 /* safe to assume integers are NUL terminated? */
1846 lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
1847 if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && errno == ERANGE ) {
1848 return LDAP_CONSTRAINT_VIOLATION;
1851 lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10);
1852 if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX )
1853 && errno == ERANGE )
1855 return LDAP_CONSTRAINT_VIOLATION;
1858 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1859 return LDAP_SUCCESS;
1863 serialNumberAndIssuerValidate(
1867 int rc = LDAP_INVALID_SYNTAX;
1868 struct berval serialNumber, issuer;
1870 serialNumber.bv_val = in->bv_val;
1871 for( serialNumber.bv_len = 0;
1872 serialNumber.bv_len < in->bv_len;
1873 serialNumber.bv_len++ )
1875 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1876 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1877 issuer.bv_len = in->bv_len - (serialNumber.bv_len+1);
1879 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1881 rc = integerValidate( NULL, &serialNumber );
1884 rc = dnValidate( NULL, &issuer );
1893 serialNumberAndIssuerNormalize(
1898 struct berval *normalized,
1901 int rc = LDAP_INVALID_SYNTAX;
1902 struct berval serialNumber, issuer, nissuer;
1904 serialNumber.bv_val = val->bv_val;
1905 for( serialNumber.bv_len = 0;
1906 serialNumber.bv_len < val->bv_len;
1907 serialNumber.bv_len++ )
1909 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1910 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1911 issuer.bv_len = val->bv_len - (serialNumber.bv_len+1);
1913 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1915 rc = dnNormalize( usage, syntax, mr, &issuer, &nissuer, ctx );
1918 normalized->bv_len = serialNumber.bv_len + 1 + nissuer.bv_len;
1919 normalized->bv_val = ch_malloc( normalized->bv_len + 1);
1921 AC_MEMCPY( normalized->bv_val,
1922 serialNumber.bv_val, serialNumber.bv_len );
1923 normalized->bv_val[serialNumber.bv_len] = '$';
1924 AC_MEMCPY( &normalized->bv_val[serialNumber.bv_len+1],
1925 nissuer.bv_val, nissuer.bv_len );
1926 normalized->bv_val[normalized->bv_len] = '\0';
1935 #include <openssl/x509.h>
1936 #include <openssl/err.h>
1939 * Next function returns a string representation of a ASN1_INTEGER.
1940 * It works for unlimited lengths.
1943 static struct berval *
1944 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1948 static char digit[] = "0123456789";
1950 /* We work backwards, make it fill from the end of buf */
1951 p = buf + sizeof(buf) - 1;
1954 if ( a == NULL || a->length == 0 ) {
1962 /* We want to preserve the original */
1963 copy = ch_malloc(n*sizeof(unsigned int));
1964 for (i = 0; i<n; i++) {
1965 copy[i] = a->data[i];
1969 * base indicates the index of the most significant
1970 * byte that might be nonzero. When it goes off the
1971 * end, we now there is nothing left to do.
1977 for (i = base; i<n; i++ ) {
1978 copy[i] += carry*256;
1979 carry = copy[i] % 10;
1984 * Way too large, we need to leave
1985 * room for sign if negative
1990 *--p = digit[carry];
1992 if (copy[base] == 0) base++;
1997 if ( a->type == V_ASN1_NEG_INTEGER ) {
2001 return ber_str2bv( p, 0, 1, bv );
2005 * Given a certificate in DER format, extract the corresponding
2006 * assertion value for certificateExactMatch
2009 certificateExactConvert(
2011 struct berval * out )
2015 unsigned char *p = in->bv_val;
2016 struct berval serial;
2017 struct berval issuer_dn;
2019 xcert = d2i_X509(NULL, &p, in->bv_len);
2022 LDAP_LOG( CONFIG, ENTRY,
2023 "certificateExactConvert: error parsing cert: %s\n",
2024 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2026 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2027 "error parsing cert: %s\n",
2028 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2030 return LDAP_INVALID_SYNTAX;
2033 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2035 return LDAP_INVALID_SYNTAX;
2038 rc = dnX509normalize( X509_get_issuer_name(xcert), &issuer_dn );
2039 if( rc != LDAP_SUCCESS ) {
2041 ber_memfree(serial.bv_val);
2042 return LDAP_INVALID_SYNTAX;
2047 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2048 out->bv_val = ch_malloc(out->bv_len);
2050 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2052 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2054 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2055 p += issuer_dn.bv_len;
2059 LDAP_LOG( CONFIG, ARGS, "certificateExactConvert: %s\n",
2060 out->bv_val, 0, 0 );
2062 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: %s\n",
2063 out->bv_val, NULL, NULL );
2066 ber_memfree(serial.bv_val);
2067 ber_memfree(issuer_dn.bv_val);
2069 return LDAP_SUCCESS;
2073 certificateExactNormalize(
2078 struct berval *normalized,
2083 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage ) ) {
2084 rc = serialNumberAndIssuerNormalize( usage, syntax, mr,
2085 val, normalized, ctx );
2088 rc = certificateExactConvert( val, normalized );
2093 #endif /* HAVE_TLS */
2096 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2097 /* slight optimization - does not need the start parameter */
2098 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2103 check_time_syntax (struct berval *val,
2106 struct berval *fraction)
2109 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2110 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2111 * GeneralizedTime supports leap seconds, UTCTime does not.
2113 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2114 static const int mdays[2][12] = {
2115 /* non-leap years */
2116 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2118 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2121 int part, c, c1, c2, tzoffset, leapyear = 0;
2124 e = p + val->bv_len;
2126 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2127 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2129 for (part = start; part < 7 && p < e; part++) {
2131 if (!ASCII_DIGIT(c1)) {
2136 return LDAP_INVALID_SYNTAX;
2139 if (!ASCII_DIGIT(c)) {
2140 return LDAP_INVALID_SYNTAX;
2142 c += c1 * 10 - '0' * 11;
2143 if ((part | 1) == 3) {
2146 return LDAP_INVALID_SYNTAX;
2149 if (c >= ceiling[part]) {
2150 if (! (c == 60 && part == 6 && start == 0))
2151 return LDAP_INVALID_SYNTAX;
2155 if (part < 5 + start) {
2156 return LDAP_INVALID_SYNTAX;
2158 for (; part < 9; part++) {
2162 /* leapyear check for the Gregorian calendar (year>1581) */
2163 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2168 if (parts[3] >= mdays[leapyear][parts[2]]) {
2169 return LDAP_INVALID_SYNTAX;
2173 fraction->bv_val = p;
2174 fraction->bv_len = 0;
2175 if (p < e && (*p == '.' || *p == ',')) {
2177 while (++p < e && ASCII_DIGIT(*p))
2179 if (p - fraction->bv_val == 1) {
2180 return LDAP_INVALID_SYNTAX;
2182 for (end_num = p; end_num[-1] == '0'; --end_num)
2184 c = end_num - fraction->bv_val;
2186 fraction->bv_len = c;
2192 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2198 return LDAP_INVALID_SYNTAX;
2204 for (part = 7; part < 9 && p < e; part++) {
2206 if (!ASCII_DIGIT(c1)) {
2211 return LDAP_INVALID_SYNTAX;
2214 if (!ASCII_DIGIT(c2)) {
2215 return LDAP_INVALID_SYNTAX;
2217 parts[part] = c1 * 10 + c2 - '0' * 11;
2218 if (parts[part] >= ceiling[part]) {
2219 return LDAP_INVALID_SYNTAX;
2222 if (part < 8 + start) {
2223 return LDAP_INVALID_SYNTAX;
2226 if (tzoffset == '-') {
2227 /* negative offset to UTC, ie west of Greenwich */
2228 parts[4] += parts[7];
2229 parts[5] += parts[8];
2230 /* offset is just hhmm, no seconds */
2231 for (part = 6; --part >= 0; ) {
2235 c = mdays[leapyear][parts[2]];
2237 if (parts[part] >= c) {
2239 return LDAP_INVALID_SYNTAX;
2244 } else if (part != 5) {
2249 /* positive offset to UTC, ie east of Greenwich */
2250 parts[4] -= parts[7];
2251 parts[5] -= parts[8];
2252 for (part = 6; --part >= 0; ) {
2253 if (parts[part] < 0) {
2255 return LDAP_INVALID_SYNTAX;
2260 /* make first arg to % non-negative */
2261 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2266 } else if (part != 5) {
2273 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2276 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2283 struct berval *normalized )
2287 rc = check_time_syntax(val, 1, parts, NULL);
2288 if (rc != LDAP_SUCCESS) {
2292 normalized->bv_val = ch_malloc( 14 );
2293 if ( normalized->bv_val == NULL ) {
2294 return LBER_ERROR_MEMORY;
2297 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2298 parts[1], parts[2] + 1, parts[3] + 1,
2299 parts[4], parts[5], parts[6] );
2300 normalized->bv_len = 13;
2302 return LDAP_SUCCESS;
2312 return check_time_syntax(in, 1, parts, NULL);
2315 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2318 generalizedTimeValidate(
2323 struct berval fraction;
2324 return check_time_syntax(in, 0, parts, &fraction);
2328 generalizedTimeNormalize(
2333 struct berval *normalized,
2338 struct berval fraction;
2340 rc = check_time_syntax(val, 0, parts, &fraction);
2341 if (rc != LDAP_SUCCESS) {
2345 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2346 normalized->bv_val = sl_malloc( len + 1, ctx );
2347 if ( normalized->bv_val == NULL ) {
2348 return LBER_ERROR_MEMORY;
2351 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2352 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2353 parts[4], parts[5], parts[6] );
2354 if ( fraction.bv_len ) {
2355 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2356 fraction.bv_val, fraction.bv_len );
2357 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2359 strcpy( normalized->bv_val + len-1, "Z" );
2360 normalized->bv_len = len;
2362 return LDAP_SUCCESS;
2366 generalizedTimeOrderingMatch(
2371 struct berval *value,
2372 void *assertedValue )
2374 struct berval *asserted = (struct berval *) assertedValue;
2375 ber_len_t v_len = value->bv_len;
2376 ber_len_t av_len = asserted->bv_len;
2378 /* ignore trailing 'Z' when comparing */
2379 int match = memcmp( value->bv_val, asserted->bv_val,
2380 (v_len < av_len ? v_len : av_len) - 1 );
2381 if ( match == 0 ) match = v_len - av_len;
2384 return LDAP_SUCCESS;
2388 nisNetgroupTripleValidate(
2390 struct berval *val )
2395 if ( val->bv_len == 0 ) {
2396 return LDAP_INVALID_SYNTAX;
2399 p = (char *)val->bv_val;
2400 e = p + val->bv_len;
2402 if ( *p != '(' /*')'*/ ) {
2403 return LDAP_INVALID_SYNTAX;
2406 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2410 return LDAP_INVALID_SYNTAX;
2413 } else if ( !AD_CHAR( *p ) ) {
2414 return LDAP_INVALID_SYNTAX;
2418 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2419 return LDAP_INVALID_SYNTAX;
2425 return LDAP_INVALID_SYNTAX;
2428 return LDAP_SUCCESS;
2432 bootParameterValidate(
2434 struct berval *val )
2438 if ( val->bv_len == 0 ) {
2439 return LDAP_INVALID_SYNTAX;
2442 p = (char *)val->bv_val;
2443 e = p + val->bv_len;
2446 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2447 if ( !AD_CHAR( *p ) ) {
2448 return LDAP_INVALID_SYNTAX;
2453 return LDAP_INVALID_SYNTAX;
2457 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2458 if ( !AD_CHAR( *p ) ) {
2459 return LDAP_INVALID_SYNTAX;
2464 return LDAP_INVALID_SYNTAX;
2468 for ( p++; p < e; p++ ) {
2469 if ( !SLAP_PRINTABLE( *p ) ) {
2470 return LDAP_INVALID_SYNTAX;
2474 return LDAP_SUCCESS;
2478 firstComponentNormalize(
2483 struct berval *normalized,
2490 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2492 if( val->bv_val[0] != '(' /*')'*/ &&
2493 val->bv_val[0] != '{' /*'}'*/ )
2495 return LDAP_INVALID_SYNTAX;
2498 /* trim leading white space */
2500 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2506 /* grab next word */
2507 oid.bv_val = &val->bv_val[len];
2508 len = val->bv_len - len;
2510 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2516 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2517 rc = numericoidValidate( NULL, &oid );
2518 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2519 rc = integerValidate( NULL, &oid );
2521 rc = LDAP_INVALID_SYNTAX;
2525 if( rc == LDAP_SUCCESS ) {
2526 ber_dupbv_x( normalized, &oid, ctx );
2533 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2534 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2536 static slap_syntax_defs_rec syntax_defs[] = {
2537 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2538 X_BINARY X_NOT_H_R ")",
2539 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2540 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2542 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2544 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2546 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2547 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2549 SLAP_SYNTAX_BER, berValidate, NULL},
2550 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2551 0, bitStringValidate, NULL },
2552 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2553 0, booleanValidate, NULL},
2554 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2555 X_BINARY X_NOT_H_R ")",
2556 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2557 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2558 X_BINARY X_NOT_H_R ")",
2559 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2560 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2561 X_BINARY X_NOT_H_R ")",
2562 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2563 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2564 0, countryStringValidate, NULL},
2565 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2566 0, dnValidate, dnPretty},
2567 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2569 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2571 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2572 0, UTF8StringValidate, NULL},
2573 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2575 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2577 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2579 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2581 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2583 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2584 0, printablesStringValidate, NULL},
2585 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2586 SLAP_SYNTAX_BLOB, NULL, NULL},
2587 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2588 0, generalizedTimeValidate, NULL},
2589 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2591 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2592 0, IA5StringValidate, NULL},
2593 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2594 0, integerValidate, NULL},
2595 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2596 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2597 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2599 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2601 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2603 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2605 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2607 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2608 0, nameUIDValidate, nameUIDPretty },
2609 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2611 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2612 0, numericStringValidate, NULL},
2613 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2615 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2616 0, numericoidValidate, NULL},
2617 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2618 0, IA5StringValidate, NULL},
2619 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2620 0, blobValidate, NULL},
2621 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2622 0, UTF8StringValidate, NULL},
2623 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2625 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2627 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2628 0, printableStringValidate, NULL},
2629 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2630 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2631 0, subtreeSpecificationValidate, NULL},
2632 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2633 X_BINARY X_NOT_H_R ")",
2634 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2635 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2636 0, printableStringValidate, NULL},
2637 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2639 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2640 0, printablesStringValidate, NULL},
2641 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2642 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2643 0, utcTimeValidate, NULL},
2645 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2647 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2649 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2651 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2653 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2656 /* RFC 2307 NIS Syntaxes */
2657 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2658 0, nisNetgroupTripleValidate, NULL},
2659 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2660 0, bootParameterValidate, NULL},
2663 /* These OIDs are not published yet, but will be in the next
2664 * I-D for PKIX LDAPv3 schema as have been advanced by David
2665 * Chadwick in private mail.
2667 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2668 0, serialNumberAndIssuerValidate, NULL},
2670 /* OpenLDAP Experimental Syntaxes */
2671 #ifdef SLAPD_ACI_ENABLED
2672 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2674 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2678 #ifdef SLAPD_AUTHPASSWD
2679 /* needs updating */
2680 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2681 SLAP_SYNTAX_HIDE, NULL, NULL},
2684 /* OpenLDAP Void Syntax */
2685 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2686 SLAP_SYNTAX_HIDE, inValidate, NULL},
2687 {NULL, 0, NULL, NULL}
2691 char *certificateExactMatchSyntaxes[] = {
2692 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2696 char *directoryStringSyntaxes[] = {
2697 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2700 char *integerFirstComponentMatchSyntaxes[] = {
2701 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2702 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2705 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2706 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2707 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2708 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2709 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2710 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2711 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2712 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2713 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2718 * Other matching rules in X.520 that we do not use (yet):
2720 * 2.5.13.9 numericStringOrderingMatch
2721 * 2.5.13.25 uTCTimeMatch
2722 * 2.5.13.26 uTCTimeOrderingMatch
2723 * 2.5.13.31 directoryStringFirstComponentMatch
2724 * 2.5.13.32 wordMatch
2725 * 2.5.13.33 keywordMatch
2726 * 2.5.13.35 certificateMatch
2727 * 2.5.13.36 certificatePairExactMatch
2728 * 2.5.13.37 certificatePairMatch
2729 * 2.5.13.38 certificateListExactMatch
2730 * 2.5.13.39 certificateListMatch
2731 * 2.5.13.40 algorithmIdentifierMatch
2732 * 2.5.13.41 storedPrefixMatch
2733 * 2.5.13.42 attributeCertificateMatch
2734 * 2.5.13.43 readerAndKeyIDMatch
2735 * 2.5.13.44 attributeIntegrityMatch
2737 static slap_mrule_defs_rec mrule_defs[] = {
2739 * EQUALITY matching rules must be listed after associated APPROX
2740 * matching rules. So, we list all APPROX matching rules first.
2742 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2743 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2744 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2745 NULL, NULL, directoryStringApproxMatch,
2746 directoryStringApproxIndexer, directoryStringApproxFilter,
2749 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2750 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2751 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2752 NULL, NULL, IA5StringApproxMatch,
2753 IA5StringApproxIndexer, IA5StringApproxFilter,
2757 * Other matching rules
2760 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2761 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2762 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2763 NULL, NULL, octetStringMatch,
2764 octetStringIndexer, octetStringFilter,
2767 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2768 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2769 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2770 NULL, dnNormalize, dnMatch,
2771 octetStringIndexer, octetStringFilter,
2774 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2775 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2776 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2777 NULL, UTF8StringNormalize, octetStringMatch,
2778 octetStringIndexer, octetStringFilter,
2779 directoryStringApproxMatchOID },
2781 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2782 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2783 SLAP_MR_ORDERING, directoryStringSyntaxes,
2784 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2786 "caseIgnoreMatch" },
2788 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2789 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2790 SLAP_MR_SUBSTR, NULL,
2791 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2792 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2793 "caseIgnoreMatch" },
2795 {"( 2.5.13.5 NAME 'caseExactMatch' "
2796 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2797 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2798 NULL, UTF8StringNormalize, octetStringMatch,
2799 octetStringIndexer, octetStringFilter,
2800 directoryStringApproxMatchOID },
2802 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2803 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2804 SLAP_MR_ORDERING, directoryStringSyntaxes,
2805 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2809 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2810 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2811 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2812 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2813 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2816 {"( 2.5.13.8 NAME 'numericStringMatch' "
2817 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2818 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2819 NULL, numericStringNormalize, octetStringSubstringsMatch,
2820 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2823 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2824 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2825 SLAP_MR_SUBSTR, NULL,
2826 NULL, numericStringNormalize, octetStringSubstringsMatch,
2827 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2828 "numericStringMatch" },
2830 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2831 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2832 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2833 NULL, NULL, NULL, NULL, NULL, NULL },
2835 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2836 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2837 SLAP_MR_SUBSTR, NULL,
2838 NULL, NULL, NULL, NULL, NULL,
2839 "caseIgnoreListMatch" },
2841 {"( 2.5.13.13 NAME 'booleanMatch' "
2842 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2843 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2844 NULL, NULL, booleanMatch,
2845 octetStringIndexer, octetStringFilter,
2848 {"( 2.5.13.14 NAME 'integerMatch' "
2849 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2850 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2851 NULL, NULL, integerMatch,
2852 octetStringIndexer, octetStringFilter,
2855 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2856 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2857 SLAP_MR_ORDERING, NULL,
2858 NULL, NULL, integerMatch,
2862 {"( 2.5.13.16 NAME 'bitStringMatch' "
2863 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2864 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2865 NULL, NULL, octetStringMatch,
2866 octetStringIndexer, octetStringFilter,
2869 {"( 2.5.13.17 NAME 'octetStringMatch' "
2870 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2871 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2872 NULL, NULL, octetStringMatch,
2873 octetStringIndexer, octetStringFilter,
2876 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2877 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2878 SLAP_MR_ORDERING, NULL,
2879 NULL, NULL, octetStringOrderingMatch,
2881 "octetStringMatch" },
2883 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2884 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2885 SLAP_MR_SUBSTR, NULL,
2886 NULL, NULL, octetStringSubstringsMatch,
2887 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2888 "octetStringMatch" },
2890 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2891 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2892 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2894 telephoneNumberNormalize, octetStringMatch,
2895 octetStringIndexer, octetStringFilter,
2898 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2899 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2900 SLAP_MR_SUBSTR, NULL,
2901 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2902 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2903 "telephoneNumberMatch" },
2905 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2906 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2907 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2908 NULL, NULL, NULL, NULL, NULL, NULL },
2910 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2911 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2912 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2913 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2917 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2918 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2919 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2920 NULL, NULL, NULL, NULL, NULL, NULL },
2922 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2923 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2924 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2925 NULL, generalizedTimeNormalize, octetStringMatch,
2929 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2930 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2931 SLAP_MR_ORDERING, NULL,
2932 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
2934 "generalizedTimeMatch" },
2936 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
2937 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2938 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2939 integerFirstComponentMatchSyntaxes,
2940 NULL, firstComponentNormalize, integerMatch,
2941 octetStringIndexer, octetStringFilter,
2944 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
2945 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2946 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2947 objectIdentifierFirstComponentMatchSyntaxes,
2948 NULL, firstComponentNormalize, octetStringMatch,
2949 octetStringIndexer, octetStringFilter,
2953 {"( 2.5.13.34 NAME 'certificateExactMatch' "
2954 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
2955 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
2956 NULL, certificateExactNormalize, octetStringMatch,
2957 octetStringIndexer, octetStringFilter,
2961 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
2962 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2963 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2964 NULL, IA5StringNormalize, octetStringMatch,
2965 octetStringIndexer, octetStringFilter,
2966 IA5StringApproxMatchOID },
2968 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
2969 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2970 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2971 NULL, IA5StringNormalize, octetStringMatch,
2972 octetStringIndexer, octetStringFilter,
2973 IA5StringApproxMatchOID },
2975 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
2976 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2977 SLAP_MR_SUBSTR, NULL,
2978 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2979 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2980 "caseIgnoreIA5Match" },
2982 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
2983 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2984 SLAP_MR_SUBSTR, NULL,
2985 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2986 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2987 "caseExactIA5Match" },
2989 #ifdef SLAPD_AUTHPASSWD
2990 /* needs updating */
2991 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
2992 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2993 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
2994 NULL, NULL, authPasswordMatch,
2999 #ifdef SLAPD_ACI_ENABLED
3000 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3001 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3002 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
3003 NULL, NULL, OpenLDAPaciMatch,
3008 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3009 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3011 NULL, NULL, integerBitAndMatch,
3015 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3016 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3018 NULL, NULL, integerBitOrMatch,
3022 {NULL, SLAP_MR_NONE, NULL,
3023 NULL, NULL, NULL, NULL, NULL,
3028 slap_schema_init( void )
3033 /* we should only be called once (from main) */
3034 assert( schema_init_done == 0 );
3036 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3037 res = register_syntax( &syntax_defs[i] );
3040 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3041 syntax_defs[i].sd_desc );
3046 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3047 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3048 mrule_defs[i].mrd_compat_syntaxes == NULL )
3051 "slap_schema_init: Ignoring unusable matching rule %s\n",
3052 mrule_defs[i].mrd_desc );
3056 res = register_matching_rule( &mrule_defs[i] );
3060 "slap_schema_init: Error registering matching rule %s\n",
3061 mrule_defs[i].mrd_desc );
3066 res = slap_schema_load();
3067 schema_init_done = 1;
3072 schema_destroy( void )