mirror of
https://github.com/pocoproject/poco.git
synced 2025-05-29 23:42:39 +02:00
parent
d28d2b7a80
commit
3ca91a8fe1
@ -159,6 +159,10 @@ public:
|
|||||||
/// Specifies whether the builtin CA certificates from OpenSSL are used.
|
/// Specifies whether the builtin CA certificates from OpenSSL are used.
|
||||||
/// Defaults to false.
|
/// Defaults to false.
|
||||||
|
|
||||||
|
bool ocspStaplingVerification;
|
||||||
|
/// Specifies whether Client should verify OCSP Response
|
||||||
|
/// Defaults to false.
|
||||||
|
|
||||||
std::string cipherList;
|
std::string cipherList;
|
||||||
/// Specifies the supported ciphers in OpenSSL notation.
|
/// Specifies the supported ciphers in OpenSSL notation.
|
||||||
/// Defaults to "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH".
|
/// Defaults to "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH".
|
||||||
@ -402,6 +406,10 @@ public:
|
|||||||
/// 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;
|
||||||
|
/// Returns true if automatic OCSP response
|
||||||
|
/// reception and verification is enabled for client connections
|
||||||
|
|
||||||
void setInvalidCertificateHandler(InvalidCertificateHandlerPtr pInvalidCertificageHandler);
|
void setInvalidCertificateHandler(InvalidCertificateHandlerPtr pInvalidCertificageHandler);
|
||||||
/// Sets a Context-specific InvalidCertificateHandler.
|
/// Sets a Context-specific InvalidCertificateHandler.
|
||||||
///
|
///
|
||||||
@ -430,6 +438,7 @@ private:
|
|||||||
VerificationMode _mode;
|
VerificationMode _mode;
|
||||||
SSL_CTX* _pSSLContext;
|
SSL_CTX* _pSSLContext;
|
||||||
bool _extendedCertificateVerification;
|
bool _extendedCertificateVerification;
|
||||||
|
bool _ocspStaplingResponseVerification;
|
||||||
InvalidCertificateHandlerPtr _pInvalidCertificateHandler;
|
InvalidCertificateHandlerPtr _pInvalidCertificateHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -472,6 +481,12 @@ inline bool Context::extendedCertificateVerificationEnabled() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Context::ocspStaplingResponseVerificationEnabled() const
|
||||||
|
{
|
||||||
|
return _ocspStaplingResponseVerification;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline Context::InvalidCertificateHandlerPtr Context::getInvalidCertificateHandler() const
|
inline Context::InvalidCertificateHandlerPtr Context::getInvalidCertificateHandler() const
|
||||||
{
|
{
|
||||||
return _pInvalidCertificateHandler;
|
return _pInvalidCertificateHandler;
|
||||||
|
@ -272,6 +272,11 @@ 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.
|
||||||
///
|
///
|
||||||
|
@ -34,6 +34,7 @@ Context::Params::Params():
|
|||||||
verificationMode(VERIFY_RELAXED),
|
verificationMode(VERIFY_RELAXED),
|
||||||
verificationDepth(9),
|
verificationDepth(9),
|
||||||
loadDefaultCAs(false),
|
loadDefaultCAs(false),
|
||||||
|
ocspStaplingVerification(false),
|
||||||
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"),
|
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"),
|
||||||
dhUse2048Bits(false)
|
dhUse2048Bits(false)
|
||||||
{
|
{
|
||||||
@ -44,7 +45,8 @@ Context::Context(Usage usage, const Params& params):
|
|||||||
_usage(usage),
|
_usage(usage),
|
||||||
_mode(params.verificationMode),
|
_mode(params.verificationMode),
|
||||||
_pSSLContext(0),
|
_pSSLContext(0),
|
||||||
_extendedCertificateVerification(true)
|
_extendedCertificateVerification(true),
|
||||||
|
_ocspStaplingResponseVerification(false)
|
||||||
{
|
{
|
||||||
init(params);
|
init(params);
|
||||||
}
|
}
|
||||||
@ -62,7 +64,8 @@ Context::Context(
|
|||||||
_usage(usage),
|
_usage(usage),
|
||||||
_mode(verificationMode),
|
_mode(verificationMode),
|
||||||
_pSSLContext(0),
|
_pSSLContext(0),
|
||||||
_extendedCertificateVerification(true)
|
_extendedCertificateVerification(true),
|
||||||
|
_ocspStaplingResponseVerification(false)
|
||||||
{
|
{
|
||||||
Params params;
|
Params params;
|
||||||
params.privateKeyFile = privateKeyFile;
|
params.privateKeyFile = privateKeyFile;
|
||||||
@ -86,7 +89,8 @@ Context::Context(
|
|||||||
_usage(usage),
|
_usage(usage),
|
||||||
_mode(verificationMode),
|
_mode(verificationMode),
|
||||||
_pSSLContext(0),
|
_pSSLContext(0),
|
||||||
_extendedCertificateVerification(true)
|
_extendedCertificateVerification(true),
|
||||||
|
_ocspStaplingResponseVerification(false)
|
||||||
{
|
{
|
||||||
Params params;
|
Params params;
|
||||||
params.caLocation = caLocation;
|
params.caLocation = caLocation;
|
||||||
@ -178,6 +182,17 @@ void Context::init(const Params& params)
|
|||||||
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
|
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
|
||||||
SSL_CTX_set_ex_data(_pSSLContext, SSLManager::instance().contextIndex(), this);
|
SSL_CTX_set_ex_data(_pSSLContext, SSLManager::instance().contextIndex(), this);
|
||||||
|
|
||||||
|
if (!isForServerUse() && params.ocspStaplingVerification)
|
||||||
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||||||
|
_ocspStaplingResponseVerification = true;
|
||||||
|
SSL_CTX_set_tlsext_status_cb(_pSSLContext, &SSLManager::verifyOCSPResponseCallback);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,10 @@
|
|||||||
#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/tls1.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@ -271,6 +274,145 @@ int SSLManager::privateKeyPassphraseCallback(char* pBuf, int size, int flag, voi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SSLManager::verifyOCSPResponseCallback(SSL* pSSL, void* arg)
|
||||||
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||||||
|
const long OCSP_VALIDITY_LEEWAY = 5*60;
|
||||||
|
|
||||||
|
Poco::Net::Context* pContext = static_cast<Poco::Net::Context*>(arg);
|
||||||
|
|
||||||
|
// Fetch the OSCP verify flag
|
||||||
|
bool ocspVerifyFlag = pContext->ocspStaplingResponseVerificationEnabled();
|
||||||
|
|
||||||
|
const unsigned char* pResp;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
OCSP_BASICRESP* pBasicResp = OCSP_response_get1_basic(pOcspResp);
|
||||||
|
if (!pBasicResp)
|
||||||
|
{
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509* pPeerCert = SSL_get_peer_certificate(pSSL);
|
||||||
|
if (!pPeerCert)
|
||||||
|
{
|
||||||
|
OCSP_BASICRESP_free(pBasicResp);
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509* pPeerIssuerCert = NULL;
|
||||||
|
STACK_OF(X509)* pCertChain = SSL_get_peer_cert_chain(pSSL);
|
||||||
|
unsigned certChainLen = sk_X509_num(pCertChain);
|
||||||
|
for (int i= 0; i < certChainLen ; i++)
|
||||||
|
{
|
||||||
|
if (!pPeerIssuerCert)
|
||||||
|
{
|
||||||
|
X509* pIssuerCert = sk_X509_value(pCertChain, i);
|
||||||
|
if (X509_check_issued(pIssuerCert, pPeerCert) == X509_V_OK)
|
||||||
|
{
|
||||||
|
pPeerIssuerCert = pIssuerCert;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pPeerIssuerCert)
|
||||||
|
{
|
||||||
|
X509_free(pPeerCert);
|
||||||
|
OCSP_BASICRESP_free(pBasicResp);
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STACK_OF(X509)* pCerts = sk_X509_new_null();
|
||||||
|
if (pCerts)
|
||||||
|
{
|
||||||
|
X509* pCert = X509_dup(pPeerIssuerCert);
|
||||||
|
if (pCert && !sk_X509_push(pCerts, pCert))
|
||||||
|
{
|
||||||
|
X509_free(pCert);
|
||||||
|
sk_X509_free(pCerts);
|
||||||
|
pCerts = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_STORE* pStore = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(pSSL));
|
||||||
|
|
||||||
|
int verifyStatus = OCSP_basic_verify(pBasicResp, pCerts, pStore, OCSP_TRUSTOTHER);
|
||||||
|
|
||||||
|
sk_X509_pop_free(pCerts, X509_free);
|
||||||
|
|
||||||
|
if (verifyStatus <= 0)
|
||||||
|
{
|
||||||
|
X509_free(pPeerCert);
|
||||||
|
OCSP_BASICRESP_free(pBasicResp);
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OCSP_CERTID* pCertId = OCSP_cert_to_id(NULL, pPeerCert, pPeerIssuerCert);
|
||||||
|
if (!pCertId)
|
||||||
|
{
|
||||||
|
X509_free(pPeerCert);
|
||||||
|
OCSP_BASICRESP_free(pBasicResp);
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_free(pPeerCert);
|
||||||
|
|
||||||
|
ASN1_GENERALIZEDTIME* pRevTime;
|
||||||
|
ASN1_GENERALIZEDTIME* pThisUpdate;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
OCSP_CERTID_free(pCertId);
|
||||||
|
|
||||||
|
if (certStatus != V_OCSP_CERTSTATUS_GOOD)
|
||||||
|
{
|
||||||
|
OCSP_BASICRESP_free(pBasicResp);
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OCSP_check_validity(pThisUpdate, pNextUpdate, OCSP_VALIDITY_LEEWAY, -1))
|
||||||
|
{
|
||||||
|
OCSP_BASICRESP_free(pBasicResp);
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OCSP_BASICRESP_free(pBasicResp);
|
||||||
|
OCSP_RESPONSE_free(pOcspResp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SSLManager::initDefaultContext(bool server)
|
void SSLManager::initDefaultContext(bool server)
|
||||||
{
|
{
|
||||||
if (server && _ptrDefaultServerContext) return;
|
if (server && _ptrDefaultServerContext) return;
|
||||||
|
@ -164,6 +164,13 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||||||
|
if(_pContext->ocspStaplingResponseVerificationEnabled())
|
||||||
|
{
|
||||||
|
SSL_set_tlsext_status_type(_pSSL, TLSEXT_STATUSTYPE_ocsp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (_pSession)
|
if (_pSession)
|
||||||
{
|
{
|
||||||
SSL_set_session(_pSSL, _pSession->sslSession());
|
SSL_set_session(_pSSL, _pSession->sslSession());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user