diff options
author | Tobias Markmann <tm@ayena.de> | 2012-05-04 21:39:30 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2012-05-11 19:29:38 (GMT) |
commit | 0f91f88ac69644fb7e7bdbf601b7e098194490fa (patch) | |
tree | e66ca4acbf869c82bba607ca9c394a47615c6e6e /Swiften | |
parent | 15ed4a079a8bbe3cc9ee2ca47233be7b890464ec (diff) | |
download | swift-contrib-0f91f88ac69644fb7e7bdbf601b7e098194490fa.zip swift-contrib-0f91f88ac69644fb7e7bdbf601b7e098194490fa.tar.bz2 |
Showing stream encryption status in the roster header. Provide native certificate viewers on click.
Native viewers for Windows and Mac OS X are implemented.
Added TODOs to OpenSSL based TLS interface related to CRL and OCSP.
Resolves: #167
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swiften')
22 files changed, 107 insertions, 0 deletions
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h index 2205c8d..b67b23d 100644 --- a/Swiften/Client/ClientSession.h +++ b/Swiften/Client/ClientSession.h @@ -98,6 +98,10 @@ namespace Swift { return rosterVersioningSupported; } + std::vector<Certificate::ref> getPeerCertificateChain() const { + return stream->getPeerCertificateChain(); + } + const JID& getLocalJID() const { return localJID; } diff --git a/Swiften/Client/ClientSessionStanzaChannel.cpp b/Swiften/Client/ClientSessionStanzaChannel.cpp index 5dc0a42..8d85953 100644 --- a/Swiften/Client/ClientSessionStanzaChannel.cpp +++ b/Swiften/Client/ClientSessionStanzaChannel.cpp @@ -82,6 +82,13 @@ bool ClientSessionStanzaChannel::getStreamManagementEnabled() const { return false; } +std::vector<Certificate::ref> ClientSessionStanzaChannel::getPeerCertificateChain() const { + if (session) { + return session->getPeerCertificateChain(); + } + return std::vector<Certificate::ref>(); +} + void ClientSessionStanzaChannel::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) { onStanzaAcked(stanza); } diff --git a/Swiften/Client/ClientSessionStanzaChannel.h b/Swiften/Client/ClientSessionStanzaChannel.h index 47fb50e..2743a16 100644 --- a/Swiften/Client/ClientSessionStanzaChannel.h +++ b/Swiften/Client/ClientSessionStanzaChannel.h @@ -27,6 +27,7 @@ namespace Swift { void sendMessage(boost::shared_ptr<Message> message); void sendPresence(boost::shared_ptr<Presence> presence); bool getStreamManagementEnabled() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; bool isAvailable() const { return session && session->getState() == ClientSession::Initialized; diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 8a922ba..36e27eb 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -360,6 +360,10 @@ bool CoreClient::getStreamManagementEnabled() const { return stanzaChannel_->getStreamManagementEnabled(); } +bool CoreClient::isStreamEncrypted() const { + return sessionStream_->isTLSEncrypted(); +} + StanzaChannel* CoreClient::getStanzaChannel() const { return stanzaChannel_; } diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h index cafc634..985bf7f 100644 --- a/Swiften/Client/CoreClient.h +++ b/Swiften/Client/CoreClient.h @@ -127,6 +127,11 @@ namespace Swift { */ bool getStreamManagementEnabled() const; + /** + * Checks whether stream encryption (TLS) is currently active. + */ + bool isStreamEncrypted() const; + StanzaChannel* getStanzaChannel() const; /** diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h index c2f3919..5cdedba 100644 --- a/Swiften/Client/DummyStanzaChannel.h +++ b/Swiften/Client/DummyStanzaChannel.h @@ -79,6 +79,10 @@ namespace Swift { return boost::dynamic_pointer_cast<T>(sentStanzas[index]); } + std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + std::vector<boost::shared_ptr<Stanza> > sentStanzas; bool available_; }; diff --git a/Swiften/Client/StanzaChannel.h b/Swiften/Client/StanzaChannel.h index f1d76e0..5e85d3c 100644 --- a/Swiften/Client/StanzaChannel.h +++ b/Swiften/Client/StanzaChannel.h @@ -12,6 +12,7 @@ #include <Swiften/Queries/IQChannel.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> +#include <Swiften/TLS/Certificate.h> namespace Swift { class StanzaChannel : public IQChannel { @@ -20,6 +21,7 @@ namespace Swift { virtual void sendPresence(boost::shared_ptr<Presence>) = 0; virtual bool isAvailable() const = 0; virtual bool getStreamManagementEnabled() const = 0; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; boost::signal<void (bool /* isAvailable */)> onAvailableChanged; boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp index 6793643..d1ca70a 100644 --- a/Swiften/Client/UnitTest/ClientSessionTest.cpp +++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp @@ -399,6 +399,10 @@ class ClientSessionTest : public CppUnit::TestFixture { return Certificate::ref(new SimpleCertificate()); } + virtual std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { return boost::shared_ptr<CertificateVerificationError>(); } diff --git a/Swiften/Component/ComponentSessionStanzaChannel.h b/Swiften/Component/ComponentSessionStanzaChannel.h index 45f90b5..4e133b8 100644 --- a/Swiften/Component/ComponentSessionStanzaChannel.h +++ b/Swiften/Component/ComponentSessionStanzaChannel.h @@ -31,6 +31,11 @@ namespace Swift { return false; } + std::vector<Certificate::ref> getPeerCertificateChain() const { + // TODO: actually implement this method + return std::vector<Certificate::ref>(); + } + bool isAvailable() const { return session && session->getState() == ComponentSession::Initialized; } diff --git a/Swiften/Component/UnitTest/ComponentSessionTest.cpp b/Swiften/Component/UnitTest/ComponentSessionTest.cpp index da9ca7d..238d0b0 100644 --- a/Swiften/Component/UnitTest/ComponentSessionTest.cpp +++ b/Swiften/Component/UnitTest/ComponentSessionTest.cpp @@ -138,6 +138,10 @@ class ComponentSessionTest : public CppUnit::TestFixture { return Certificate::ref(); } + virtual std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { return boost::shared_ptr<CertificateVerificationError>(); } diff --git a/Swiften/Session/BOSHSessionStream.cpp b/Swiften/Session/BOSHSessionStream.cpp index 237a394..6f15b84 100644 --- a/Swiften/Session/BOSHSessionStream.cpp +++ b/Swiften/Session/BOSHSessionStream.cpp @@ -129,6 +129,10 @@ Certificate::ref BOSHSessionStream::getPeerCertificate() const { return Certificate::ref(); } +std::vector<Certificate::ref> BOSHSessionStream::getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); +} + boost::shared_ptr<CertificateVerificationError> BOSHSessionStream::getPeerCertificateVerificationError() const { return boost::shared_ptr<CertificateVerificationError>(); } diff --git a/Swiften/Session/BOSHSessionStream.h b/Swiften/Session/BOSHSessionStream.h index 497d391..99851b5 100644 --- a/Swiften/Session/BOSHSessionStream.h +++ b/Swiften/Session/BOSHSessionStream.h @@ -61,6 +61,7 @@ namespace Swift { virtual void addTLSEncryption(); virtual bool isTLSEncrypted(); virtual Certificate::ref getPeerCertificate() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; virtual ByteArray getTLSFinishMessage() const; diff --git a/Swiften/Session/BasicSessionStream.cpp b/Swiften/Session/BasicSessionStream.cpp index b49ffc9..cbe85ab 100644 --- a/Swiften/Session/BasicSessionStream.cpp +++ b/Swiften/Session/BasicSessionStream.cpp @@ -129,6 +129,10 @@ Certificate::ref BasicSessionStream::getPeerCertificate() const { return tlsLayer->getPeerCertificate(); } +std::vector<Certificate::ref> BasicSessionStream::getPeerCertificateChain() const { + return tlsLayer->getPeerCertificateChain(); +} + boost::shared_ptr<CertificateVerificationError> BasicSessionStream::getPeerCertificateVerificationError() const { return tlsLayer->getPeerCertificateVerificationError(); } diff --git a/Swiften/Session/BasicSessionStream.h b/Swiften/Session/BasicSessionStream.h index e1f32f4..084a191 100644 --- a/Swiften/Session/BasicSessionStream.h +++ b/Swiften/Session/BasicSessionStream.h @@ -55,6 +55,8 @@ namespace Swift { virtual void addTLSEncryption(); virtual bool isTLSEncrypted(); virtual Certificate::ref getPeerCertificate() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; + virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; virtual ByteArray getTLSFinishMessage() const; diff --git a/Swiften/Session/SessionStream.h b/Swiften/Session/SessionStream.h index 32cb6b6..4735d5f 100644 --- a/Swiften/Session/SessionStream.h +++ b/Swiften/Session/SessionStream.h @@ -67,6 +67,7 @@ namespace Swift { } virtual Certificate::ref getPeerCertificate() const = 0; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const = 0; virtual ByteArray getTLSFinishMessage() const = 0; diff --git a/Swiften/StreamStack/TLSLayer.cpp b/Swiften/StreamStack/TLSLayer.cpp index 6d416bc..86221ea 100644 --- a/Swiften/StreamStack/TLSLayer.cpp +++ b/Swiften/StreamStack/TLSLayer.cpp @@ -45,6 +45,10 @@ Certificate::ref TLSLayer::getPeerCertificate() const { return context->getPeerCertificate(); } +std::vector<Certificate::ref> TLSLayer::getPeerCertificateChain() const { + return context->getPeerCertificateChain(); +} + boost::shared_ptr<CertificateVerificationError> TLSLayer::getPeerCertificateVerificationError() const { return context->getPeerCertificateVerificationError(); } diff --git a/Swiften/StreamStack/TLSLayer.h b/Swiften/StreamStack/TLSLayer.h index ce0c89b..24978e0 100644 --- a/Swiften/StreamStack/TLSLayer.h +++ b/Swiften/StreamStack/TLSLayer.h @@ -26,6 +26,7 @@ namespace Swift { bool setClientCertificate(CertificateWithKey::ref cert); Certificate::ref getPeerCertificate() const; + std::vector<Certificate::ref> getPeerCertificateChain() const; boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; void writeData(const SafeByteArray& data); diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp index 8c03052..58a8d05 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp @@ -39,6 +39,12 @@ OpenSSLContext::OpenSSLContext() : state_(Start), context_(0), handle_(0), readB ensureLibraryInitialized(); context_ = SSL_CTX_new(TLSv1_client_method()); + // TODO: implement CRL checking + // TODO: download CRL (HTTP transport) + // TODO: cache CRL downloads for configurable time period + + // TODO: implement OCSP support + // TODO: handle OCSP stapling see https://www.rfc-editor.org/rfc/rfc4366.txt // Load system certs #if defined(SWIFTEN_PLATFORM_WINDOWS) X509_STORE* store = SSL_CTX_get_cert_store(context_); @@ -236,6 +242,18 @@ Certificate::ref OpenSSLContext::getPeerCertificate() const { } } +std::vector<Certificate::ref> OpenSSLContext::getPeerCertificateChain() const { + std::vector<Certificate::ref> result; + STACK_OF(X509)* chain = SSL_get_peer_cert_chain(handle_); + for (int i = 0; i < sk_X509_num(chain); ++i) { + boost::shared_ptr<X509> x509Cert(X509_dup(sk_X509_value(chain, i)), X509_free); + + Certificate::ref cert = boost::make_shared<OpenSSLCertificate>(x509Cert); + result.push_back(cert); + } + return result; +} + boost::shared_ptr<CertificateVerificationError> OpenSSLContext::getPeerCertificateVerificationError() const { int verifyResult = SSL_get_verify_result(handle_); if (verifyResult != X509_V_OK) { diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h index d8d0d2f..cee4f79 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLContext.h +++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h @@ -28,6 +28,7 @@ namespace Swift { void handleDataFromApplication(const SafeByteArray&); Certificate::ref getPeerCertificate() const; + std::vector<Certificate::ref> getPeerCertificateChain() const; boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const; virtual ByteArray getFinishMessage() const; diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp index 641568d..997d760 100644 --- a/Swiften/TLS/Schannel/SchannelContext.cpp +++ b/Swiften/TLS/Schannel/SchannelContext.cpp @@ -633,6 +633,35 @@ Certificate::ref SchannelContext::getPeerCertificate() const { //------------------------------------------------------------------------ +std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const { + std::vector<Certificate::ref> certificateChain; + ScopedCertContext pServerCert; + ScopedCertContext pIssuerCert; + ScopedCertContext pCurrentCert; + SECURITY_STATUS status = QueryContextAttributes(m_ctxtHandle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset()); + + if (status != SEC_E_OK) { + return certificateChain; + } + certificateChain.push_back(boost::make_shared<SchannelCertificate>(pServerCert)); + + pCurrentCert = pServerCert; + while(pCurrentCert.GetPointer()) { + DWORD dwVerificationFlags = 0; + pIssuerCert = CertGetIssuerCertificateFromStore(pServerCert->hCertStore, pCurrentCert, NULL, &dwVerificationFlags ); + if (!(*pIssuerCert.GetPointer())) { + break; + } + certificateChain.push_back(boost::make_shared<SchannelCertificate>(pIssuerCert)); + + pCurrentCert = pIssuerCert; + pIssuerCert = NULL; + } + return certificateChain; +} + +//------------------------------------------------------------------------ + CertificateVerificationError::ref SchannelContext::getPeerCertificateVerificationError() const { return m_verificationError ? boost::make_shared<CertificateVerificationError>(*m_verificationError) : CertificateVerificationError::ref(); } diff --git a/Swiften/TLS/Schannel/SchannelContext.h b/Swiften/TLS/Schannel/SchannelContext.h index 587d0e7..2d65a8a 100644 --- a/Swiften/TLS/Schannel/SchannelContext.h +++ b/Swiften/TLS/Schannel/SchannelContext.h @@ -51,6 +51,7 @@ namespace Swift virtual void handleDataFromApplication(const SafeByteArray& data); virtual Certificate::ref getPeerCertificate() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const; virtual ByteArray getFinishMessage() const; diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h index 5640fe1..388f8ee 100644 --- a/Swiften/TLS/TLSContext.h +++ b/Swiften/TLS/TLSContext.h @@ -29,6 +29,7 @@ namespace Swift { virtual void handleDataFromApplication(const SafeByteArray&) = 0; virtual Certificate::ref getPeerCertificate() const = 0; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const = 0; virtual ByteArray getFinishMessage() const = 0; |