From b22970e26da3f812c7ff6c177583603005eb3702 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: May 22 2014 22:16:46 +0000 Subject: Ticket #47720 - Normalization from old DN format to New DN format doesnt handel condition properly when there is space in a suffix after the seperator operator. Description: DN normalizer (slapi_dn_normalize_ext) follows RFC 4514 and keeps a white space if the RDN attribute type is not based on the DN syntax. But Directory server's configuration entry sometimes uses "cn" to store a DN value (e.g., dn: cn="dc=A,dc=com",cn=mapping tree, cn=config), which expects the value of cn treated as DN although cn is not a DN syntax type. To solve the problem, this patch introduces a configuration parameter "nsslapd-cn-uses-dn-syntax-in-dns" to "cn= config" which takes "on" or "off". If "on" is set, if the value of cn under "cn=config" is quoted, it's processed as DN. By default, nsslapd-cn-uses-dn-syntax-in-dns: off https://fedorahosted.org/389/ticket/47720 Reviewed by mreynolds@redhat.com (Thank you, Mark!!) --- diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c index 76b33da..cea593b 100644 --- a/ldap/servers/slapd/dn.c +++ b/ldap/servers/slapd/dn.c @@ -61,6 +61,7 @@ static void reset_rdn_avs( struct berval **rdn_avsp, int *rdn_av_countp ); static void sort_rdn_avs( struct berval *avs, int count, int escape ); static int rdn_av_cmp( struct berval *av1, struct berval *av2 ); static void rdn_av_swap( struct berval *av1, struct berval *av2, int escape ); +static int does_cn_uses_dn_syntax_in_dns(char *type, char *dn); /* normalized dn cache related definitions*/ struct @@ -621,6 +622,10 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) /* Reset the character we modified. */ *d = savechar; + if (!is_dn_syntax) { + is_dn_syntax = does_cn_uses_dn_syntax_in_dns(typestart, src); + } + state = B4VALUE; *d++ = *s++; } else if (ISCLOSEBRACKET(*s)) { /* special care for ACL macro */ @@ -639,6 +644,10 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) /* Reset the character we modified. */ *d = savechar; + if (!is_dn_syntax) { + is_dn_syntax = does_cn_uses_dn_syntax_in_dns(typestart, src); + } + state = INVALUE; /* skip a trailing space */ *d++ = *s++; } else if (ISSPACE(*s)) { @@ -657,6 +666,10 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) /* Reset the character we modified. */ *d = savechar; + if (!is_dn_syntax) { + is_dn_syntax = does_cn_uses_dn_syntax_in_dns(typestart, src); + } + state = B4EQUAL; /* skip a trailing space */ } else if (ISQUOTE(*s) || SEPARATOR(*s)) { /* type includes quote / separator; not a valid dn */ @@ -1030,6 +1043,18 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len) s++; } } + } else if (ISSPACE(*s)) { + while (ISSPACE(*s)) { + s++; + } + /* + * dn_syntax_attr=ABC, XYZ --> dn_syntax_attr=ABC,XYZ + * non_dn_syntax_attr=ABC, XYZ --> dn_syntax_attr=ABC, XYZ + */ + if (!is_dn_syntax) { + --s; + *d++ = *s++; + } } else { *d++ = *s++; } @@ -3172,3 +3197,23 @@ slapi_sdn_common_ancestor(Slapi_DN *dn1, Slapi_DN *dn2) charray_free(dns2); return slapi_sdn_new_ndn_passin(common); } + +/* + * Return 1 - if nsslapd-cn-uses-dn-syntax-in-dns is true && + * the type is "cn" && dn is under "cn=config" + * Return 0 - otherwise + */ +static int +does_cn_uses_dn_syntax_in_dns(char *type, char *dn) +{ + int rc = 0; /* by default off */ + char *ptr = NULL; + if (type && dn && config_get_cn_uses_dn_syntax_in_dns() && + (PL_strcasecmp(type, "cn") == 0) && (ptr = PL_strrchr(dn, ','))) { + if (PL_strcasecmp(++ptr, "cn=config") == 0) { + rc = 1; + } + } + return rc; +} + diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c index d1a3dc0..040649b 100644 --- a/ldap/servers/slapd/libglobs.c +++ b/ldap/servers/slapd/libglobs.c @@ -271,6 +271,7 @@ slapi_int_t init_connection_buffer; slapi_int_t init_listen_backlog_size; slapi_onoff_t init_ignore_time_skew; slapi_onoff_t init_dynamic_plugins; +slapi_onoff_t init_cn_uses_dn_syntax_in_dns; #if defined (LINUX) slapi_int_t init_malloc_mxfast; slapi_int_t init_malloc_trim_threshold; @@ -1092,6 +1093,10 @@ static struct config_get_and_set { NULL, 0, (void**)&global_slapdFrontendConfig.dynamic_plugins, CONFIG_ON_OFF, (ConfigGetFunc)config_get_dynamic_plugins, &init_dynamic_plugins}, + {CONFIG_CN_USES_DN_SYNTAX_IN_DNS, config_set_cn_uses_dn_syntax_in_dns, + NULL, 0, + (void**)&global_slapdFrontendConfig.cn_uses_dn_syntax_in_dns, CONFIG_ON_OFF, + (ConfigGetFunc)config_get_cn_uses_dn_syntax_in_dns, &init_cn_uses_dn_syntax_in_dns}, #if defined(LINUX) {CONFIG_MALLOC_MXFAST, config_set_malloc_mxfast, NULL, 0, @@ -1558,6 +1563,7 @@ FrontendConfig_init () { init_listen_backlog_size = cfg->listen_backlog_size = DAEMON_LISTEN_SIZE; init_ignore_time_skew = cfg->ignore_time_skew = LDAP_OFF; init_dynamic_plugins = cfg->dynamic_plugins = LDAP_OFF; + init_cn_uses_dn_syntax_in_dns = cfg->cn_uses_dn_syntax_in_dns = LDAP_OFF; #if defined(LINUX) init_malloc_mxfast = cfg->malloc_mxfast = DEFAULT_MALLOC_UNSET; init_malloc_trim_threshold = cfg->malloc_trim_threshold = DEFAULT_MALLOC_UNSET; @@ -3289,6 +3295,7 @@ config_set_dynamic_plugins( const char *attrname, char *value, char *errorbuf, i return retVal; } + int config_get_dynamic_plugins() { slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); @@ -3302,6 +3309,34 @@ config_get_dynamic_plugins() { } int +config_set_cn_uses_dn_syntax_in_dns(const char *attrname, char *value, char *errorbuf, int apply) +{ + int retVal = LDAP_SUCCESS; + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + + retVal = config_set_onoff ( attrname, + value, + &(slapdFrontendConfig->cn_uses_dn_syntax_in_dns), + errorbuf, + apply); + + return retVal; +} + +int +config_get_cn_uses_dn_syntax_in_dns() +{ + slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); + int retVal; + + CFG_ONOFF_LOCK_READ(slapdFrontendConfig); + retVal = (int)slapdFrontendConfig->cn_uses_dn_syntax_in_dns; + CFG_ONOFF_UNLOCK_READ(slapdFrontendConfig); + + return retVal; +} + +int config_set_security( const char *attrname, char *value, char *errorbuf, int apply ) { int retVal = LDAP_SUCCESS; slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 4c3e517..34c4ac6 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -586,6 +586,8 @@ int config_set_plugin_logging(const char *attrname, char *value, char *errorbuf, int config_get_listen_backlog_size(void); int config_set_dynamic_plugins(const char *attrname, char *value, char *errorbuf, int apply); int config_get_dynamic_plugins(); +int config_set_cn_uses_dn_syntax_in_dns(const char *attrname, char *value, char *errorbuf, int apply); +int config_get_cn_uses_dn_syntax_in_dns(); PLHashNumber hashNocaseString(const void *key); PRIntn hashNocaseCompare(const void *v1, const void *v2); diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index 642f3b2..5401a66 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -2152,6 +2152,8 @@ typedef struct _slapdEntryPoints { #define CONFIG_DYNAMIC_PLUGINS "nsslapd-dynamic-plugins" #define CONFIG_RETURN_DEFAULT_OPATTR "nsslapd-return-default-opattr" +#define CONFIG_CN_USES_DN_SYNTAX_IN_DNS "nsslapd-cn-uses-dn-syntax-in-dns" + /* getenv alternative */ #define CONFIG_MALLOC_MXFAST "nsslapd-malloc-mxfast" #define CONFIG_MALLOC_TRIM_THRESHOLD "nsslapd-malloc-trim-threshold" @@ -2415,6 +2417,7 @@ typedef struct _slapdFrontendConfig { slapi_onoff_t plugin_logging; /* log all internal plugin operations */ slapi_onoff_t ignore_time_skew; slapi_onoff_t dynamic_plugins; /* allow plugins to be dynamically enabled/disabled */ + slapi_onoff_t cn_uses_dn_syntax_in_dns; /* indicates the cn value in dns has dn syntax */ #if defined(LINUX) int malloc_mxfast; /* mallopt M_MXFAST */ int malloc_trim_threshold; /* mallopt M_TRIM_THRESHOLD */