style fixes for #2935; check OpenSSL version

This commit is contained in:
Günter Obiltschnig
2020-02-28 08:57:31 +01:00
parent edc975ab70
commit 7ca90cb0c3
5 changed files with 139 additions and 98 deletions

View File

@@ -399,8 +399,8 @@ public:
/// When choosing a cipher, use the server's preferences instead of the client /// When choosing a cipher, use the server's preferences instead of the client
/// preferences. When not called, the SSL server will always follow the clients /// preferences. When not called, the SSL server will always follow the clients
/// preferences. When called, the SSL/TLS server will choose following its own /// preferences. When called, the SSL/TLS server will choose following its own
/// preferences. /// preferences.
bool ocspStaplingResponseVerificationEnabled() const; bool ocspStaplingResponseVerificationEnabled() const;
/// Returns true if automatic OCSP response /// Returns true if automatic OCSP response
/// reception and verification is enabled for client connections /// reception and verification is enabled for client connections
@@ -465,6 +465,12 @@ inline bool Context::extendedCertificateVerificationEnabled() const
} }
inline bool Context::ocspStaplingResponseVerificationEnabled() const
{
return _ocspStaplingResponseVerification;
}
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -272,17 +272,17 @@ protected:
/// The request is delegated to the PrivatekeyPassword event. This method returns the /// The request is delegated to the PrivatekeyPassword event. This method returns the
/// length of the password. /// length of the password.
static int verifyOCSPResponseCallback(SSL* pSSL, void* arg);
/// The return value of this method defines how errors in
/// verification are handled. Return 0 to terminate the handshake,
/// or 1 to continue despite the error.
static Poco::Util::AbstractConfiguration& appConfig(); static Poco::Util::AbstractConfiguration& appConfig();
/// Returns the application configuration. /// Returns the application configuration.
/// ///
/// Throws a InvalidStateException if not application instance /// Throws a InvalidStateException if not application instance
/// is available. /// is available.
static int verifyOCSPResponse(SSL *s, void *arg);
/// The return value of this method defines how errors in
/// verification are handled. Return 0 to terminate the handshake,
/// or 1 to continue despite the error.
private: private:
SSLManager(); SSLManager();
/// Creates the SSLManager. /// Creates the SSLManager.

View File

@@ -46,7 +46,7 @@ Context::Context(Usage usage, const Params& params):
_mode(params.verificationMode), _mode(params.verificationMode),
_pSSLContext(0), _pSSLContext(0),
_extendedCertificateVerification(true), _extendedCertificateVerification(true),
_ocspStaplingResponseVerification(false) _ocspStaplingResponseVerification(false)
{ {
init(params); init(params);
} }
@@ -65,7 +65,7 @@ Context::Context(
_mode(verificationMode), _mode(verificationMode),
_pSSLContext(0), _pSSLContext(0),
_extendedCertificateVerification(true), _extendedCertificateVerification(true),
_ocspStaplingResponseVerification(false) _ocspStaplingResponseVerification(false)
{ {
Params params; Params params;
params.privateKeyFile = privateKeyFile; params.privateKeyFile = privateKeyFile;
@@ -90,7 +90,7 @@ Context::Context(
_mode(verificationMode), _mode(verificationMode),
_pSSLContext(0), _pSSLContext(0),
_extendedCertificateVerification(true), _extendedCertificateVerification(true),
_ocspStaplingResponseVerification(false) _ocspStaplingResponseVerification(false)
{ {
Params params; Params params;
params.caLocation = caLocation; params.caLocation = caLocation;
@@ -179,11 +179,17 @@ void Context::init(const Params& params)
SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF); SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
if (!isForServerUse() && params.ocspStaplingVerification){ if (!isForServerUse() && params.ocspStaplingVerification)
{
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
_ocspStaplingResponseVerification = true; _ocspStaplingResponseVerification = true;
SSL_CTX_set_tlsext_status_cb(_pSSLContext, &SSLManager::verifyOCSPResponse); SSL_CTX_set_tlsext_status_cb(_pSSLContext, &SSLManager::verifyOCSPResponseCallback);
SSL_CTX_set_tlsext_status_arg(_pSSLContext, this); SSL_CTX_set_tlsext_status_arg(_pSSLContext, this);
#else
throw SSLContextException("OCSP Stapling is not supported by this OpenSSL version");
#endif
} }
initDH(params.dhUse2048Bits, params.dhParamsFile); initDH(params.dhUse2048Bits, params.dhParamsFile);
initECDH(params.ecdhCurve); initECDH(params.ecdhCurve);
} }

View File

@@ -24,9 +24,11 @@
#include "Poco/StringTokenizer.h" #include "Poco/StringTokenizer.h"
#include "Poco/Util/Application.h" #include "Poco/Util/Application.h"
#include "Poco/Util/OptionException.h" #include "Poco/Util/OptionException.h"
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
#include <openssl/ocsp.h> #include <openssl/ocsp.h>
#include <openssl/tls1.h> #include <openssl/tls1.h>
#endif
namespace Poco { namespace Poco {
namespace Net { namespace Net {
@@ -236,124 +238,147 @@ int SSLManager::privateKeyPassphraseCallback(char* pBuf, int size, int flag, voi
return size; return size;
} }
int SSLManager::verifyOCSPResponse(SSL *ssl, void *arg)
{
Poco::Net::Context* pocoCtx = (Poco::Net::Context*)arg;
//Fetch the OSCP verify flag
bool ocspverifyFlag = pocoCtx->ocspStaplingResponseVerificationEnabled();
const unsigned char *resp; int SSLManager::verifyOCSPResponseCallback(SSL* pSSL, void* arg)
int len = SSL_get_tlsext_status_ocsp_resp(ssl,&resp); {
if (!resp) { #if OPENSSL_VERSION_NUMBER >= 0x10001000L
//OCSP response not received const long OCSP_VALIDITY_LEEWAY = 5*60;
return ocspverifyFlag ? 0 : 1;
}
OCSP_RESPONSE *ocspResp = d2i_OCSP_RESPONSE(NULL,&resp,len); Poco::Net::Context* pContext = static_cast<Poco::Net::Context*>(arg);
if (!ocspResp) {
return 0; // Fetch the OSCP verify flag
} bool ocspVerifyFlag = pContext->ocspStaplingResponseVerificationEnabled();
if (OCSP_response_status(ocspResp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) { const unsigned char* pResp;
OCSP_RESPONSE_free(ocspResp); int len = SSL_get_tlsext_status_ocsp_resp(pSSL, &pResp);
if (!pResp)
{
// OCSP response not received
return ocspVerifyFlag ? 0 : 1;
}
OCSP_RESPONSE* pOcspResp = d2i_OCSP_RESPONSE(NULL, &pResp, len);
if (!pOcspResp) return 0;
if (OCSP_response_status(pOcspResp) != OCSP_RESPONSE_STATUS_SUCCESSFUL)
{
OCSP_RESPONSE_free(pOcspResp);
return 0; return 0;
} }
OCSP_BASICRESP *basicResp = OCSP_response_get1_basic(ocspResp); OCSP_BASICRESP* pBasicResp = OCSP_response_get1_basic(pOcspResp);
if (!basicResp) { if (!pBasicResp)
OCSP_RESPONSE_free(ocspResp); {
OCSP_RESPONSE_free(pOcspResp);
return 0; return 0;
} }
X509 *peerCert = SSL_get_peer_certificate(ssl); X509* pPeerCert = SSL_get_peer_certificate(pSSL);
if (!peerCert) { if (!pPeerCert)
OCSP_BASICRESP_free(basicResp); {
OCSP_RESPONSE_free(ocspResp); OCSP_BASICRESP_free(pBasicResp);
OCSP_RESPONSE_free(pOcspResp);
return 0; return 0;
} }
X509 *peerIssuerCert = NULL; X509* pPeerIssuerCert = NULL;
STACK_OF(X509) *certChain = SSL_get_peer_cert_chain(ssl); STACK_OF(X509)* pCertChain = SSL_get_peer_cert_chain(pSSL);
unsigned certChainLen = sk_X509_num(certChain); unsigned certChainLen = sk_X509_num(pCertChain);
for (int i= 0; i < certChainLen ; i++) { for (int i= 0; i < certChainLen ; i++)
if(!peerIssuerCert){ {
X509 *issuer = sk_X509_value(certChain,i); if (!pPeerIssuerCert)
if (X509_check_issued(issuer,peerCert) == X509_V_OK){ {
peerIssuerCert = issuer; X509* pIssuerCert = sk_X509_value(pCertChain, i);
if (X509_check_issued(pIssuerCert, pPeerCert) == X509_V_OK)
{
pPeerIssuerCert = pIssuerCert;
break; break;
} }
} }
} }
if (!peerIssuerCert) { if (!pPeerIssuerCert)
X509_free(peerCert); {
OCSP_BASICRESP_free(basicResp); X509_free(pPeerCert);
OCSP_RESPONSE_free(ocspResp); OCSP_BASICRESP_free(pBasicResp);
OCSP_RESPONSE_free(pOcspResp);
return 0; return 0;
} }
STACK_OF(X509) *certs = sk_X509_new_null(); STACK_OF(X509)* pCerts = sk_X509_new_null();
if (certs) { if (pCerts)
X509 *cert = X509_dup(peerIssuerCert); {
if (cert && !sk_X509_push(certs,cert)) { X509* pCert = X509_dup(pPeerIssuerCert);
X509_free(cert); if (pCert && !sk_X509_push(pCerts, pCert))
sk_X509_free(certs); {
certs = NULL; X509_free(pCert);
} sk_X509_free(pCerts);
pCerts = NULL;
}
} }
X509_STORE *store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(ssl));
int verifyStatus = OCSP_basic_verify(basicResp,certs,store,OCSP_TRUSTOTHER);
sk_X509_pop_free(certs, X509_free); X509_STORE* pStore = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(pSSL));
if (verifyStatus <= 0) { int verifyStatus = OCSP_basic_verify(pBasicResp, pCerts, pStore, OCSP_TRUSTOTHER);
X509_free(peerCert);
OCSP_BASICRESP_free(basicResp);
OCSP_RESPONSE_free(ocspResp);
return 0;
}
OCSP_CERTID *certId = OCSP_cert_to_id(NULL,peerCert,peerIssuerCert); sk_X509_pop_free(pCerts, X509_free);
if (!certId) {
X509_free(peerCert); if (verifyStatus <= 0)
OCSP_BASICRESP_free(basicResp); {
OCSP_RESPONSE_free(ocspResp); X509_free(pPeerCert);
OCSP_BASICRESP_free(pBasicResp);
OCSP_RESPONSE_free(pOcspResp);
return 0; return 0;
} }
X509_free(peerCert); OCSP_CERTID* pCertId = OCSP_cert_to_id(NULL, pPeerCert, pPeerIssuerCert);
if (!pCertId)
ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd; {
int certstatus,reason; X509_free(pPeerCert);
if (!OCSP_resp_find_status(basicResp,certId,&certstatus,&reason,&revtime,&thisupd,&nextupd)) { OCSP_BASICRESP_free(pBasicResp);
OCSP_CERTID_free(certId); OCSP_RESPONSE_free(pOcspResp);
OCSP_BASICRESP_free(basicResp);
OCSP_RESPONSE_free(ocspResp);
return 0; return 0;
} }
OCSP_CERTID_free(certId); X509_free(pPeerCert);
if (certstatus != V_OCSP_CERTSTATUS_GOOD){ ASN1_GENERALIZEDTIME* pRevTime;
OCSP_BASICRESP_free(basicResp); ASN1_GENERALIZEDTIME* pThisUpdate;
OCSP_RESPONSE_free(ocspResp); ASN1_GENERALIZEDTIME* pNextUpdate;
int certStatus;
int reason;
if (!OCSP_resp_find_status(pBasicResp, pCertId, &certStatus, &reason, &pRevTime, &pThisUpdate, &pNextUpdate))
{
OCSP_CERTID_free(pCertId);
OCSP_BASICRESP_free(pBasicResp);
OCSP_RESPONSE_free(pOcspResp);
return 0; return 0;
} }
if (!OCSP_check_validity(thisupd,nextupd,5*60,-1)) { OCSP_CERTID_free(pCertId);
OCSP_BASICRESP_free(basicResp);
OCSP_RESPONSE_free(ocspResp); if (certStatus != V_OCSP_CERTSTATUS_GOOD)
{
OCSP_BASICRESP_free(pBasicResp);
OCSP_RESPONSE_free(pOcspResp);
return 0; return 0;
} }
OCSP_BASICRESP_free(basicResp); if (!OCSP_check_validity(pThisUpdate, pNextUpdate, OCSP_VALIDITY_LEEWAY, -1))
OCSP_RESPONSE_free(ocspResp); {
OCSP_BASICRESP_free(pBasicResp);
OCSP_RESPONSE_free(pOcspResp);
return 0;
}
OCSP_BASICRESP_free(pBasicResp);
OCSP_RESPONSE_free(pOcspResp);
#endif
return 1; return 1;
} }
void SSLManager::initDefaultContext(bool server) void SSLManager::initDefaultContext(bool server)
{ {
if (server && _ptrDefaultServerContext) return; if (server && _ptrDefaultServerContext) return;

View File

@@ -163,9 +163,13 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
SSL_set_tlsext_host_name(_pSSL, _peerHostName.c_str()); SSL_set_tlsext_host_name(_pSSL, _peerHostName.c_str());
} }
#endif #endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
if(_pContext->ocspStaplingResponseVerificationEnabled()) if(_pContext->ocspStaplingResponseVerificationEnabled())
{
SSL_set_tlsext_status_type(_pSSL, TLSEXT_STATUSTYPE_ocsp); SSL_set_tlsext_status_type(_pSSL, TLSEXT_STATUSTYPE_ocsp);
}
#endif
if (_pSession) if (_pSession)
{ {