From 4ecce4aa6bfa3bd7b79df27f423a8e961cbee5ec Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Fri, 12 Jul 2013 12:22:02 +0200 Subject: [PATCH] Ticket 47369 - provide default syntax plugin Bug Description: syntax plugins are laoded during bootstrapping, but in that phase already attributes are handled eg in dse.ldif and schema files and no proper way to normalize or comare values is provided. This became visible with teh fix for ticket #346 where large attribute sets will be sorted Fix Description: when the first attribute syntax init is done, create a plugin for directory string syntax and register it with a dummy attribute name. if for any attribute the syntax lookup fails fall back to using this plugin. It will only be used until the syntax plugins are loaded and in the startup phase it is acceptable to use directory string. The impelemenation of the default plugin is reduce to the necasstry minimum not to duplicate the code of the syntax plugins. A more rigorus solution would be to refactor the code and and move the common code from the syntax plugin to the slapd level and reuse it in the default plugin. But this would be a major change and should only be done with a review of the syntax plugin code, whic could probabyly be optimized. https://fedorahosted.org/389/ticket/47369 Reviewed by: ? --- ldap/servers/slapd/attrsyntax.c | 168 ++++++++++++++++++++++++++++++++++++++++ ldap/servers/slapd/slap.h | 2 + 2 files changed, 170 insertions(+) diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c index 82adad4..71fd00c 100644 --- a/ldap/servers/slapd/attrsyntax.c +++ b/ldap/servers/slapd/attrsyntax.c @@ -308,6 +308,8 @@ struct asyntaxinfo *asi = NULL; asi = attr_syntax_get_by_name_locking_optional(name, PR_TRUE); if (asi == NULL) asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX); + if ( asi == NULL ) + asi = attr_syntax_get_by_name(PSEUDO_ATTR_DEFAULT_SYNTAX); return asi; } @@ -545,6 +547,157 @@ attr_syntax_exists(const char *attr_name) return 0; } +static void default_dirstring_normalize_int(char *s, int trim_spaces); + +static +int default_dirstring_filter_ava( struct berval *bvfilter, Slapi_Value **bvals,int ftype, Slapi_Value **retVal ) +{ + return(0); +} + +static +int default_dirstring_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,Slapi_Value ***ivals, int ftype ) +{ + int numbvals = 0; + Slapi_Value **nbvals, **nbvlp; + Slapi_Value **bvlp; + char *c; + + if (NULL == ivals) { + return 1; + } + *ivals = NULL; + if (NULL == bvals) { + return 1; + } + switch ( ftype ) { + case LDAP_FILTER_EQUALITY: + /* allocate a new array for the normalized values */ + for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) { + numbvals++; + } + nbvals = (Slapi_Value **) slapi_ch_calloc( (numbvals + 1), sizeof(Slapi_Value *)); + + for ( bvlp = bvals, nbvlp = nbvals; bvlp && *bvlp; bvlp++, nbvlp++ ) { + c = slapi_ch_strdup(slapi_value_get_string(*bvlp)); + default_dirstring_normalize_int( c, 1 ); + *nbvlp = slapi_value_new_string_passin(c); + c = NULL; + } + *ivals = nbvals; + break; + + case LDAP_FILTER_APPROX: + case LDAP_FILTER_SUBSTRINGS: + default: + /* default plugin only handles equality so far */ + LDAPDebug( LDAP_DEBUG_ANY, + "default_dirstring_values2keys: unsupported ftype 0x%x\n", + ftype, 0, 0 ); + break; + } + return(0); +} + +static +int default_dirstring_assertion2keys_ava(Slapi_PBlock *pb,Slapi_Value *val,Slapi_Value ***ivals,int ftype ) +{ + return(0); +} + +static +int default_dirstring_cmp(struct berval *v1,struct berval *v2, int normalize) +{ + return(0); +} + +static +void default_dirstring_normalize(Slapi_PBlock *pb, char *s, int trim_spaces, char **alt) +{ + default_dirstring_normalize_int(s, trim_spaces); +} + +static +void default_dirstring_normalize_int(char *s, int trim_spaces) +{ + char *head = s; + char *d; + int prevspace, curspace; + + if (NULL == s) { + return; + } + d = s; + if (trim_spaces) { + /* strip leading blanks */ + while (ldap_utf8isspace(s)) { + LDAP_UTF8INC(s); + } + } + + /* handle value of all spaces - turn into single space */ + if ( *s == '\0' && s != d ) { + *d++ = ' '; + *d = '\0'; + return; + } + prevspace = 0; + while ( *s ) { + int ssz, dsz; + curspace = ldap_utf8isspace(s); + + /* compress multiple blanks */ + if ( prevspace && curspace ) { + LDAP_UTF8INC(s); + continue; + } + prevspace = curspace; + slapi_utf8ToLower((unsigned char*)s, (unsigned char *)d, &ssz, &dsz); + s += ssz; + d += dsz; + } + *d = '\0'; + /* strip trailing blanks */ + if (prevspace && trim_spaces) { + char *nd; + + nd = ldap_utf8prev(d); + while (nd && nd >= head && ldap_utf8isspace(nd)) { + d = nd; + nd = ldap_utf8prev(d); + *d = '\0'; + } + } +} + +struct slapdplugin * +attr_syntax_default_plugin ( const char *nameoroid ) +{ + struct slapdplugin *pi = NULL; + + /* firs version, derived from plugin_setup */ + + + /* + * create a new plugin structure, fill it in, and prepare to + * call the plugin's init function. the init function will + * set the plugin function pointers. + */ + pi = (struct slapdplugin *)slapi_ch_calloc(1, sizeof(struct slapdplugin)); + + pi->plg_dn = slapi_ch_smprintf("default plugin for %s",nameoroid); + pi->plg_closed = 0; + pi->plg_syntax_oid = slapi_ch_strdup(nameoroid); + + + pi->plg_syntax_filter_ava = (IFP) default_dirstring_filter_ava; + pi->plg_syntax_values2keys = (IFP) default_dirstring_values2keys; + pi->plg_syntax_assertion2keys_ava = (IFP) default_dirstring_assertion2keys_ava; + pi->plg_syntax_compare = (IFP) default_dirstring_cmp; + pi->plg_syntax_normalize = (VFPV) default_dirstring_normalize; + + return (pi); +} /* check syntax */ static void * @@ -563,6 +716,8 @@ attr_syntax_get_plugin_by_name_with_default( const char *type ) * attribute type that has that syntax. */ asi = attr_syntax_get_by_name(ATTR_WITH_OCTETSTRING_SYNTAX); + if ( asi == NULL ) + asi = attr_syntax_get_by_name(PSEUDO_ATTR_DEFAULT_SYNTAX); } if ( NULL != asi ) { plugin = asi->asi_plugin; @@ -720,6 +875,12 @@ attr_syntax_create( a.asi_mr_substring = (char*)mr_substring; a.asi_extensions = extensions; a.asi_plugin = plugin_syntax_find( attr_syntax ); + /* if we couldn't find the syntax plugin and the attribute is + * a default attribute, just used at startup until the syntax plugins + * are loaded: create a simple default + */ + if ( a.asi_plugin == NULL && 0 == strcasecmp(a.asi_name,PSEUDO_ATTR_DEFAULT_SYNTAX)) + a.asi_plugin = attr_syntax_default_plugin (attr_syntax ); a.asi_syntaxlength = syntaxlength; /* ideally, we would report an error and fail to start if there was some problem with the matching rule - but since this functionality is new, and we might @@ -1178,6 +1339,13 @@ attr_syntax_init(void) "slapi_new_rwlock() for oid2asi lock failed\n" ); return 1; } + /* add a default syntax plugin as fallback, required during startup + */ + slapi_add_internal_attr_syntax( PSEUDO_ATTR_DEFAULT_SYNTAX, + PSEUDO_ATTR_DEFAULT_SYNTAX_OID, + DIRSTRING_SYNTAX_OID, 0, + SLAPI_ATTR_FLAG_NOUSERMOD| + SLAPI_ATTR_FLAG_NOEXPOSE); } return 0; } diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index fff4646..1fb7de7 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -2454,6 +2454,8 @@ extern char *attr_dataversion; #if defined(USE_OLD_UNHASHED) #define PSEUDO_ATTR_UNHASHEDUSERPASSWORD_OID "2.16.840.1.113730.3.1.2110" #endif +#define PSEUDO_ATTR_DEFAULT_SYNTAX_OID "2.16.840.1.113730.3.1.2210" +#define PSEUDO_ATTR_DEFAULT_SYNTAX "pseudo#attr#defaultsyntax" /* virtualListViewError is a relatively new concept that was added long * after we implemented VLV. Until added to LDAP SDK, we define -- 1.7.11.7