From 58cb75187926ea9a8acb857c7ba7c999a539f71a Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Fri, 1 Mar 2013 17:36:05 -0800 Subject: [PATCH] Ticket #604 - Required attribute not checked during search operation Bug description: If attribute list passed from the ldapsearch contains a string with a space and following characters, the same string is returned to the client. E.g., ldapsearch -b "(filter)" "sn garbage" returns dn: sn garbage: Fix description: This patch introduces a config parameter nsslapd-search-return-original-type-switch. It takes on | off. By default, it is off. When it is off, search returns the attribute from which a space and following characters are chopped. dn: sn: If it is on, it respects the current behaviour and returns the original attribute string. --- ldap/servers/slapd/attrsyntax.c | 51 ++++++++++++++++++++++++++++++++---- ldap/servers/slapd/libglobs.c | 29 +++++++++++++++++++++ ldap/servers/slapd/operation.c | 2 +- ldap/servers/slapd/proto-slap.h | 3 ++ ldap/servers/slapd/search.c | 29 +++++++++++++++------ ldap/servers/slapd/slap.h | 7 +++++ ldap/servers/slapd/slapi-plugin.h | 18 +++++++++++++ 7 files changed, 124 insertions(+), 15 deletions(-) diff --git a/ldap/servers/slapd/attrsyntax.c b/ldap/servers/slapd/attrsyntax.c index 26e09db..227369c 100644 --- a/ldap/servers/slapd/attrsyntax.c +++ b/ldap/servers/slapd/attrsyntax.c @@ -450,9 +450,6 @@ attr_syntax_delete_no_lock( struct asyntaxinfo *asi, * * Warning: The caller must free the returned string. */ - - - char * slapi_attr_syntax_normalize( const char *s ) { @@ -470,6 +467,29 @@ slapi_attr_syntax_normalize( const char *s ) return r; } +/* + * flags: + * 0 -- same as slapi_attr_syntax_normalize + * ATTR_SYNTAX_NORM_ORIG_ATTR -- In addition to slapi_attr_syntax_normalize, + * a space and following characters are removed + * from the given string 's'. + */ +char * +slapi_attr_syntax_normalize_ext( char *s, int flags ) +{ + struct asyntaxinfo *asi = NULL; + char *r = NULL; + + if((asi=attr_syntax_get_by_name(s)) != NULL ) { + r = slapi_ch_strdup(asi->asi_name); + attr_syntax_return( asi ); + } + if ( NULL == asi ) { + slapi_ch_free_string( &r ); + r = attr_syntax_normalize_no_lookup_ext( s, flags ); + } + return r; +} /* * attr_syntax_exists: return 1 if attr_name exists, 0 otherwise @@ -883,14 +903,33 @@ attr_syntax_print() /* lowercase the attr name and chop trailing spaces */ /* note that s may contain options also, e.g., userCertificate;binary */ char * +attr_syntax_normalize_no_lookup_ext( char *s, int flags ) +{ + char *save, *tmps; + + tmps = slapi_ch_strdup(s); + for ( save = tmps; (*tmps != '\0') && (*tmps != ' '); tmps++ ) + { + *tmps = TOLOWER( *tmps ); + } + *tmps = '\0'; + if (flags & ATTR_SYNTAX_NORM_ORIG_ATTR) { + /* Chop trailing spaces + following strings */ + *(s + (tmps - save)) = '\0'; + } + + return save; +} + +char * attr_syntax_normalize_no_lookup( const char *s ) { char *save, *tmps; - tmps = slapi_ch_strdup(s); - for ( save = tmps; (*tmps != '\0') && (*tmps != ' '); tmps++ ) + tmps = slapi_ch_strdup(s); + for ( save = tmps; (*tmps != '\0') && (*tmps != ' '); tmps++ ) { - *tmps = TOLOWER( *tmps ); + *tmps = TOLOWER( *tmps ); } *tmps = '\0'; diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c index 17ac377..59790bc 100644 --- a/ldap/servers/slapd/libglobs.c +++ b/ldap/servers/slapd/libglobs.c @@ -253,6 +253,7 @@ slapi_onoff_t init_disk_logging_critical; slapi_onoff_t init_disk_preserve_logging; slapi_onoff_t init_ndn_cache_enabled; slapi_onoff_t init_sasl_mapping_fallback; +slapi_onoff_t init_return_orig_type; #ifdef MEMPOOL_EXPERIMENTAL slapi_onoff_t init_mempool_switch; #endif @@ -1028,6 +1029,10 @@ static struct config_get_and_set { CONFIG_SPECIAL_UNHASHED_PW_SWITCH, (ConfigGetFunc)config_get_unhashed_pw_switch, DEFAULT_UNHASHED_PW_SWITCH}, + {CONFIG_SEARCH_RETURN_ORIGINAL_TYPE, config_set_return_orig_type_switch, + NULL, 0, + (void**)&global_slapdFrontendConfig.return_orig_type, + CONFIG_ON_OFF, (ConfigGetFunc)config_get_return_orig_type_switch, &init_return_orig_type} #ifdef MEMPOOL_EXPERIMENTAL ,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch, NULL, 0, @@ -1458,6 +1463,7 @@ FrontendConfig_init () { cfg->sasl_mapping_fallback = slapi_counter_new(); init_sasl_mapping_fallback = LDAP_OFF; cfg->unhashed_pw_switch = SLAPD_UNHASHED_PW_ON; + init_return_orig_type = cfg->return_orig_type = LDAP_OFF; #ifdef MEMPOOL_EXPERIMENTAL init_mempool_switch = cfg->mempool_switch = LDAP_ON; @@ -1740,6 +1746,17 @@ config_set_ndn_cache_max_size(const char *attrname, char *value, char *errorbuf, return retVal; } +int +config_set_return_orig_type_switch(const char *attrname, char *value, char *errorbuf, int apply) +{ + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal; + + retVal = config_set_onoff(attrname, value, &(slapdFrontendConfig->return_orig_type), errorbuf, apply); + + return retVal; +} + int config_set_port( const char *attrname, char *port, char *errorbuf, int apply ) { long nPort; @@ -5738,6 +5755,18 @@ config_get_ndn_cache_enabled(){ return retVal; } +int +config_get_return_orig_type_switch() +{ + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal; + + CFG_ONOFF_LOCK_READ(slapdFrontendConfig); + retVal = (int)slapdFrontendConfig->return_orig_type; + CFG_ONOFF_UNLOCK_READ(slapdFrontendConfig); + return retVal; +} + char * config_get_basedn() { slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c index 13e05c1..743b9ce 100644 --- a/ldap/servers/slapd/operation.c +++ b/ldap/servers/slapd/operation.c @@ -220,7 +220,7 @@ operation_free( Slapi_Operation **op, Connection *conn ) slapi_sdn_free(&(*op)->o_target_spec); slapi_ch_free_string( &(*op)->o_authtype ); if ( (*op)->o_searchattrs != NULL ) { - cool_charray_free( (*op)->o_searchattrs ); + charray_free( (*op)->o_searchattrs ); } if ( NULL != (*op)->o_params.request_controls ) { ldap_controls_free( (*op)->o_params.request_controls ); diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 0a07a29..acea92f 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -127,6 +127,7 @@ int attr_syntax_create( const char *attr_oid, char *const*attr_names, void attr_syntax_free( struct asyntaxinfo *a ); int attr_syntax_add( struct asyntaxinfo *asip ); char *attr_syntax_normalize_no_lookup( const char *s ); +char *attr_syntax_normalize_no_lookup_ext( char *s, int flags ); void attr_syntax_enumerate_attrs(AttrEnumFunc aef, void *arg, PRBool writelock); void attr_syntax_all_clear_flag( unsigned long flag ); void attr_syntax_delete_all_not_flagged( unsigned long flag ); @@ -394,6 +395,7 @@ int config_set_auditlog_unhashed_pw(const char *attrname, char *value, char *err int config_set_ndn_cache_enabled(const char *attrname, char *value, char *errorbuf, int apply); int config_set_ndn_cache_max_size(const char *attrname, char *value, char *errorbuf, int apply); int config_set_unhashed_pw_switch(const char *attrname, char *value, char *errorbuf, int apply); +int config_set_return_orig_type_switch(const char *attrname, char *value, char *errorbuf, int apply); #if !defined(_WIN32) && !defined(AIX) int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply ); @@ -552,6 +554,7 @@ int config_get_disk_logging_critical(); int config_get_ndn_cache_count(); size_t config_get_ndn_cache_size(); int config_get_ndn_cache_enabled(); +int config_get_return_orig_type_switch(); char *config_get_allowed_sasl_mechs(); int config_set_allowed_sasl_mechs(const char *attrname, char *value, char *errorbuf, int apply); int config_get_schemamod(); diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c index c3d51d6..974cb6a 100644 --- a/ldap/servers/slapd/search.c +++ b/ldap/servers/slapd/search.c @@ -329,16 +329,29 @@ do_search( Slapi_PBlock *pb ) gerattrs[gerattridx] = NULL; } - operation->o_searchattrs = cool_charray_dup( attrs ); - for ( i = 0; attrs[i] != NULL; i++ ) { - char *type; - - type = slapi_attr_syntax_normalize(attrs[i]); - slapi_ch_free( (void**)&(attrs[i]) ); - attrs[i] = type; + if (config_get_return_orig_type_switch()) { + /* return the original type, e.g., "sn (surname)" */ + operation->o_searchattrs = charray_dup( attrs ); + for ( i = 0; attrs[i] != NULL; i++ ) { + char *type; + type = slapi_attr_syntax_normalize(attrs[i]); + slapi_ch_free( (void**)&(attrs[i]) ); + attrs[i] = type; + } + } else { + /* return the chopped type, e.g., "sn" */ + operation->o_searchattrs = NULL; + for ( i = 0; attrs[i] != NULL; i++ ) { + char *type; + type = slapi_attr_syntax_normalize_ext(attrs[i], + ATTR_SYNTAX_NORM_ORIG_ATTR); + /* attrs[i] is consumed */ + charray_add(&operation->o_searchattrs, attrs[i]); + attrs[i] = type; + } } } - if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) { + if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) { char abuf[ 1024 ], *astr; if ( NULL == attrs ) { diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index a44bced..02cb121 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -530,6 +530,10 @@ typedef int (*AttrEnumFunc)(struct asyntaxinfo *asi, void *arg); #define ATTR_SYNTAX_ENUM_STOP 1 /* halt the enumeration */ #define ATTR_SYNTAX_ENUM_REMOVE 2 /* unhash current node and continue */ +/* flags for slapi_attr_syntax_normalize_ext */ +#define ATTR_SYNTAX_NORM_ORIG_ATTR 0x1 /* a space and following characters are + removed from the given string */ + /* This is the type of the function passed into plugin_syntax_enumerate */ typedef int (*SyntaxEnumFunc)(char **names, Slapi_PluginDesc *plugindesc, void *arg); @@ -2066,6 +2070,7 @@ typedef struct _slapdEntryPoints { #define CONFIG_ALLOWED_SASL_MECHS "nsslapd-allowed-sasl-mechanisms" #define CONFIG_IGNORE_VATTRS "nsslapd-ignore-virtual-attrs" #define CONFIG_SASL_MAPPING_FALLBACK "nsslapd-sasl-mapping-fallback" +#define CONFIG_SEARCH_RETURN_ORIGINAL_TYPE "nsslapd-search-return-original-type-switch" #ifdef MEMPOOL_EXPERIMENTAL #define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool" @@ -2301,6 +2306,8 @@ typedef struct _slapdFrontendConfig { slapi_onoff_t ndn_cache_enabled; size_t ndn_cache_max_size; + slapi_onoff_t return_orig_type; /* if on, search returns original type set in attr list */ + /* atomic settings */ Slapi_Counter *ignore_vattrs; Slapi_Counter *sasl_mapping_fallback; diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 127cbcd..8979c18 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -4037,6 +4037,24 @@ int slapi_attr_get_bervals_copy( Slapi_Attr *a, struct berval ***vals ); */ char * slapi_attr_syntax_normalize( const char *s ); +/** + * Normalize an attribute type. + * + * The attribute type will be looked up in the defined syntaxes to + * get the normalized form. If it is not found, the passed in type + * will be normalized. If ATTR_SYNTAX_NORM_ORIG_ATTR is set to flags, + * the upper and lower cases are kept but trailing spaces are chopped + * from the original attribute type. + * + * \param s The attribute type that you want to normalize. + * \param flags 0 or ATTR_SYNTAX_NORM_ORIG_ATTR + * \return A normalized copy of the passed in attribute type. + * \warning You should free the returned string using slapi_ch_free_string(). + * \see slapi_ch_free_string() + */ +char * slapi_attr_syntax_normalize_ext( char *s, int flags ); + + /* * value routines */ -- 1.7.7.6