ldap/servers/slapd/bind.c | 13 +++++++++++--
ldap/servers/slapd/connection.c | 10 +++++++++-
ldap/servers/slapd/libglobs.c | 35 +++++++++++++++++++++++++++++++++++
ldap/servers/slapd/modify.c | 22 ++++++++++++++++++++++
ldap/servers/slapd/proto-slap.h | 2 ++
ldap/servers/slapd/search.c | 29 ++++++++++++++++++++++++++++-
ldap/servers/slapd/slap.h | 2 ++
7 files changed, 109 insertions(+), 4 deletions(-)
New commits:
commit 48e99c1d2ffba4b83df4a499d37bb444ea9b5673
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Jan 17 18:25:11 2012 -0800
Trac Ticket 168 - minssf should not apply to rootdse
https://fedorahosted.org/389/ticket/168
Fix description: This patch is for supporting a request to
allow accessing rootdse with lower ssf than minssf configuration
setting.
. introduced a on/off type config parameter:
nsslapd-minssf-exclude-rootdse.
. by default, the value is off.
. when it is off, the server's behavior remains intact.
. when it is on, the server allows to access rootdse even if
the ssf value is less than nsslapd-minssf value.
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 12d6650..1d860b6 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -138,6 +138,7 @@ do_bind( Slapi_PBlock *pb )
Slapi_Entry *bind_target_entry = NULL;
int auto_bind = 0;
int minssf = 0;
+ int minssf_exclude_rootdse = 0;
LDAPDebug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
@@ -493,7 +494,15 @@ do_bind( Slapi_PBlock *pb )
/* Check if the minimum SSF requirement has been met. */
minssf = config_get_minssf();
- if ((pb->pb_conn->c_sasl_ssf < minssf) &&
(pb->pb_conn->c_ssl_ssf < minssf) &&
+ /*
+ * If nsslapd-minssf-exclude-rootdse is on, we have to go to the
+ * next step and check if the operation is against rootdse or not.
+ * Once found it's not on rootdse, return LDAP_UNWILLING_TO_PERFORM
+ * there.
+ */
+ minssf_exclude_rootdse = config_get_minssf_exclude_rootdse();
+ if (!minssf_exclude_rootdse && (pb->pb_conn->c_sasl_ssf <
minssf) &&
+ (pb->pb_conn->c_ssl_ssf < minssf) &&
(pb->pb_conn->c_local_ssf < minssf)) {
send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
"Minimum SSF not met.", 0, NULL);
@@ -560,7 +569,7 @@ do_bind( Slapi_PBlock *pb )
goto free_and_return;
}
/* Check if simple binds are allowed over an insecure channel. We only check
- * this for authenticated binds. */
+ * this for authenticated binds. */
} else if (config_get_require_secure_binds() == 1) {
Connection *conn = NULL;
int sasl_ssf = 0;
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 27e4fe1..cabfe71 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -496,6 +496,7 @@ static void
connection_dispatch_operation(Connection *conn, Operation *op, Slapi_PBlock *pb)
{
int minssf = config_get_minssf();
+ int minssf_exclude_rootdse = 0;
/* Get the effective key length now since the first SSL handshake should be complete */
connection_set_ssl_ssf( conn );
@@ -508,7 +509,14 @@ connection_dispatch_operation(Connection *conn, Operation *op,
Slapi_PBlock *pb)
* code will ensure that only SASL binds and startTLS are
* allowed, which gives the connection a chance to meet the
* SSF requirements. We also allow UNBIND and ABANDON.*/
- if ((conn->c_sasl_ssf < minssf) && (conn->c_ssl_ssf < minssf)
&&
+ /*
+ * If nsslapd-minssf-exclude-rootdse is on, we have to go to the
+ * next step and check if the operation is against rootdse or not.
+ * Once found it's not on rootdse, return LDAP_UNWILLING_TO_PERFORM there.
+ */
+ minssf_exclude_rootdse = config_get_minssf_exclude_rootdse();
+ if (!minssf_exclude_rootdse &&
+ (conn->c_sasl_ssf < minssf) && (conn->c_ssl_ssf < minssf)
&&
(conn->c_local_ssf < minssf) &&(op->o_tag != LDAP_REQ_BIND)
&&
(op->o_tag != LDAP_REQ_EXTENDED) && (op->o_tag != LDAP_REQ_UNBIND)
&&
(op->o_tag != LDAP_REQ_ABANDON)) {
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 2177934..4c4c31f 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -626,6 +626,11 @@ static struct config_get_and_set {
{CONFIG_MINSSF_ATTRIBUTE, config_set_minssf,
NULL, 0,
(void**)&global_slapdFrontendConfig.minssf, CONFIG_INT, NULL},
+ {CONFIG_MINSSF_EXCLUDE_ROOTDSE, config_set_minssf_exclude_rootdse,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.minssf_exclude_rootdse,
+ CONFIG_ON_OFF,
+ (ConfigGetFunc)config_get_minssf_exclude_rootdse},
{CONFIG_FORCE_SASL_EXTERNAL_ATTRIBUTE, config_set_force_sasl_external,
NULL, 0,
(void**)&global_slapdFrontendConfig.force_sasl_external, CONFIG_ON_OFF,
@@ -918,6 +923,8 @@ FrontendConfig_init () {
cfg->maxsasliosize = SLAPD_DEFAULT_MAX_SASLIO_SIZE;
cfg->localssf = SLAPD_DEFAULT_LOCAL_SSF;
cfg->minssf = SLAPD_DEFAULT_MIN_SSF;
+ cfg->minssf_exclude_rootdse = LDAP_OFF; /* minssf is applied to rootdse,
+ by default */
cfg->validate_cert = SLAPD_VALIDATE_CERT_WARN;
#ifdef _WIN32
@@ -4881,6 +4888,22 @@ config_set_minssf( const char *attrname, char *value, char
*errorbuf, int apply
}
int
+config_set_minssf_exclude_rootdse( const char *attrname, char *value,
+ char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff ( attrname,
+ value,
+ &(slapdFrontendConfig->minssf_exclude_rootdse),
+ errorbuf,
+ apply );
+
+ return retVal;
+}
+
+int
config_get_localssf()
{
int localssf;
@@ -4903,6 +4926,18 @@ config_get_minssf()
}
int
+config_get_minssf_exclude_rootdse()
+{
+ int retVal;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->minssf_exclude_rootdse;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
config_set_max_filter_nest_level( const char *attrname, char *value,
char *errorbuf, int apply )
{
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index e872f35..563512d 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -141,6 +141,7 @@ do_modify( Slapi_PBlock *pb )
int has_password_mod = 0; /* number of password mods */
char *old_pw = NULL; /* remember the old password */
char *rawdn = NULL;
+ int minssf_exclude_rootdse = 0;
LDAPDebug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
@@ -197,6 +198,27 @@ do_modify( Slapi_PBlock *pb )
LDAPDebug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", rawdn, 0, 0 );
+ /*
+ * If nsslapd-minssf-exclude-rootdse is on, the minssf check has been
+ * postponed until here. We should do it now.
+ */
+ minssf_exclude_rootdse = config_get_minssf_exclude_rootdse();
+ if (minssf_exclude_rootdse) {
+ int minssf = 0;
+ /* Check if the minimum SSF requirement has been met. */
+ minssf = config_get_minssf();
+ if ((pb->pb_conn->c_sasl_ssf < minssf) &&
+ (pb->pb_conn->c_ssl_ssf < minssf) &&
+ (pb->pb_conn->c_local_ssf < minssf)) {
+ op_shared_log_error_access(pb, "MOD", rawdn?rawdn:"",
+ "Minimum SSF not met");
+ send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "Minimum SSF not met.", 0, NULL);
+ slapi_ch_free((void **) &rawdn);
+ return;
+ }
+ }
+
slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &pb->pb_op->o_isroot);
slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, rawdn );
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index a3fcc5f..f3e85c9 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -370,6 +370,7 @@ int config_set_require_secure_binds(const char *attrname, char *value,
char *err
int config_set_anon_access_switch(const char *attrname, char *value, char *errorbuf, int
apply );
int config_set_localssf(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_minssf(const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_minssf_exclude_rootdse( const char *attrname, char *value, char *errorbuf,
int apply );
int config_set_validate_cert_switch(const char *attrname, char *value, char *errorbuf,
int apply );
int config_set_accesslogbuffering(const char *attrname, char *value, char *errorbuf, int
apply);
int config_set_csnlogging(const char *attrname, char *value, char *errorbuf, int apply);
@@ -510,6 +511,7 @@ int config_get_require_secure_binds(void);
int config_get_anon_access_switch(void);
int config_get_localssf(void);
int config_get_minssf(void);
+int config_get_minssf_exclude_rootdse(void);
int config_get_validate_cert_switch(void);
int config_get_csnlogging();
#ifdef MEMPOOL_EXPERIMENTAL
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index 6da7aa0..5beb8ce 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -80,6 +80,7 @@ do_search( Slapi_PBlock *pb )
int changesonly = 0;
int rc = -1;
int strict = 0;
+ int minssf_exclude_rootdse = 0;
LDAPDebug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
@@ -141,7 +142,8 @@ do_search( Slapi_PBlock *pb )
if ((slapi_sdn_get_dn(&(operation->o_sdn)) == NULL) &&
(scope != LDAP_SCOPE_BASE) &&
(config_get_anon_access_switch() == SLAPD_ANON_ACCESS_ROOTDSE)) {
- op_shared_log_error_access(pb, "SRCH", base?base:"",
"anonymous search not allowed");
+ op_shared_log_error_access(pb, "SRCH", rawbase?rawbase:"",
+ "anonymous search not allowed");
send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
"Anonymous access is not allowed.", 0, NULL );
@@ -149,6 +151,31 @@ do_search( Slapi_PBlock *pb )
goto free_and_return;
}
+ /*
+ * If nsslapd-minssf-exclude-rootdse is on, the minssf check has been
+ * postponed till this moment since we need to know whether the basedn
+ * is rootdse or not.
+ *
+ * If (minssf_exclude_rootdse && (basedn is rootdse),
+ * then we allow accessing rootdse.
+ * Otherwise, return Minimum SSF not met.
+ */
+ minssf_exclude_rootdse = config_get_minssf_exclude_rootdse();
+ if (!minssf_exclude_rootdse || (rawbase && strlen(rawbase) > 0)) {
+ int minssf = 0;
+ /* Check if the minimum SSF requirement has been met. */
+ minssf = config_get_minssf();
+ if ((pb->pb_conn->c_sasl_ssf < minssf) &&
+ (pb->pb_conn->c_ssl_ssf < minssf) &&
+ (pb->pb_conn->c_local_ssf < minssf)) {
+ op_shared_log_error_access(pb, "SRCH", rawbase?rawbase:"",
+ "Minimum SSF not met");
+ send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "Minimum SSF not met.", 0, NULL);
+ goto free_and_return;
+ }
+ }
+
/*
* ignore negative time and size limits since they make no sense
*/
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index b59299c..d0ae067 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1869,6 +1869,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_ANON_ACCESS_ATTRIBUTE "nsslapd-allow-anonymous-access"
#define CONFIG_LOCALSSF_ATTRIBUTE "nsslapd-localssf"
#define CONFIG_MINSSF_ATTRIBUTE "nsslapd-minssf"
+#define CONFIG_MINSSF_EXCLUDE_ROOTDSE "nsslapd-minssf-exclude-rootdse"
#define CONFIG_VALIDATE_CERT_ATTRIBUTE "nsslapd-validate-cert"
#ifndef _WIN32
#define CONFIG_LOCALUSER_ATTRIBUTE "nsslapd-localuser"
@@ -2176,6 +2177,7 @@ typedef struct _slapdFrontendConfig {
int allow_anon_access; /* switch to enable/disable anonymous access */
int localssf; /* the security strength factor to assign to local conns (ldapi) */
int minssf; /* minimum security strength factor (for SASL and SSL/TLS) */
+ int minssf_exclude_rootdse; /* ON: minssf is ignored when searching rootdse */
size_t maxsasliosize; /* limit incoming SASL IO packet size */
char *anon_limits_dn; /* template entry for anonymous resource limits */
#ifndef _WIN32