From: Kurt Zeilenga Date: Mon, 24 Jan 2000 23:31:26 +0000 (+0000) Subject: Modify slapd syntax struct to have both a validation and normalization X-Git-Tag: UCDATA_2_4~7 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=117a37272d505d016080555b69dbfc32dfc28b1d;p=openldap Modify slapd syntax struct to have both a validation and normalization routine. Could be combined into one routine. Modify slapd matching rule struct to only have match function. Modify old attribute such that 'bin' implies octetString, not 'binary'. Add compatibility for IA5 strings. Only directoryStrings were handled before. Treat attribute types without syntax as incomplete, not default. Add OctetStringValidate (always returns okay). Add {UTF8,IA5}StringValidate/Normalize (IA5 based loosely on case_exact_normalize). Need case{Exact,Ignore}UTFMatch, using IA5 versions for now. Removed default of syntax/mr handlders, should just skip registration of syntax/mr's without handlers. Added comments to slap.h about types versus descriptions. --- 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 (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) syn_add LDAP_P((LDAP_SYNTAX *syn, + slap_syntax_validate_func *validate, + slap_syntax_normalize_func *normalize, + 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_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 (MatchingRule *) mr_find LDAP_P((const char *mrname)); +LIBSLAPD_F (int) mr_add LDAP_P((LDAP_MATCHING_RULE *mr, + slap_mr_match_func *match, + const char **err)); + +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 (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,54 +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; + char *p, *q, *s; + + newval = ch_malloc( sizeof( struct berval ) ); + + p = val->bv_val; - newval = ber_bvdup( val ); - p = q = newval->bv_val; /* Ignore initial whitespace */ - while ( isspace( *p++ ) ) - ; + 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 ) { - if ( isspace( *p ) ) { - *q++ = *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 ( isspace(*p++) ) - ; + while ( ldap_utf8_isspace( p ) ) { + LDAP_UTF8_INCR( p ); + } } else { - *q++ = *p++; + 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 ( p != newval->bv_val && isspace( *(p-1) ) ) { - *(q-1) = '\0'; + + if ( s != NULL ) { + q = s; } - newval->bv_len = strlen( newval->bv_val ); + + /* 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 -caseExactIA5Match( - struct berval *val1, - struct berval *val2 -) +IA5StringValidate( struct berval *val ) { - return strcmp( val1->bv_val, val2->bv_val ); + int i; + + for(i=0; i < val->bv_len; i++) { + if( !isascii(val->bv_val[i]) ) return -1; + } + + return 0; } -int -caseIgnoreIA5Normalize( +static int +IA5StringNormalize( struct berval *val, struct berval **normalized ) @@ -841,35 +914,74 @@ caseIgnoreIA5Normalize( 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++ = TOUPPER( *p++ ); + *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; } +static int +caseExactIA5Match( + struct berval *val1, + struct berval *val2 +) +{ + return strcmp( val1->bv_val, val2->bv_val ); +} + 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