Merge branch 'master' of github.com:hanzz/libtransport
This commit is contained in:
commit
5c5cd0e346
5 changed files with 573 additions and 1 deletions
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Isode Limited.
|
||||
* All rights reserved.
|
||||
* See the COPYING file for more information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Security/SecureTransport.h>
|
||||
#include <Swiften/TLS/TLSError.h>
|
||||
#include "Swiften/TLS/TLSServerContext.h"
|
||||
|
||||
namespace Swift {
|
||||
|
||||
class SecureTransportServerContext : public TLSServerContext {
|
||||
public:
|
||||
SecureTransportServerContext(bool checkCertificateRevocation);
|
||||
virtual ~SecureTransportServerContext();
|
||||
|
||||
virtual void connect();
|
||||
|
||||
virtual bool setClientCertificate(CertificateWithKey::ref cert);
|
||||
|
||||
virtual void handleDataFromNetwork(const SafeByteArray&);
|
||||
virtual void handleDataFromApplication(const SafeByteArray&);
|
||||
|
||||
virtual std::vector<Certificate::ref> getPeerCertificateChain() const;
|
||||
virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const;
|
||||
|
||||
virtual ByteArray getFinishMessage() const;
|
||||
|
||||
private:
|
||||
static OSStatus SSLSocketReadCallback(SSLConnectionRef connection, void *data, size_t *dataLength);
|
||||
static OSStatus SSLSocketWriteCallback(SSLConnectionRef connection, const void *data, size_t *dataLength);
|
||||
|
||||
private:
|
||||
enum State { None, Handshake, HandshakeDone, Error};
|
||||
static std::string stateToString(State state);
|
||||
void setState(State newState);
|
||||
|
||||
static boost::shared_ptr<TLSError> nativeToTLSError(OSStatus error);
|
||||
boost::shared_ptr<CertificateVerificationError> CSSMErrorToVerificationError(OSStatus resultCode);
|
||||
|
||||
void processHandshake();
|
||||
void verifyServerCertificate();
|
||||
|
||||
void fatalError(boost::shared_ptr<TLSError> error, boost::shared_ptr<CertificateVerificationError> certificateError);
|
||||
|
||||
private:
|
||||
boost::shared_ptr<SSLContext> sslContext_;
|
||||
SafeByteArray readingBuffer_;
|
||||
State state_;
|
||||
CertificateVerificationError::ref verificationError_;
|
||||
CertificateWithKey::ref clientCertificate_;
|
||||
bool checkCertificateRevocation_;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,500 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Isode Limited.
|
||||
* All rights reserved.
|
||||
* See the COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include <Swiften/TLS/SecureTransport/SecureTransportServerContext.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);
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
namespace Swift {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
CFArrayRef CreateClientCertificateChainAsCFArrayRef(CertificateWithKey::ref key) {
|
||||
boost::shared_ptr<PKCS12Certificate> pkcs12 = boost::dynamic_pointer_cast<PKCS12Certificate>(key);
|
||||
if (!key) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SafeByteArray safePassword = pkcs12->getPassword();
|
||||
CFIndex passwordSize = 0;
|
||||
try {
|
||||
passwordSize = boost::numeric_cast<CFIndex>(safePassword.size());
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFMutableArrayRef certChain = CFArrayCreateMutable(NULL, 0, 0);
|
||||
|
||||
OSStatus securityError = errSecSuccess;
|
||||
CFStringRef password = CFStringCreateWithBytes(kCFAllocatorDefault, safePassword.data(), passwordSize, kCFStringEncodingUTF8, false);
|
||||
const void* keys[] = { kSecImportExportPassphrase };
|
||||
const void* values[] = { password };
|
||||
|
||||
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
|
||||
|
||||
CFArrayRef items = NULL;
|
||||
CFDataRef pkcs12Data = bridge_cast<CFDataRef>([NSData dataWithBytes: static_cast<const void *>(pkcs12->getData().data()) length:pkcs12->getData().size()]);
|
||||
securityError = SecPKCS12Import(pkcs12Data, options, &items);
|
||||
CFRelease(options);
|
||||
NSArray* nsItems = bridge_cast<NSArray*>(items);
|
||||
|
||||
switch(securityError) {
|
||||
case errSecSuccess:
|
||||
break;
|
||||
case errSecAuthFailed:
|
||||
// Password did not work for decoding the certificate.
|
||||
SWIFT_LOG(warning) << "Invalid password." << std::endl;
|
||||
break;
|
||||
case errSecDecode:
|
||||
// Other decoding error.
|
||||
SWIFT_LOG(warning) << "PKCS12 decoding error." << std::endl;
|
||||
break;
|
||||
default:
|
||||
SWIFT_LOG(warning) << "Unknown error." << std::endl;
|
||||
}
|
||||
|
||||
if (securityError != errSecSuccess) {
|
||||
if (items) {
|
||||
CFRelease(items);
|
||||
items = NULL;
|
||||
}
|
||||
CFRelease(certChain);
|
||||
certChain = NULL;
|
||||
}
|
||||
|
||||
if (certChain) {
|
||||
CFArrayAppendValue(certChain, nsItems[0][@"identity"]);
|
||||
|
||||
for (CFIndex index = 0; index < CFArrayGetCount(bridge_cast<CFArrayRef>(nsItems[0][@"chain"])); index++) {
|
||||
CFArrayAppendValue(certChain, CFArrayGetValueAtIndex(bridge_cast<CFArrayRef>(nsItems[0][@"chain"]), index));
|
||||
}
|
||||
}
|
||||
return certChain;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SecureTransportContext::SecureTransportServerContext(bool checkCertificateRevocation) : state_(None), checkCertificateRevocation_(checkCertificateRevocation) {
|
||||
sslContext_ = boost::shared_ptr<SSLContext>(SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType), CFRelease);
|
||||
|
||||
OSStatus error = noErr;
|
||||
// set IO callbacks
|
||||
error = SSLSetIOFuncs(sslContext_.get(), &SecureTransportContext::SSLSocketReadCallback, &SecureTransportContext::SSLSocketWriteCallback);
|
||||
if (error != noErr) {
|
||||
SWIFT_LOG(error) << "Unable to set IO functions to SSL context." << std::endl;
|
||||
sslContext_.reset();
|
||||
}
|
||||
|
||||
error = SSLSetConnection(sslContext_.get(), this);
|
||||
if (error != noErr) {
|
||||
SWIFT_LOG(error) << "Unable to set connection to SSL context." << std::endl;
|
||||
sslContext_.reset();
|
||||
}
|
||||
|
||||
|
||||
error = SSLSetSessionOption(sslContext_.get(), kSSLSessionOptionBreakOnServerAuth, true);
|
||||
if (error != noErr) {
|
||||
SWIFT_LOG(error) << "Unable to set kSSLSessionOptionBreakOnServerAuth on session." << std::endl;
|
||||
sslContext_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
SecureTransportServerContext::~SecureTransportServerContext() {
|
||||
if (sslContext_) {
|
||||
SSLClose(sslContext_.get());
|
||||
}
|
||||
}
|
||||
|
||||
std::string SecureTransportContext::stateToString(State state) {
|
||||
std::string returnValue;
|
||||
switch(state) {
|
||||
case Handshake:
|
||||
returnValue = "Handshake";
|
||||
break;
|
||||
case HandshakeDone:
|
||||
returnValue = "HandshakeDone";
|
||||
break;
|
||||
case None:
|
||||
returnValue = "None";
|
||||
break;
|
||||
case Error:
|
||||
returnValue = "Error";
|
||||
break;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void SecureTransportServerContext::setState(State newState) {
|
||||
SWIFT_LOG(debug) << "Switch state from " << stateToString(state_) << " to " << stateToString(newState) << "." << std::endl;
|
||||
state_ = newState;
|
||||
}
|
||||
|
||||
void SecureTransportServerContext::connect() {
|
||||
SWIFT_LOG_ASSERT(state_ == None, error) << "current state '" << stateToString(state_) << " invalid." << std::endl;
|
||||
if (clientCertificate_) {
|
||||
CFArrayRef certs = CreateClientCertificateChainAsCFArrayRef(clientCertificate_);
|
||||
if (certs) {
|
||||
boost::shared_ptr<CFArray> certRefs(certs, CFRelease);
|
||||
OSStatus result = SSLSetCertificate(sslContext_.get(), certRefs.get());
|
||||
if (result != noErr) {
|
||||
SWIFT_LOG(error) << "SSLSetCertificate failed with error " << result << "." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
processHandshake();
|
||||
}
|
||||
|
||||
void SecureTransportServerContext::processHandshake() {
|
||||
SWIFT_LOG_ASSERT(state_ == None || state_ == Handshake, error) << "current state '" << stateToString(state_) << " invalid." << std::endl;
|
||||
OSStatus error = SSLHandshake(sslContext_.get());
|
||||
if (error == errSSLWouldBlock) {
|
||||
setState(Handshake);
|
||||
}
|
||||
else if (error == noErr) {
|
||||
SWIFT_LOG(debug) << "TLS handshake successful." << std::endl;
|
||||
setState(HandshakeDone);
|
||||
onConnected();
|
||||
}
|
||||
else if (error == errSSLPeerAuthCompleted) {
|
||||
SWIFT_LOG(debug) << "Received server certificate. Start verification." << std::endl;
|
||||
setState(Handshake);
|
||||
verifyServerCertificate();
|
||||
}
|
||||
else {
|
||||
SWIFT_LOG(debug) << "Error returned from SSLHandshake call is " << error << "." << std::endl;
|
||||
fatalError(nativeToTLSError(error), boost::make_shared<CertificateVerificationError>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
void SecureTransportServerContext::verifyServerCertificate() {
|
||||
SecTrustRef trust = NULL;
|
||||
OSStatus error = SSLCopyPeerTrust(sslContext_.get(), &trust);
|
||||
if (error != noErr) {
|
||||
fatalError(boost::make_shared<TLSError>(), boost::make_shared<CertificateVerificationError>());
|
||||
return;
|
||||
}
|
||||
boost::shared_ptr<SecTrust> trustRef = boost::shared_ptr<SecTrust>(trust, CFRelease);
|
||||
|
||||
if (checkCertificateRevocation_) {
|
||||
error = SecTrustSetOptions(trust, kSecTrustOptionRequireRevPerCert | kSecTrustOptionFetchIssuerFromNet);
|
||||
if (error != noErr) {
|
||||
fatalError(boost::make_shared<TLSError>(), boost::make_shared<CertificateVerificationError>());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SecTrustResultType trustResult;
|
||||
error = SecTrustEvaluate(trust, &trustResult);
|
||||
if (error != errSecSuccess) {
|
||||
fatalError(boost::make_shared<TLSError>(), boost::make_shared<CertificateVerificationError>());
|
||||
return;
|
||||
}
|
||||
|
||||
OSStatus cssmResult = 0;
|
||||
switch(trustResult) {
|
||||
case kSecTrustResultUnspecified:
|
||||
SWIFT_LOG(warning) << "Successful implicit validation. Result unspecified." << std::endl;
|
||||
break;
|
||||
case kSecTrustResultProceed:
|
||||
SWIFT_LOG(warning) << "Validation resulted in explicitly trusted." << std::endl;
|
||||
break;
|
||||
case kSecTrustResultRecoverableTrustFailure:
|
||||
SWIFT_LOG(warning) << "recoverable trust failure" << std::endl;
|
||||
error = SecTrustGetCssmResultCode(trust, &cssmResult);
|
||||
if (error == errSecSuccess) {
|
||||
verificationError_ = CSSMErrorToVerificationError(cssmResult);
|
||||
if (cssmResult == CSSMERR_TP_VERIFY_ACTION_FAILED || cssmResult == CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK ) {
|
||||
// Find out the reason why the verification failed.
|
||||
CFArrayRef certChain;
|
||||
CSSM_TP_APPLE_EVIDENCE_INFO* statusChain;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
bool SecureTransportServerContext::setClientCertificate(CertificateWithKey::ref cert) {
|
||||
CFArrayRef nativeClientChain = CreateClientCertificateChainAsCFArrayRef(cert);
|
||||
if (nativeClientChain) {
|
||||
clientCertificate_ = cert;
|
||||
CFRelease(nativeClientChain);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SecureTransportServerContext::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;
|
||||
case Handshake:
|
||||
processHandshake();
|
||||
break;
|
||||
case HandshakeDone:
|
||||
while (error == noErr) {
|
||||
applicationData.resize(readingBuffer_.size());
|
||||
error = SSLRead(sslContext_.get(), applicationData.data(), applicationData.size(), &bytesRead);
|
||||
if (error == noErr) {
|
||||
// Read successful.
|
||||
}
|
||||
else if (error == errSSLWouldBlock) {
|
||||
// Secure Transport does not want more data.
|
||||
break;
|
||||
}
|
||||
else {
|
||||
SWIFT_LOG(error) << "SSLRead failed with error " << error << ", read bytes: " << bytesRead << "." << std::endl;
|
||||
fatalError(boost::make_shared<TLSError>(), boost::make_shared<CertificateVerificationError>());
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytesRead > 0) {
|
||||
applicationData.resize(bytesRead);
|
||||
onDataForApplication(applicationData);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Error:
|
||||
SWIFT_LOG(debug) << "Igoring received data in error state." << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SecureTransportServerContext::handleDataFromApplication(const SafeByteArray& data) {
|
||||
size_t processedBytes = 0;
|
||||
OSStatus error = SSLWrite(sslContext_.get(), data.data(), data.size(), &processedBytes);
|
||||
switch(error) {
|
||||
case errSSLWouldBlock:
|
||||
SWIFT_LOG(warning) << "Unexpected because the write callback does not block." << std::endl;
|
||||
return;
|
||||
case errSSLClosedGraceful:
|
||||
case noErr:
|
||||
return;
|
||||
default:
|
||||
SWIFT_LOG(warning) << "SSLWrite returned error code: " << error << ", processed bytes: " << processedBytes << std::endl;
|
||||
fatalError(boost::make_shared<TLSError>(), boost::shared_ptr<CertificateVerificationError>());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Certificate::ref> SecureTransportServerContext::getPeerCertificateChain() const {
|
||||
std::vector<Certificate::ref> peerCertificateChain;
|
||||
|
||||
if (sslContext_) {
|
||||
typedef boost::remove_pointer<SecTrustRef>::type SecTrust;
|
||||
boost::shared_ptr<SecTrust> securityTrust;
|
||||
|
||||
SecTrustRef secTrust = NULL;;
|
||||
OSStatus error = SSLCopyPeerTrust(sslContext_.get(), &secTrust);
|
||||
if (error == noErr) {
|
||||
securityTrust = boost::shared_ptr<SecTrust>(secTrust, CFRelease);
|
||||
|
||||
CFIndex chainSize = SecTrustGetCertificateCount(securityTrust.get());
|
||||
for (CFIndex n = 0; n < chainSize; n++) {
|
||||
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(securityTrust.get(), n);
|
||||
if (certificate) {
|
||||
peerCertificateChain.push_back(boost::make_shared<SecureTransportCertificate>(certificate));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
SWIFT_LOG(warning) << "Failed to obtain peer trust structure; error = " << error << "." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return peerCertificateChain;
|
||||
}
|
||||
|
||||
CertificateVerificationError::ref SecureTransportServerContext::getPeerCertificateVerificationError() const {
|
||||
return verificationError_;
|
||||
}
|
||||
|
||||
ByteArray SecureTransportServerContext::getFinishMessage() const {
|
||||
SWIFT_LOG(warning) << "Access to TLS handshake finish message is not part of OS X Secure Transport APIs." << std::endl;
|
||||
return ByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* This I/O callback simulates an asynchronous read to the read buffer of the context. If it is empty, it returns errSSLWouldBlock; else
|
||||
* the data within the buffer is returned.
|
||||
*/
|
||||
OSStatus SecureTransportServerContext::SSLSocketReadCallback(SSLConnectionRef connection, void *data, size_t *dataLength) {
|
||||
SecureTransportContext* context = const_cast<SecureTransportContext*>(static_cast<const SecureTransportContext*>(connection));
|
||||
OSStatus retValue = noErr;
|
||||
|
||||
if (context->readingBuffer_.size() < *dataLength) {
|
||||
// Would block because Secure Transport is trying to read more data than there currently is available in the buffer.
|
||||
*dataLength = 0;
|
||||
retValue = errSSLWouldBlock;
|
||||
}
|
||||
else {
|
||||
size_t bufferLen = *dataLength;
|
||||
size_t copyToBuffer = bufferLen < context->readingBuffer_.size() ? bufferLen : context->readingBuffer_.size();
|
||||
|
||||
memcpy(data, context->readingBuffer_.data(), copyToBuffer);
|
||||
|
||||
context->readingBuffer_ = SafeByteArray(context->readingBuffer_.data() + copyToBuffer, context->readingBuffer_.data() + context->readingBuffer_.size());
|
||||
*dataLength = copyToBuffer;
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
OSStatus SecureTransportServerContext::SSLSocketWriteCallback(SSLConnectionRef connection, const void *data, size_t *dataLength) {
|
||||
SecureTransportContext* context = const_cast<SecureTransportContext*>(static_cast<const SecureTransportContext*>(connection));
|
||||
OSStatus retValue = noErr;
|
||||
|
||||
SafeByteArray safeData;
|
||||
safeData.resize(*dataLength);
|
||||
memcpy(safeData.data(), data, safeData.size());
|
||||
|
||||
context->onDataForNetwork(safeData);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
boost::shared_ptr<TLSError> SecureTransportServerContext::nativeToTLSError(OSStatus /* error */) {
|
||||
boost::shared_ptr<TLSError> swiftenError;
|
||||
swiftenError = boost::make_shared<TLSError>();
|
||||
return swiftenError;
|
||||
}
|
||||
|
||||
boost::shared_ptr<CertificateVerificationError> SecureTransportServerContext::CSSMErrorToVerificationError(OSStatus resultCode) {
|
||||
boost::shared_ptr<CertificateVerificationError> error;
|
||||
switch(resultCode) {
|
||||
case CSSMERR_TP_NOT_TRUSTED:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_NOT_TRUSTED" << std::endl;
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::Untrusted);
|
||||
break;
|
||||
case CSSMERR_TP_CERT_NOT_VALID_YET:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_CERT_NOT_VALID_YET" << std::endl;
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::NotYetValid);
|
||||
break;
|
||||
case CSSMERR_TP_CERT_EXPIRED:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_CERT_EXPIRED" << std::endl;
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::Expired);
|
||||
break;
|
||||
case CSSMERR_TP_CERT_REVOKED:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_CERT_REVOKED" << std::endl;
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::Revoked);
|
||||
break;
|
||||
case CSSMERR_TP_VERIFY_ACTION_FAILED:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_TP_VERIFY_ACTION_FAILED" << std::endl;
|
||||
break;
|
||||
case CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK" << std::endl;
|
||||
if (checkCertificateRevocation_) {
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::RevocationCheckFailed);
|
||||
}
|
||||
break;
|
||||
case CSSMERR_APPLETP_OCSP_UNAVAILABLE:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_APPLETP_OCSP_UNAVAILABLE" << std::endl;
|
||||
if (checkCertificateRevocation_) {
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::RevocationCheckFailed);
|
||||
}
|
||||
break;
|
||||
case CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE:
|
||||
SWIFT_LOG(debug) << "CSSM result code: CSSMERR_APPLETP_SSL_BAD_EXT_KEY_USE" << std::endl;
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidPurpose);
|
||||
break;
|
||||
default:
|
||||
SWIFT_LOG(warning) << "unhandled CSSM error: " << resultCode << ", CSSM_TP_BASE_TP_ERROR: " << CSSM_TP_BASE_TP_ERROR << std::endl;
|
||||
error = boost::make_shared<CertificateVerificationError>(CertificateVerificationError::UnknownError);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void SecureTransportServerContext::fatalError(boost::shared_ptr<TLSError> error, boost::shared_ptr<CertificateVerificationError> certificateError) {
|
||||
setState(Error);
|
||||
if (sslContext_) {
|
||||
SSLClose(sslContext_.get());
|
||||
}
|
||||
verificationError_ = certificateError;
|
||||
onError(error);
|
||||
}
|
||||
|
||||
}
|
|
@ -37,6 +37,9 @@
|
|||
#include <Swiften/TLS/CAPICertificate.h>
|
||||
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
|
||||
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
|
||||
#elif defined(__APPLE__) && HAVE_SWIFTEN_3
|
||||
#include <Swiften/TLS/SecureTransport/SecureTransportCertificate.h>
|
||||
#include <Swiften/TLS/SecureTransport/SecureTransportServerContext.h>
|
||||
#else
|
||||
#include "Swiften/TLS/PKCS12Certificate.h"
|
||||
#include "Swiften/TLS/CertificateWithKey.h"
|
||||
|
@ -87,12 +90,14 @@ void XMPPFrontend::init(Component *transport, Swift::EventLoop *loop, Swift::Net
|
|||
m_server = new Swift::Server(loop, factories, userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
|
||||
if (!CONFIG_STRING(m_config, "service.cert").empty()) {
|
||||
#ifndef _WIN32
|
||||
#ifndef __APPLE__
|
||||
//TODO: fix
|
||||
LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
|
||||
LOG4CXX_INFO(logger, "SSLv23_server_method used.");
|
||||
TLSServerContextFactory *f = new OpenSSLServerContextFactory();
|
||||
CertificateWithKey::ref certificate = boost::make_shared<PKCS12Certificate>(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password")));
|
||||
m_server->addTLSEncryption(f, certificate);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "transport/Frontend.h"
|
||||
|
||||
#include <vector>
|
||||
#include <Swiften/Version.h>
|
||||
#define HAVE_SWIFTEN_3 (SWIFTEN_VERSION >= 0x030000)
|
||||
#include "Swiften/Server/Server.h"
|
||||
#include "Swiften/Disco/GetDiscoInfoRequest.h"
|
||||
#include "Swiften/Disco/EntityCapsManager.h"
|
||||
|
|
|
@ -4,9 +4,16 @@ FILE(GLOB_RECURSE SWIFTEN_SRC ../include/Swiften/*.cpp)
|
|||
|
||||
# Build without openssl on msvc
|
||||
if (NOT MSVC)
|
||||
string(REGEX REPLACE "[^;]+;?/Schannel/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
|
||||
if (APPLE)
|
||||
string(REGEX REPLACE "[^;]+;?/Schannel/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
|
||||
string(REGEX REPLACE "[^;]+;?/OpenSSL/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
|
||||
else()
|
||||
string(REGEX REPLACE "[^;]+;?/Schannel/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
|
||||
string(REGEX REPLACE "[^;]+;?/SecureTransport/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
|
||||
endif()
|
||||
else()
|
||||
string(REGEX REPLACE "[^;]+;?/OpenSSL/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
|
||||
string(REGEX REPLACE "[^;]+;?/SecureTransport/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}")
|
||||
endif()
|
||||
|
||||
FILE(GLOB HEADERS ../include/transport/*.h)
|
||||
|
|
Loading…
Add table
Reference in a new issue