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;
1796 struct berval *value,
1797 void *assertedValue )
1799 long lValue, lAssertedValue;
1801 /* safe to assume integers are NUL terminated? */
1802 lValue = strtol(value->bv_val, NULL, 10);
1803 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1804 return LDAP_CONSTRAINT_VIOLATION;
1807 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1808 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1809 && errno == ERANGE )
1811 return LDAP_CONSTRAINT_VIOLATION;
1814 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1815 return LDAP_SUCCESS;
1824 struct berval *value,
1825 void *assertedValue )
1827 long lValue, lAssertedValue;
1829 /* safe to assume integers are NUL terminated? */
1830 lValue = strtol(value->bv_val, NULL, 10);
1831 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1832 return LDAP_CONSTRAINT_VIOLATION;
1835 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1836 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1837 && errno == ERANGE )
1839 return LDAP_CONSTRAINT_VIOLATION;
1842 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1843 return LDAP_SUCCESS;
1847 serialNumberAndIssuerValidate(
1851 int rc = LDAP_INVALID_SYNTAX;
1852 struct berval serialNumber, issuer;
1854 serialNumber.bv_val = in->bv_val;
1855 for( serialNumber.bv_len = 0;
1856 serialNumber.bv_len < in->bv_len;
1857 serialNumber.bv_len++ )
1859 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1860 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1861 issuer.bv_len = in->bv_len - (serialNumber.bv_len+1);
1863 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1865 rc = integerValidate( NULL, &serialNumber );
1868 rc = dnValidate( NULL, &issuer );
1877 serialNumberAndIssuerNormalize(
1882 struct berval *normalized,
1885 int rc = LDAP_INVALID_SYNTAX;
1886 struct berval serialNumber, issuer, nissuer;
1888 serialNumber.bv_val = val->bv_val;
1889 for( serialNumber.bv_len = 0;
1890 serialNumber.bv_len < val->bv_len;
1891 serialNumber.bv_len++ )
1893 if ( serialNumber.bv_val[serialNumber.bv_len] == '$' ) {
1894 issuer.bv_val = &serialNumber.bv_val[serialNumber.bv_len+1];
1895 issuer.bv_len = val->bv_len - (serialNumber.bv_len+1);
1897 if( serialNumber.bv_len == 0 || issuer.bv_len == 0 ) break;
1899 rc = dnNormalize( usage, syntax, mr, &issuer, &nissuer, ctx );
1902 normalized->bv_len = serialNumber.bv_len + 1 + nissuer.bv_len;
1903 normalized->bv_val = ch_malloc( normalized->bv_len + 1);
1905 AC_MEMCPY( normalized->bv_val,
1906 serialNumber.bv_val, serialNumber.bv_len );
1907 normalized->bv_val[serialNumber.bv_len] = '$';
1908 AC_MEMCPY( &normalized->bv_val[serialNumber.bv_len+1],
1909 nissuer.bv_val, nissuer.bv_len );
1910 normalized->bv_val[normalized->bv_len] = '\0';
1919 #include <openssl/x509.h>
1920 #include <openssl/err.h>
1923 * Next function returns a string representation of a ASN1_INTEGER.
1924 * It works for unlimited lengths.
1927 static struct berval *
1928 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1932 static char digit[] = "0123456789";
1934 /* We work backwards, make it fill from the end of buf */
1935 p = buf + sizeof(buf) - 1;
1938 if ( a == NULL || a->length == 0 ) {
1946 /* We want to preserve the original */
1947 copy = ch_malloc(n*sizeof(unsigned int));
1948 for (i = 0; i<n; i++) {
1949 copy[i] = a->data[i];
1953 * base indicates the index of the most significant
1954 * byte that might be nonzero. When it goes off the
1955 * end, we now there is nothing left to do.
1961 for (i = base; i<n; i++ ) {
1962 copy[i] += carry*256;
1963 carry = copy[i] % 10;
1968 * Way too large, we need to leave
1969 * room for sign if negative
1974 *--p = digit[carry];
1976 if (copy[base] == 0) base++;
1981 if ( a->type == V_ASN1_NEG_INTEGER ) {
1985 return ber_str2bv( p, 0, 1, bv );
1989 * Given a certificate in DER format, extract the corresponding
1990 * assertion value for certificateExactMatch
1993 certificateExactConvert(
1995 struct berval * out )
1999 unsigned char *p = in->bv_val;
2000 struct berval serial;
2001 struct berval issuer_dn;
2003 xcert = d2i_X509(NULL, &p, in->bv_len);
2006 LDAP_LOG( CONFIG, ENTRY,
2007 "certificateExactConvert: error parsing cert: %s\n",
2008 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2010 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2011 "error parsing cert: %s\n",
2012 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2014 return LDAP_INVALID_SYNTAX;
2017 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2019 return LDAP_INVALID_SYNTAX;
2022 rc = dnX509normalize( X509_get_issuer_name(xcert), &issuer_dn );
2023 if( rc != LDAP_SUCCESS ) {
2025 ber_memfree(serial.bv_val);
2026 return LDAP_INVALID_SYNTAX;
2031 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2032 out->bv_val = ch_malloc(out->bv_len);
2034 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2036 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2038 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2039 p += issuer_dn.bv_len;
2043 LDAP_LOG( CONFIG, ARGS, "certificateExactConvert: %s\n",
2044 out->bv_val, 0, 0 );
2046 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: %s\n",
2047 out->bv_val, NULL, NULL );
2050 ber_memfree(serial.bv_val);
2051 ber_memfree(issuer_dn.bv_val);
2053 return LDAP_SUCCESS;
2057 certificateExactNormalize(
2062 struct berval *normalized,
2067 if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage ) ) {
2068 rc = serialNumberAndIssuerNormalize( usage, syntax, mr,
2069 val, normalized, ctx );
2072 rc = certificateExactConvert( val, normalized );
2077 #endif /* HAVE_TLS */
2080 #ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
2081 /* slight optimization - does not need the start parameter */
2082 #define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
2087 check_time_syntax (struct berval *val,
2090 struct berval *fraction)
2093 * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
2094 * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
2095 * GeneralizedTime supports leap seconds, UTCTime does not.
2097 static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
2098 static const int mdays[2][12] = {
2099 /* non-leap years */
2100 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2102 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
2105 int part, c, c1, c2, tzoffset, leapyear = 0;
2108 e = p + val->bv_len;
2110 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2111 parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
2113 for (part = start; part < 7 && p < e; part++) {
2115 if (!ASCII_DIGIT(c1)) {
2120 return LDAP_INVALID_SYNTAX;
2123 if (!ASCII_DIGIT(c)) {
2124 return LDAP_INVALID_SYNTAX;
2126 c += c1 * 10 - '0' * 11;
2127 if ((part | 1) == 3) {
2130 return LDAP_INVALID_SYNTAX;
2133 if (c >= ceiling[part]) {
2134 if (! (c == 60 && part == 6 && start == 0))
2135 return LDAP_INVALID_SYNTAX;
2139 if (part < 5 + start) {
2140 return LDAP_INVALID_SYNTAX;
2142 for (; part < 9; part++) {
2146 /* leapyear check for the Gregorian calendar (year>1581) */
2147 if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
2152 if (parts[3] >= mdays[leapyear][parts[2]]) {
2153 return LDAP_INVALID_SYNTAX;
2157 fraction->bv_val = p;
2158 fraction->bv_len = 0;
2159 if (p < e && (*p == '.' || *p == ',')) {
2161 while (++p < e && ASCII_DIGIT(*p))
2163 if (p - fraction->bv_val == 1) {
2164 return LDAP_INVALID_SYNTAX;
2166 for (end_num = p; end_num[-1] == '0'; --end_num)
2168 c = end_num - fraction->bv_val;
2170 fraction->bv_len = c;
2176 return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2182 return LDAP_INVALID_SYNTAX;
2188 for (part = 7; part < 9 && p < e; part++) {
2190 if (!ASCII_DIGIT(c1)) {
2195 return LDAP_INVALID_SYNTAX;
2198 if (!ASCII_DIGIT(c2)) {
2199 return LDAP_INVALID_SYNTAX;
2201 parts[part] = c1 * 10 + c2 - '0' * 11;
2202 if (parts[part] >= ceiling[part]) {
2203 return LDAP_INVALID_SYNTAX;
2206 if (part < 8 + start) {
2207 return LDAP_INVALID_SYNTAX;
2210 if (tzoffset == '-') {
2211 /* negative offset to UTC, ie west of Greenwich */
2212 parts[4] += parts[7];
2213 parts[5] += parts[8];
2214 /* offset is just hhmm, no seconds */
2215 for (part = 6; --part >= 0; ) {
2219 c = mdays[leapyear][parts[2]];
2221 if (parts[part] >= c) {
2223 return LDAP_INVALID_SYNTAX;
2228 } else if (part != 5) {
2233 /* positive offset to UTC, ie east of Greenwich */
2234 parts[4] -= parts[7];
2235 parts[5] -= parts[8];
2236 for (part = 6; --part >= 0; ) {
2237 if (parts[part] < 0) {
2239 return LDAP_INVALID_SYNTAX;
2244 /* make first arg to % non-negative */
2245 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2250 } else if (part != 5) {
2257 return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
2260 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2267 struct berval *normalized )
2271 rc = check_time_syntax(val, 1, parts, NULL);
2272 if (rc != LDAP_SUCCESS) {
2276 normalized->bv_val = ch_malloc( 14 );
2277 if ( normalized->bv_val == NULL ) {
2278 return LBER_ERROR_MEMORY;
2281 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2282 parts[1], parts[2] + 1, parts[3] + 1,
2283 parts[4], parts[5], parts[6] );
2284 normalized->bv_len = 13;
2286 return LDAP_SUCCESS;
2296 return check_time_syntax(in, 1, parts, NULL);
2299 #endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
2302 generalizedTimeValidate(
2307 struct berval fraction;
2308 return check_time_syntax(in, 0, parts, &fraction);
2312 generalizedTimeNormalize(
2317 struct berval *normalized,
2322 struct berval fraction;
2324 rc = check_time_syntax(val, 0, parts, &fraction);
2325 if (rc != LDAP_SUCCESS) {
2329 len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
2330 normalized->bv_val = sl_malloc( len + 1, ctx );
2331 if ( normalized->bv_val == NULL ) {
2332 return LBER_ERROR_MEMORY;
2335 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
2336 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2337 parts[4], parts[5], parts[6] );
2338 if ( fraction.bv_len ) {
2339 memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
2340 fraction.bv_val, fraction.bv_len );
2341 normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
2343 strcpy( normalized->bv_val + len-1, "Z" );
2344 normalized->bv_len = len;
2346 return LDAP_SUCCESS;
2350 generalizedTimeOrderingMatch(
2355 struct berval *value,
2356 void *assertedValue )
2358 struct berval *asserted = (struct berval *) assertedValue;
2359 ber_len_t v_len = value->bv_len;
2360 ber_len_t av_len = asserted->bv_len;
2362 /* ignore trailing 'Z' when comparing */
2363 int match = memcmp( value->bv_val, asserted->bv_val,
2364 (v_len < av_len ? v_len : av_len) - 1 );
2365 if ( match == 0 ) match = v_len - av_len;
2368 return LDAP_SUCCESS;
2372 nisNetgroupTripleValidate(
2374 struct berval *val )
2379 if ( val->bv_len == 0 ) {
2380 return LDAP_INVALID_SYNTAX;
2383 p = (char *)val->bv_val;
2384 e = p + val->bv_len;
2386 if ( *p != '(' /*')'*/ ) {
2387 return LDAP_INVALID_SYNTAX;
2390 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2394 return LDAP_INVALID_SYNTAX;
2397 } else if ( !AD_CHAR( *p ) ) {
2398 return LDAP_INVALID_SYNTAX;
2402 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2403 return LDAP_INVALID_SYNTAX;
2409 return LDAP_INVALID_SYNTAX;
2412 return LDAP_SUCCESS;
2416 bootParameterValidate(
2418 struct berval *val )
2422 if ( val->bv_len == 0 ) {
2423 return LDAP_INVALID_SYNTAX;
2426 p = (char *)val->bv_val;
2427 e = p + val->bv_len;
2430 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2431 if ( !AD_CHAR( *p ) ) {
2432 return LDAP_INVALID_SYNTAX;
2437 return LDAP_INVALID_SYNTAX;
2441 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2442 if ( !AD_CHAR( *p ) ) {
2443 return LDAP_INVALID_SYNTAX;
2448 return LDAP_INVALID_SYNTAX;
2452 for ( p++; p < e; p++ ) {
2453 if ( !SLAP_PRINTABLE( *p ) ) {
2454 return LDAP_INVALID_SYNTAX;
2458 return LDAP_SUCCESS;
2462 firstComponentNormalize(
2467 struct berval *normalized,
2474 if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
2476 if( val->bv_val[0] != '(' /*')'*/ &&
2477 val->bv_val[0] != '{' /*'}'*/ )
2479 return LDAP_INVALID_SYNTAX;
2482 /* trim leading white space */
2484 len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
2490 /* grab next word */
2491 oid.bv_val = &val->bv_val[len];
2492 len = val->bv_len - len;
2494 !ASCII_SPACE(oid.bv_val[oid.bv_len]) && oid.bv_len < len;
2500 if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
2501 rc = numericoidValidate( NULL, &oid );
2502 } else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
2503 rc = integerValidate( NULL, &oid );
2505 rc = LDAP_INVALID_SYNTAX;
2509 if( rc == LDAP_SUCCESS ) {
2510 ber_dupbv_x( normalized, &oid, ctx );
2517 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2518 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2520 static slap_syntax_defs_rec syntax_defs[] = {
2521 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2522 X_BINARY X_NOT_H_R ")",
2523 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2524 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2526 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2528 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2530 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2531 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2533 SLAP_SYNTAX_BER, berValidate, NULL},
2534 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2535 0, bitStringValidate, NULL },
2536 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2537 0, booleanValidate, NULL},
2538 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2539 X_BINARY X_NOT_H_R ")",
2540 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2541 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2542 X_BINARY X_NOT_H_R ")",
2543 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2544 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2545 X_BINARY X_NOT_H_R ")",
2546 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2547 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2548 0, countryStringValidate, NULL},
2549 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2550 0, dnValidate, dnPretty},
2551 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2553 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2555 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2556 0, UTF8StringValidate, NULL},
2557 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2559 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2561 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2563 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2565 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2567 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2568 0, printablesStringValidate, NULL},
2569 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2570 SLAP_SYNTAX_BLOB, NULL, NULL},
2571 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2572 0, generalizedTimeValidate, NULL},
2573 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2575 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2576 0, IA5StringValidate, NULL},
2577 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2578 0, integerValidate, NULL},
2579 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2580 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2581 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2583 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2585 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2587 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2589 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2591 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2592 0, nameUIDValidate, nameUIDPretty },
2593 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2595 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2596 0, numericStringValidate, NULL},
2597 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2599 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2600 0, numericoidValidate, NULL},
2601 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2602 0, IA5StringValidate, NULL},
2603 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2604 0, blobValidate, NULL},
2605 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2606 0, UTF8StringValidate, NULL},
2607 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2609 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2611 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2612 0, printableStringValidate, NULL},
2613 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
2614 #define subtreeSpecificationValidate UTF8StringValidate /* FIXME */
2615 0, subtreeSpecificationValidate, NULL},
2616 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2617 X_BINARY X_NOT_H_R ")",
2618 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2619 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2620 0, printableStringValidate, NULL},
2621 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2623 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2624 0, printablesStringValidate, NULL},
2625 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2626 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2627 0, utcTimeValidate, NULL},
2629 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2631 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2633 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2635 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2637 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2640 /* RFC 2307 NIS Syntaxes */
2641 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2642 0, nisNetgroupTripleValidate, NULL},
2643 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2644 0, bootParameterValidate, NULL},
2647 /* These OIDs are not published yet, but will be in the next
2648 * I-D for PKIX LDAPv3 schema as have been advanced by David
2649 * Chadwick in private mail.
2651 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2652 0, serialNumberAndIssuerValidate, NULL},
2654 /* OpenLDAP Experimental Syntaxes */
2655 #ifdef SLAPD_ACI_ENABLED
2656 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2658 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2662 #ifdef SLAPD_AUTHPASSWD
2663 /* needs updating */
2664 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2665 SLAP_SYNTAX_HIDE, NULL, NULL},
2668 /* OpenLDAP Void Syntax */
2669 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2670 SLAP_SYNTAX_HIDE, inValidate, NULL},
2671 {NULL, 0, NULL, NULL}
2675 char *certificateExactMatchSyntaxes[] = {
2676 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2680 char *directoryStringSyntaxes[] = {
2681 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2684 char *integerFirstComponentMatchSyntaxes[] = {
2685 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2686 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2689 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2690 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2691 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2692 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2693 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2694 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2695 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2696 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2697 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2702 * Other matching rules in X.520 that we do not use (yet):
2704 * 2.5.13.9 numericStringOrderingMatch
2705 * 2.5.13.25 uTCTimeMatch
2706 * 2.5.13.26 uTCTimeOrderingMatch
2707 * 2.5.13.31 directoryStringFirstComponentMatch
2708 * 2.5.13.32 wordMatch
2709 * 2.5.13.33 keywordMatch
2710 * 2.5.13.35 certificateMatch
2711 * 2.5.13.36 certificatePairExactMatch
2712 * 2.5.13.37 certificatePairMatch
2713 * 2.5.13.38 certificateListExactMatch
2714 * 2.5.13.39 certificateListMatch
2715 * 2.5.13.40 algorithmIdentifierMatch
2716 * 2.5.13.41 storedPrefixMatch
2717 * 2.5.13.42 attributeCertificateMatch
2718 * 2.5.13.43 readerAndKeyIDMatch
2719 * 2.5.13.44 attributeIntegrityMatch
2721 static slap_mrule_defs_rec mrule_defs[] = {
2723 * EQUALITY matching rules must be listed after associated APPROX
2724 * matching rules. So, we list all APPROX matching rules first.
2726 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2728 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2729 NULL, NULL, directoryStringApproxMatch,
2730 directoryStringApproxIndexer, directoryStringApproxFilter,
2733 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2734 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2735 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2736 NULL, NULL, IA5StringApproxMatch,
2737 IA5StringApproxIndexer, IA5StringApproxFilter,
2741 * Other matching rules
2744 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2745 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2746 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2747 NULL, NULL, octetStringMatch,
2748 octetStringIndexer, octetStringFilter,
2751 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2752 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2753 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2754 NULL, dnNormalize, dnMatch,
2755 octetStringIndexer, octetStringFilter,
2758 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2759 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2760 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2761 NULL, UTF8StringNormalize, octetStringMatch,
2762 octetStringIndexer, octetStringFilter,
2763 directoryStringApproxMatchOID },
2765 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2766 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2767 SLAP_MR_ORDERING, directoryStringSyntaxes,
2768 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2770 "caseIgnoreMatch" },
2772 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2773 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2774 SLAP_MR_SUBSTR, NULL,
2775 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2776 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2777 "caseIgnoreMatch" },
2779 {"( 2.5.13.5 NAME 'caseExactMatch' "
2780 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2781 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2782 NULL, UTF8StringNormalize, octetStringMatch,
2783 octetStringIndexer, octetStringFilter,
2784 directoryStringApproxMatchOID },
2786 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2787 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2788 SLAP_MR_ORDERING, directoryStringSyntaxes,
2789 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2793 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2794 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2795 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2796 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2797 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2800 {"( 2.5.13.8 NAME 'numericStringMatch' "
2801 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2802 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2803 NULL, numericStringNormalize, octetStringSubstringsMatch,
2804 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2807 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2808 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2809 SLAP_MR_SUBSTR, NULL,
2810 NULL, numericStringNormalize, octetStringSubstringsMatch,
2811 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2812 "numericStringMatch" },
2814 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2815 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2816 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2817 NULL, NULL, NULL, NULL, NULL, NULL },
2819 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2820 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2821 SLAP_MR_SUBSTR, NULL,
2822 NULL, NULL, NULL, NULL, NULL,
2823 "caseIgnoreListMatch" },
2825 {"( 2.5.13.13 NAME 'booleanMatch' "
2826 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2827 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2828 NULL, NULL, booleanMatch,
2829 octetStringIndexer, octetStringFilter,
2832 {"( 2.5.13.14 NAME 'integerMatch' "
2833 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2834 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2835 NULL, NULL, integerMatch,
2836 octetStringIndexer, octetStringFilter,
2839 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2840 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2841 SLAP_MR_ORDERING, NULL,
2842 NULL, NULL, integerMatch,
2846 {"( 2.5.13.16 NAME 'bitStringMatch' "
2847 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2848 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2849 NULL, NULL, octetStringMatch,
2850 octetStringIndexer, octetStringFilter,
2853 {"( 2.5.13.17 NAME 'octetStringMatch' "
2854 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2855 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2856 NULL, NULL, octetStringMatch,
2857 octetStringIndexer, octetStringFilter,
2860 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
2861 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2862 SLAP_MR_ORDERING, NULL,
2863 NULL, NULL, octetStringOrderingMatch,
2865 "octetStringMatch" },
2867 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
2868 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2869 SLAP_MR_SUBSTR, NULL,
2870 NULL, NULL, octetStringSubstringsMatch,
2871 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2872 "octetStringMatch" },
2874 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2875 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2876 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2878 telephoneNumberNormalize, octetStringMatch,
2879 octetStringIndexer, octetStringFilter,
2882 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2883 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2884 SLAP_MR_SUBSTR, NULL,
2885 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
2886 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2887 "telephoneNumberMatch" },
2889 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2890 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2891 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2892 NULL, NULL, NULL, NULL, NULL, NULL },
2894 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2895 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2896 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2897 NULL, uniqueMemberNormalize, uniqueMemberMatch,
2901 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2902 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2903 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2904 NULL, NULL, NULL, NULL, NULL, NULL },
2906 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2907 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2908 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2909 NULL, generalizedTimeNormalize, octetStringMatch,
2913 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2914 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2915 SLAP_MR_ORDERING, NULL,
2916 NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
2918 "generalizedTimeMatch" },
2920 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
2921 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2922 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2923 integerFirstComponentMatchSyntaxes,
2924 NULL, firstComponentNormalize, integerMatch,
2925 octetStringIndexer, octetStringFilter,
2928 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
2929 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2930 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2931 objectIdentifierFirstComponentMatchSyntaxes,
2932 NULL, firstComponentNormalize, octetStringMatch,
2933 octetStringIndexer, octetStringFilter,
2937 {"( 2.5.13.34 NAME 'certificateExactMatch' "
2938 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
2939 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
2940 NULL, certificateExactNormalize, octetStringMatch,
2941 octetStringIndexer, octetStringFilter,
2945 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
2946 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2947 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2948 NULL, IA5StringNormalize, octetStringMatch,
2949 octetStringIndexer, octetStringFilter,
2950 IA5StringApproxMatchOID },
2952 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
2953 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2954 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2955 NULL, IA5StringNormalize, octetStringMatch,
2956 octetStringIndexer, octetStringFilter,
2957 IA5StringApproxMatchOID },
2959 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
2960 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2961 SLAP_MR_SUBSTR, NULL,
2962 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2963 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2964 "caseIgnoreIA5Match" },
2966 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
2967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2968 SLAP_MR_SUBSTR, NULL,
2969 NULL, IA5StringNormalize, octetStringSubstringsMatch,
2970 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2971 "caseExactIA5Match" },
2973 #ifdef SLAPD_AUTHPASSWD
2974 /* needs updating */
2975 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
2976 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2977 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
2978 NULL, NULL, authPasswordMatch,
2983 #ifdef SLAPD_ACI_ENABLED
2984 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
2985 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
2986 SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
2987 NULL, NULL, OpenLDAPaciMatch,
2992 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
2993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2995 NULL, NULL, integerBitAndMatch,
2999 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3002 NULL, NULL, integerBitOrMatch,
3006 {NULL, SLAP_MR_NONE, NULL,
3007 NULL, NULL, NULL, NULL, NULL,
3012 slap_schema_init( void )
3017 /* we should only be called once (from main) */
3018 assert( schema_init_done == 0 );
3020 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3021 res = register_syntax( &syntax_defs[i] );
3024 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3025 syntax_defs[i].sd_desc );
3030 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3031 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3032 mrule_defs[i].mrd_compat_syntaxes == NULL )
3035 "slap_schema_init: Ignoring unusable matching rule %s\n",
3036 mrule_defs[i].mrd_desc );
3040 res = register_matching_rule( &mrule_defs[i] );
3044 "slap_schema_init: Error registering matching rule %s\n",
3045 mrule_defs[i].mrd_desc );
3050 res = slap_schema_load();
3051 schema_init_done = 1;
3056 schema_destroy( void )