diff options
Diffstat (limited to 'Swiften/TLS/SecureTransport/SecureTransportContext.mm')
-rw-r--r-- | Swiften/TLS/SecureTransport/SecureTransportContext.mm | 17 |
1 files changed, 6 insertions, 11 deletions
diff --git a/Swiften/TLS/SecureTransport/SecureTransportContext.mm b/Swiften/TLS/SecureTransport/SecureTransportContext.mm index 2357579..ca6c5bb 100644 --- a/Swiften/TLS/SecureTransport/SecureTransportContext.mm +++ b/Swiften/TLS/SecureTransport/SecureTransportContext.mm @@ -1,32 +1,32 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/TLS/SecureTransport/SecureTransportContext.h> #include <boost/type_traits.hpp> #include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/Log.h> #include <Swiften/TLS/SecureTransport/SecureTransportCertificate.h> #include <Swiften/TLS/PKCS12Certificate.h> #include <Swiften/TLS/CertificateWithKey.h> #include <Cocoa/Cocoa.h> #import <Security/SecCertificate.h> #import <Security/SecImportExport.h> namespace { typedef boost::remove_pointer<CFArrayRef>::type CFArray; typedef boost::remove_pointer<SecTrustRef>::type SecTrust; } template <typename T, typename S> T bridge_cast(S source) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wold-style-cast" return (__bridge T)(source); @@ -243,70 +243,65 @@ void SecureTransportContext::verifyServerCertificate() { error = SecTrustGetResult(trustRef.get(), &trustResult, &certChain, &statusChain); if (error == errSecSuccess) { boost::shared_ptr<CFArray> certChainRef = boost::shared_ptr<CFArray>(certChain, CFRelease); for (CFIndex index = 0; index < CFArrayGetCount(certChainRef.get()); index++) { for (CFIndex n = 0; n < statusChain[index].NumStatusCodes; n++) { // Even though Secure Transport reported CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK on the whole certificate // chain, the actual cause can be that a revocation check for a specific cert returned CSSMERR_TP_CERT_REVOKED. if (!verificationError_ || verificationError_->getType() == CertificateVerificationError::RevocationCheckFailed) { verificationError_ = CSSMErrorToVerificationError(statusChain[index].StatusCodes[n]); } } } } else { } } } else { verificationError_ = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); } break; case kSecTrustResultOtherError: verificationError_ = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError); break; default: SWIFT_LOG(warning) << "Unhandled trust result " << trustResult << "." << std::endl; break; } - if (verificationError_) { - setState(Error); - SSLClose(sslContext_.get()); - sslContext_.reset(); - onError(boost::make_shared<TLSError>()); - } - else { - // proceed with handshake - processHandshake(); - } + // We proceed with the TLS handshake here to give the application an opportunity + // to apply custom validation and trust management. The application is responsible + // to call \ref getPeerCertificateVerificationError directly after the \ref onConnected + // signal is called and before any application data is send to the context. + processHandshake(); } #pragma clang diagnostic pop bool SecureTransportContext::setClientCertificate(CertificateWithKey::ref cert) { CFArrayRef nativeClientChain = CreateClientCertificateChainAsCFArrayRef(cert); if (nativeClientChain) { clientCertificate_ = cert; CFRelease(nativeClientChain); return true; } else { return false; } } void SecureTransportContext::handleDataFromNetwork(const SafeByteArray& data) { SWIFT_LOG(debug) << std::endl; SWIFT_LOG_ASSERT(state_ == HandshakeDone || state_ == Handshake, error) << "current state '" << stateToString(state_) << " invalid." << std::endl; append(readingBuffer_, data); size_t bytesRead = 0; OSStatus error = noErr; SafeByteArray applicationData; switch(state_) { case None: assert(false && "Invalid state 'None'."); break; |