mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-19 08:46:41 +01:00
Configuration to receive OCSP stapling response for client connections and callback implementation to verify the response if the server returns any response
This commit is contained in:
parent
7c1bc7e67b
commit
1811445758
@ -156,6 +156,10 @@ public:
|
||||
/// Specifies whether the builtin CA certificates from OpenSSL are used.
|
||||
/// Defaults to false.
|
||||
|
||||
bool ocspStaplingVerification;
|
||||
/// Specifies whether Client should verify OCSP Response
|
||||
/// Defaults to false.
|
||||
|
||||
std::string cipherList;
|
||||
/// Specifies the supported ciphers in OpenSSL notation.
|
||||
/// Defaults to "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH".
|
||||
@ -395,7 +399,11 @@ public:
|
||||
/// 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 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
|
||||
|
||||
private:
|
||||
void init(const Params& params);
|
||||
@ -415,6 +423,7 @@ private:
|
||||
VerificationMode _mode;
|
||||
SSL_CTX* _pSSLContext;
|
||||
bool _extendedCertificateVerification;
|
||||
bool _ocspStaplingResponseVerification;
|
||||
};
|
||||
|
||||
|
||||
|
@ -278,6 +278,11 @@ protected:
|
||||
/// Throws a InvalidStateException if not application instance
|
||||
/// 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:
|
||||
SSLManager();
|
||||
/// Creates the SSLManager.
|
||||
|
@ -34,6 +34,7 @@ Context::Params::Params():
|
||||
verificationMode(VERIFY_RELAXED),
|
||||
verificationDepth(9),
|
||||
loadDefaultCAs(false),
|
||||
ocspStaplingVerification(false),
|
||||
cipherList("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"),
|
||||
dhUse2048Bits(false)
|
||||
{
|
||||
@ -44,7 +45,8 @@ Context::Context(Usage usage, const Params& params):
|
||||
_usage(usage),
|
||||
_mode(params.verificationMode),
|
||||
_pSSLContext(0),
|
||||
_extendedCertificateVerification(true)
|
||||
_extendedCertificateVerification(true),
|
||||
_ocspStaplingResponseVerification(false)
|
||||
{
|
||||
init(params);
|
||||
}
|
||||
@ -62,7 +64,8 @@ Context::Context(
|
||||
_usage(usage),
|
||||
_mode(verificationMode),
|
||||
_pSSLContext(0),
|
||||
_extendedCertificateVerification(true)
|
||||
_extendedCertificateVerification(true),
|
||||
_ocspStaplingResponseVerification(false)
|
||||
{
|
||||
Params params;
|
||||
params.privateKeyFile = privateKeyFile;
|
||||
@ -86,7 +89,8 @@ Context::Context(
|
||||
_usage(usage),
|
||||
_mode(verificationMode),
|
||||
_pSSLContext(0),
|
||||
_extendedCertificateVerification(true)
|
||||
_extendedCertificateVerification(true),
|
||||
_ocspStaplingResponseVerification(false)
|
||||
{
|
||||
Params params;
|
||||
params.caLocation = caLocation;
|
||||
@ -175,6 +179,11 @@ void Context::init(const Params& params)
|
||||
SSL_CTX_set_mode(_pSSLContext, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF);
|
||||
|
||||
if (!isForServerUse() && params.ocspStaplingVerification){
|
||||
_ocspStaplingResponseVerification = true;
|
||||
SSL_CTX_set_tlsext_status_cb(_pSSLContext, &SSLManager::verifyOCSPResponse);
|
||||
SSL_CTX_set_tlsext_status_arg(_pSSLContext, this);
|
||||
}
|
||||
initDH(params.dhUse2048Bits, params.dhParamsFile);
|
||||
initECDH(params.ecdhCurve);
|
||||
}
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "Poco/Util/Application.h"
|
||||
#include "Poco/Util/OptionException.h"
|
||||
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/tls1.h>
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
@ -234,6 +236,123 @@ int SSLManager::privateKeyPassphraseCallback(char* pBuf, int size, int flag, voi
|
||||
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 len = SSL_get_tlsext_status_ocsp_resp(ssl,&resp);
|
||||
if (!resp) {
|
||||
//OCSP response not received
|
||||
return ocspverifyFlag ? 0 : 1;
|
||||
}
|
||||
|
||||
OCSP_RESPONSE *ocspResp = d2i_OCSP_RESPONSE(NULL,&resp,len);
|
||||
if (!ocspResp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (OCSP_response_status(ocspResp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OCSP_BASICRESP *basicResp = OCSP_response_get1_basic(ocspResp);
|
||||
if (!basicResp) {
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
X509 *peerCert = SSL_get_peer_certificate(ssl);
|
||||
if (!peerCert) {
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
X509 *peerIssuerCert = NULL;
|
||||
STACK_OF(X509) *certChain = SSL_get_peer_cert_chain(ssl);
|
||||
unsigned certChainLen = sk_X509_num(certChain);
|
||||
for (int i= 0; i < certChainLen ; i++) {
|
||||
if(!peerIssuerCert){
|
||||
X509 *issuer = sk_X509_value(certChain,i);
|
||||
if (X509_check_issued(issuer,peerCert) == X509_V_OK){
|
||||
peerIssuerCert = issuer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!peerIssuerCert) {
|
||||
X509_free(peerCert);
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STACK_OF(X509) *certs = sk_X509_new_null();
|
||||
if (certs) {
|
||||
X509 *cert = X509_dup(peerIssuerCert);
|
||||
if (cert && !sk_X509_push(certs,cert)) {
|
||||
X509_free(cert);
|
||||
sk_X509_free(certs);
|
||||
certs = 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);
|
||||
|
||||
if (verifyStatus <= 0) {
|
||||
X509_free(peerCert);
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OCSP_CERTID *certId = OCSP_cert_to_id(NULL,peerCert,peerIssuerCert);
|
||||
if (!certId) {
|
||||
X509_free(peerCert);
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
X509_free(peerCert);
|
||||
|
||||
ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd;
|
||||
int certstatus,reason;
|
||||
if (!OCSP_resp_find_status(basicResp,certId,&certstatus,&reason,&revtime,&thisupd,&nextupd)) {
|
||||
OCSP_CERTID_free(certId);
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OCSP_CERTID_free(certId);
|
||||
|
||||
if (certstatus != V_OCSP_CERTSTATUS_GOOD){
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!OCSP_check_validity(thisupd,nextupd,5*60,-1)) {
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OCSP_BASICRESP_free(basicResp);
|
||||
OCSP_RESPONSE_free(ocspResp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SSLManager::initDefaultContext(bool server)
|
||||
{
|
||||
|
@ -163,6 +163,9 @@ void SecureSocketImpl::connectSSL(bool performHandshake)
|
||||
SSL_set_tlsext_host_name(_pSSL, _peerHostName.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
if(_pContext->ocspStaplingResponseVerificationEnabled())
|
||||
SSL_set_tlsext_status_type(_pSSL, TLSEXT_STATUSTYPE_ocsp);
|
||||
|
||||
if (_pSession)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user