diff --git a/NetSSL_OpenSSL/include/Poco/Net/Context.h b/NetSSL_OpenSSL/include/Poco/Net/Context.h index 6b06f9c79..6633a0d9b 100644 --- a/NetSSL_OpenSSL/include/Poco/Net/Context.h +++ b/NetSSL_OpenSSL/include/Poco/Net/Context.h @@ -399,8 +399,8 @@ 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 @@ -465,6 +465,12 @@ inline bool Context::extendedCertificateVerificationEnabled() const } +inline bool Context::ocspStaplingResponseVerificationEnabled() const +{ + return _ocspStaplingResponseVerification; +} + + } } // namespace Poco::Net diff --git a/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h b/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h index 82817c7f7..3472c3d23 100644 --- a/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h +++ b/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h @@ -272,17 +272,17 @@ protected: /// The request is delegated to the PrivatekeyPassword event. This method returns the /// 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(); /// Returns the application configuration. /// /// 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. diff --git a/NetSSL_OpenSSL/src/Context.cpp b/NetSSL_OpenSSL/src/Context.cpp index 4fb0e6480..fcab0a27d 100644 --- a/NetSSL_OpenSSL/src/Context.cpp +++ b/NetSSL_OpenSSL/src/Context.cpp @@ -46,7 +46,7 @@ Context::Context(Usage usage, const Params& params): _mode(params.verificationMode), _pSSLContext(0), _extendedCertificateVerification(true), - _ocspStaplingResponseVerification(false) + _ocspStaplingResponseVerification(false) { init(params); } @@ -65,7 +65,7 @@ Context::Context( _mode(verificationMode), _pSSLContext(0), _extendedCertificateVerification(true), - _ocspStaplingResponseVerification(false) + _ocspStaplingResponseVerification(false) { Params params; params.privateKeyFile = privateKeyFile; @@ -90,7 +90,7 @@ Context::Context( _mode(verificationMode), _pSSLContext(0), _extendedCertificateVerification(true), - _ocspStaplingResponseVerification(false) + _ocspStaplingResponseVerification(false) { Params params; 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_session_cache_mode(_pSSLContext, SSL_SESS_CACHE_OFF); - if (!isForServerUse() && params.ocspStaplingVerification){ + if (!isForServerUse() && params.ocspStaplingVerification) + { +#if OPENSSL_VERSION_NUMBER >= 0x10001000L _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); +#else + throw SSLContextException("OCSP Stapling is not supported by this OpenSSL version"); +#endif } + initDH(params.dhUse2048Bits, params.dhParamsFile); initECDH(params.ecdhCurve); } diff --git a/NetSSL_OpenSSL/src/SSLManager.cpp b/NetSSL_OpenSSL/src/SSLManager.cpp index 7958652fe..40fd872ba 100644 --- a/NetSSL_OpenSSL/src/SSLManager.cpp +++ b/NetSSL_OpenSSL/src/SSLManager.cpp @@ -24,9 +24,11 @@ #include "Poco/StringTokenizer.h" #include "Poco/Util/Application.h" #include "Poco/Util/OptionException.h" - +#if OPENSSL_VERSION_NUMBER >= 0x10001000L #include #include +#endif + namespace Poco { namespace Net { @@ -236,124 +238,147 @@ 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; - } +int SSLManager::verifyOCSPResponseCallback(SSL* pSSL, void* arg) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10001000L + const long OCSP_VALIDITY_LEEWAY = 5*60; - 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); + Poco::Net::Context* pContext = static_cast(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 *basicResp = OCSP_response_get1_basic(ocspResp); - if (!basicResp) { - OCSP_RESPONSE_free(ocspResp); + OCSP_BASICRESP* pBasicResp = OCSP_response_get1_basic(pOcspResp); + if (!pBasicResp) + { + OCSP_RESPONSE_free(pOcspResp); return 0; } - X509 *peerCert = SSL_get_peer_certificate(ssl); - if (!peerCert) { - OCSP_BASICRESP_free(basicResp); - OCSP_RESPONSE_free(ocspResp); + X509* pPeerCert = SSL_get_peer_certificate(pSSL); + if (!pPeerCert) + { + OCSP_BASICRESP_free(pBasicResp); + OCSP_RESPONSE_free(pOcspResp); 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; + } + + 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 (!peerIssuerCert) { - X509_free(peerCert); - OCSP_BASICRESP_free(basicResp); - OCSP_RESPONSE_free(ocspResp); + } + if (!pPeerIssuerCert) + { + X509_free(pPeerCert); + OCSP_BASICRESP_free(pBasicResp); + OCSP_RESPONSE_free(pOcspResp); 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; - } + 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 *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) { - X509_free(peerCert); - OCSP_BASICRESP_free(basicResp); - OCSP_RESPONSE_free(ocspResp); - return 0; - } + int verifyStatus = OCSP_basic_verify(pBasicResp, pCerts, pStore, OCSP_TRUSTOTHER); - OCSP_CERTID *certId = OCSP_cert_to_id(NULL,peerCert,peerIssuerCert); - if (!certId) { - X509_free(peerCert); - OCSP_BASICRESP_free(basicResp); - OCSP_RESPONSE_free(ocspResp); + sk_X509_pop_free(pCerts, X509_free); + + if (verifyStatus <= 0) + { + X509_free(pPeerCert); + OCSP_BASICRESP_free(pBasicResp); + OCSP_RESPONSE_free(pOcspResp); 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); + 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; } - OCSP_CERTID_free(certId); + X509_free(pPeerCert); - if (certstatus != V_OCSP_CERTSTATUS_GOOD){ - OCSP_BASICRESP_free(basicResp); - OCSP_RESPONSE_free(ocspResp); + 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; } - if (!OCSP_check_validity(thisupd,nextupd,5*60,-1)) { - OCSP_BASICRESP_free(basicResp); - OCSP_RESPONSE_free(ocspResp); + OCSP_CERTID_free(pCertId); + + if (certStatus != V_OCSP_CERTSTATUS_GOOD) + { + OCSP_BASICRESP_free(pBasicResp); + OCSP_RESPONSE_free(pOcspResp); return 0; } - - OCSP_BASICRESP_free(basicResp); - OCSP_RESPONSE_free(ocspResp); - + + 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) { if (server && _ptrDefaultServerContext) return; diff --git a/NetSSL_OpenSSL/src/SecureSocketImpl.cpp b/NetSSL_OpenSSL/src/SecureSocketImpl.cpp index 8a2008288..9d4ac2dbd 100644 --- a/NetSSL_OpenSSL/src/SecureSocketImpl.cpp +++ b/NetSSL_OpenSSL/src/SecureSocketImpl.cpp @@ -163,9 +163,13 @@ void SecureSocketImpl::connectSSL(bool performHandshake) SSL_set_tlsext_host_name(_pSSL, _peerHostName.c_str()); } #endif - + +#if OPENSSL_VERSION_NUMBER >= 0x10001000L if(_pContext->ocspStaplingResponseVerificationEnabled()) + { SSL_set_tlsext_status_type(_pSSL, TLSEXT_STATUSTYPE_ocsp); + } +#endif if (_pSession) {