diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c index 1c4067c749..4d94aced30 100644 --- a/servers/slapd/attr.c +++ b/servers/slapd/attr.c @@ -282,31 +282,45 @@ attr_syntax_config( at = (LDAP_ATTRIBUTE_TYPE *) ch_calloc( 1, sizeof(LDAP_ATTRIBUTE_TYPE) ); +#define SYNTAX_DS_OID "1.3.6.1.4.1.1466.115.121.1.15" +#define SYNTAX_DSCE_OID "2.5.13.5" +#define SYNTAX_IA5_OID "1.3.6.1.4.1.1466.115.121.1.26" +#define SYNTAX_IA5CE_OID "1.3.6.1.4.1.1466.109.114.1" +#define SYNTAX_DN_OID "1.3.6.1.4.1.1466.115.121.1.12" +#define SYNTAX_TEL_OID "1.3.6.1.4.1.1466.115.121.1.50" +#define SYNTAX_BIN_OID "1.3.6.1.4.1.1466.115.121.1.40" /* octetString */ + lasti = argc - 1; if ( strcasecmp( argv[lasti], "caseignorestring" ) == 0 || strcasecmp( argv[lasti], "cis" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15"; + at->at_syntax_oid = SYNTAX_DS_OID; at->at_equality_oid = "2.5.13.2"; at->at_ordering_oid = "2.5.13.3"; at->at_substr_oid = "2.5.13.4"; + } else if ( strcasecmp( argv[lasti], "telephone" ) == 0 || strcasecmp( argv[lasti], "tel" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.50"; + at->at_syntax_oid = SYNTAX_TEL_OID; at->at_equality_oid = "2.5.13.20"; at->at_substr_oid = "2.5.13.21"; + } else if ( strcasecmp( argv[lasti], "dn" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.12"; + at->at_syntax_oid = SYNTAX_DN_OID; at->at_equality_oid = "2.5.13.1"; + } else if ( strcasecmp( argv[lasti], "caseexactstring" ) == 0 || strcasecmp( argv[lasti], "ces" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.15"; - at->at_equality_oid = "2.5.13.5"; + at->at_syntax_oid = SYNTAX_DS_OID; + at->at_equality_oid = SYNTAX_DSCE_OID; at->at_ordering_oid = "2.5.13.6"; at->at_substr_oid = "2.5.13.7"; + } else if ( strcasecmp( argv[lasti], "binary" ) == 0 || strcasecmp( argv[lasti], "bin" ) == 0 ) { - at->at_syntax_oid = "1.3.6.1.4.1.1466.115.121.1.5"; - /* There is no match for binary syntax. Really */ + /* bin -> octetString, not binary! */ + at->at_syntax_oid = SYNTAX_BIN_OID; + at->at_equality_oid = "2.5.13.17"; + } else { Debug( LDAP_DEBUG_ANY, "%s: line %d: unknown syntax \"%s\" in attribute line (ignored)\n", @@ -572,6 +586,7 @@ at_add( } sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) ); memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE)); + if ( at->at_sup_oid ) { if ( (sat1 = at_find(at->at_sup_oid)) ) { sat->sat_sup = sat1; @@ -585,6 +600,19 @@ at_add( } } + /* + * Inherit definitions from superiors. We only check the + * direct superior since that one has already inherited from + * its own superiorss + */ + if ( sat->sat_sup ) { + sat->sat_syntax = sat->sat_sup->sat_syntax; + + sat->sat_equality = sat->sat_sup->sat_equality; + sat->sat_ordering = sat->sat_sup->sat_ordering; + sat->sat_substr = sat->sat_sup->sat_substr; + } + if ( at->at_syntax_oid ) { if ( (syn = syn_find(sat->sat_syntax_oid)) ) { sat->sat_syntax = syn; @@ -592,27 +620,40 @@ at_add( *err = sat->sat_syntax_oid; return SLAP_SCHERR_SYN_NOT_FOUND; } - if ( !strcmp(at->at_syntax_oid, - "1.3.6.1.4.1.1466.115.121.1.15") ) { - if ( at->at_equality_oid && - !strcmp(at->at_equality_oid, "2.5.13.5") ) { + + if ( !strcmp(at->at_syntax_oid, SYNTAX_DS_OID) ) { + if ( at->at_equality_oid && ( + !strcmp(at->at_equality_oid, SYNTAX_DSCE_OID) ) ) + { sat->sat_syntax_compat = SYNTAX_CES; } else { sat->sat_syntax_compat = SYNTAX_CIS; } - } else if ( !strcmp(at->at_syntax_oid, - "1.3.6.1.4.1.1466.115.121.1.50") ) { - sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL; - } else if ( !strcmp(at->at_syntax_oid, - "1.3.6.1.4.1.1466.115.121.1.12") ) { + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_IA5_OID) ) { + if ( at->at_equality_oid && ( + !strcmp(at->at_equality_oid, SYNTAX_IA5CE_OID) ) ) + { + sat->sat_syntax_compat = SYNTAX_CES; + } else { + sat->sat_syntax_compat = SYNTAX_CIS; + } + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_DN_OID ) ) { sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN; - } else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.5") ) { + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_TEL_OID ) ) { + sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL; + + } else if ( !strcmp(at->at_syntax_oid, SYNTAX_BIN_OID ) ) { sat->sat_syntax_compat = SYNTAX_BIN; + } else { sat->sat_syntax_compat = DEFAULT_SYNTAX; } - } else { - sat->sat_syntax_compat = DEFAULT_SYNTAX; + + } else if ( sat->sat_syntax == NULL ) { + return SLAP_SCHERR_ATTR_INCOMPLETE; } if ( sat->sat_equality_oid ) { @@ -622,7 +663,9 @@ at_add( *err = sat->sat_equality_oid; return SLAP_SCHERR_MR_NOT_FOUND; } + } + if ( sat->sat_ordering_oid ) { if ( (mr = mr_find(sat->sat_ordering_oid)) ) { sat->sat_ordering = mr; @@ -631,6 +674,7 @@ at_add( return SLAP_SCHERR_MR_NOT_FOUND; } } + if ( sat->sat_substr_oid ) { if ( (mr = mr_find(sat->sat_substr_oid)) ) { sat->sat_substr = mr; @@ -640,26 +684,6 @@ at_add( } } - /* - * Now inherit definitions from superiors. We only check the - * direct superior since that one has already inherited from - * its own superiorss - */ - if ( sat->sat_sup ) { - if ( !sat->sat_syntax ) { - sat->sat_syntax = sat->sat_sup->sat_syntax; - sat->sat_syntax_len = sat->sat_sup->sat_syntax_len; - } - if ( !sat->sat_equality ) { - sat->sat_equality = sat->sat_sup->sat_equality; - } - if ( !sat->sat_ordering ) { - sat->sat_ordering = sat->sat_sup->sat_ordering; - } - if ( !sat->sat_substr ) { - sat->sat_substr = sat->sat_sup->sat_substr; - } - } code = at_insert(sat,err); return code; } diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 8e19bb2d88..2b5150f79b 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -444,20 +444,31 @@ LIBSLAPD_F (int) oc_check_usermod_attr LDAP_P(( const char *type )); LIBSLAPD_F (int) oc_check_no_usermod_attr LDAP_P(( const char *type )); LIBSLAPD_F (ObjectClass *) oc_find LDAP_P((const char *ocname)); LIBSLAPD_F (int) oc_add LDAP_P((LDAP_OBJECT_CLASS *oc, const char **err)); + LIBSLAPD_F (Syntax *) syn_find LDAP_P((const char *synname)); LIBSLAPD_F (Syntax *) syn_find_desc LDAP_P((const char *syndesc, int *slen)); -LIBSLAPD_F (int) syn_add LDAP_P((LDAP_SYNTAX *syn, slap_syntax_check_func *check, const char **err)); +LIBSLAPD_F (int) syn_add LDAP_P((LDAP_SYNTAX *syn, + slap_syntax_validate_func *validate, + slap_syntax_normalize_func *normalize, + const char **err)); + LIBSLAPD_F (MatchingRule *) mr_find LDAP_P((const char *mrname)); -LIBSLAPD_F (int) mr_add LDAP_P((LDAP_MATCHING_RULE *mr, slap_mr_normalize_func *normalize, slap_mr_compare_func *compare, const char **err)); +LIBSLAPD_F (int) mr_add LDAP_P((LDAP_MATCHING_RULE *mr, + slap_mr_match_func *match, + const char **err)); -LIBSLAPD_F (int) caseIngoreIA5Normalize LDAP_P((struct berval *val, struct berval **normalized)); +LIBSLAPD_F (int) register_syntax LDAP_P((char *desc, + slap_syntax_validate_func *validate, + slap_syntax_normalize_func *normalize )); +LIBSLAPD_F (int) register_matching_rule LDAP_P((char * desc, + slap_mr_match_func *match )); -LIBSLAPD_F (int) register_syntax LDAP_P((char *desc, slap_syntax_check_func *check )); -LIBSLAPD_F (int) register_matching_rule LDAP_P((char * desc, slap_mr_normalize_func *normalize, slap_mr_compare_func *compare)); -LIBSLAPD_F (void) schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly)); +LIBSLAPD_F (void) schema_info LDAP_P((Connection *conn, Operation *op, + char **attrs, int attrsonly)); LIBSLAPD_F (int) schema_init LDAP_P((void)); -LIBSLAPD_F (int) is_entry_objectclass LDAP_P(( Entry *, const char* objectclass )); +LIBSLAPD_F (int) is_entry_objectclass LDAP_P(( + Entry *, const char* objectclass )); #define is_entry_alias(e) is_entry_objectclass((e), "ALIAS") #define is_entry_referral(e) is_entry_objectclass((e), "REFERRAL") diff --git a/servers/slapd/schema.c b/servers/slapd/schema.c index 375638d394..12c30af94e 100644 --- a/servers/slapd/schema.c +++ b/servers/slapd/schema.c @@ -14,11 +14,11 @@ #include #include "slap.h" +#include "ldap_pvt.h" static char * oc_check_required(Entry *e, char *ocname); static int oc_check_allowed(char *type, struct berval **ocl); - /* * oc_check - check that entry e conforms to the schema required by * its object class(es). returns 0 if so, non-zero otherwise. @@ -650,7 +650,8 @@ syn_insert( int syn_add( LDAP_SYNTAX *syn, - slap_syntax_check_func *check, + slap_syntax_validate_func *validate, + slap_syntax_normalize_func *normalize, const char **err ) { @@ -659,7 +660,8 @@ syn_add( ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) ); memcpy( &ssyn->ssyn_syn, syn, sizeof(LDAP_SYNTAX)); - ssyn->ssyn_check = check; + ssyn->ssyn_validate = validate; + ssyn->ssyn_normalize = normalize; code = syn_insert(ssyn,err); return code; } @@ -757,8 +759,7 @@ mr_insert( int mr_add( LDAP_MATCHING_RULE *mr, - slap_mr_normalize_func *normalize, - slap_mr_compare_func *compare, + slap_mr_match_func *match, const char **err ) { @@ -768,8 +769,7 @@ mr_add( smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) ); memcpy( &smr->smr_mrule, mr, sizeof(LDAP_MATCHING_RULE)); - smr->smr_normalize = normalize; - smr->smr_compare = compare; + smr->smr_match = match; if ( smr->smr_syntax_oid ) { if ( (syn = syn_find(smr->smr_syntax_oid)) ) { smr->smr_syntax = syn; @@ -786,7 +786,127 @@ mr_add( } static int -caseExactIA5Normalize( +octetStringValidate( struct berval *val ) +{ + /* any value allowed */ + return 0; +} + +static int +UTF8StringValidate( struct berval *val ) +{ + ber_len_t count; + int len; + unsigned char *u = val->bv_val; + + for( count = val->bv_len; count > 0; count+=len, u+=len ) { + /* get the length indicated by the first byte */ + len = LDAP_UTF8_CHARLEN( u ); + + /* should not be zero */ + if( len == 0 ) return -1; + + /* make sure len corresponds with the offset + to the next character */ + if( LDAP_UTF8_OFFSET( u ) != len ) return -1; + } + + if( count != 0 ) return -1; + + return 0; +} + +static int +UTF8StringNormalize( + struct berval *val, + struct berval **normalized +) +{ + struct berval *newval; + char *p, *q, *s; + + newval = ch_malloc( sizeof( struct berval ) ); + + p = val->bv_val; + + /* Ignore initial whitespace */ + while ( ldap_utf8_isspace( p ) ) { + LDAP_UTF8_INCR( p ); + } + + if( *p ) { + ch_free( newval ); + return 1; + } + + newval->bv_val = ch_strdup( p ); + p = q = newval->bv_val; + s = NULL; + + while ( *p ) { + int len; + + if ( ldap_utf8_isspace( p ) ) { + len = LDAP_UTF8_COPY(q,p); + s=q; + p+=len; + q+=len; + + /* Ignore the extra whitespace */ + while ( ldap_utf8_isspace( p ) ) { + LDAP_UTF8_INCR( p ); + } + } else { + len = LDAP_UTF8_COPY(q,p); + s=NULL; + p+=len; + q+=len; + } + } + + assert( *newval->bv_val ); + assert( newval->bv_val < p ); + assert( p <= q ); + + /* cannot start with a space */ + assert( !ldap_utf8_isspace(newval->bv_val) ); + + /* + * If the string ended in space, backup the pointer one + * position. One is enough because the above loop collapsed + * all whitespace to a single space. + */ + + if ( s != NULL ) { + q = s; + } + + /* cannot end with a space */ + assert( !ldap_utf8_isspace( LDAP_UTF8_PREV(q) ) ); + + /* null terminate */ + *q = '\0'; + + newval->bv_len = q - newval->bv_val; + normalized = &newval; + + return 0; +} + +static int +IA5StringValidate( struct berval *val ) +{ + int i; + + for(i=0; i < val->bv_len; i++) { + if( !isascii(val->bv_val[i]) ) return -1; + } + + return 0; +} + +static int +IA5StringNormalize( struct berval *val, struct berval **normalized ) @@ -794,30 +914,60 @@ caseExactIA5Normalize( struct berval *newval; char *p, *q; - newval = ber_bvdup( val ); - p = q = newval->bv_val; + newval = ch_malloc( sizeof( struct berval ) ); + + p = val->bv_val; + /* Ignore initial whitespace */ - while ( isspace( *p++ ) ) - ; + while ( isspace( *p++ ) ) { + /* EMPTY */ ; + } + + if( *p ) { + ch_free( newval ); + return 1; + } + + newval->bv_val = ch_strdup( p ); + p = q = newval->bv_val; + while ( *p ) { if ( isspace( *p ) ) { *q++ = *p++; + /* Ignore the extra whitespace */ - while ( isspace(*p++) ) - ; + while ( isspace( *p++ ) ) { + /* EMPTY */ ; + } } else { *q++ = *p++; } } + + assert( *newval->bv_val ); + assert( newval->bv_val < p ); + assert( p <= q ); + + /* cannot start with a space */ + assert( !isspace(*newval->bv_val) ); + /* * If the string ended in space, backup the pointer one * position. One is enough because the above loop collapsed * all whitespace to a single space. */ - if ( p != newval->bv_val && isspace( *(p-1) ) ) { - *(q-1) = '\0'; + + if ( isspace( q[-1] ) ) { + --q; } - newval->bv_len = strlen( newval->bv_val ); + + /* cannot end with a space */ + assert( !isspace( q[-1] ) ); + + /* null terminate */ + *q = '\0'; + + newval->bv_len = q - newval->bv_val; normalized = &newval; return 0; @@ -832,44 +982,6 @@ caseExactIA5Match( return strcmp( val1->bv_val, val2->bv_val ); } -int -caseIgnoreIA5Normalize( - struct berval *val, - struct berval **normalized -) -{ - struct berval *newval; - char *p, *q; - - newval = ber_bvdup( val ); - p = q = newval->bv_val; - /* Ignore initial whitespace */ - while ( isspace( *p++ ) ) - ; - while ( *p ) { - if ( isspace( *p ) ) { - *q++ = *p++; - /* Ignore the extra whitespace */ - while ( isspace(*p++) ) - ; - } else { - *q++ = TOUPPER( *p++ ); - } - } - /* - * If the string ended in space, backup the pointer one - * position. One is enough because the above loop collapsed - * all whitespace to a single space. - */ - if ( p != newval->bv_val && isspace( *(p-1) ) ) { - *(q-1) = '\0'; - } - newval->bv_len = strlen( newval->bv_val ); - normalized = &newval; - - return 0; -} - static int caseIgnoreIA5Match( struct berval *val1, @@ -882,7 +994,8 @@ caseIgnoreIA5Match( int register_syntax( char * desc, - slap_syntax_check_func *check ) + slap_syntax_validate_func *validate, + slap_syntax_normalize_func *normalize ) { LDAP_SYNTAX *syn; int code; @@ -894,7 +1007,7 @@ register_syntax( ldap_scherr2str(code), err, desc ); return( -1 ); } - code = syn_add( syn, check, &err ); + code = syn_add( syn, validate, normalize, &err ); if ( code ) { Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n", scherr2str(code), err, desc ); @@ -906,8 +1019,7 @@ register_syntax( int register_matching_rule( char * desc, - slap_mr_normalize_func *normalize, - slap_mr_compare_func *compare ) + slap_mr_match_func *match ) { LDAP_MATCHING_RULE *mr; int code; @@ -919,7 +1031,7 @@ register_matching_rule( ldap_scherr2str(code), err, desc ); return( -1 ); } - code = mr_add( mr, normalize, compare, &err ); + code = mr_add( mr, match, &err ); if ( code ) { Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s for %s in %s\n", scherr2str(code), err, desc ); @@ -930,65 +1042,106 @@ register_matching_rule( struct syntax_defs_rec { char *sd_desc; - slap_syntax_check_func *sd_check; + slap_syntax_validate_func *sd_validate; + slap_syntax_normalize_func *sd_normalize; }; struct syntax_defs_rec syntax_defs[] = { - {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'AttributeTypeDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'BitString' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'CertificateList' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'CertificatePair' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'DN' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'DeliveryMethod' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'DirectoryString' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DITContentRuleDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DITStructureRuleDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'EnhancedGuide' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'FacsimileTelephoneNumber' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'GeneralizedTime' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5String' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'MatchingRuleDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'MatchingRuleUseDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'MailPreference' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'NameAndOptionalUID' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'NameFormDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'NumericString' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'ObjectClassDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'OtherMailbox' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'OctetString' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'PostalAddress' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'ProtocolInformation' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'PresentationAddress' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'PrintableString' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'SupportedAlgorithm' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'TelephoneNumber' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'TeletexTerminalIdentifier' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'TelexNumber' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTCTime' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAPSyntaxDescription' )", NULL}, - {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'SubstringAssertion' )", NULL}, - {"( 1.3.6.1.1.1.0.0 DESC 'NISnetgrouptriple' )", NULL}, - {"( 1.3.6.1.1.1.0.1 DESC 'Bootparameter' )", NULL}, - {NULL, NULL} + {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'AttributeTypeDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'BitString' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'CertificateList' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'CertificatePair' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'DN' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'DeliveryMethod' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'DirectoryString' )", + UTF8StringValidate, UTF8StringNormalize}, + {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DITContentRuleDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DITStructureRuleDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'EnhancedGuide' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'FacsimileTelephoneNumber' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'GeneralizedTime' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5String' )", + IA5StringValidate, IA5StringNormalize}, + {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'MatchingRuleDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'MatchingRuleUseDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'MailPreference' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'NameAndOptionalUID' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'NameFormDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'NumericString' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'ObjectClassDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'OtherMailbox' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'OctetString' )", + octetStringValidate, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'PostalAddress' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'ProtocolInformation' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'PresentationAddress' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'PrintableString' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'SupportedAlgorithm' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'TelephoneNumber' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'TeletexTerminalIdentifier' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'TelexNumber' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTCTime' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAPSyntaxDescription' )", + NULL, NULL}, + {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'SubstringAssertion' )", + NULL, NULL}, + + {NULL, NULL, NULL} }; struct mrule_defs_rec { char *mrd_desc; - slap_mr_normalize_func *mrd_normalize; - slap_mr_compare_func *mrd_compare; + slap_mr_match_func *mrd_match; }; /* * Other matching rules in X.520 that we do not use: * - * 2.5.13.9 numericStringOrderingMatch + * 2.5.13.9 numericStringOrderingMatch * 2.5.13.12 caseIgnoreListSubstringsMatch * 2.5.13.13 booleanMatch * 2.5.13.15 integerOrderingMatch @@ -1012,42 +1165,141 @@ struct mrule_defs_rec { * 2.5.13.44 attributeIntegrityMatch */ +/* recycled matching functions */ +#define caseIgnoreMatch caseIgnoreIA5Match +#define caseExactMatch caseExactIA5Match + +/* unimplemented matching functions */ +#define objectIdentifierMatch NULL +#define distinguishedNameMatch NULL +#define caseIgnoreOrderingMatch NULL +#define caseIgnoreSubstringsMatch NULL +#define caseExactOrderingMatch NULL +#define caseExactSubstringsMatch NULL +#define numericStringMatch NULL +#define numericStringSubstringsMatch NULL +#define caseIgnoreListMatch NULL +#define integerMatch NULL +#define bitStringMatch NULL +#define octetStringMatch NULL +#define telephoneNumberMatch NULL +#define telephoneNumberSubstringsMatch NULL +#define presentationAddressMatch NULL +#define uniqueMemberMatch NULL +#define protocolInformationMatch NULL +#define generalizedTimeMatch NULL +#define generalizedTimeOrderingMatch NULL +#define integerFirstComponentMatch NULL +#define objectIdentifierFirstComponentMatch NULL +#define caseIgnoreIA5SubstringsMatch NULL + struct mrule_defs_rec mrule_defs[] = { - {"( 2.5.13.0 NAME 'objectIdentifierMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", NULL, NULL}, - {"( 2.5.13.1 NAME 'distinguishedNameMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", NULL, NULL}, - {"( 2.5.13.2 NAME 'caseIgnoreMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", - caseIgnoreIA5Normalize, caseIgnoreIA5Match}, - {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", - caseIgnoreIA5Normalize, caseIgnoreIA5Match}, - {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", - caseIgnoreIA5Normalize, caseIgnoreIA5Match}, + {"( 2.5.13.0 NAME 'objectIdentifierMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", + objectIdentifierMatch}, + + {"( 2.5.13.1 NAME 'distinguishedNameMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", + distinguishedNameMatch}, + + {"( 2.5.13.2 NAME 'caseIgnoreMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", + caseIgnoreMatch}, + + {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", + caseIgnoreOrderingMatch}, + + {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", + caseIgnoreSubstringsMatch}, + /* Next three are not in the RFC's, but are needed for compatibility */ - {"( 2.5.13.5 NAME 'caseExactMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", - caseExactIA5Normalize, caseExactIA5Match}, - {"( 2.5.13.6 NAME 'caseExactOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", - caseExactIA5Normalize, caseExactIA5Match}, - {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", - caseExactIA5Normalize, caseExactIA5Match}, - {"( 2.5.13.8 NAME 'numericStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", NULL, NULL}, - {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", NULL, NULL}, - {"( 2.5.13.11 NAME 'caseIgnoreListMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", NULL, NULL}, - {"( 2.5.13.14 NAME 'integerMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", NULL, NULL}, - {"( 2.5.13.16 NAME 'bitStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", NULL, NULL}, - {"( 2.5.13.17 NAME 'octetStringMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", NULL, NULL}, - {"( 2.5.13.20 NAME 'telephoneNumberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", NULL, NULL}, - {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", NULL, NULL}, - {"( 2.5.13.22 NAME 'presentationAddressMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", NULL, NULL}, - {"( 2.5.13.23 NAME 'uniqueMemberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", NULL, NULL}, - {"( 2.5.13.24 NAME 'protocolInformationMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", NULL, NULL}, - {"( 2.5.13.27 NAME 'generalizedTimeMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", NULL, NULL}, - {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", NULL, NULL}, - {"( 2.5.13.29 NAME 'integerFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", NULL, NULL}, - {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", NULL, NULL}, - {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", - caseExactIA5Normalize, caseExactIA5Match}, - {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", - caseIgnoreIA5Normalize, caseIgnoreIA5Match}, - {NULL, NULL, NULL} + {"( 2.5.13.5 NAME 'caseExactMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", + caseExactMatch}, + + {"( 2.5.13.6 NAME 'caseExactOrderingMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", + caseExactOrderingMatch}, + + {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", + caseExactSubstringsMatch}, + + {"( 2.5.13.8 NAME 'numericStringMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )", + numericStringMatch}, + + {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", + numericStringSubstringsMatch}, + + {"( 2.5.13.11 NAME 'caseIgnoreListMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", + caseIgnoreListMatch}, + + {"( 2.5.13.14 NAME 'integerMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", + integerMatch}, + + {"( 2.5.13.16 NAME 'bitStringMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )", + bitStringMatch}, + + {"( 2.5.13.17 NAME 'octetStringMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", + octetStringMatch}, + + {"( 2.5.13.20 NAME 'telephoneNumberMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )", + telephoneNumberMatch}, + + {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", + telephoneNumberSubstringsMatch}, + + {"( 2.5.13.22 NAME 'presentationAddressMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )", + presentationAddressMatch}, + + {"( 2.5.13.23 NAME 'uniqueMemberMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", + uniqueMemberMatch}, + + {"( 2.5.13.24 NAME 'protocolInformationMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )", + protocolInformationMatch}, + + {"( 2.5.13.27 NAME 'generalizedTimeMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", + generalizedTimeMatch}, + + {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", + generalizedTimeOrderingMatch}, + + {"( 2.5.13.29 NAME 'integerFirstComponentMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", + integerFirstComponentMatch}, + + {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", + objectIdentifierFirstComponentMatch}, + + {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", + caseExactIA5Match}, + + {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", + caseIgnoreIA5Match}, + + {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", + caseIgnoreIA5SubstringsMatch}, + + {NULL, NULL} }; int @@ -1060,21 +1312,23 @@ schema_init( void ) /* We are called from read_config that is recursive */ if ( schema_init_done ) return( 0 ); + for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) { res = register_syntax( syntax_defs[i].sd_desc, - syntax_defs[i].sd_check ); + syntax_defs[i].sd_validate, + syntax_defs[i].sd_normalize ); + if ( res ) { fprintf( stderr, "schema_init: Error registering syntax %s\n", syntax_defs[i].sd_desc ); exit( EXIT_FAILURE ); } } + for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) { res = register_matching_rule( mrule_defs[i].mrd_desc, - ( mrule_defs[i].mrd_normalize ? - mrule_defs[i].mrd_normalize : caseIgnoreIA5Normalize ), - ( mrule_defs[i].mrd_compare ? - mrule_defs[i].mrd_compare : caseIgnoreIA5Match ) ); + mrule_defs[i].mrd_match ); + if ( res ) { fprintf( stderr, "schema_init: Error registering matching rule %s\n", mrule_defs[i].mrd_desc ); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index a9b82c6015..64d3b14497 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -115,13 +115,13 @@ struct replog_moddn { * represents an attribute value assertion (i.e., attr=value) */ typedef struct slap_ava { - char *ava_type; + char *ava_type; /* attribute description */ struct berval ava_value; } Ava; typedef struct slap_mra { char *mra_rule; - char *mra_type; + char *mra_type; /* attribute description */ char *mra_value; int mra_dnattrs; } Mra; @@ -180,7 +180,7 @@ typedef struct slap_filter { * represents an attribute (type + values + syntax) */ typedef struct slap_attr { - char *a_type; + char *a_type; /* description */ struct berval **a_vals; int a_syntax; struct slap_attr *a_next; @@ -365,31 +365,37 @@ typedef struct slap_oid_macro { int oidlen; } OidMacro; -typedef int slap_syntax_check_func LDAP_P((struct berval * val)); +typedef int slap_syntax_validate_func LDAP_P(( + struct berval * in)); + +typedef int slap_syntax_normalize_func LDAP_P(( + struct berval * in, + struct berval ** out)); typedef struct slap_syntax { LDAP_SYNTAX ssyn_syn; - slap_syntax_check_func *ssyn_check; + slap_syntax_validate_func *ssyn_validate; + slap_syntax_normalize_func *ssyn_normalize; struct slap_syntax *ssyn_next; -} Syntax; #define ssyn_oid ssyn_syn.syn_oid #define ssyn_desc ssyn_syn.syn_desc +} Syntax; -typedef int slap_mr_normalize_func LDAP_P((struct berval * val, struct berval **normalized)); -typedef int slap_mr_compare_func LDAP_P((struct berval * val1, struct berval * val2)); +typedef int slap_mr_match_func LDAP_P(( + struct berval * atval, + struct berval * matchval)); typedef struct slap_matching_rule { LDAP_MATCHING_RULE smr_mrule; - slap_mr_normalize_func *smr_normalize; - slap_mr_compare_func *smr_compare; + slap_mr_match_func *smr_match; Syntax *smr_syntax; struct slap_matching_rule *smr_next; -} MatchingRule; #define smr_oid smr_mrule.mr_oid #define smr_names smr_mrule.mr_names #define smr_desc smr_mrule.mr_desc #define smr_obsolete smr_mrule.mr_obsolete #define smr_syntax_oid smr_mrule.mr_syntax_oid +} MatchingRule; typedef struct slap_attribute_type { LDAP_ATTRIBUTE_TYPE sat_atype; @@ -402,7 +408,6 @@ typedef struct slap_attribute_type { /* The next one is created to help in the transition */ int sat_syntax_compat; struct slap_attribute_type *sat_next; -} AttributeType; #define sat_oid sat_atype.at_oid #define sat_names sat_atype.at_names #define sat_desc sat_atype.at_desc @@ -412,11 +417,11 @@ typedef struct slap_attribute_type { #define sat_ordering_oid sat_atype.at_ordering_oid #define sat_substr_oid sat_atype.at_substr_oid #define sat_syntax_oid sat_atype.at_syntax_oid -#define sat_syntax_len sat_atype.at_syntax_len #define sat_single_value sat_atype.at_single_value #define sat_collective sat_atype.at_collective #define sat_no_user_mods sat_atype.at_no_user_mods #define sat_usage sat_atype.at_usage +} AttributeType; typedef struct slap_object_class { LDAP_OBJECT_CLASS soc_oclass; @@ -424,7 +429,6 @@ typedef struct slap_object_class { AttributeType **soc_required; AttributeType **soc_allowed; struct slap_object_class *soc_next; -} ObjectClass; #define soc_oid soc_oclass.oc_oid #define soc_names soc_oclass.oc_names #define soc_desc soc_oclass.oc_desc @@ -433,6 +437,7 @@ typedef struct slap_object_class { #define soc_kind soc_oclass.oc_kind #define soc_at_oids_must soc_oclass.oc_at_oids_must #define soc_at_oids_may soc_oclass.oc_at_oids_may +} ObjectClass; /* * Backend-info