summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/TLS/OpenSSL/OpenSSLContext.cpp')
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContext.cpp141
1 files changed, 85 insertions, 56 deletions
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
index 6dd75d6..86b0504 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
@@ -121,52 +121,57 @@ OpenSSLContext::OpenSSLContext(const TLSOptions& options, Mode mode) : mode_(mod
// TODO: implement OCSP support
// TODO: handle OCSP stapling see https://www.rfc-editor.org/rfc/rfc4366.txt
- // Load system certs
+
+ // Default for ignoreSystemTrustAnchors is false, i.e. load System TAs by default,
+ // to preserve previous behaviour
+ if (!options.ignoreSystemTrustAnchors) {
+ // Load system certs
#if defined(SWIFTEN_PLATFORM_WINDOWS)
- X509_STORE* store = SSL_CTX_get_cert_store(context_.get());
- HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT");
- if (systemStore) {
- PCCERT_CONTEXT certContext = nullptr;
- while (true) {
- certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, certContext);
- if (!certContext) {
- break;
- }
- OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded));
- if (store && cert.getInternalX509()) {
- X509_STORE_add_cert(store, cert.getInternalX509().get());
+ X509_STORE* store = SSL_CTX_get_cert_store(context_.get());
+ HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT");
+ if (systemStore) {
+ PCCERT_CONTEXT certContext = nullptr;
+ while (true) {
+ certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, certContext);
+ if (!certContext) {
+ break;
+ }
+ OpenSSLCertificate cert(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded));
+ if (store && cert.getInternalX509()) {
+ X509_STORE_add_cert(store, cert.getInternalX509().get());
+ }
}
}
- }
#elif !defined(SWIFTEN_PLATFORM_MACOSX)
- SSL_CTX_set_default_verify_paths(context_.get());
+ SSL_CTX_set_default_verify_paths(context_.get());
#elif defined(SWIFTEN_PLATFORM_MACOSX) && !defined(SWIFTEN_PLATFORM_IPHONE)
- // On Mac OS X 10.5 (OpenSSL < 0.9.8), OpenSSL does not automatically look in the system store.
- // On Mac OS X 10.6 (OpenSSL >= 0.9.8), OpenSSL *does* look in the system store to determine trust.
- // However, if there is a certificate error, it will always emit the "Invalid CA" error if we didn't add
- // the certificates first. See
- // http://opensource.apple.com/source/OpenSSL098/OpenSSL098-27/src/crypto/x509/x509_vfy_apple.c
- // to understand why. We therefore add all certs from the system store ourselves.
- X509_STORE* store = SSL_CTX_get_cert_store(context_.get());
- CFArrayRef anchorCertificates;
- if (SecTrustCopyAnchorCertificates(&anchorCertificates) == 0) {
- for (int i = 0; i < CFArrayGetCount(anchorCertificates); ++i) {
- SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(anchorCertificates, i)));
- CSSM_DATA certCSSMData;
- if (SecCertificateGetData(cert, &certCSSMData) != 0 || certCSSMData.Length == 0) {
- continue;
- }
- std::vector<unsigned char> certData;
- certData.resize(certCSSMData.Length);
- memcpy(&certData[0], certCSSMData.Data, certCSSMData.Length);
- OpenSSLCertificate certificate(certData);
- if (store && certificate.getInternalX509()) {
- X509_STORE_add_cert(store, certificate.getInternalX509().get());
+ // On Mac OS X 10.5 (OpenSSL < 0.9.8), OpenSSL does not automatically look in the system store.
+ // On Mac OS X 10.6 (OpenSSL >= 0.9.8), OpenSSL *does* look in the system store to determine trust.
+ // However, if there is a certificate error, it will always emit the "Invalid CA" error if we didn't add
+ // the certificates first. See
+ // http://opensource.apple.com/source/OpenSSL098/OpenSSL098-27/src/crypto/x509/x509_vfy_apple.c
+ // to understand why. We therefore add all certs from the system store ourselves.
+ X509_STORE* store = SSL_CTX_get_cert_store(context_.get());
+ CFArrayRef anchorCertificates;
+ if (SecTrustCopyAnchorCertificates(&anchorCertificates) == 0) {
+ for (int i = 0; i < CFArrayGetCount(anchorCertificates); ++i) {
+ SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(const_cast<void*>(CFArrayGetValueAtIndex(anchorCertificates, i)));
+ CSSM_DATA certCSSMData;
+ if (SecCertificateGetData(cert, &certCSSMData) != 0 || certCSSMData.Length == 0) {
+ continue;
+ }
+ std::vector<unsigned char> certData;
+ certData.resize(certCSSMData.Length);
+ memcpy(&certData[0], certCSSMData.Data, certCSSMData.Length);
+ OpenSSLCertificate certificate(certData);
+ if (store && certificate.getInternalX509()) {
+ X509_STORE_add_cert(store, certificate.getInternalX509().get());
+ }
}
+ CFRelease(anchorCertificates);
}
- CFRelease(anchorCertificates);
- }
#endif
+ }
configure(options);
}
@@ -202,7 +207,7 @@ static int certVerifyCallback(X509_STORE_CTX* store_ctx, void* arg)
if (cb != nullptr) {
ret = cb(static_cast<const OpenSSLContext*>(context));
} else {
- SWIFT_LOG(warning) << "certVerifyCallback called but context.verifyCertCallback is unset" << std::endl;
+ SWIFT_LOG(debug) << "certVerifyCallback called but context.verifyCertCallback is unset";
ret = 0;
}
@@ -245,12 +250,12 @@ static int verifyCallback(int preverifyOk, X509_STORE_CTX* ctx)
SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
SSL_CTX* sslctx = ssl ? SSL_get_SSL_CTX(ssl) : nullptr;
if (!sslctx) {
- SWIFT_LOG(error) << "verifyCallback: internal error" << std::endl;
+ SWIFT_LOG(debug) << "verifyCallback: internal error";
return preverifyOk;
}
if (SSL_CTX_get_verify_mode(sslctx) == SSL_VERIFY_NONE) {
- SWIFT_LOG(info) << "verifyCallback: no verification required" << std::endl;
+ SWIFT_LOG(debug) << "verifyCallback: no verification required";
// No verification requested
return 1;
}
@@ -281,14 +286,18 @@ static int verifyCallback(int preverifyOk, X509_STORE_CTX* ctx)
X509_NAME* issuerName = X509_get_issuer_name(errCert);
issuerString = X509_NAME_to_text(issuerName);
}
- SWIFT_LOG(error) << "verifyCallback: verification error" <<
- X509_verify_cert_error_string(err) << " depth: " <<
- depth << " issuer: " << ((issuerString.length() > 0) ? issuerString : "<unknown>") << std::endl;
- } else {
- SWIFT_LOG(info) << "verifyCallback: SSL depth: " << depth << " Subject: " <<
- ((subjectString.length() > 0) ? subjectString : "<>") << std::endl;
- }
- return preverifyOk;
+ SWIFT_LOG(debug) << "verifyCallback: verification error " <<
+ X509_verify_cert_error_string(err) << " depth: " <<
+ depth << " issuer: " << ((issuerString.length() > 0) ? issuerString : "<unknown>");
+ } else {
+ SWIFT_LOG(debug) << "verifyCallback: SSL depth: " << depth << " Subject: " <<
+ ((subjectString.length() > 0) ? subjectString : "<>");
+ }
+ // Always return "OK", as check on verification status
+ // will be performed once TLS handshake has completed,
+ // by calling OpenSSLContext::getVerificationErrorTypeForResult() to
+ // get the value set via X509_STORE_CTX_set_error() above.
+ return 1;
}
bool OpenSSLContext::configure(const TLSOptions &options)
@@ -296,7 +305,7 @@ bool OpenSSLContext::configure(const TLSOptions &options)
if (options.cipherSuites) {
std::string cipherSuites = *(options.cipherSuites);
if (SSL_CTX_set_cipher_list(context_.get(), cipherSuites.c_str()) != 1 ) {
- SWIFT_LOG(error) << "Failed to set cipher-suites" << std::endl;
+ SWIFT_LOG(debug) << "Failed to set cipher-suites";
return false;
}
}
@@ -307,7 +316,7 @@ bool OpenSSLContext::configure(const TLSOptions &options)
if (SSL_CTX_set_session_id_context(context_.get(),
reinterpret_cast<const unsigned char *>(contextId.c_str()),
contextId.length()) != 1) {
- SWIFT_LOG(error) << "Failed to set context-id" << std::endl;
+ SWIFT_LOG(debug) << "Failed to set context-id";
return false;
}
}
@@ -315,12 +324,12 @@ bool OpenSSLContext::configure(const TLSOptions &options)
if (options.sessionCacheTimeout) {
int scto = *options.sessionCacheTimeout;
if (scto <= 0) {
- SWIFT_LOG(error) << "Invalid value for session-cache-timeout" << std::endl;
+ SWIFT_LOG(debug) << "Invalid value for session-cache-timeout";
return false;
}
(void)SSL_CTX_set_timeout(context_.get(), scto);
if (SSL_CTX_get_timeout(context_.get()) != scto) {
- SWIFT_LOG(error) << "Failed to set session-cache-timeout" << std::endl;
+ SWIFT_LOG(debug) << "Failed to set session-cache-timeout";
return false;
}
}
@@ -362,7 +371,7 @@ bool OpenSSLContext::configure(const TLSOptions &options)
if (options.verifyDepth) {
int depth = *options.verifyDepth;
if (depth <= 0) {
- SWIFT_LOG(error) << "Invalid value for verify-depth" << std::endl;
+ SWIFT_LOG(debug) << "Invalid value for verify-depth";
return false;
}
@@ -584,7 +593,7 @@ void OpenSSLContext::sendPendingDataToApplication() {
bool OpenSSLContext::setCertificateChain(const std::vector<std::shared_ptr<Certificate>>& certificateChain) {
if (certificateChain.size() == 0) {
- SWIFT_LOG(warning) << "Trying to load empty certificate chain." << std::endl;
+ SWIFT_LOG(debug) << "Trying to load empty certificate chain.";
return false;
}
@@ -607,7 +616,7 @@ bool OpenSSLContext::setCertificateChain(const std::vector<std::shared_ptr<Certi
}
if (SSL_CTX_add_extra_chain_cert(context_.get(), openSSLCert->getInternalX509().get()) != 1) {
- SWIFT_LOG(warning) << "Trying to load empty certificate chain." << std::endl;
+ SWIFT_LOG(debug) << "Trying to load empty certificate chain.";
return false;
}
// Have to manually increment reference count as SSL_CTX_add_extra_chain_cert does not do so
@@ -746,13 +755,33 @@ bool OpenSSLContext::setDiffieHellmanParameters(const ByteArray& parametersInOpe
std::vector<Certificate::ref> OpenSSLContext::getPeerCertificateChain() const {
std::vector<Certificate::ref> result;
+
+ // When this context is a server, the peer (client) certificate
+ // is obtained via SSL_get_peer_certificate, and any other
+ // certificates set by the peer are available via SSL_get_peer_cert_chain.
+ // When this context is a client, all of the server's certificates are
+ // obtained using SSL_get_peer_cert_chain
+ if (mode_ == Mode::Server) {
+ auto cert = SSL_get_peer_certificate(handle_.get());
+ if (cert) {
+ // Do not need to copy the returned cert as SSL_get_peer_certificate
+ // increments the reference count on the certificate
+ std::shared_ptr<X509> x509Cert(cert, X509_free);
+ Certificate::ref cert = std::make_shared<OpenSSLCertificate>(x509Cert);
+ result.push_back(cert);
+ }
+ }
+
STACK_OF(X509)* chain = SSL_get_peer_cert_chain(handle_.get());
for (int i = 0; i < sk_X509_num(chain); ++i) {
+ // Here we do need to copy the returned cert, since SSL_get_peer_cert_chain
+ // does not increment the reference count on each certificate
std::shared_ptr<X509> x509Cert(X509_dup(sk_X509_value(chain, i)), X509_free);
Certificate::ref cert = std::make_shared<OpenSSLCertificate>(x509Cert);
result.push_back(cert);
}
+
return result;
}