ldap/admin/src/scripts/DSMigration.pm.in | 1
ldap/ldif/template-dse.ldif.in | 1
ldap/servers/slapd/bind.c | 12 +++++-
ldap/servers/slapd/connection.c | 24 ++++++++-----
ldap/servers/slapd/daemon.c | 1
ldap/servers/slapd/extendop.c | 3 +
ldap/servers/slapd/libglobs.c | 57 +++++++++++++++++++++++++++++++
ldap/servers/slapd/passwd_extop.c | 12 +++++-
ldap/servers/slapd/pblock.c | 10 +++++
ldap/servers/slapd/proto-slap.h | 2 +
ldap/servers/slapd/slap.h | 4 ++
ldap/servers/slapd/slapi-plugin.h | 1
12 files changed, 114 insertions(+), 14 deletions(-)
New commits:
commit b5bee52888069417aa780ab79b897d0736f306c9
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Feb 1 11:54:08 2011 -0800
Bug 670616 - Allow SSF to be set for local (ldapi) connections
This patch adds a new config parameter named nsslapd-localssf.
This parameter can be set to the SSF that one wants to apply for
ocal (LDAPI) connections. This SSF will be used with the minssf
global and ACI settings. The local SSF can also be used to satisfy
the confidentiality requirements for secure binds and password
modify extended operations.
diff --git a/ldap/admin/src/scripts/DSMigration.pm.in
b/ldap/admin/src/scripts/DSMigration.pm.in
index 5434075..7d1c48f 100644
--- a/ldap/admin/src/scripts/DSMigration.pm.in
+++ b/ldap/admin/src/scripts/DSMigration.pm.in
@@ -103,6 +103,7 @@ my %ignoreOld =
# these are new attrs that we should just pass through
'nsslapd-allow-unauthenticated-binds' =>
'nsslapd-allow-unauthenticated-binds',
'nsslapd-allow-anonymous-access' =>
'nsslapd-allow-anonymous-access',
+ 'nsslapd-localssf' => 'nsslapd-localssf',
'nsslapd-minssf' => 'nsslapd-minssf',
'nsslapd-saslpath' => 'nsslapd-saslpath',
'nsslapd-rundir' => 'nsslapd-rundir',
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index f607f44..cd98d16 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -32,6 +32,7 @@ nsslapd-ssl-check-hostname: on
nsslapd-allow-unauthenticated-binds: off
nsslapd-require-secure-binds: off
nsslapd-allow-anonymous-access: on
+nsslapd-localssf: 71
nsslapd-minssf: 0
nsslapd-port: %ds_port%
nsslapd-localuser: %ds_user%
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 8b666f1..679cbff 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -499,7 +499,8 @@ 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 ((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);
/* increment BindSecurityErrorcount */
@@ -569,6 +570,7 @@ do_bind( Slapi_PBlock *pb )
} else if (config_get_require_secure_binds() == 1) {
Connection *conn = NULL;
int sasl_ssf = 0;
+ int local_ssf = 0;
/* Allow simple binds only for SSL/TLS established connections
* or connections using SASL privacy layers */
@@ -579,8 +581,14 @@ do_bind( Slapi_PBlock *pb )
sasl_ssf = 0;
}
+ if ( slapi_pblock_get(pb, SLAPI_CONN_LOCAL_SSF, &local_ssf) != 0) {
+ slapi_log_error( SLAPI_LOG_PLUGIN, "do_bind",
+ "Could not get local SSF from
connection\n" );
+ local_ssf = 0;
+ }
+
if (((conn->c_flags & CONN_FLAG_SSL) != CONN_FLAG_SSL) &&
- (sasl_ssf <= 1) ) {
+ (sasl_ssf <= 1) && (local_ssf <= 1)) {
send_ldap_result(pb, LDAP_CONFIDENTIALITY_REQUIRED, NULL,
"Operation requires a secure
connection",
0, NULL);
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 7b00a21..7f93a0f 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -196,6 +196,7 @@ connection_cleanup(Connection *conn)
conn->c_prev= NULL;
conn->c_extension= NULL;
conn->c_ssl_ssf = 0;
+ conn->c_local_ssf = 0;
conn->c_unix_local = 0;
/* destroy any sasl context */
sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn);
@@ -388,6 +389,7 @@ connection_reset(Connection* conn, int ns, PRNetAddr * from, int
fromLen, int is
/* Just initialize the SSL SSF to 0 now since the handshake isn't complete
* yet, which prevents us from getting the effective key length. */
conn->c_ssl_ssf = 0;
+ conn->c_local_ssf = 0;
}
/* Create a pool of threads for handling the operations */
@@ -507,12 +509,14 @@ connection_dispatch_operation(Connection *conn, Operation *op,
Slapi_PBlock *pb)
* 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)
&&
- (op->o_tag != LDAP_REQ_BIND) && (op->o_tag != LDAP_REQ_EXTENDED)
&&
- (op->o_tag != LDAP_REQ_UNBIND) && (op->o_tag != LDAP_REQ_ABANDON)) {
+ (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)) {
slapi_log_access( LDAP_DEBUG_STATS,
"conn=%" NSPRIu64 " op=%d UNPROCESSED OPERATION"
- " - Insufficient SSF (sasl_ssf=%d ssl_ssf=%d)\n",
- conn->c_connid, op->o_opid, conn->c_sasl_ssf, conn->c_ssl_ssf );
+ " - Insufficient SSF (local_ssf=%d sasl_ssf=%d ssl_ssf=%d)\n",
+ conn->c_connid, op->o_opid, conn->c_local_ssf,
+ conn->c_sasl_ssf, conn->c_ssl_ssf );
send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
"Minimum SSF not met.", 0, NULL );
return;
@@ -2631,15 +2635,17 @@ op_copy_identity(Connection *conn, Operation *op)
/* copy isroot flag as well so root DN privileges are preserved */
op->o_isroot = conn->c_isroot;
- /* copy the highest SSF (between SASL and SSL/TLS) into the
- * operation for use by access control. */
- if (conn->c_sasl_ssf >= conn->c_ssl_ssf) {
+ /* copy the highest SSF (between local, SASL, and SSL/TLS)
+ * into the operation for use by access control. */
+ if ((conn->c_sasl_ssf >= conn->c_ssl_ssf) && (conn->c_sasl_ssf
>= conn->c_local_ssf)) {
op->o_ssf = conn->c_sasl_ssf;
- } else {
+ } else if ((conn->c_ssl_ssf >= conn->c_sasl_ssf) &&
(conn->c_ssl_ssf >= conn->c_local_ssf)){
op->o_ssf = conn->c_ssl_ssf;
+ } else {
+ op->o_ssf = conn->c_local_ssf;
}
- PR_Unlock( conn->c_mutex );
+ PR_Unlock( conn->c_mutex );
}
/* Sets the SSL SSF in the connection struct. */
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 6678269..cda4a04 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -2207,6 +2207,7 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc
*pr_acceptfd, i
if( local )
{
conn->c_unix_local = 1;
+ conn->c_local_ssf = config_get_localssf();
slapd_identify_local_user(conn);
}
#endif
diff --git a/ldap/servers/slapd/extendop.c b/ldap/servers/slapd/extendop.c
index f7e6ebe..17b2f7b 100644
--- a/ldap/servers/slapd/extendop.c
+++ b/ldap/servers/slapd/extendop.c
@@ -335,7 +335,8 @@ do_extended( Slapi_PBlock *pb )
}
/* If the minssf is not met, only allow startTLS. */
- if ((pb->pb_conn->c_sasl_ssf < minssf) &&
(pb->pb_conn->c_ssl_ssf < minssf)) {
+ if ((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 );
goto free_and_return;
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 15f2aca..c3047bf 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -619,6 +619,9 @@ static struct config_get_and_set {
NULL, 0,
(void**)&global_slapdFrontendConfig.allow_anon_access,
CONFIG_SPECIAL_ANON_ACCESS_SWITCH,
(ConfigGetFunc)config_get_anon_access_switch},
+ {CONFIG_LOCALSSF_ATTRIBUTE, config_set_localssf,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.localssf, CONFIG_INT, NULL},
{CONFIG_MINSSF_ATTRIBUTE, config_set_minssf,
NULL, 0,
(void**)&global_slapdFrontendConfig.minssf, CONFIG_INT, NULL},
@@ -900,6 +903,7 @@ FrontendConfig_init () {
cfg->outbound_ldap_io_timeout = SLAPD_DEFAULT_OUTBOUND_LDAP_IO_TIMEOUT;
cfg->max_filter_nest_level = SLAPD_DEFAULT_MAX_FILTER_NEST_LEVEL;
cfg->maxsasliosize = SLAPD_DEFAULT_MAX_SASLIO_SIZE;
+ cfg->localssf = SLAPD_DEFAULT_LOCAL_SSF;
cfg->minssf = SLAPD_DEFAULT_MIN_SSF;
#ifdef _WIN32
@@ -4710,6 +4714,48 @@ config_get_maxsasliosize()
}
int
+config_set_localssf( const char *attrname, char *value, char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ int localssf;
+ char *endptr;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if ( config_value_is_null( attrname, value, errorbuf, 0 )) {
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ localssf = (int) strtol(value, &endptr, 10);
+
+ /* Check for non-numeric garbage in the value */
+ if (*endptr != '\0') {
+ retVal = LDAP_OPERATIONS_ERROR;
+ }
+
+ /* Check for a value overflow */
+ if (((localssf == INT_MAX) || (localssf == INT_MIN)) && (errno == ERANGE)){
+ retVal = LDAP_OPERATIONS_ERROR;
+ }
+
+ /* Don't allow negative values. */
+ if (localssf < 0) {
+ retVal = LDAP_OPERATIONS_ERROR;
+ }
+
+ if (retVal != LDAP_SUCCESS) {
+ PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: \"%s\" is invalid. Value must range from 0 to
%d",
+ attrname, value, INT_MAX );
+ } else if (apply) {
+ CFG_LOCK_WRITE(slapdFrontendConfig);
+ slapdFrontendConfig->localssf = localssf;
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+ }
+
+ return retVal;
+}
+
+int
config_set_minssf( const char *attrname, char *value, char *errorbuf, int apply )
{
int retVal = LDAP_SUCCESS;
@@ -4752,6 +4798,17 @@ config_set_minssf( const char *attrname, char *value, char
*errorbuf, int apply
}
int
+config_get_localssf()
+{
+ int localssf;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ localssf = slapdFrontendConfig->localssf;
+
+ return localssf;
+}
+
+int
config_get_minssf()
{
int minssf;
diff --git a/ldap/servers/slapd/passwd_extop.c b/ldap/servers/slapd/passwd_extop.c
index e22a52d..c1f00d2 100644
--- a/ldap/servers/slapd/passwd_extop.c
+++ b/ldap/servers/slapd/passwd_extop.c
@@ -462,7 +462,7 @@ passwd_modify_extop( Slapi_PBlock *pb )
char *oldPasswd = NULL;
char *newPasswd = NULL;
char *errMesg = NULL;
- int ret=0, rc=0, sasl_ssf=0, need_pwpolicy_ctrl=0;
+ int ret=0, rc=0, sasl_ssf=0, local_ssf=0, need_pwpolicy_ctrl=0;
ber_tag_t tag=0;
ber_len_t len=(ber_len_t)-1;
struct berval *extop_value = NULL;
@@ -517,8 +517,16 @@ passwd_modify_extop( Slapi_PBlock *pb )
goto free_and_return;
}
+ if ( slapi_pblock_get(pb, SLAPI_CONN_LOCAL_SSF, &local_ssf) != 0) {
+ errMesg = "Could not get local SSF from connection\n";
+ rc = LDAP_OPERATIONS_ERROR;
+ slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_extop",
+ errMesg );
+ goto free_and_return;
+ }
+
if ( ((conn->c_flags & CONN_FLAG_SSL) != CONN_FLAG_SSL) &&
- (sasl_ssf <= 1) ) {
+ (sasl_ssf <= 1) && (local_ssf <= 1)) {
errMesg = "Operation requires a secure connection.\n";
rc = LDAP_CONFIDENTIALITY_REQUIRED;
goto free_and_return;
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 3d945cd..6bc2375 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -362,6 +362,16 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
(*(int *)value) = pblock->pb_conn->c_ssl_ssf;
PR_Unlock( pblock->pb_conn->c_mutex );
break;
+ case SLAPI_CONN_LOCAL_SSF:
+ if (pblock->pb_conn == NULL) {
+ LDAPDebug( LDAP_DEBUG_ANY,
+ "Connection is NULL and hence cannot access SLAPI_CONN_LOCAL_SSF \n", 0,
0, 0 );
+ return (-1);
+ }
+ PR_Lock( pblock->pb_conn->c_mutex );
+ (*(int *)value) = pblock->pb_conn->c_local_ssf;
+ PR_Unlock( pblock->pb_conn->c_mutex );
+ break;
case SLAPI_CONN_CERT:
if (pblock->pb_conn == NULL) {
LDAPDebug( LDAP_DEBUG_ANY,
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index dd7ec88..3d22da5 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -367,6 +367,7 @@ int config_set_outbound_ldap_io_timeout( const char *attrname, char
*value,
int config_set_unauth_binds_switch(const char *attrname, char *value, char *errorbuf, int
apply );
int config_set_require_secure_binds(const char *attrname, char *value, char *errorbuf,
int apply );
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_accesslogbuffering(const char *attrname, char *value, char *errorbuf, int
apply);
int config_set_csnlogging(const char *attrname, char *value, char *errorbuf, int apply);
@@ -504,6 +505,7 @@ int config_get_outbound_ldap_io_timeout(void);
int config_get_unauth_binds_switch(void);
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_csnlogging();
#ifdef MEMPOOL_EXPERIMENTAL
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 9c655ef..65ee8ce 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -285,6 +285,7 @@ typedef void (*VFP0)(void);
#define SLAPD_DEFAULT_MAX_THREADS 30 /* connection pool threads */
#define SLAPD_DEFAULT_MAX_THREADS_PER_CONN 5 /* allowed per connection */
#define SLAPD_DEFAULT_SCHEMA_IGNORE_TRAILING_SPACES LDAP_OFF
+#define SLAPD_DEFAULT_LOCAL_SSF 71 /* assume local connections are secure */
#define SLAPD_DEFAULT_MIN_SSF 0 /* allow unsecured connections (no privacy or
integrity) */
/* We'd like this number to be prime for
@@ -1358,6 +1359,7 @@ typedef struct conn {
Slapi_Backend *c_bi_backend; /* which backend is doing the import */
void *c_extension; /* plugins are able to extend the Connection object */
void *c_sasl_conn; /* sasl library connection sasl_conn_t */
+ int c_local_ssf; /* flag to tell us the local SSF */
int c_sasl_ssf; /* flag to tell us the SASL SSF */
int c_ssl_ssf; /* flag to tell us the SSL/TLS SSF */
int c_unix_local; /* flag true for LDAPI */
@@ -1820,6 +1822,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_UNAUTH_BINDS_ATTRIBUTE "nsslapd-allow-unauthenticated-binds"
#define CONFIG_REQUIRE_SECURE_BINDS_ATTRIBUTE "nsslapd-require-secure-binds"
#define CONFIG_ANON_ACCESS_ATTRIBUTE "nsslapd-allow-anonymous-access"
+#define CONFIG_LOCALSSF_ATTRIBUTE "nsslapd-localssf"
#define CONFIG_MINSSF_ATTRIBUTE "nsslapd-minssf"
#ifndef _WIN32
#define CONFIG_LOCALUSER_ATTRIBUTE "nsslapd-localuser"
@@ -2123,6 +2126,7 @@ typedef struct _slapdFrontendConfig {
int allow_unauth_binds; /* switch to enable/disable unauthenticated binds */
int require_secure_binds; /* switch to require simple binds to use a secure channel */
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) */
size_t maxsasliosize; /* limit incoming SASL IO packet size */
char *anon_limits_dn; /* template entry for anonymous resource limits */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 821b911..e2c7750 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5630,6 +5630,7 @@ int slapi_reslimit_get_integer_limit( Slapi_Connection *conn, int
handle,
#define SLAPI_CONN_AUTHMETHOD 746
#define SLAPI_CONN_SASL_SSF 748
#define SLAPI_CONN_SSL_SSF 749
+#define SLAPI_CONN_LOCAL_SSF 751
/*
* Types of authentication for SLAPI_CONN_AUTHMETHOD