ldap/ldif/template-dse.ldif.in | 1
ldap/servers/slapd/libglobs.c | 78 ++++++++++++++++++++++++++++++++++++++--
ldap/servers/slapd/proto-slap.h | 2 +
ldap/servers/slapd/slap.h | 7 +++
ldap/servers/slapd/ssl.c | 42 ++++++++++++++-------
5 files changed, 113 insertions(+), 17 deletions(-)
New commits:
commit 971dded69619961bfce22daa0684180282f1ce9c
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Aug 23 14:18:22 2011 -0700
Bug 728592 - Allow ns-slapd to start with an invalid server cert
This patch adds a new config attribute (nsslapd-validate-cert).
This new attribute allows one to control the validation of the
server certificate used for SSL/TLS.
The valid settings are "on", "off", and "warn". The
"on" setting
will make the server validate the certificate, treating an invalid
certificate as a hard failure that prevents ns-slapd from starting.
The "warn" setting will validate the certificate, but the server
will start and log an error if the certificate is invalid. The
"off" setting will skip certificate validation completely, allowing
ns-slapd to start with no reported errors when the certicate is
invalid. The default setting is "warn" if the attribute is not
specified.
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index d8b8965..5107d72 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -29,6 +29,7 @@ nsslapd-dn-validate-strict: off
nsslapd-rewrite-rfc1274: off
nsslapd-return-exact-case: on
nsslapd-ssl-check-hostname: on
+nsslapd-validate-cert: warn
nsslapd-allow-unauthenticated-binds: off
nsslapd-require-secure-binds: off
nsslapd-allow-anonymous-access: on
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 694880e..ce6188b 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -114,9 +114,10 @@ typedef enum {
CONFIG_CONSTANT_STRING, /* for #define values, e.g. */
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_SPECIAL_ERRORLOGLEVEL, /* requires & with LDAP_DEBUG_ANY */
CONFIG_STRING_OR_EMPTY, /* use an empty string */
- CONFIG_SPECIAL_ANON_ACCESS_SWITCH /* maps strings to an enumeration */
+ CONFIG_SPECIAL_ANON_ACCESS_SWITCH, /* maps strings to an enumeration */
+ CONFIG_SPECIAL_VALIDATE_CERT_SWITCH /* maps strings to an enumeration */
} ConfigVarType;
static int config_set_onoff( const char *attrname, char *value,
@@ -640,7 +641,11 @@ static struct config_get_and_set {
{CONFIG_ALLOWED_TO_DELETE_ATTRIBUTE, config_set_allowed_to_delete_attrs,
NULL, 0,
(void**)&global_slapdFrontendConfig.allowed_to_delete_attrs,
- CONFIG_STRING, (ConfigGetFunc)config_get_allowed_to_delete_attrs}
+ CONFIG_STRING, (ConfigGetFunc)config_get_allowed_to_delete_attrs},
+ {CONFIG_VALIDATE_CERT_ATTRIBUTE, config_set_validate_cert_switch,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.validate_cert,
CONFIG_SPECIAL_VALIDATE_CERT_SWITCH,
+ (ConfigGetFunc)config_get_validate_cert_switch}
#ifdef MEMPOOL_EXPERIMENTAL
,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
NULL, 0,
@@ -905,6 +910,7 @@ FrontendConfig_init () {
cfg->maxsasliosize = SLAPD_DEFAULT_MAX_SASLIO_SIZE;
cfg->localssf = SLAPD_DEFAULT_LOCAL_SSF;
cfg->minssf = SLAPD_DEFAULT_MIN_SSF;
+ cfg->validate_cert = SLAPD_VALIDATE_CERT_WARN;
#ifdef _WIN32
cfg->conntablesize = SLAPD_DEFAULT_CONNTABLESIZE;
@@ -4626,6 +4632,17 @@ config_get_anon_access_switch(void)
}
int
+config_get_validate_cert_switch(void)
+{
+ int retVal = 0;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->validate_cert;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+ return retVal;
+}
+
+int
config_set_maxbersize( const char *attrname, char *value, char *errorbuf, int apply )
{
int retVal = LDAP_SUCCESS;
@@ -5576,6 +5593,44 @@ config_set_anon_access_switch( const char *attrname, char *value,
}
int
+config_set_validate_cert_switch( const char *attrname, char *value,
+ char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ if (config_value_is_null(attrname, value, errorbuf, 0)) {
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ if ((strcasecmp(value, "on") != 0) && (strcasecmp(value,
"off") != 0) &&
+ (strcasecmp(value, "warn") != 0)) {
+ PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+ "%s: invalid value \"%s\". Valid values are \"on\", "
+ "\"off\", or \"warn\".", 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->validate_cert = SLAPD_VALIDATE_CERT_ON;
+ } else if (strcasecmp(value, "off") == 0 ) {
+ slapdFrontendConfig->validate_cert = SLAPD_VALIDATE_CERT_OFF;
+ } else if (strcasecmp(value, "warn") == 0) {
+ slapdFrontendConfig->validate_cert = SLAPD_VALIDATE_CERT_WARN;
+ }
+
+ CFG_UNLOCK_WRITE(slapdFrontendConfig);
+ return retVal;
+}
+
+int
config_get_force_sasl_external(void)
{
int retVal;
@@ -5884,6 +5939,23 @@ config_set_value(
slapi_entry_attr_set_charptr(e, cgas->attr_name, sval);
break;
+ case CONFIG_SPECIAL_VALIDATE_CERT_SWITCH:
+ if (!value) {
+ slapi_entry_attr_set_charptr(e, cgas->attr_name, "off");
+ break;
+ }
+
+ if (*((int *)value) == SLAPD_VALIDATE_CERT_ON) {
+ sval = "on";
+ } else if (*((int *)value) == SLAPD_VALIDATE_CERT_WARN) {
+ sval = "warn";
+ } 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/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index fb9554b..72ef58e 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -369,6 +369,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_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);
int config_set_force_sasl_external(const char *attrname, char *value, char *errorbuf, int
apply );
@@ -507,6 +508,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_validate_cert_switch(void);
int config_get_csnlogging();
#ifdef MEMPOOL_EXPERIMENTAL
int config_get_mempool_switch();
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index a9befd7..ce95b1b 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -334,6 +334,11 @@ typedef void (*VFP0)(void);
#define SLAPD_ANON_ACCESS_ON 1
#define SLAPD_ANON_ACCESS_ROOTDSE 2
+/* Server certificate validation */
+#define SLAPD_VALIDATE_CERT_OFF 0
+#define SLAPD_VALIDATE_CERT_ON 1
+#define SLAPD_VALIDATE_CERT_WARN 2
+
struct subfilt {
char *sf_type;
char *sf_initial;
@@ -1829,6 +1834,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_VALIDATE_CERT_ATTRIBUTE "nsslapd-validate-cert"
#ifndef _WIN32
#define CONFIG_LOCALUSER_ATTRIBUTE "nsslapd-localuser"
#endif /* !_WIN32 */
@@ -2004,6 +2010,7 @@ typedef struct _slapdFrontendConfig {
int security;
int SSLclientAuth;
int ssl_check_hostname;
+ int validate_cert;
int sizelimit;
int SNMPenabled;
char *SNMPdescription;
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index b0a3f43..e90e00a 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -1016,11 +1016,38 @@ int slapd_ssl_init2(PRFileDesc **fd, int startTLS)
/* Step Six -- Configure Secure Server Mode */
if(pr_sock) {
SECCertificateUsage returnedUsages;
- rv = CERT_VerifyCertificateNow(
+
+ if (config_get_validate_cert_switch() == SLAPD_VALIDATE_CERT_OFF) {
+ /* If we're set to ignore certificate verification issues,
+ * just skip performing verification. */
+ rv = SECSuccess;
+ } else {
+ /* Check if the certificate is valid. */
+ rv = CERT_VerifyCertificateNow(
CERT_GetDefaultCertDB(), cert, PR_TRUE,
certificateUsageSSLServer,
SSL_RevealPinArg(pr_sock),
&returnedUsages);
+
+ if (rv != SECSuccess) {
+ /* Log warning */
+ errorCode = PR_GetError();
+ slapd_SSL_warn("CERT_VerifyCertificateNow: "
+ "verify certificate failed "
+ "for cert %s of family %s ("
+ SLAPI_COMPONENT_NAME_NSPR
+ " error %d - %s)",
+ cert_name, *family, errorCode,
+ slapd_pr_strerror(errorCode));
+
+ /* If we're set to only warn, go ahead and
+ * override rv to allow us to start up. */
+ if (config_get_validate_cert_switch() ==
SLAPD_VALIDATE_CERT_WARN) {
+ rv = SECSuccess;
+ }
+ }
+ }
+
if (SECSuccess == rv) {
if( slapd_pk11_fortezzaHasKEA(cert) == PR_TRUE ) {
rv = SSL_ConfigSecureServer(*fd, cert, key, kt_fortezza);
@@ -1037,19 +1064,6 @@ int slapd_ssl_init2(PRFileDesc **fd, int startTLS)
cert_name, *family, errorCode,
slapd_pr_strerror(errorCode));
}
- } else {
- /* verify certificate failed */
- /* If the common name in the subject DN for the certificate
- * is not identical to the domain name passed in the
- * hostname parameter, SECFailure. */
- errorCode = PR_GetError();
- slapd_SSL_warn("CERT_VerifyCertificateNow: "
- "verify certificate failed "
- "for cert %s of family %s ("
- SLAPI_COMPONENT_NAME_NSPR
- " error %d - %s)",
- cert_name, *family, errorCode,
- slapd_pr_strerror(errorCode));
}
}
if (cert) {