incorrect behavior of allow/try options of VerifyCert and TLS_REQCERT
Resolves: #725819
This commit is contained in:
parent
67c9630d50
commit
49f6078a21
28
openldap-nss-reqcert-hostname.patch
Normal file
28
openldap-nss-reqcert-hostname.patch
Normal file
@ -0,0 +1,28 @@
|
||||
Do not check server hostname when TLS_REQCERT is 'allow'.
|
||||
|
||||
If server certificate hostname does not match the server hostname,
|
||||
connection is closed even if client has set TLS_REQCERT to 'allow'. This
|
||||
is wrong - the documentation says, that bad certificates are being
|
||||
ignored when TLS_REQCERT is set to 'allow'.
|
||||
|
||||
Author: Jan Vcelak <jvcelak@redhat.com>
|
||||
Upstream ITS: #7014
|
||||
Resolves: #725819
|
||||
|
||||
diff --git a/libraries/libldap/tls2.c b/libraries/libldap/tls2.c
|
||||
index f38db27..3f05c1e 100644
|
||||
--- a/libraries/libldap/tls2.c
|
||||
+++ b/libraries/libldap/tls2.c
|
||||
@@ -838,7 +838,8 @@ ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv )
|
||||
/*
|
||||
* compare host with name(s) in certificate
|
||||
*/
|
||||
- if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER) {
|
||||
+ if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER &&
|
||||
+ ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) {
|
||||
ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host );
|
||||
if (ld->ld_errno != LDAP_SUCCESS) {
|
||||
return ld->ld_errno;
|
||||
--
|
||||
1.7.6
|
||||
|
209
openldap-nss-verifycert.patch
Normal file
209
openldap-nss-verifycert.patch
Normal file
@ -0,0 +1,209 @@
|
||||
Fix server side VerifyCert allow/try behavior
|
||||
|
||||
If the olcTLSVerifyClient is set to a value other than "never", the server
|
||||
should request that the client send a client certificate for possible use
|
||||
with client cert auth (e.g. SASL/EXTERNAL).
|
||||
If set to "allow", if the client sends a cert, and there are problems with
|
||||
it, the server will warn about problems, but will allow the SSL session to
|
||||
proceed without a client cert.
|
||||
If set to "try", if the client sends a cert, and there are problems with
|
||||
it, the server will warn about those problems, and shutdown the SSL session.
|
||||
If set to "demand" or "hard", the client must send a cert, and the server
|
||||
will shutdown the SSL session if there are problems.
|
||||
I added a new member of the tlsm context structure - tc_warn_only - if this
|
||||
is set, tlsm_verify_cert will only warn about errors, and only if TRACE
|
||||
level debug is set. This allows the server to warn but allow bad certs
|
||||
if "allow" is set, and warn and fail if "try" is set.
|
||||
|
||||
Author: Rich Megginson <rmeggins@redhat.com>
|
||||
Upstream ITS: #7002
|
||||
Upstream commit: 210b156ece28a71cb625283fa5c30ee76d639cdc
|
||||
Resolves: #725819
|
||||
|
||||
diff --git a/libraries/libldap/tls_m.c b/libraries/libldap/tls_m.c
|
||||
index 72fdf49..997b3eb 100644
|
||||
--- a/libraries/libldap/tls_m.c
|
||||
+++ b/libraries/libldap/tls_m.c
|
||||
@@ -96,6 +96,7 @@ typedef struct tlsm_ctx {
|
||||
#endif
|
||||
PK11GenericObject **tc_pem_objs; /* array of objects to free */
|
||||
int tc_n_pem_objs; /* number of objects */
|
||||
+ PRBool tc_warn_only; /* only warn of errors in validation */
|
||||
#ifdef LDAP_R_COMPILE
|
||||
ldap_pvt_thread_mutex_t tc_refmutex;
|
||||
#endif
|
||||
@@ -945,6 +946,11 @@ tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
|
||||
CERTVerifyLog verifylog;
|
||||
SECStatus ret = SECSuccess;
|
||||
const char *name;
|
||||
+ int debug_level = LDAP_DEBUG_ANY;
|
||||
+
|
||||
+ if ( errorToIgnore == -1 ) {
|
||||
+ debug_level = LDAP_DEBUG_TRACE;
|
||||
+ }
|
||||
|
||||
/* the log captures information about every cert in the chain, so we can tell
|
||||
which cert caused the problem and what the problem was */
|
||||
@@ -965,7 +971,7 @@ tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
|
||||
/* it is possible for CERT_VerifyCertificate return with an error with no logging */
|
||||
if ( ret != SECSuccess ) {
|
||||
PRErrorCode errcode = PR_GetError();
|
||||
- Debug( LDAP_DEBUG_ANY,
|
||||
+ Debug( debug_level,
|
||||
"TLS: certificate [%s] is not valid - error %d:%s.\n",
|
||||
name ? name : "(unknown)",
|
||||
errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
|
||||
@@ -995,17 +1001,17 @@ tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
|
||||
"please fix your certs if possible\n", name, 0, 0 );
|
||||
} else { /* does not have basicconstraint, or some other error */
|
||||
ret = SECFailure;
|
||||
- Debug( LDAP_DEBUG_ANY,
|
||||
+ Debug( debug_level,
|
||||
"TLS: certificate [%s] is not valid - CA cert is not valid\n",
|
||||
name, 0, 0 );
|
||||
}
|
||||
} else if ( errorToIgnore && ( node->error == errorToIgnore ) ) {
|
||||
- Debug( LDAP_DEBUG_ANY,
|
||||
+ Debug( debug_level,
|
||||
"TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n",
|
||||
name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
|
||||
} else {
|
||||
ret = SECFailure;
|
||||
- Debug( LDAP_DEBUG_ANY,
|
||||
+ Debug( debug_level,
|
||||
"TLS: certificate [%s] is not valid - error %ld:%s.\n",
|
||||
name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
|
||||
}
|
||||
@@ -1020,7 +1026,9 @@ tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
|
||||
if ( ret == SECSuccess ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"TLS: certificate [%s] is valid\n", name, 0, 0 );
|
||||
- }
|
||||
+ } else if ( errorToIgnore == -1 ) {
|
||||
+ ret = SECSuccess;
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1032,10 +1040,15 @@ tlsm_auth_cert_handler(void *arg, PRFileDesc *fd,
|
||||
SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
|
||||
SECStatus ret = SECSuccess;
|
||||
CERTCertificate *peercert = SSL_PeerCertificate( fd );
|
||||
+ int errorToIgnore = 0;
|
||||
+ tlsm_ctx *ctx = (tlsm_ctx *)arg;
|
||||
+
|
||||
+ if (ctx && ctx->tc_warn_only )
|
||||
+ errorToIgnore = -1;
|
||||
|
||||
- ret = tlsm_verify_cert( (CERTCertDBHandle *)arg, peercert,
|
||||
+ ret = tlsm_verify_cert( ctx->tc_certdb, peercert,
|
||||
SSL_RevealPinArg( fd ),
|
||||
- checksig, certUsage, 0 );
|
||||
+ checksig, certUsage, errorToIgnore );
|
||||
CERT_DestroyCertificate( peercert );
|
||||
|
||||
return ret;
|
||||
@@ -1758,6 +1771,8 @@ tlsm_find_and_verify_cert_key(tlsm_ctx *ctx, PRFileDesc *fd, const char *certnam
|
||||
SECCertificateUsage certUsage;
|
||||
PRBool checkSig = PR_TRUE;
|
||||
SECStatus status;
|
||||
+ /* may not have a CA cert - ok - ignore SEC_ERROR_UNKNOWN_ISSUER */
|
||||
+ int errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER;
|
||||
|
||||
if ( pRetKey ) {
|
||||
*pRetKey = key; /* caller will deal with this */
|
||||
@@ -1774,9 +1789,11 @@ tlsm_find_and_verify_cert_key(tlsm_ctx *ctx, PRFileDesc *fd, const char *certnam
|
||||
} else {
|
||||
checkSig = PR_FALSE;
|
||||
}
|
||||
- /* may not have a CA cert - ok - ignore SEC_ERROR_UNKNOWN_ISSUER */
|
||||
+ if ( ctx->tc_warn_only ) {
|
||||
+ errorToIgnore = -1;
|
||||
+ }
|
||||
status = tlsm_verify_cert( ctx->tc_certdb, cert, pin_arg,
|
||||
- checkSig, certUsage, SEC_ERROR_UNKNOWN_ISSUER );
|
||||
+ checkSig, certUsage, errorToIgnore );
|
||||
if ( status == SECSuccess ) {
|
||||
rc = 0;
|
||||
}
|
||||
@@ -1803,10 +1820,14 @@ tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
|
||||
{
|
||||
tlsm_ctx *ctx = (tlsm_ctx *)arg;
|
||||
int rc;
|
||||
+ PRBool saveval;
|
||||
|
||||
/* don't need caNames - this function will call CERT_VerifyCertificateNow
|
||||
which will verify the cert against the known CAs */
|
||||
+ saveval = ctx->tc_warn_only;
|
||||
+ ctx->tc_warn_only = PR_TRUE;
|
||||
rc = tlsm_find_and_verify_cert_key( ctx, fd, ctx->tc_certname, 0, pRetCert, pRetKey );
|
||||
+ ctx->tc_warn_only = saveval;
|
||||
if ( rc ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"TLS: error: unable to perform client certificate authentication for "
|
||||
@@ -1837,8 +1858,12 @@ tlsm_clientauth_init( tlsm_ctx *ctx )
|
||||
{
|
||||
SECStatus status = SECFailure;
|
||||
int rc;
|
||||
+ PRBool saveval;
|
||||
|
||||
+ saveval = ctx->tc_warn_only;
|
||||
+ ctx->tc_warn_only = PR_TRUE;
|
||||
rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, 0, NULL, NULL );
|
||||
+ ctx->tc_warn_only = saveval;
|
||||
if ( rc ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"TLS: error: unable to set up client certificate authentication for "
|
||||
@@ -1887,6 +1912,7 @@ tlsm_ctx_new ( struct ldapoptions *lo )
|
||||
#endif /* HAVE_NSS_INITCONTEXT */
|
||||
ctx->tc_pem_objs = NULL;
|
||||
ctx->tc_n_pem_objs = 0;
|
||||
+ ctx->tc_warn_only = PR_FALSE;
|
||||
}
|
||||
return (tls_ctx *)ctx;
|
||||
}
|
||||
@@ -2048,7 +2074,9 @@ tlsm_deferred_ctx_init( void *arg )
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if ( ctx->tc_require_cert ) {
|
||||
+ if ( !ctx->tc_require_cert ) {
|
||||
+ ctx->tc_verify_cert = PR_FALSE;
|
||||
+ } else if ( !ctx->tc_is_server ) {
|
||||
request_cert = PR_TRUE;
|
||||
require_cert = SSL_REQUIRE_NO_ERROR;
|
||||
if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
|
||||
@@ -2057,8 +2085,22 @@ tlsm_deferred_ctx_init( void *arg )
|
||||
}
|
||||
if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
|
||||
ctx->tc_verify_cert = PR_TRUE;
|
||||
- } else {
|
||||
- ctx->tc_verify_cert = PR_FALSE;
|
||||
+ } else { /* server */
|
||||
+ /* server does not request certs by default */
|
||||
+ /* if allow - client may send cert, server will ignore if errors */
|
||||
+ /* if try - client may send cert, server will error if bad cert */
|
||||
+ /* if hard or demand - client must send cert, server will error if bad cert */
|
||||
+ request_cert = PR_TRUE;
|
||||
+ require_cert = SSL_REQUIRE_NO_ERROR;
|
||||
+ if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
|
||||
+ ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
|
||||
+ require_cert = SSL_REQUIRE_ALWAYS;
|
||||
+ }
|
||||
+ if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
|
||||
+ ctx->tc_verify_cert = PR_TRUE;
|
||||
+ } else {
|
||||
+ ctx->tc_warn_only = PR_TRUE;
|
||||
+ }
|
||||
}
|
||||
|
||||
if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
|
||||
@@ -2193,7 +2235,7 @@ tlsm_deferred_ctx_init( void *arg )
|
||||
|
||||
/* Callback for authenticating certificate */
|
||||
if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
|
||||
- ctx->tc_certdb ) != SECSuccess ) {
|
||||
+ ctx ) != SECSuccess ) {
|
||||
PRErrorCode err = PR_GetError();
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
|
@ -31,6 +31,8 @@ Patch5: openldap-ldaprc-currentdir.patch
|
||||
Patch6: openldap-userconfig-setgid.patch
|
||||
Patch7: openldap-nss-free-peer-cert.patch
|
||||
Patch8: openldap-nss-init-threadsafe.patch
|
||||
Patch9: openldap-nss-reqcert-hostname.patch
|
||||
Patch10: openldap-nss-verifycert.patch
|
||||
|
||||
# patches for the evolution library (see README.evolution)
|
||||
Patch200: openldap-evolution-ntlm.patch
|
||||
@ -132,6 +134,8 @@ pushd openldap-%{version}
|
||||
%patch6 -p1 -b .userconfig-setgid
|
||||
%patch7 -p1 -b .nss-free-peer-cert
|
||||
%patch8 -p1 -b .nss-init-threadsafe
|
||||
%patch9 -p1 -b .nss-reqcert-hostname
|
||||
%patch10 -p1 -b .nss-verifycert
|
||||
|
||||
cp %{_datadir}/libtool/config/config.{sub,guess} build/
|
||||
|
||||
@ -658,6 +662,7 @@ exit 0
|
||||
* Wed Aug 24 2011 Jan Vcelak <jvcelak@redhat.com> 2.4.26-2
|
||||
- security hardening: library needs partial RELRO support added (#733071)
|
||||
- fix: NSS_Init* functions are not thread safe (#731112)
|
||||
- fix: incorrect behavior of allow/try options of VerifyCert and TLS_REQCERT (#725819)
|
||||
|
||||
* Sun Aug 14 2011 Rex Dieter <rdieter@fedoraproject.org> - 2.4.26-1.1
|
||||
- Rebuilt for rpm (#728707)
|
||||
|
Loading…
Reference in New Issue
Block a user