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 SLAP_NVALUES 1
33 #define SLAP_MR_ASSOCIATED(mr, with) \
34 ((mr) == (with) || (mr)->smr_associated == (with))
36 #define xUTF8StringNormalize NULL
37 #define xIA5StringNormalize NULL
38 #define xtelephoneNumberNormalize NULL
39 #define xgeneralizedTimeNormalize NULL
40 #define xintegerNormalize NULL
41 #define xnumericStringNormalize NULL
42 #define xnameUIDNormalize NULL
43 #define xdnNormalize NULL
45 /* (new) normalization routines */
46 #define caseExactIA5Normalize IA5StringNormalize
47 #define caseIgnoreIA5Normalize IA5StringNormalize
48 #define caseExactNormalize UTF8StringNormalize
49 #define caseIgnoreNormalize UTF8StringNormalize
51 #define integerFirstComponentNormalize NULL
52 #define objectIdentifierNormalize NULL
53 #define objectIdentifierFirstComponentNormalize NULL
55 #define distinguishedNameNormalize dnNormalize
56 #define distinguishedNameMatch dnMatch
57 #define distinguishedNameIndexer octetStringIndexer
58 #define distinguishedNameFilter octetStringFilter
60 #define integerOrderingMatch integerMatch
61 #define integerFirstComponentMatch NULL
62 #define integerIndexer octetStringIndexer
63 #define integerFilter octetStringFilter
65 #define generalizedTimeMatch caseIgnoreIA5Match
66 #define generalizedTimeOrderingMatch caseIgnoreIA5Match
68 #define uniqueMemberMatch dnMatch /* FIXME! */
70 #define objectIdentifierMatch octetStringMatch
71 #define objectIdentifierIndexer octetStringIndexer
72 #define objectIdentifierFilter octetStringFilter
74 #define OpenLDAPaciMatch NULL
76 #define bitStringMatch octetStringMatch
77 #define bitStringIndexer octetStringIndexer
78 #define bitStringFilter octetStringFilter
80 #define caseIgnoreMatch octetStringMatch
81 #define caseIgnoreOrderingMatch octetStringOrderingMatch
82 #define caseIgnoreIndexer octetStringIndexer
83 #define caseIgnoreFilter octetStringFilter
85 #define caseIgnoreSubstringsMatch octetStringSubstringsMatch
86 #define caseIgnoreSubstringsIndexer octetStringSubstringsIndexer
87 #define caseIgnoreSubstringsFilter octetStringSubstringsFilter
89 #define caseExactMatch octetStringMatch
90 #define caseExactOrderingMatch octetStringOrderingMatch
91 #define caseExactIndexer octetStringIndexer
92 #define caseExactFilter octetStringFilter
94 #define caseExactSubstringsMatch octetStringSubstringsMatch
95 #define caseExactSubstringsIndexer octetStringSubstringsIndexer
96 #define caseExactSubstringsFilter octetStringSubstringsFilter
98 #define caseExactIA5Match octetStringMatch
99 #define caseExactIA5Indexer octetStringIndexer
100 #define caseExactIA5Filter octetStringFilter
102 #define caseExactIA5SubstringsMatch octetStringSubstringsMatch
103 #define caseExactIA5SubstringsIndexer octetStringSubstringsIndexer
104 #define caseExactIA5SubstringsFilter octetStringSubstringsFilter
106 #define caseIgnoreIA5Match octetStringMatch
107 #define caseIgnoreIA5Indexer octetStringIndexer
108 #define caseIgnoreIA5Filter octetStringFilter
110 #define caseIgnoreIA5SubstringsMatch caseExactIA5SubstringsMatch
111 #define caseIgnoreIA5SubstringsIndexer caseExactIA5SubstringsIndexer
112 #define caseIgnoreIA5SubstringsFilter caseExactIA5SubstringsFilter
114 #define numericStringMatch octetStringMatch
115 #define numericStringIndexer octetStringIndexer
116 #define numericStringFilter octetStringFilter
118 #define numericStringSubstringsMatch caseExactIA5SubstringsMatch
119 #define numericStringSubstringsIndexer caseExactIA5SubstringsIndexer
120 #define numericStringSubstringsFilter caseExactIA5SubstringsFilter
122 #define telephoneNumberMatch octetStringMatch
123 #define telephoneNumberIndexer octetStringIndexer
124 #define telephoneNumberFilter octetStringFilter
126 #define telephoneNumberSubstringsMatch caseExactIA5SubstringsMatch
127 #define telephoneNumberSubstringsIndexer caseExactIA5SubstringsIndexer
128 #define telephoneNumberSubstringsFilter caseExactIA5SubstringsFilter
130 #define booleanIndexer octetStringIndexer
131 #define booleanFilter octetStringFilter
133 /* validatation routines */
134 #define berValidate blobValidate
136 /* approx matching rules */
138 #define directoryStringApproxMatchOID NULL
139 #define IA5StringApproxMatchOID NULL
141 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
142 #define directoryStringApproxMatch approxMatch
143 #define directoryStringApproxIndexer approxIndexer
144 #define directoryStringApproxFilter approxFilter
145 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
146 #define IA5StringApproxMatch approxMatch
147 #define IA5StringApproxIndexer approxIndexer
148 #define IA5StringApproxFilter approxFilter
151 static char *bvcasechr( struct berval *bv, unsigned char c, ber_len_t *len )
154 char lower = TOLOWER( c );
155 char upper = TOUPPER( c );
157 if( c == 0 ) return NULL;
159 for( i=0; i < bv->bv_len; i++ ) {
160 if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
162 return &bv->bv_val[i];
175 struct berval *value,
176 void *assertedValue )
178 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
181 match = memcmp( value->bv_val,
182 ((struct berval *) assertedValue)->bv_val,
191 octetStringOrderingMatch(
196 struct berval *value,
197 void *assertedValue )
199 ber_len_t v_len = value->bv_len;
200 ber_len_t av_len = ((struct berval *) assertedValue)->bv_len;
202 int match = memcmp( value->bv_val,
203 ((struct berval *) assertedValue)->bv_val,
204 (v_len < av_len ? v_len : av_len) );
206 if( match == 0 ) match = v_len - av_len;
212 /* Index generation function */
213 int octetStringIndexer(
218 struct berval *prefix,
225 HASH_CONTEXT HASHcontext;
226 unsigned char HASHdigest[HASH_BYTES];
227 struct berval digest;
228 digest.bv_val = HASHdigest;
229 digest.bv_len = sizeof(HASHdigest);
231 for( i=0; values[i].bv_val != NULL; i++ ) {
232 /* just count them */
235 /* we should have at least one value at this point */
238 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
240 slen = syntax->ssyn_oidlen;
241 mlen = mr->smr_oidlen;
243 for( i=0; values[i].bv_val != NULL; i++ ) {
244 HASH_Init( &HASHcontext );
245 if( prefix != NULL && prefix->bv_len > 0 ) {
246 HASH_Update( &HASHcontext,
247 prefix->bv_val, prefix->bv_len );
249 HASH_Update( &HASHcontext,
250 syntax->ssyn_oid, slen );
251 HASH_Update( &HASHcontext,
253 HASH_Update( &HASHcontext,
254 values[i].bv_val, values[i].bv_len );
255 HASH_Final( HASHdigest, &HASHcontext );
257 ber_dupbv( &keys[i], &digest );
260 keys[i].bv_val = NULL;
268 /* Index generation function */
269 int octetStringFilter(
274 struct berval *prefix,
275 void * assertedValue,
280 HASH_CONTEXT HASHcontext;
281 unsigned char HASHdigest[HASH_BYTES];
282 struct berval *value = (struct berval *) assertedValue;
283 struct berval digest;
284 digest.bv_val = HASHdigest;
285 digest.bv_len = sizeof(HASHdigest);
287 slen = syntax->ssyn_oidlen;
288 mlen = mr->smr_oidlen;
290 keys = ch_malloc( sizeof( struct berval ) * 2 );
292 HASH_Init( &HASHcontext );
293 if( prefix != NULL && prefix->bv_len > 0 ) {
294 HASH_Update( &HASHcontext,
295 prefix->bv_val, prefix->bv_len );
297 HASH_Update( &HASHcontext,
298 syntax->ssyn_oid, slen );
299 HASH_Update( &HASHcontext,
301 HASH_Update( &HASHcontext,
302 value->bv_val, value->bv_len );
303 HASH_Final( HASHdigest, &HASHcontext );
305 ber_dupbv( keys, &digest );
306 keys[1].bv_val = NULL;
319 /* no value allowed */
320 return LDAP_INVALID_SYNTAX;
328 /* any value allowed */
339 /* very unforgiving validation, requires no normalization
340 * before simplistic matching
342 if( in->bv_len < 3 ) {
343 return LDAP_INVALID_SYNTAX;
347 * rfc 2252 section 6.3 Bit String
348 * bitstring = "'" *binary-digit "'"
349 * binary-digit = "0" / "1"
350 * example: '0101111101'B
353 if( in->bv_val[0] != '\'' ||
354 in->bv_val[in->bv_len-2] != '\'' ||
355 in->bv_val[in->bv_len-1] != 'B' )
357 return LDAP_INVALID_SYNTAX;
360 for( i=in->bv_len-3; i>0; i-- ) {
361 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
362 return LDAP_INVALID_SYNTAX;
377 if( in->bv_len == 0 ) return LDAP_SUCCESS;
379 ber_dupbv( &dn, in );
380 if( !dn.bv_val ) return LDAP_OTHER;
382 if( dn.bv_val[dn.bv_len-1] == 'B'
383 && dn.bv_val[dn.bv_len-2] == '\'' )
385 /* assume presence of optional UID */
388 for(i=dn.bv_len-3; i>1; i--) {
389 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
393 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
394 ber_memfree( dn.bv_val );
395 return LDAP_INVALID_SYNTAX;
398 /* trim the UID to allow use of dnValidate */
399 dn.bv_val[i-1] = '\0';
403 rc = dnValidate( NULL, &dn );
405 ber_memfree( dn.bv_val );
410 uniqueMemberNormalize(
415 struct berval *normalized )
420 ber_dupbv( &out, val );
421 if( out.bv_len != 0 ) {
422 struct berval uid = { 0, NULL };
424 if( out.bv_val[out.bv_len-1] == 'B'
425 && out.bv_val[out.bv_len-2] == '\'' )
427 /* assume presence of optional UID */
428 uid.bv_val = strrchr( out.bv_val, '#' );
430 if( uid.bv_val == NULL ) {
432 return LDAP_INVALID_SYNTAX;
435 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
436 out.bv_len -= uid.bv_len--;
438 /* temporarily trim the UID */
439 *(uid.bv_val++) = '\0';
442 rc = dnNormalize2( NULL, &out, normalized );
444 if( rc != LDAP_SUCCESS ) {
446 return LDAP_INVALID_SYNTAX;
450 normalized->bv_val = ch_realloc( normalized->bv_val,
451 normalized->bv_len + uid.bv_len + sizeof("#") );
453 /* insert the separator */
454 normalized->bv_val[normalized->bv_len++] = '#';
457 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
458 uid.bv_val, uid.bv_len );
459 normalized->bv_len += uid.bv_len;
462 normalized->bv_val[normalized->bv_len] = '\0';
472 * Handling boolean syntax and matching is quite rigid.
473 * A more flexible approach would be to allow a variety
474 * of strings to be normalized and prettied into TRUE
482 /* very unforgiving validation, requires no normalization
483 * before simplistic matching
486 if( in->bv_len == 4 ) {
487 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
490 } else if( in->bv_len == 5 ) {
491 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
496 return LDAP_INVALID_SYNTAX;
505 struct berval *value,
506 void *assertedValue )
508 /* simplistic matching allowed by rigid validation */
509 struct berval *asserted = (struct berval *) assertedValue;
510 *matchp = value->bv_len != asserted->bv_len;
514 /*-------------------------------------------------------------------
515 LDAP/X.500 string syntax / matching rules have a few oddities. This
516 comment attempts to detail how slapd(8) treats them.
519 StringSyntax X.500 LDAP Matching/Comments
520 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
521 PrintableString subset subset i/e + ignore insignificant spaces
522 PrintableString subset subset i/e + ignore insignificant spaces
523 NumericString subset subset ignore all spaces
524 IA5String ASCII ASCII i/e + ignore insignificant spaces
525 TeletexString T.61 T.61 i/e + ignore insignificant spaces
527 TelephoneNumber subset subset i + ignore all spaces and "-"
529 See draft-ietf-ldapbis-strpro for details (once published).
533 In X.500(93), a directory string can be either a PrintableString,
534 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
535 In later versions, more CHOICEs were added. In all cases the string
538 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
539 A directory string cannot be zero length.
541 For matching, there are both case ignore and exact rules. Both
542 also require that "insignificant" spaces be ignored.
543 spaces before the first non-space are ignored;
544 spaces after the last non-space are ignored;
545 spaces after a space are ignored.
546 Note: by these rules (and as clarified in X.520), a string of only
547 spaces is to be treated as if held one space, not empty (which
548 would be a syntax error).
551 In ASN.1, numeric string is just a string of digits and spaces
552 and could be empty. However, in X.500, all attribute values of
553 numeric string carry a non-empty constraint. For example:
555 internationalISDNNumber ATTRIBUTE ::= {
556 WITH SYNTAX InternationalISDNNumber
557 EQUALITY MATCHING RULE numericStringMatch
558 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
559 ID id-at-internationalISDNNumber }
560 InternationalISDNNumber ::=
561 NumericString (SIZE(1..ub-international-isdn-number))
563 Unforunately, some assertion values are don't carry the same
564 constraint (but its unclear how such an assertion could ever
565 be true). In LDAP, there is one syntax (numericString) not two
566 (numericString with constraint, numericString without constraint).
567 This should be treated as numericString with non-empty constraint.
568 Note that while someone may have no ISDN number, there are no ISDN
569 numbers which are zero length.
571 In matching, spaces are ignored.
574 In ASN.1, Printable string is just a string of printable characters
575 and can be empty. In X.500, semantics much like NumericString (see
576 serialNumber for a like example) excepting uses insignificant space
577 handling instead of ignore all spaces.
580 Basically same as PrintableString. There are no examples in X.500,
581 but same logic applies. So we require them to be non-empty as
584 -------------------------------------------------------------------*/
593 unsigned char *u = in->bv_val;
595 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
596 /* directory strings cannot be empty */
597 return LDAP_INVALID_SYNTAX;
600 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
601 /* get the length indicated by the first byte */
602 len = LDAP_UTF8_CHARLEN2( u, len );
604 /* very basic checks */
607 if( (u[5] & 0xC0) != 0x80 ) {
608 return LDAP_INVALID_SYNTAX;
611 if( (u[4] & 0xC0) != 0x80 ) {
612 return LDAP_INVALID_SYNTAX;
615 if( (u[3] & 0xC0) != 0x80 ) {
616 return LDAP_INVALID_SYNTAX;
619 if( (u[2] & 0xC0 )!= 0x80 ) {
620 return LDAP_INVALID_SYNTAX;
623 if( (u[1] & 0xC0) != 0x80 ) {
624 return LDAP_INVALID_SYNTAX;
627 /* CHARLEN already validated it */
630 return LDAP_INVALID_SYNTAX;
633 /* make sure len corresponds with the offset
634 to the next character */
635 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
639 return LDAP_INVALID_SYNTAX;
651 struct berval *normalized )
653 struct berval tmp, nvalue;
657 if( val->bv_val == NULL ) {
658 /* assume we're dealing with a syntax (e.g., UTF8String)
659 * which allows empty strings
661 normalized->bv_len = 0;
662 normalized->bv_val = NULL;
666 flags = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactMatch )
667 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
668 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
669 ? LDAP_UTF8_APPROX : 0;
671 val = UTF8bvnormalize( val, &tmp, flags );
676 /* collapse spaces (in place) */
678 nvalue.bv_val = tmp.bv_val;
680 wasspace=1; /* trim leading spaces */
681 for( i=0; i<tmp.bv_len; i++) {
682 if ( ASCII_SPACE( tmp.bv_val[i] )) {
683 if( wasspace++ == 0 ) {
684 /* trim repeated spaces */
685 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
689 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
693 if( nvalue.bv_len ) {
695 /* last character was a space, trim it */
698 nvalue.bv_val[nvalue.bv_len] = '\0';
701 /* string of all spaces is treated as one space */
702 nvalue.bv_val[0] = ' ';
703 nvalue.bv_val[1] = '\0';
707 *normalized = nvalue;
713 #ifndef SLAPD_APPROX_OLDSINGLESTRING
714 #if defined(SLAPD_APPROX_INITIALS)
715 #define SLAPD_APPROX_DELIMITER "._ "
716 #define SLAPD_APPROX_WORDLEN 2
718 #define SLAPD_APPROX_DELIMITER " "
719 #define SLAPD_APPROX_WORDLEN 1
728 struct berval *value,
729 void *assertedValue )
731 struct berval *nval, *assertv;
732 char *val, **values, **words, *c;
733 int i, count, len, nextchunk=0, nextavail=0;
735 /* Yes, this is necessary */
736 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
742 /* Yes, this is necessary */
743 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
744 NULL, LDAP_UTF8_APPROX );
745 if( assertv == NULL ) {
751 /* Isolate how many words there are */
752 for ( c = nval->bv_val, count = 1; *c; c++ ) {
753 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
754 if ( c == NULL ) break;
759 /* Get a phonetic copy of each word */
760 words = (char **)ch_malloc( count * sizeof(char *) );
761 values = (char **)ch_malloc( count * sizeof(char *) );
762 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
764 values[i] = phonetic(c);
767 /* Work through the asserted value's words, to see if at least some
768 of the words are there, in the same order. */
770 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
771 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
776 #if defined(SLAPD_APPROX_INITIALS)
777 else if( len == 1 ) {
778 /* Single letter words need to at least match one word's initial */
779 for( i=nextavail; i<count; i++ )
780 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
787 /* Isolate the next word in the asserted value and phonetic it */
788 assertv->bv_val[nextchunk+len] = '\0';
789 val = phonetic( assertv->bv_val + nextchunk );
791 /* See if this phonetic chunk is in the remaining words of *value */
792 for( i=nextavail; i<count; i++ ){
793 if( !strcmp( val, values[i] ) ){
801 /* This chunk in the asserted value was NOT within the *value. */
807 /* Go on to the next word in the asserted value */
811 /* If some of the words were seen, call it a match */
812 if( nextavail > 0 ) {
820 ber_bvfree( assertv );
821 for( i=0; i<count; i++ ) {
822 ch_free( values[i] );
837 struct berval *prefix,
842 int i,j, len, wordcount, keycount=0;
843 struct berval *newkeys;
846 for( j=0; values[j].bv_val != NULL; j++ ) {
847 struct berval val = { 0, NULL };
848 /* Yes, this is necessary */
849 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
850 assert( val.bv_val != NULL );
852 /* Isolate how many words there are. There will be a key for each */
853 for( wordcount = 0, c = val.bv_val; *c; c++) {
854 len = strcspn(c, SLAPD_APPROX_DELIMITER);
855 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
857 if (*c == '\0') break;
861 /* Allocate/increase storage to account for new keys */
862 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
863 * sizeof(struct berval) );
864 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
865 if( keys ) ch_free( keys );
868 /* Get a phonetic copy of each word */
869 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
871 if( len < SLAPD_APPROX_WORDLEN ) continue;
872 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
877 ber_memfree( val.bv_val );
879 keys[keycount].bv_val = NULL;
891 struct berval *prefix,
892 void * assertedValue,
900 /* Yes, this is necessary */
901 val = UTF8bvnormalize( ((struct berval *)assertedValue),
902 NULL, LDAP_UTF8_APPROX );
903 if( val == NULL || val->bv_val == NULL ) {
904 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
905 keys[0].bv_val = NULL;
911 /* Isolate how many words there are. There will be a key for each */
912 for( count = 0,c = val->bv_val; *c; c++) {
913 len = strcspn(c, SLAPD_APPROX_DELIMITER);
914 if( len >= SLAPD_APPROX_WORDLEN ) count++;
916 if (*c == '\0') break;
920 /* Allocate storage for new keys */
921 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
923 /* Get a phonetic copy of each word */
924 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
926 if( len < SLAPD_APPROX_WORDLEN ) continue;
927 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
933 keys[count].bv_val = NULL;
940 /* No other form of Approximate Matching is defined */
948 struct berval *value,
949 void *assertedValue )
951 char *vapprox, *avapprox;
954 /* Yes, this is necessary */
955 s = UTF8normalize( value, UTF8_NOCASEFOLD );
961 /* Yes, this is necessary */
962 t = UTF8normalize( ((struct berval *)assertedValue),
970 vapprox = phonetic( strip8bitChars( s ) );
971 avapprox = phonetic( strip8bitChars( t ) );
976 *matchp = strcmp( vapprox, avapprox );
990 struct berval *prefix,
998 for( i=0; values[i].bv_val != NULL; i++ ) {
999 /* empty - just count them */
1002 /* we should have at least one value at this point */
1005 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1007 /* Copy each value and run it through phonetic() */
1008 for( i=0; values[i].bv_val != NULL; i++ ) {
1009 /* Yes, this is necessary */
1010 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1012 /* strip 8-bit chars and run through phonetic() */
1013 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1016 keys[i].bv_val = NULL;
1019 return LDAP_SUCCESS;
1028 struct berval *prefix,
1029 void * assertedValue,
1035 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1037 /* Yes, this is necessary */
1038 s = UTF8normalize( ((struct berval *)assertedValue),
1043 /* strip 8-bit chars and run through phonetic() */
1044 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1050 return LDAP_SUCCESS;
1053 #endif /* !SLAP_NVALUES */
1055 /* Substrings Index generation function */
1057 octetStringSubstringsIndexer (
1062 struct berval *prefix,
1066 ber_len_t i, j, nkeys;
1070 HASH_CONTEXT HASHcontext;
1071 unsigned char HASHdigest[HASH_BYTES];
1072 struct berval digest;
1073 digest.bv_val = HASHdigest;
1074 digest.bv_len = sizeof(HASHdigest);
1078 for( i=0; values[i].bv_val != NULL; i++ ) {
1079 /* count number of indices to generate */
1080 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1084 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1085 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1086 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1087 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1089 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1093 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1094 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1095 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1099 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1100 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1101 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1102 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1104 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1110 /* no keys to generate */
1112 return LDAP_SUCCESS;
1115 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1117 slen = syntax->ssyn_oidlen;
1118 mlen = mr->smr_oidlen;
1121 for( i=0; values[i].bv_val != NULL; i++ ) {
1124 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1126 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1127 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1129 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1130 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1132 for( j=0; j<max; j++ ) {
1133 HASH_Init( &HASHcontext );
1134 if( prefix != NULL && prefix->bv_len > 0 ) {
1135 HASH_Update( &HASHcontext,
1136 prefix->bv_val, prefix->bv_len );
1139 HASH_Update( &HASHcontext,
1140 &pre, sizeof( pre ) );
1141 HASH_Update( &HASHcontext,
1142 syntax->ssyn_oid, slen );
1143 HASH_Update( &HASHcontext,
1144 mr->smr_oid, mlen );
1145 HASH_Update( &HASHcontext,
1146 &values[i].bv_val[j],
1147 SLAP_INDEX_SUBSTR_MAXLEN );
1148 HASH_Final( HASHdigest, &HASHcontext );
1150 ber_dupbv( &keys[nkeys++], &digest );
1154 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1155 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1157 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1160 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1161 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1162 HASH_Init( &HASHcontext );
1163 if( prefix != NULL && prefix->bv_len > 0 ) {
1164 HASH_Update( &HASHcontext,
1165 prefix->bv_val, prefix->bv_len );
1167 HASH_Update( &HASHcontext,
1168 &pre, sizeof( pre ) );
1169 HASH_Update( &HASHcontext,
1170 syntax->ssyn_oid, slen );
1171 HASH_Update( &HASHcontext,
1172 mr->smr_oid, mlen );
1173 HASH_Update( &HASHcontext,
1174 values[i].bv_val, j );
1175 HASH_Final( HASHdigest, &HASHcontext );
1177 ber_dupbv( &keys[nkeys++], &digest );
1180 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1181 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1182 HASH_Init( &HASHcontext );
1183 if( prefix != NULL && prefix->bv_len > 0 ) {
1184 HASH_Update( &HASHcontext,
1185 prefix->bv_val, prefix->bv_len );
1187 HASH_Update( &HASHcontext,
1188 &pre, sizeof( pre ) );
1189 HASH_Update( &HASHcontext,
1190 syntax->ssyn_oid, slen );
1191 HASH_Update( &HASHcontext,
1192 mr->smr_oid, mlen );
1193 HASH_Update( &HASHcontext,
1194 &values[i].bv_val[values[i].bv_len-j], j );
1195 HASH_Final( HASHdigest, &HASHcontext );
1197 ber_dupbv( &keys[nkeys++], &digest );
1205 keys[nkeys].bv_val = NULL;
1212 return LDAP_SUCCESS;
1216 octetStringSubstringsFilter (
1221 struct berval *prefix,
1222 void * assertedValue,
1225 SubstringsAssertion *sa;
1228 ber_len_t nkeys = 0;
1229 size_t slen, mlen, klen;
1231 HASH_CONTEXT HASHcontext;
1232 unsigned char HASHdigest[HASH_BYTES];
1233 struct berval *value;
1234 struct berval digest;
1236 sa = (SubstringsAssertion *) assertedValue;
1238 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
1239 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1244 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1246 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1247 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1248 /* don't bother accounting for stepping */
1249 nkeys += sa->sa_any[i].bv_len -
1250 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1255 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1256 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1263 return LDAP_SUCCESS;
1266 digest.bv_val = HASHdigest;
1267 digest.bv_len = sizeof(HASHdigest);
1269 slen = syntax->ssyn_oidlen;
1270 mlen = mr->smr_oidlen;
1272 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1275 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1276 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1278 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1279 value = &sa->sa_initial;
1281 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1282 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1284 HASH_Init( &HASHcontext );
1285 if( prefix != NULL && prefix->bv_len > 0 ) {
1286 HASH_Update( &HASHcontext,
1287 prefix->bv_val, prefix->bv_len );
1289 HASH_Update( &HASHcontext,
1290 &pre, sizeof( pre ) );
1291 HASH_Update( &HASHcontext,
1292 syntax->ssyn_oid, slen );
1293 HASH_Update( &HASHcontext,
1294 mr->smr_oid, mlen );
1295 HASH_Update( &HASHcontext,
1296 value->bv_val, klen );
1297 HASH_Final( HASHdigest, &HASHcontext );
1299 ber_dupbv( &keys[nkeys++], &digest );
1302 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1304 pre = SLAP_INDEX_SUBSTR_PREFIX;
1305 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1307 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1308 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1312 value = &sa->sa_any[i];
1315 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1316 j += SLAP_INDEX_SUBSTR_STEP )
1318 HASH_Init( &HASHcontext );
1319 if( prefix != NULL && prefix->bv_len > 0 ) {
1320 HASH_Update( &HASHcontext,
1321 prefix->bv_val, prefix->bv_len );
1323 HASH_Update( &HASHcontext,
1324 &pre, sizeof( pre ) );
1325 HASH_Update( &HASHcontext,
1326 syntax->ssyn_oid, slen );
1327 HASH_Update( &HASHcontext,
1328 mr->smr_oid, mlen );
1329 HASH_Update( &HASHcontext,
1330 &value->bv_val[j], klen );
1331 HASH_Final( HASHdigest, &HASHcontext );
1333 ber_dupbv( &keys[nkeys++], &digest );
1339 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1340 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1342 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1343 value = &sa->sa_final;
1345 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1346 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1348 HASH_Init( &HASHcontext );
1349 if( prefix != NULL && prefix->bv_len > 0 ) {
1350 HASH_Update( &HASHcontext,
1351 prefix->bv_val, prefix->bv_len );
1353 HASH_Update( &HASHcontext,
1354 &pre, sizeof( pre ) );
1355 HASH_Update( &HASHcontext,
1356 syntax->ssyn_oid, slen );
1357 HASH_Update( &HASHcontext,
1358 mr->smr_oid, mlen );
1359 HASH_Update( &HASHcontext,
1360 &value->bv_val[value->bv_len-klen], klen );
1361 HASH_Final( HASHdigest, &HASHcontext );
1363 ber_dupbv( &keys[nkeys++], &digest );
1367 keys[nkeys].bv_val = NULL;
1374 return LDAP_SUCCESS;
1377 /* Remove all spaces and '-' characters */
1379 telephoneNumberNormalize(
1384 struct berval *normalized )
1388 /* validator should have refused an empty string */
1389 assert( val->bv_len );
1391 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1393 for( p = val->bv_val; *p; p++ ) {
1394 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1400 normalized->bv_len = q - normalized->bv_val;
1402 if( normalized->bv_len == 0 ) {
1403 free( normalized->bv_val );
1404 return LDAP_INVALID_SYNTAX;
1407 return LDAP_SUCCESS;
1413 struct berval *val )
1417 if( val->bv_len == 0 ) {
1418 /* disallow empty strings */
1419 return LDAP_INVALID_SYNTAX;
1422 if( OID_LEADCHAR(val->bv_val[0]) ) {
1424 for(i=1; i < val->bv_len; i++) {
1425 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1426 if( dot++ ) return 1;
1427 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1430 return LDAP_INVALID_SYNTAX;
1434 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1436 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1437 for(i=1; i < val->bv_len; i++) {
1438 if( !DESC_CHAR(val->bv_val[i] ) ) {
1439 return LDAP_INVALID_SYNTAX;
1443 return LDAP_SUCCESS;
1446 return LDAP_INVALID_SYNTAX;
1455 struct berval *value,
1456 void *assertedValue )
1459 int vsign = 1, avsign = 1; /* default sign = '+' */
1460 struct berval *asserted;
1461 ber_len_t vlen, avlen;
1464 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1466 vlen = value->bv_len;
1468 #ifndef SLAP_NVALUES
1469 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1470 char *tmp = memchr( v, '$', vlen );
1471 if( tmp ) vlen = tmp - v;
1472 while( vlen && ASCII_SPACE( v[vlen-1] )) vlen--;
1476 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) { /* ANSI 2.2.1 */
1477 if( *v == '-' ) vsign = -1;
1480 if( vlen == 0 ) vsign = 0;
1482 /* Do the same with the *assertedValue number */
1483 asserted = (struct berval *) assertedValue;
1484 av = asserted->bv_val;
1485 avlen = asserted->bv_len;
1486 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1492 match = vsign - avsign;
1494 match = (vlen != avlen
1495 ? ( vlen < avlen ? -1 : 1 )
1496 : memcmp( v, av, vlen ));
1502 return LDAP_SUCCESS;
1508 struct berval *val )
1512 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1514 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1515 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1517 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1518 return LDAP_INVALID_SYNTAX;
1521 for( i=1; i < val->bv_len; i++ ) {
1522 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1525 return LDAP_SUCCESS;
1534 struct berval *normalized )
1544 /* Ignore leading spaces */
1545 while ( len && ( *p == ' ' )) {
1552 negative = ( *p == '-' );
1553 if(( *p == '-' ) || ( *p == '+' )) {
1559 /* Ignore leading zeros */
1560 while ( len && ( *p == '0' )) {
1565 /* If there are no non-zero digits left, the number is zero, otherwise
1566 allocate space for the number and copy it into the buffer */
1568 normalized->bv_val = ch_strdup("0");
1569 normalized->bv_len = 1;
1572 normalized->bv_len = len+negative;
1573 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1574 if( negative ) normalized->bv_val[0] = '-';
1575 AC_MEMCPY( normalized->bv_val + negative, p, len );
1576 normalized->bv_val[len+negative] = '\0';
1579 return LDAP_SUCCESS;
1583 countryStringValidate(
1585 struct berval *val )
1587 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1589 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1590 return LDAP_INVALID_SYNTAX;
1592 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1593 return LDAP_INVALID_SYNTAX;
1596 return LDAP_SUCCESS;
1600 printableStringValidate(
1602 struct berval *val )
1606 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1608 for(i=0; i < val->bv_len; i++) {
1609 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1610 return LDAP_INVALID_SYNTAX;
1614 return LDAP_SUCCESS;
1618 printablesStringValidate(
1620 struct berval *val )
1624 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1626 for(i=0,len=0; i < val->bv_len; i++) {
1627 int c = val->bv_val[i];
1631 return LDAP_INVALID_SYNTAX;
1635 } else if ( SLAP_PRINTABLE(c) ) {
1638 return LDAP_INVALID_SYNTAX;
1643 return LDAP_INVALID_SYNTAX;
1646 return LDAP_SUCCESS;
1652 struct berval *val )
1656 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1658 for(i=0; i < val->bv_len; i++) {
1659 if( !LDAP_ASCII(val->bv_val[i]) ) {
1660 return LDAP_INVALID_SYNTAX;
1664 return LDAP_SUCCESS;
1673 struct berval *normalized )
1676 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1678 assert( val->bv_len );
1682 /* Ignore initial whitespace */
1683 while ( ASCII_SPACE( *p ) ) {
1687 normalized->bv_val = ch_strdup( p );
1688 p = q = normalized->bv_val;
1691 if ( ASCII_SPACE( *p ) ) {
1694 /* Ignore the extra whitespace */
1695 while ( ASCII_SPACE( *p ) ) {
1699 } else if ( casefold ) {
1700 /* Most IA5 rules require casefolding */
1701 *q++ = TOLOWER(*p++);
1708 assert( normalized->bv_val <= p );
1712 * If the string ended in space, backup the pointer one
1713 * position. One is enough because the above loop collapsed
1714 * all whitespace to a single space.
1717 if ( ASCII_SPACE( q[-1] ) ) {
1721 /* null terminate */
1724 normalized->bv_len = q - normalized->bv_val;
1726 if( normalized->bv_len == 0 ) {
1727 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1728 normalized->bv_val[0] = ' ';
1729 normalized->bv_val[1] = '\0';
1730 normalized->bv_len = 1;
1733 return LDAP_SUCCESS;
1737 octetStringSubstringsMatch (
1742 struct berval *value,
1743 void *assertedValue )
1746 SubstringsAssertion *sub = assertedValue;
1747 struct berval left = *value;
1751 /* Add up asserted input length */
1752 if( sub->sa_initial.bv_val ) {
1753 inlen += sub->sa_initial.bv_len;
1756 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1757 inlen += sub->sa_any[i].bv_len;
1760 if( sub->sa_final.bv_val ) {
1761 inlen += sub->sa_final.bv_len;
1764 if( sub->sa_initial.bv_val ) {
1765 if( inlen > left.bv_len ) {
1770 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1771 sub->sa_initial.bv_len );
1777 left.bv_val += sub->sa_initial.bv_len;
1778 left.bv_len -= sub->sa_initial.bv_len;
1779 inlen -= sub->sa_initial.bv_len;
1782 if( sub->sa_final.bv_val ) {
1783 if( inlen > left.bv_len ) {
1788 match = memcmp( sub->sa_final.bv_val,
1789 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1790 sub->sa_final.bv_len );
1796 left.bv_len -= sub->sa_final.bv_len;
1797 inlen -= sub->sa_final.bv_len;
1801 for(i=0; sub->sa_any[i].bv_val; i++) {
1806 if( inlen > left.bv_len ) {
1807 /* not enough length */
1812 if( sub->sa_any[i].bv_len == 0 ) {
1816 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
1823 idx = p - left.bv_val;
1825 if( idx >= left.bv_len ) {
1826 /* this shouldn't happen */
1833 if( sub->sa_any[i].bv_len > left.bv_len ) {
1834 /* not enough left */
1839 match = memcmp( left.bv_val,
1840 sub->sa_any[i].bv_val,
1841 sub->sa_any[i].bv_len );
1849 left.bv_val += sub->sa_any[i].bv_len;
1850 left.bv_len -= sub->sa_any[i].bv_len;
1851 inlen -= sub->sa_any[i].bv_len;
1857 return LDAP_SUCCESS;
1861 numericStringValidate(
1867 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1869 for(i=0; i < in->bv_len; i++) {
1870 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1871 return LDAP_INVALID_SYNTAX;
1875 return LDAP_SUCCESS;
1879 numericStringNormalize(
1884 struct berval *normalized )
1886 /* removal all spaces */
1889 assert( val->bv_len );
1891 normalized->bv_val = ch_malloc( val->bv_len + 1 );
1894 q = normalized->bv_val;
1897 if ( ASCII_SPACE( *p ) ) {
1898 /* Ignore whitespace */
1905 /* we should have copied no more then is in val */
1906 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1908 /* null terminate */
1911 normalized->bv_len = q - normalized->bv_val;
1913 if( normalized->bv_len == 0 ) {
1914 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1915 normalized->bv_val[0] = ' ';
1916 normalized->bv_val[1] = '\0';
1917 normalized->bv_len = 1;
1920 return LDAP_SUCCESS;
1923 #ifndef SLAP_NVALUES
1925 objectIdentifierFirstComponentMatch(
1930 struct berval *value,
1931 void *assertedValue )
1933 int rc = LDAP_SUCCESS;
1935 struct berval *asserted = (struct berval *) assertedValue;
1939 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1940 return LDAP_INVALID_SYNTAX;
1943 /* trim leading white space */
1944 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1948 /* grab next word */
1949 oid.bv_val = &value->bv_val[i];
1950 j = value->bv_len - i;
1951 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1956 /* insert attributeTypes, objectclass check here */
1957 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1958 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1961 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1962 MatchingRule *asserted_mr = mr_bvfind( asserted );
1963 MatchingRule *stored_mr = mr_bvfind( &oid );
1965 if( asserted_mr == NULL ) {
1966 rc = SLAPD_COMPARE_UNDEFINED;
1968 match = asserted_mr != stored_mr;
1971 } else if ( !strcmp( syntax->ssyn_oid,
1972 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1974 AttributeType *asserted_at = at_bvfind( asserted );
1975 AttributeType *stored_at = at_bvfind( &oid );
1977 if( asserted_at == NULL ) {
1978 rc = SLAPD_COMPARE_UNDEFINED;
1980 match = asserted_at != stored_at;
1983 } else if ( !strcmp( syntax->ssyn_oid,
1984 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1986 ObjectClass *asserted_oc = oc_bvfind( asserted );
1987 ObjectClass *stored_oc = oc_bvfind( &oid );
1989 if( asserted_oc == NULL ) {
1990 rc = SLAPD_COMPARE_UNDEFINED;
1992 match = asserted_oc != stored_oc;
1998 LDAP_LOG( CONFIG, ENTRY,
1999 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
2000 match, value->bv_val, asserted->bv_val );
2002 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
2003 "%d\n\t\"%s\"\n\t\"%s\"\n",
2004 match, value->bv_val, asserted->bv_val );
2007 if( rc == LDAP_SUCCESS ) *matchp = match;
2018 struct berval *value,
2019 void *assertedValue )
2021 long lValue, lAssertedValue;
2023 /* safe to assume integers are NUL terminated? */
2024 lValue = strtol(value->bv_val, NULL, 10);
2025 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
2026 return LDAP_CONSTRAINT_VIOLATION;
2029 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
2030 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
2031 && errno == ERANGE )
2033 return LDAP_CONSTRAINT_VIOLATION;
2036 *matchp = (lValue & lAssertedValue) ? 0 : 1;
2037 return LDAP_SUCCESS;
2046 struct berval *value,
2047 void *assertedValue )
2049 long lValue, lAssertedValue;
2051 /* safe to assume integers are NUL terminated? */
2052 lValue = strtol(value->bv_val, NULL, 10);
2053 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
2054 return LDAP_CONSTRAINT_VIOLATION;
2057 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
2058 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
2059 && errno == ERANGE )
2061 return LDAP_CONSTRAINT_VIOLATION;
2064 *matchp = (lValue | lAssertedValue) ? 0 : -1;
2065 return LDAP_SUCCESS;
2068 #ifndef SLAP_NVALUES
2070 #include <openssl/x509.h>
2071 #include <openssl/err.h>
2074 * Next function returns a string representation of a ASN1_INTEGER.
2075 * It works for unlimited lengths.
2078 static struct berval *
2079 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
2083 static char digit[] = "0123456789";
2085 /* We work backwards, make it fill from the end of buf */
2086 p = buf + sizeof(buf) - 1;
2089 if ( a == NULL || a->length == 0 ) {
2097 /* We want to preserve the original */
2098 copy = ch_malloc(n*sizeof(unsigned int));
2099 for (i = 0; i<n; i++) {
2100 copy[i] = a->data[i];
2104 * base indicates the index of the most significant
2105 * byte that might be nonzero. When it goes off the
2106 * end, we now there is nothing left to do.
2112 for (i = base; i<n; i++ ) {
2113 copy[i] += carry*256;
2114 carry = copy[i] % 10;
2119 * Way too large, we need to leave
2120 * room for sign if negative
2125 *--p = digit[carry];
2127 if (copy[base] == 0) base++;
2132 if ( a->type == V_ASN1_NEG_INTEGER ) {
2136 return ber_str2bv( p, 0, 1, bv );
2140 * Given a certificate in DER format, extract the corresponding
2141 * assertion value for certificateExactMatch
2144 certificateExactConvert(
2146 struct berval * out )
2149 unsigned char *p = in->bv_val;
2150 struct berval serial;
2151 struct berval issuer_dn;
2153 xcert = d2i_X509(NULL, &p, in->bv_len);
2156 LDAP_LOG( CONFIG, ENTRY,
2157 "certificateExactConvert: error parsing cert: %s\n",
2158 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2160 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2161 "error parsing cert: %s\n",
2162 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2164 return LDAP_INVALID_SYNTAX;
2167 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2169 return LDAP_INVALID_SYNTAX;
2171 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2175 ber_memfree(serial.bv_val);
2176 return LDAP_INVALID_SYNTAX;
2181 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2182 out->bv_val = ch_malloc(out->bv_len);
2184 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2186 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2188 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2189 p += issuer_dn.bv_len;
2193 LDAP_LOG( CONFIG, ARGS,
2194 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2196 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2198 out->bv_val, NULL, NULL );
2201 ber_memfree(serial.bv_val);
2202 ber_memfree(issuer_dn.bv_val);
2204 return LDAP_SUCCESS;
2208 serial_and_issuer_parse(
2209 struct berval *assertion,
2210 struct berval *serial,
2211 struct berval *issuer_dn
2219 begin = assertion->bv_val;
2220 end = assertion->bv_val+assertion->bv_len-1;
2221 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2222 if ( p > end ) return LDAP_INVALID_SYNTAX;
2224 /* p now points at the $ sign, now use
2225 * begin and end to delimit the serial number
2227 while (ASCII_SPACE(*begin)) begin++;
2229 while (ASCII_SPACE(*end)) end--;
2231 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2233 bv.bv_len = end-begin+1;
2235 ber_dupbv(serial, &bv);
2237 /* now extract the issuer, remember p was at the dollar sign */
2239 end = assertion->bv_val+assertion->bv_len-1;
2240 while (ASCII_SPACE(*begin)) begin++;
2241 /* should we trim spaces at the end too? is it safe always? no, no */
2243 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2246 bv.bv_len = end-begin+1;
2249 dnNormalize2( NULL, &bv, issuer_dn );
2252 return LDAP_SUCCESS;
2256 certificateExactMatch(
2261 struct berval *value,
2262 void *assertedValue )
2265 unsigned char *p = value->bv_val;
2266 struct berval serial;
2267 struct berval issuer_dn;
2268 struct berval asserted_serial;
2269 struct berval asserted_issuer_dn;
2272 xcert = d2i_X509(NULL, &p, value->bv_len);
2275 LDAP_LOG( CONFIG, ENTRY,
2276 "certificateExactMatch: error parsing cert: %s\n",
2277 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2279 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2280 "error parsing cert: %s\n",
2281 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2283 return LDAP_INVALID_SYNTAX;
2286 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2287 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2291 serial_and_issuer_parse(assertedValue,
2292 &asserted_serial, &asserted_issuer_dn);
2297 slap_schema.si_syn_integer,
2298 slap_schema.si_mr_integerMatch,
2301 if ( ret == LDAP_SUCCESS ) {
2302 if ( *matchp == 0 ) {
2303 /* We need to normalize everything for dnMatch */
2307 slap_schema.si_syn_distinguishedName,
2308 slap_schema.si_mr_distinguishedNameMatch,
2310 &asserted_issuer_dn);
2315 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2316 "%d\n\t\"%s $ %s\"\n",
2317 *matchp, serial.bv_val, issuer_dn.bv_val );
2318 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2319 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2322 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2323 "%d\n\t\"%s $ %s\"\n",
2324 *matchp, serial.bv_val, issuer_dn.bv_val );
2325 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2326 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2330 ber_memfree(serial.bv_val);
2331 ber_memfree(issuer_dn.bv_val);
2332 ber_memfree(asserted_serial.bv_val);
2333 ber_memfree(asserted_issuer_dn.bv_val);
2339 * Index generation function
2340 * We just index the serials, in most scenarios the issuer DN is one of
2341 * a very small set of values.
2343 static int certificateExactIndexer(
2348 struct berval *prefix,
2356 struct berval serial;
2358 /* we should have at least one value at this point */
2359 assert( values != NULL && values[0].bv_val != NULL );
2361 for( i=0; values[i].bv_val != NULL; i++ ) {
2362 /* empty -- just count them */
2365 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2367 for( i=0; values[i].bv_val != NULL; i++ ) {
2368 p = values[i].bv_val;
2369 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2372 LDAP_LOG( CONFIG, ENTRY,
2373 "certificateExactIndexer: error parsing cert: %s\n",
2374 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2376 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2377 "error parsing cert: %s\n",
2378 ERR_error_string(ERR_get_error(),NULL),
2381 /* Do we leak keys on error? */
2382 return LDAP_INVALID_SYNTAX;
2385 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2387 xintegerNormalize( slap_schema.si_syn_integer,
2388 &serial, &keys[i] );
2389 ber_memfree(serial.bv_val);
2391 LDAP_LOG( CONFIG, ENTRY,
2392 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2394 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2401 keys[i].bv_val = NULL;
2403 return LDAP_SUCCESS;
2406 /* Index generation function */
2407 /* We think this is always called with a value in matching rule syntax */
2408 static int certificateExactFilter(
2413 struct berval *prefix,
2414 void * assertedValue,
2418 struct berval asserted_serial;
2421 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2422 if( ret != LDAP_SUCCESS ) return ret;
2424 keys = ch_malloc( sizeof( struct berval ) * 2 );
2425 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2426 keys[1].bv_val = NULL;
2429 ber_memfree(asserted_serial.bv_val);
2430 return LDAP_SUCCESS;
2436 check_time_syntax (struct berval *val,
2440 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2441 static int mdays[2][12] = {
2442 /* non-leap years */
2443 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2445 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2448 int part, c, tzoffset, leapyear = 0 ;
2450 if( val->bv_len == 0 ) {
2451 return LDAP_INVALID_SYNTAX;
2454 p = (char *)val->bv_val;
2455 e = p + val->bv_len;
2457 /* Ignore initial whitespace */
2458 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2462 if (e - p < 13 - (2 * start)) {
2463 return LDAP_INVALID_SYNTAX;
2466 for (part = 0; part < 9; part++) {
2470 for (part = start; part < 7; part++) {
2472 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2479 return LDAP_INVALID_SYNTAX;
2481 if (c < 0 || c > 9) {
2482 return LDAP_INVALID_SYNTAX;
2488 return LDAP_INVALID_SYNTAX;
2490 if (c < 0 || c > 9) {
2491 return LDAP_INVALID_SYNTAX;
2496 if (part == 2 || part == 3) {
2499 if (parts[part] < 0) {
2500 return LDAP_INVALID_SYNTAX;
2502 if (parts[part] > ceiling[part]) {
2503 return LDAP_INVALID_SYNTAX;
2507 /* leapyear check for the Gregorian calendar (year>1581) */
2508 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2509 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2514 if (parts[3] > mdays[leapyear][parts[2]]) {
2515 return LDAP_INVALID_SYNTAX;
2520 tzoffset = 0; /* UTC */
2521 } else if (c != '+' && c != '-') {
2522 return LDAP_INVALID_SYNTAX;
2526 } else /* c == '+' */ {
2531 return LDAP_INVALID_SYNTAX;
2534 for (part = 7; part < 9; part++) {
2536 if (c < 0 || c > 9) {
2537 return LDAP_INVALID_SYNTAX;
2542 if (c < 0 || c > 9) {
2543 return LDAP_INVALID_SYNTAX;
2547 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2548 return LDAP_INVALID_SYNTAX;
2553 /* Ignore trailing whitespace */
2554 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2558 return LDAP_INVALID_SYNTAX;
2561 switch ( tzoffset ) {
2562 case -1: /* negativ offset to UTC, ie west of Greenwich */
2563 parts[4] += parts[7];
2564 parts[5] += parts[8];
2565 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2569 c = mdays[leapyear][parts[2]];
2571 if (parts[part] > c) {
2572 parts[part] -= c + 1;
2577 case 1: /* positive offset to UTC, ie east of Greenwich */
2578 parts[4] -= parts[7];
2579 parts[5] -= parts[8];
2580 for (part = 6; --part > 0; ) {
2584 /* first arg to % needs to be non negativ */
2585 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2587 if (parts[part] < 0) {
2588 parts[part] += c + 1;
2593 case 0: /* already UTC */
2597 return LDAP_SUCCESS;
2600 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2605 struct berval *normalized )
2609 rc = check_time_syntax(val, 1, parts);
2610 if (rc != LDAP_SUCCESS) {
2614 normalized->bv_val = ch_malloc( 14 );
2615 if ( normalized->bv_val == NULL ) {
2616 return LBER_ERROR_MEMORY;
2619 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2620 parts[1], parts[2] + 1, parts[3] + 1,
2621 parts[4], parts[5], parts[6] );
2622 normalized->bv_len = 13;
2624 return LDAP_SUCCESS;
2634 return check_time_syntax(in, 1, parts);
2639 generalizedTimeValidate(
2645 return check_time_syntax(in, 0, parts);
2649 generalizedTimeNormalize(
2654 struct berval *normalized )
2658 rc = check_time_syntax(val, 0, parts);
2659 if (rc != LDAP_SUCCESS) {
2663 normalized->bv_val = ch_malloc( 16 );
2664 if ( normalized->bv_val == NULL ) {
2665 return LBER_ERROR_MEMORY;
2668 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2669 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2670 parts[4], parts[5], parts[6] );
2671 normalized->bv_len = 15;
2673 return LDAP_SUCCESS;
2677 nisNetgroupTripleValidate(
2679 struct berval *val )
2684 if ( val->bv_len == 0 ) {
2685 return LDAP_INVALID_SYNTAX;
2688 p = (char *)val->bv_val;
2689 e = p + val->bv_len;
2691 if ( *p != '(' /*')'*/ ) {
2692 return LDAP_INVALID_SYNTAX;
2695 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2699 return LDAP_INVALID_SYNTAX;
2702 } else if ( !AD_CHAR( *p ) ) {
2703 return LDAP_INVALID_SYNTAX;
2707 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2708 return LDAP_INVALID_SYNTAX;
2714 return LDAP_INVALID_SYNTAX;
2717 return LDAP_SUCCESS;
2721 bootParameterValidate(
2723 struct berval *val )
2727 if ( val->bv_len == 0 ) {
2728 return LDAP_INVALID_SYNTAX;
2731 p = (char *)val->bv_val;
2732 e = p + val->bv_len;
2735 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2736 if ( !AD_CHAR( *p ) ) {
2737 return LDAP_INVALID_SYNTAX;
2742 return LDAP_INVALID_SYNTAX;
2746 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2747 if ( !AD_CHAR( *p ) ) {
2748 return LDAP_INVALID_SYNTAX;
2753 return LDAP_INVALID_SYNTAX;
2757 for ( p++; p < e; p++ ) {
2758 if ( !SLAP_PRINTABLE( *p ) ) {
2759 return LDAP_INVALID_SYNTAX;
2763 return LDAP_SUCCESS;
2766 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2767 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2769 static slap_syntax_defs_rec syntax_defs[] = {
2770 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2771 X_BINARY X_NOT_H_R ")",
2772 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
2773 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2774 0, NULL, NULL, NULL},
2775 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2776 0, NULL, NULL, NULL},
2777 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2779 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
2780 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2782 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2783 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2784 0, bitStringValidate, NULL, NULL },
2785 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2786 0, booleanValidate, NULL, NULL},
2787 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2788 X_BINARY X_NOT_H_R ")",
2789 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2790 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2791 X_BINARY X_NOT_H_R ")",
2792 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2793 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2794 X_BINARY X_NOT_H_R ")",
2795 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2796 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2797 0, countryStringValidate, xIA5StringNormalize, NULL},
2798 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2799 0, dnValidate, xdnNormalize, dnPretty2},
2800 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2801 0, NULL, NULL, NULL},
2802 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2803 0, NULL, NULL, NULL},
2804 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2805 0, UTF8StringValidate, xUTF8StringNormalize, NULL},
2806 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2807 0, NULL, NULL, NULL},
2808 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2809 0, NULL, NULL, NULL},
2810 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2811 0, NULL, NULL, NULL},
2812 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2813 0, NULL, NULL, NULL},
2814 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2815 0, NULL, NULL, NULL},
2816 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2817 0, printablesStringValidate, xtelephoneNumberNormalize, NULL},
2818 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2819 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
2820 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2821 0, generalizedTimeValidate, xgeneralizedTimeNormalize, NULL},
2822 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2823 0, NULL, NULL, NULL},
2824 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2825 0, IA5StringValidate, xIA5StringNormalize, NULL},
2826 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2827 0, integerValidate, xintegerNormalize, NULL},
2828 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2829 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
2830 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2831 0, NULL, NULL, NULL},
2832 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2833 0, NULL, NULL, NULL},
2834 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2835 0, NULL, NULL, NULL},
2836 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2837 0, NULL, NULL, NULL},
2838 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2839 0, NULL, NULL, NULL},
2840 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2841 0, nameUIDValidate, xnameUIDNormalize, NULL},
2842 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2843 0, NULL, NULL, NULL},
2844 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2845 0, numericStringValidate, xnumericStringNormalize, NULL},
2846 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2847 0, NULL, NULL, NULL},
2848 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2849 0, oidValidate, NULL, NULL},
2850 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2851 0, IA5StringValidate, xIA5StringNormalize, NULL},
2852 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2853 0, blobValidate, NULL, NULL},
2854 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2855 0, UTF8StringValidate, xUTF8StringNormalize, NULL},
2856 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2857 0, NULL, NULL, NULL},
2858 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2859 0, NULL, NULL, NULL},
2860 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2861 0, printableStringValidate, xIA5StringNormalize, NULL},
2862 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2863 X_BINARY X_NOT_H_R ")",
2864 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
2865 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2866 X_BINARY X_NOT_H_R ")",
2867 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2868 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2869 0, printableStringValidate, xtelephoneNumberNormalize, NULL},
2870 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2871 0, NULL, NULL, NULL},
2872 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2873 0, printablesStringValidate, xIA5StringNormalize, NULL},
2874 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2875 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2876 0, utcTimeValidate, xutcTimeNormalize, NULL},
2878 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2879 0, NULL, NULL, NULL},
2880 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2881 0, NULL, NULL, NULL},
2882 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2883 0, NULL, NULL, NULL},
2884 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2885 0, NULL, NULL, NULL},
2886 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2887 0, NULL, NULL, NULL},
2889 /* RFC 2307 NIS Syntaxes */
2890 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2891 0, nisNetgroupTripleValidate, NULL, NULL},
2892 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2893 0, bootParameterValidate, NULL, NULL},
2897 /* These OIDs are not published yet, but will be in the next
2898 * I-D for PKIX LDAPv3 schema as have been advanced by David
2899 * Chadwick in private mail.
2901 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2902 0, UTF8StringValidate, NULL, NULL},
2905 /* OpenLDAP Experimental Syntaxes */
2906 #ifdef SLAPD_ACI_ENABLED
2907 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2909 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2913 #ifdef SLAPD_AUTHPASSWD
2914 /* needs updating */
2915 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2916 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
2919 /* OpenLDAP Void Syntax */
2920 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2921 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
2922 {NULL, 0, NULL, NULL, NULL}
2926 char *certificateExactMatchSyntaxes[] = {
2927 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2931 char *directoryStringSyntaxes[] = {
2932 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2935 char *integerFirstComponentMatchSyntaxes[] = {
2936 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2937 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2940 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2941 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2942 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2943 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2944 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2945 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2946 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2947 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2948 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2953 * Other matching rules in X.520 that we do not use (yet):
2955 * 2.5.13.9 numericStringOrderingMatch
2956 * 2.5.13.25 uTCTimeMatch
2957 * 2.5.13.26 uTCTimeOrderingMatch
2958 * 2.5.13.31 directoryStringFirstComponentMatch
2959 * 2.5.13.32 wordMatch
2960 * 2.5.13.33 keywordMatch
2961 * 2.5.13.35 certificateMatch
2962 * 2.5.13.36 certificatePairExactMatch
2963 * 2.5.13.37 certificatePairMatch
2964 * 2.5.13.38 certificateListExactMatch
2965 * 2.5.13.39 certificateListMatch
2966 * 2.5.13.40 algorithmIdentifierMatch
2967 * 2.5.13.41 storedPrefixMatch
2968 * 2.5.13.42 attributeCertificateMatch
2969 * 2.5.13.43 readerAndKeyIDMatch
2970 * 2.5.13.44 attributeIntegrityMatch
2972 static slap_mrule_defs_rec mrule_defs[] = {
2974 * EQUALITY matching rules must be listed after associated APPROX
2975 * matching rules. So, we list all APPROX matching rules first.
2977 #ifndef SLAP_NVALUES
2978 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2980 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2981 NULL, NULL, directoryStringApproxMatch,
2982 directoryStringApproxIndexer, directoryStringApproxFilter,
2985 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2987 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2988 NULL, NULL, IA5StringApproxMatch,
2989 IA5StringApproxIndexer, IA5StringApproxFilter,
2994 * Other matching rules
2997 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2998 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2999 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3001 objectIdentifierNormalize, objectIdentifierMatch,
3002 objectIdentifierIndexer, objectIdentifierFilter,
3005 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3006 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3007 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3009 distinguishedNameNormalize, distinguishedNameMatch,
3010 distinguishedNameIndexer, distinguishedNameFilter,
3013 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3015 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3016 directoryStringSyntaxes,
3018 caseIgnoreNormalize, caseIgnoreMatch,
3019 caseIgnoreIndexer, caseIgnoreFilter,
3020 directoryStringApproxMatchOID },
3022 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3023 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3024 SLAP_MR_ORDERING, directoryStringSyntaxes,
3025 NULL, caseIgnoreNormalize, caseIgnoreOrderingMatch,
3028 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3029 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3030 SLAP_MR_SUBSTR, NULL,
3032 caseIgnoreSubstringsMatch,
3033 caseIgnoreSubstringsIndexer, caseIgnoreSubstringsFilter,
3036 {"( 2.5.13.5 NAME 'caseExactMatch' "
3037 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3038 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
3040 caseExactNormalize, caseExactMatch,
3041 caseExactIndexer, caseExactFilter,
3042 directoryStringApproxMatchOID },
3044 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3045 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3046 SLAP_MR_ORDERING, directoryStringSyntaxes,
3047 NULL, caseExactNormalize, caseExactOrderingMatch,
3050 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3051 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3052 SLAP_MR_SUBSTR, directoryStringSyntaxes,
3054 NULL, caseExactSubstringsMatch,
3055 caseExactSubstringsIndexer, caseExactSubstringsFilter,
3058 {"( 2.5.13.8 NAME 'numericStringMatch' "
3059 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3060 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3062 numericStringNormalize, numericStringMatch,
3063 numericStringIndexer, numericStringFilter,
3066 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3068 SLAP_MR_SUBSTR, NULL,
3070 NULL, numericStringSubstringsMatch,
3071 numericStringSubstringsIndexer, numericStringSubstringsFilter,
3074 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3075 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3076 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3077 NULL, NULL, NULL, NULL, NULL, NULL},
3079 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3080 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3081 SLAP_MR_SUBSTR, NULL,
3082 NULL, NULL, NULL, NULL, NULL, NULL},
3084 {"( 2.5.13.13 NAME 'booleanMatch' "
3085 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3086 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3089 booleanIndexer, booleanFilter,
3092 {"( 2.5.13.14 NAME 'integerMatch' "
3093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3094 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3096 integerNormalize, integerMatch,
3097 integerIndexer, integerFilter,
3100 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
3101 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3102 SLAP_MR_ORDERING, NULL, NULL,
3103 integerNormalize, integerOrderingMatch,
3104 integerIndexer, integerFilter,
3107 {"( 2.5.13.16 NAME 'bitStringMatch' "
3108 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3109 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3111 NULL, bitStringMatch,
3112 bitStringIndexer, bitStringFilter,
3115 {"( 2.5.13.17 NAME 'octetStringMatch' "
3116 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3117 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3119 octetStringMatch, octetStringIndexer, octetStringFilter,
3122 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3123 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3124 SLAP_MR_ORDERING, NULL,
3126 octetStringOrderingMatch, NULL, NULL,
3129 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3130 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3131 SLAP_MR_SUBSTR, NULL,
3133 octetStringSubstringsMatch, NULL, NULL,
3136 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3137 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3138 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3140 telephoneNumberNormalize, telephoneNumberMatch,
3141 telephoneNumberIndexer, telephoneNumberFilter,
3144 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3145 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3146 SLAP_MR_SUBSTR, NULL,
3147 NULL, NULL, telephoneNumberSubstringsMatch,
3148 telephoneNumberSubstringsIndexer, telephoneNumberSubstringsFilter,
3151 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3152 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3153 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3158 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3159 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3160 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3162 uniqueMemberNormalize, uniqueMemberMatch,
3166 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3167 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3168 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3169 NULL, NULL, NULL, NULL, NULL, NULL},
3171 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3172 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3173 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3175 generalizedTimeNormalize, generalizedTimeMatch,
3179 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3180 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3181 SLAP_MR_ORDERING, NULL,
3183 generalizedTimeNormalize, generalizedTimeOrderingMatch,
3187 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3188 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3189 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3191 integerFirstComponentNormalize, integerMatch,
3195 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3196 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3197 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3198 objectIdentifierFirstComponentMatchSyntaxes,
3200 objectIdentifierFirstComponentNormalize, objectIdentifierMatch,
3204 #ifndef SLAP_NVALUES
3206 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3207 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3208 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3209 certificateExactConvert, NULL,
3210 certificateExactMatch,
3211 certificateExactIndexer, certificateExactFilter,
3216 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3217 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3218 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3220 caseExactIA5Normalize, caseExactIA5Match,
3221 caseExactIA5Indexer, caseExactIA5Filter,
3222 IA5StringApproxMatchOID },
3224 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3225 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3226 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3228 NULL, caseIgnoreIA5Match,
3229 caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
3230 IA5StringApproxMatchOID },
3232 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3233 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3234 SLAP_MR_SUBSTR, NULL,
3236 NULL, caseIgnoreIA5SubstringsMatch,
3237 caseIgnoreIA5SubstringsIndexer, caseIgnoreIA5SubstringsFilter,
3240 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3241 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3242 SLAP_MR_SUBSTR, NULL,
3244 NULL, caseExactIA5SubstringsMatch,
3245 caseExactIA5SubstringsIndexer, caseExactIA5SubstringsFilter,
3248 #ifdef SLAPD_AUTHPASSWD
3249 /* needs updating */
3250 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3251 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3252 SLAP_MR_EQUALITY, NULL,
3254 authPasswordMatch, NULL, NULL,
3258 #ifdef SLAPD_ACI_ENABLED
3259 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3260 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3261 SLAP_MR_EQUALITY, NULL,
3263 OpenLDAPaciMatch, NULL, NULL,
3267 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3268 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3271 NULL, integerBitAndMatch, NULL, NULL,
3274 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3275 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3278 NULL, integerBitOrMatch, NULL, NULL,
3281 {NULL, SLAP_MR_NONE, NULL,
3282 NULL, NULL, NULL, NULL, NULL,
3287 slap_schema_init( void )
3292 /* we should only be called once (from main) */
3293 assert( schema_init_done == 0 );
3295 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3296 res = register_syntax( &syntax_defs[i] );
3299 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3300 syntax_defs[i].sd_desc );
3305 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3306 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3307 mrule_defs[i].mrd_compat_syntaxes == NULL )
3310 "slap_schema_init: Ignoring unusable matching rule %s\n",
3311 mrule_defs[i].mrd_desc );
3315 res = register_matching_rule( &mrule_defs[i] );
3319 "slap_schema_init: Error registering matching rule %s\n",
3320 mrule_defs[i].mrd_desc );
3325 res = slap_schema_load();
3326 schema_init_done = 1;
3331 schema_destroy( void )