ldap/servers/slapd/bind.c | 7 ++--
ldap/servers/slapd/connection.c | 18 +++++++++---
ldap/servers/slapd/extendop.c | 2 -
ldap/servers/slapd/libglobs.c | 60 ++++++++++++++++++++++++++++++++--------
ldap/servers/slapd/saslbind.c | 2 -
ldap/servers/slapd/search.c | 12 ++++++++
ldap/servers/slapd/slap.h | 5 +++
7 files changed, 86 insertions(+), 20 deletions(-)
New commits:
commit b3b0217acd2cffbf914fb1d0e61a73eb5b4e688c
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Fri Dec 10 13:05:59 2010 -0800
Bug 588791 - Allow anonymous rootDSE access only
This patch changes the nsslapd-allow-anonymous-access config
setting to allow a third value that gives anonymous access to
search the rootDSE. If you set this attribute to "rootdse", an
anonymous bind identity is only allowed to do a rootDSE search
or prove that it is someone other than anonymous. This also
required allowing explicit anonymous BIND operations through since
ldapsearch performs an explicit bind before searching. The old
behavior with the "on" and "off" settings remains unchanged.
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 5f4ab03..8b666f1 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -514,8 +514,9 @@ do_bind( Slapi_PBlock *pb )
that counter */
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
- /* Refuse the operation if anonymous access is disabled. */
- if (!config_get_anon_access_switch()) {
+ /* Refuse the operation if anonymous access is disabled. We need to allow
+ * an anonymous bind through if only root DSE anonymous access is set too.
*/
+ if (config_get_anon_access_switch() == SLAPD_ANON_ACCESS_OFF) {
send_ldap_result(pb, LDAP_INAPPROPRIATE_AUTH, NULL,
"Anonymous access is not allowed", 0, NULL);
/* increment BindSecurityErrorcount */
@@ -544,7 +545,7 @@ do_bind( Slapi_PBlock *pb )
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
/* Refuse the operation if anonymous access is disabled. */
- if (!config_get_anon_access_switch()) {
+ if (config_get_anon_access_switch() != SLAPD_ANON_ACCESS_ON) {
send_ldap_result(pb, LDAP_INAPPROPRIATE_AUTH, NULL,
"Anonymous access is not allowed", 0, NULL);
/* increment BindSecurityErrorcount */
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 75d9584..d3b3286 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -522,10 +522,20 @@ connection_dispatch_operation(Connection *conn, Operation *op,
Slapi_PBlock *pb)
* not authenticated, only allow bind and extended operations.
* We allow extended operations so one can do a startTLS prior
* to binding to protect their credentials in transit.
- * We also allow UNBIND and ABANDON. */
- if (!config_get_anon_access_switch() && (op->o_tag != LDAP_REQ_BIND)
&&
- (op->o_tag != LDAP_REQ_EXTENDED) && (op->o_tag != LDAP_REQ_UNBIND)
&&
- (op->o_tag != LDAP_REQ_ABANDON) && (slapi_sdn_get_dn(&(op->o_sdn))
== NULL )) {
+ * We also allow UNBIND and ABANDON.
+ *
+ * If anonymous access is only allowed for root DSE searches,
+ * we let SEARCH operations through as well. The search code
+ * is responsible for checking if the operation is a root DSE
+ * search. */
+ if ((slapi_sdn_get_dn(&(op->o_sdn)) == NULL ) &&
+ /* anon access off and something other than BIND, EXTOP, UNBIND or ABANDON
*/
+ (((config_get_anon_access_switch() == SLAPD_ANON_ACCESS_OFF) &&
(op->o_tag != LDAP_REQ_BIND) &&
+ (op->o_tag != LDAP_REQ_EXTENDED) && (op->o_tag !=
LDAP_REQ_UNBIND) && (op->o_tag != LDAP_REQ_ABANDON)) ||
+ /* root DSE access only and something other than BIND, EXTOP, UNBIND,
ABANDON, or SEARCH */
+ ((config_get_anon_access_switch() == SLAPD_ANON_ACCESS_ROOTDSE) &&
(op->o_tag != LDAP_REQ_BIND) &&
+ (op->o_tag != LDAP_REQ_EXTENDED) && (op->o_tag != LDAP_REQ_UNBIND)
&&
+ (op->o_tag != LDAP_REQ_ABANDON) && (op->o_tag != LDAP_REQ_SEARCH))))
{
slapi_log_access( LDAP_DEBUG_STATS,
"conn=%" NSPRIu64 " op=%d UNPROCESSED OPERATION"
" - Anonymous access not allowed\n",
diff --git a/ldap/servers/slapd/extendop.c b/ldap/servers/slapd/extendop.c
index a521cb7..f7e6ebe 100644
--- a/ldap/servers/slapd/extendop.c
+++ b/ldap/servers/slapd/extendop.c
@@ -327,7 +327,7 @@ do_extended( Slapi_PBlock *pb )
/* If anonymous access is disabled and we haven't
* authenticated yet, only allow startTLS. */
- if (!config_get_anon_access_switch() && ((pb->pb_op->o_authtype == NULL)
||
+ if ((config_get_anon_access_switch() != SLAPD_ANON_ACCESS_ON) &&
((pb->pb_op->o_authtype == NULL) ||
(strcasecmp(pb->pb_op->o_authtype, SLAPD_AUTH_NONE) == 0))) {
send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
"Anonymous access is not allowed.", 0, NULL );
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index a7cc1bc..e1fb7dd 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -115,7 +115,8 @@ typedef enum {
CONFIG_SPECIAL_REFERRALLIST, /* this is a berval list */
CONFIG_SPECIAL_SSLCLIENTAUTH, /* maps strings to an enumeration */
CONFIG_SPECIAL_ERRORLOGLEVEL, /* requires & with LDAP_DEBUG_ANY */
- CONFIG_STRING_OR_EMPTY /* use an empty string */
+ CONFIG_STRING_OR_EMPTY, /* use an empty string */
+ CONFIG_SPECIAL_ANON_ACCESS_SWITCH /* maps strings to an enumeration */
} ConfigVarType;
static int config_set_onoff( const char *attrname, char *value,
@@ -616,7 +617,7 @@ static struct config_get_and_set {
(ConfigGetFunc)config_get_require_secure_binds},
{CONFIG_ANON_ACCESS_ATTRIBUTE, config_set_anon_access_switch,
NULL, 0,
- (void**)&global_slapdFrontendConfig.allow_anon_access, CONFIG_ON_OFF,
+ (void**)&global_slapdFrontendConfig.allow_anon_access,
CONFIG_SPECIAL_ANON_ACCESS_SWITCH,
(ConfigGetFunc)config_get_anon_access_switch},
{CONFIG_MINSSF_ATTRIBUTE, config_set_minssf,
NULL, 0,
@@ -885,7 +886,7 @@ FrontendConfig_init () {
#endif
cfg->allow_unauth_binds = LDAP_OFF;
cfg->require_secure_binds = LDAP_OFF;
- cfg->allow_anon_access = LDAP_ON;
+ cfg->allow_anon_access = SLAPD_ANON_ACCESS_ON;
cfg->slapi_counters = LDAP_ON;
cfg->threadnumber = SLAPD_DEFAULT_MAX_THREADS;
cfg->maxthreadsperconn = SLAPD_DEFAULT_MAX_THREADS_PER_CONN;
@@ -4628,12 +4629,11 @@ config_get_require_secure_binds(void)
int
config_get_anon_access_switch(void)
{
- int retVal;
+ char *retVal = NULL;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
CFG_LOCK_READ(slapdFrontendConfig);
- retVal = slapdFrontendConfig->allow_anon_access;
+ retVal = slapdFrontendConfig->allow_anon_access;
CFG_UNLOCK_READ(slapdFrontendConfig);
-
return retVal;
}
@@ -5503,12 +5503,34 @@ config_set_anon_access_switch( const char *attrname, char *value,
int retVal = LDAP_SUCCESS;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- retVal = config_set_onoff(attrname,
- value,
- &(slapdFrontendConfig->allow_anon_access),
- errorbuf,
- apply);
+ if (config_value_is_null(attrname, value, errorbuf, 0)) {
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ if ((strcasecmp(value, "on") != 0) && (strcasecmp(value,
"off") != 0) &&
+ (strcasecmp(value, "rootdse") != 0)) {
+ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\". Valid values are \"on\", "
+ "\"off\", or \"rootdse\".", attrname, value);
+ retVal = LDAP_OPERATIONS_ERROR;
+ }
+
+ if (!apply) {
+ /* we can return now if we aren't applying the changes */
+ return retVal;
+ }
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+
+ if (strcasecmp(value, "on") == 0 ) {
+ slapdFrontendConfig->allow_anon_access = SLAPD_ANON_ACCESS_ON;
+ } else if (strcasecmp(value, "off") == 0 ) {
+ slapdFrontendConfig->allow_anon_access = SLAPD_ANON_ACCESS_OFF;
+ } else if (strcasecmp(value, "rootdse") == 0) {
+ slapdFrontendConfig->allow_anon_access = SLAPD_ANON_ACCESS_ROOTDSE;
+ }
+
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
return retVal;
}
@@ -5776,6 +5798,22 @@ config_set_value(
slapi_entry_attr_set_charptr(e, cgas->attr_name, "");
break;
+ case CONFIG_SPECIAL_ANON_ACCESS_SWITCH:
+ if (!value) {
+ slapi_entry_attr_set_charptr(e, cgas->attr_name, "off");
+ break;
+ }
+
+ if (*((int *)value) == SLAPD_ANON_ACCESS_ON) {
+ sval = "on";
+ } else if (*((int *)value) == SLAPD_ANON_ACCESS_ROOTDSE) {
+ sval = "rootdse";
+ } else {
+ sval = "off";
+ }
+ slapi_entry_attr_set_charptr(e, cgas->attr_name, sval);
+ break;
+
default:
PR_ASSERT(0); /* something went horribly wrong . . . */
break;
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
index 0a195de..401a82f 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -663,7 +663,7 @@ void ids_sasl_server_new(Connection *conn)
secprops.max_ssf = 0xffffffff;
secprops.min_ssf = config_get_minssf();
/* If anonymous access is disabled, set the appropriate flag */
- if (!config_get_anon_access_switch()) {
+ if (config_get_anon_access_switch() != SLAPD_ANON_ACCESS_ON) {
secprops.security_flags = SASL_SEC_NOANONYMOUS;
}
diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c
index 2909a17..ff4de17 100644
--- a/ldap/servers/slapd/search.c
+++ b/ldap/servers/slapd/search.c
@@ -152,6 +152,18 @@ do_search( Slapi_PBlock *pb )
*(base + baselen) = '\0';
}
+ /* If anonymous access is only allowed for searching the root DSE,
+ * we need to reject any other anonymous search attempts. */
+ if ((slapi_sdn_get_dn(&(operation->o_sdn)) == NULL) && ((baselen != 0) ||
(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");
+
+ send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL,
+ "Anonymous access is not allowed.", 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 d71367f..1cb5212 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -328,6 +328,11 @@ typedef void (*VFP0)(void);
#define SLAPD_LDAPI_DEFAULT_FILENAME "/var/run/ldapi"
#define SLAPD_LDAPI_DEFAULT_STATUS "off"
+/* Anonymous access */
+#define SLAPD_ANON_ACCESS_OFF 0
+#define SLAPD_ANON_ACCESS_ON 1
+#define SLAPD_ANON_ACCESS_ROOTDSE 2
+
struct subfilt {
char *sf_type;
char *sf_initial;