diff options
| -rw-r--r-- | .project | 8 | ||||
| -rw-r--r-- | BuildTools/Eclipse/Swift (Mac OS X).launch | 2 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateFileStorage.cpp | 61 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateFileStorage.h | 31 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateFileStorageFactory.h | 28 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateStorage.cpp | 14 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateStorage.h | 22 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateStorageFactory.cpp | 14 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateStorageFactory.h | 19 | ||||
| -rw-r--r-- | Swift/Controllers/CertificateStorageTrustChecker.h | 34 | ||||
| -rw-r--r-- | Swift/Controllers/MainController.cpp | 18 | ||||
| -rw-r--r-- | Swift/Controllers/MainController.h | 7 | ||||
| -rw-r--r-- | Swift/Controllers/SConscript | 3 | ||||
| -rw-r--r-- | Swift/QtUI/QtSwift.cpp | 4 | ||||
| -rw-r--r-- | Swift/QtUI/QtSwift.h | 4 | ||||
| -rw-r--r-- | Swiften/Client/ClientSession.cpp | 2 | ||||
| -rw-r--r-- | Swiften/TLS/BlindCertificateTrustChecker.h | 2 | ||||
| -rw-r--r-- | Swiften/TLS/CertificateTrustChecker.h | 2 | ||||
| -rw-r--r-- | Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp | 8 | 
19 files changed, 269 insertions, 14 deletions
| @@ -18,7 +18,7 @@  				</dictionary>  				<dictionary>  					<key>org.eclipse.cdt.make.core.autoBuildTarget</key> -					<value>doc=1 Documentation/SwiftenDevelopersGuide</value> +					<value></value>  				</dictionary>  				<dictionary>  					<key>org.eclipse.cdt.make.core.buildArguments</key> @@ -29,10 +29,6 @@  					<value>python</value>  				</dictionary>  				<dictionary> -					<key>org.eclipse.cdt.make.core.buildLocation</key> -					<value></value> -				</dictionary> -				<dictionary>  					<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>  					<value>-c</value>  				</dictionary> @@ -54,7 +50,7 @@  				</dictionary>  				<dictionary>  					<key>org.eclipse.cdt.make.core.fullBuildTarget</key> -					<value>doc=1 Documentation/SwiftenDevelopersGuide</value> +					<value></value>  				</dictionary>  				<dictionary>  					<key>org.eclipse.cdt.make.core.stopOnError</key> diff --git a/BuildTools/Eclipse/Swift (Mac OS X).launch b/BuildTools/Eclipse/Swift (Mac OS X).launch index e515972..1dc569f 100644 --- a/BuildTools/Eclipse/Swift (Mac OS X).launch +++ b/BuildTools/Eclipse/Swift (Mac OS X).launch @@ -17,7 +17,7 @@  <stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_STOP_AT_MAIN_SYMBOL" value="main"/>  <stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="Swift/QtUI/Swift.app/Contents/MacOS/Swift"/>  <stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="swift"/> -<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="0.980756260"/> +<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="0.980756260.1834106966.226646757"/>  <booleanAttribute key="org.eclipse.cdt.launch.use_terminal" value="true"/>  <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">  <listEntry value="/swift"/> diff --git a/Swift/Controllers/CertificateFileStorage.cpp b/Swift/Controllers/CertificateFileStorage.cpp new file mode 100644 index 0000000..65da1ec --- /dev/null +++ b/Swift/Controllers/CertificateFileStorage.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/Controllers/CertificateFileStorage.h> + +#include <iostream> +#include <boost/filesystem/fstream.hpp> + +#include <Swiften/StringCodecs/SHA1.h> +#include <Swiften/StringCodecs/Hexify.h> +#include <Swiften/TLS/CertificateFactory.h> +#include <Swiften/Base/Log.h> + +namespace Swift { + +CertificateFileStorage::CertificateFileStorage(const boost::filesystem::path& path, CertificateFactory* certificateFactory) : path(path), certificateFactory(certificateFactory) { +} + +bool CertificateFileStorage::hasCertificate(Certificate::ref certificate) const { +	boost::filesystem::path certificatePath = getCertificatePath(certificate); +	if (boost::filesystem::exists(certificatePath)) { +		ByteArray data; +		data.readFromFile(certificatePath.string()); +		Certificate::ref storedCertificate = certificateFactory->createCertificateFromDER(data); +		if (storedCertificate && storedCertificate->toDER() == certificate->toDER()) { +			return true; +		} +		else { +			SWIFT_LOG(warning) << "Stored certificate does not match received certificate" << std::endl; +			return false; +		} +	} +	else { +		return false; +	} +} + +void CertificateFileStorage::addCertificate(Certificate::ref certificate) { +	boost::filesystem::path certificatePath = getCertificatePath(certificate); +	if (!boost::filesystem::exists(certificatePath.parent_path())) { +		try { +			boost::filesystem::create_directories(certificatePath.parent_path()); +		} +		catch (const boost::filesystem::filesystem_error& e) { +			std::cerr << "ERROR: " << e.what() << std::endl; +		} +	} +	boost::filesystem::ofstream file(certificatePath, boost::filesystem::ofstream::binary|boost::filesystem::ofstream::out); +	ByteArray data = certificate->toDER(); +	file.write(data.getData(), data.getSize()); +	file.close(); +} + +boost::filesystem::path CertificateFileStorage::getCertificatePath(Certificate::ref certificate) const { +	return path / Hexify::hexify(SHA1::getHash(certificate->toDER())).getUTF8String(); +} + +} diff --git a/Swift/Controllers/CertificateFileStorage.h b/Swift/Controllers/CertificateFileStorage.h new file mode 100644 index 0000000..2b853ed --- /dev/null +++ b/Swift/Controllers/CertificateFileStorage.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/filesystem.hpp> + +#include "Swift/Controllers/CertificateStorage.h" + +namespace Swift { +	class CertificateFactory; + +	class CertificateFileStorage : public CertificateStorage { +		public: +			CertificateFileStorage(const boost::filesystem::path& path, CertificateFactory* certificateFactory); + +			virtual bool hasCertificate(Certificate::ref certificate) const; +			virtual void addCertificate(Certificate::ref certificate); + +		private: +			boost::filesystem::path getCertificatePath(Certificate::ref certificate) const; + +		private: +			boost::filesystem::path path; +			CertificateFactory* certificateFactory; +	}; + +} diff --git a/Swift/Controllers/CertificateFileStorageFactory.h b/Swift/Controllers/CertificateFileStorageFactory.h new file mode 100644 index 0000000..bcac56d --- /dev/null +++ b/Swift/Controllers/CertificateFileStorageFactory.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swift/Controllers/CertificateStorageFactory.h> +#include <Swift/Controllers/CertificateFileStorage.h> + +namespace Swift { +	class CertificateFactory; + +	class CertificateFileStorageFactory : public CertificateStorageFactory { +		public: +			CertificateFileStorageFactory(const boost::filesystem::path& basePath, CertificateFactory* certificateFactory) : basePath(basePath), certificateFactory(certificateFactory) {} + +			virtual CertificateStorage* createCertificateStorage(const JID& profile) const { +				boost::filesystem::path profilePath = basePath / profile.toString().getUTF8String(); +				return new CertificateFileStorage(profilePath / "certificates", certificateFactory); +			} + +		private: +			boost::filesystem::path basePath; +			CertificateFactory* certificateFactory; +	}; +} diff --git a/Swift/Controllers/CertificateStorage.cpp b/Swift/Controllers/CertificateStorage.cpp new file mode 100644 index 0000000..343fccd --- /dev/null +++ b/Swift/Controllers/CertificateStorage.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "Swift/Controllers/CertificateStorage.h" + +namespace Swift { + +CertificateStorage::~CertificateStorage() { +} + +} diff --git a/Swift/Controllers/CertificateStorage.h b/Swift/Controllers/CertificateStorage.h new file mode 100644 index 0000000..f8c6fb5 --- /dev/null +++ b/Swift/Controllers/CertificateStorage.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/filesystem.hpp> + +#include <Swiften/TLS/Certificate.h> + +namespace Swift { +	class CertificateStorage { +		public: +			virtual ~CertificateStorage(); + +			virtual bool hasCertificate(Certificate::ref certificate) const = 0; +			virtual void addCertificate(Certificate::ref certificate) = 0; +	}; + +} diff --git a/Swift/Controllers/CertificateStorageFactory.cpp b/Swift/Controllers/CertificateStorageFactory.cpp new file mode 100644 index 0000000..613a8c3 --- /dev/null +++ b/Swift/Controllers/CertificateStorageFactory.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <Swift/Controllers/CertificateStorageFactory.h> + +namespace Swift { + +CertificateStorageFactory::~CertificateStorageFactory() { +} + +} diff --git a/Swift/Controllers/CertificateStorageFactory.h b/Swift/Controllers/CertificateStorageFactory.h new file mode 100644 index 0000000..5b85757 --- /dev/null +++ b/Swift/Controllers/CertificateStorageFactory.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +namespace Swift { +	class CertificateStorage; +	class JID; + +	class CertificateStorageFactory { +		public: +			virtual ~CertificateStorageFactory(); + +			virtual CertificateStorage* createCertificateStorage(const JID& profile) const = 0; +	}; +} diff --git a/Swift/Controllers/CertificateStorageTrustChecker.h b/Swift/Controllers/CertificateStorageTrustChecker.h new file mode 100644 index 0000000..f33287c --- /dev/null +++ b/Swift/Controllers/CertificateStorageTrustChecker.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <Swiften/TLS/CertificateTrustChecker.h> +#include <Swift/Controllers/CertificateStorage.h> + +namespace Swift { +	/** +	 * A certificate trust checker that trusts certificates in a certificate storage. +	 */ +	class CertificateStorageTrustChecker : public CertificateTrustChecker { +		public: +			CertificateStorageTrustChecker(CertificateStorage* storage) : storage(storage) { +			} + +			virtual bool isCertificateTrusted(Certificate::ref certificate) { +				lastCertificate = certificate; +				return storage->hasCertificate(certificate); +			} + +			Certificate::ref getLastCertificate() const { +				return lastCertificate; +			} + +		private: +			CertificateStorage* storage; +			Certificate::ref lastCertificate; +	}; +} diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 8d78671..878ed9b 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -55,6 +55,8 @@  #include "Swift/Controllers/UIEvents/RequestChatUIEvent.h"  #include "Swift/Controllers/UIEvents/ToggleNotificationsUIEvent.h"  #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h" +#include "Swift/Controllers/CertificateStorageFactory.h" +#include "Swift/Controllers/CertificateStorageTrustChecker.h"  namespace Swift { @@ -76,6 +78,7 @@ MainController::MainController(  		ChatListWindowFactory* chatListWindowFactory,  		MUCSearchWindowFactory* mucSearchWindowFactory,  		StoragesFactory* storagesFactory, +		CertificateStorageFactory* certificateStorageFactory,  		Dock* dock,  		Notifier* notifier,  		bool useDelayForLatency) : @@ -83,6 +86,7 @@ MainController::MainController(  			networkFactories_(eventLoop),  			idleDetector_(&idleQuerier_, networkFactories_.getTimerFactory(), 100),  			storagesFactory_(storagesFactory), +			certificateStorageFactory_(certificateStorageFactory),  			chatWindowFactory_(chatWindowFactory),  			mainWindowFactory_(mainWindowFactory),  			loginWindowFactory_(loginWindowFactory), @@ -90,6 +94,7 @@ MainController::MainController(  			loginWindow_(NULL) ,  			useDelayForLatency_(useDelayForLatency) {  	storages_ = NULL; +	certificateStorage_ = NULL;  	statusTracker_ = NULL;  	client_ = NULL;  	presenceNotifier_ = NULL; @@ -182,6 +187,8 @@ void MainController::resetClient() {  	presenceNotifier_ = NULL;  	delete client_;  	client_ = NULL; +	delete certificateStorage_; +	certificateStorage_ = NULL;  	delete storages_;  	storages_ = NULL;  	delete statusTracker_; @@ -353,7 +360,11 @@ void MainController::performLoginFromCachedCredentials() {  	}  	if (!client_) {  		storages_ = storagesFactory_->createStorages(jid_); +		certificateStorage_ = certificateStorageFactory_->createCertificateStorage(jid_); +		certificateTrustChecker_ = new CertificateStorageTrustChecker(certificateStorage_);  		client_ = new Swift::Client(eventLoop_, &networkFactories_, jid_, password_, storages_); +		client_->setCertificateTrustChecker(certificateTrustChecker_); +		// FIXME: Remove this line to activate the trust checker  		client_->setAlwaysTrustCertificates();  		client_->onDataRead.connect(boost::bind(&XMLConsoleController::handleDataRead, xmlConsoleController_, _1));  		client_->onDataWritten.connect(boost::bind(&XMLConsoleController::handleDataWritten, xmlConsoleController_, _1)); @@ -427,8 +438,11 @@ void MainController::handleDisconnected(const boost::optional<ClientError>& erro  			case ClientError::InvalidCertificateSignatureError:  			case ClientError::InvalidCAError:  			case ClientError::InvalidServerIdentityError: -				// TODO -				message = "Certificate error"; break; +				// FIXME: Popup a dialog +				message = "Certificate error"; +				// FIXME: Only do this if the user accepts the certificate +				//certificateStorage_->addCertificate(certificateTrustChecker_->getLastCertificate()); +				break;  		}  		if (!rosterController_) { //hasn't been logged in yet  			signOut(); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 8f7298b..1256345 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -33,6 +33,9 @@ namespace Swift {  	class ChatWindowFactory;  	class ChatController;  	class ChatsManager; +	class CertificateStorageFactory; +	class CertificateStorage; +	class CertificateStorageTrustChecker;  	class ChatListWindowFactory;  	class EventController;  	class MainWindowFactory; @@ -77,6 +80,7 @@ namespace Swift {  					ChatListWindowFactory* chatListWindowFactory_,  					MUCSearchWindowFactory* mucSearchWindowFactory,  					StoragesFactory* storagesFactory, +					CertificateStorageFactory* certificateStorageFactory,  					Dock* dock,  					Notifier* notifier,  					bool useDelayForLatency); @@ -115,6 +119,9 @@ namespace Swift {  			ActualIdleDetector idleDetector_;  			StoragesFactory* storagesFactory_;  			Storages* storages_; +			CertificateStorageFactory* certificateStorageFactory_; +			CertificateStorage* certificateStorage_; +			CertificateStorageTrustChecker* certificateTrustChecker_;  			Client* client_;  			ChatWindowFactory* chatWindowFactory_;  			MainWindowFactory* mainWindowFactory_; diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index d8b2781..9cd2be4 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -41,6 +41,9 @@ if env["SCONS_STAGE"] == "build" :  			"UIInterfaces/XMLConsoleWidget.cpp",  			"UIInterfaces/ChatListWindow.cpp",  			"PreviousStatusStore.cpp", +			"CertificateStorageFactory.cpp", +			"CertificateStorage.cpp", +			"CertificateFileStorage.cpp",  		])  	env.Append(UNITTEST_SOURCES = [ diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index f33706a..2890357 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -24,6 +24,7 @@  #include <QSplitter>  #include <Swiften/Base/Log.h> +#include <Swift/Controllers/CertificateFileStorageFactory.h>  #include "SwifTools/Application/PlatformApplicationPathProvider.h"  #include "Swiften/Avatars/AvatarFileStorage.h"  #include "Swiften/Disco/CapsFileStorage.h" @@ -102,6 +103,7 @@ QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) {  	settings_ = new QtSettingsProvider();  	applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME);  	storagesFactory_ = new FileStoragesFactory(applicationPathProvider_->getDataDir()); +	certificateStorageFactory_ = new CertificateFileStorageFactory(applicationPathProvider_->getDataDir(), tlsFactories_.getCertificateFactory());  	chatWindowFactory_ = new QtChatWindowFactory(splitter_, settings_, tabs_, "");  	soundPlayer_ = new QtSoundPlayer(applicationPathProvider_);  #if defined(HAVE_GROWL) @@ -153,6 +155,7 @@ QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) {  				chatListWindowFactory,  				mucSearchWindowFactory,  				storagesFactory_, +				certificateStorageFactory_,  				dock_,  				notifier_,  				options.count("latency-debug") > 0); @@ -200,6 +203,7 @@ QtSwift::~QtSwift() {  	foreach (QtChatListWindowFactory* factory, chatListWindowFactories_) {  		delete factory;  	} +	delete certificateStorageFactory_;  	delete storagesFactory_;  } diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h index 6817734..a41e2d1 100644 --- a/Swift/QtUI/QtSwift.h +++ b/Swift/QtUI/QtSwift.h @@ -9,6 +9,7 @@  #include <boost/program_options/variables_map.hpp>  #include <boost/program_options/options_description.hpp> +#include <Swiften/TLS/PlatformTLSFactories.h>  #include "Swiften/Base/String.h"  #include "Swiften/Base/Platform.h"  #include "Swiften/EventLoop/Qt/QtEventLoop.h" @@ -28,6 +29,7 @@ namespace po = boost::program_options;  class QSplitter;  namespace Swift { +	class CertificateStorageFactory;  	class Dock;  	class Notifier;  	class StoragesFactory; @@ -54,6 +56,7 @@ namespace Swift {  			static po::options_description getOptionsDescription();  			~QtSwift();  		private: +			PlatformTLSFactories tlsFactories_;  			std::vector<MainController*> mainControllers_;  			QtChatWindowFactory *chatWindowFactory_;  			std::vector<QtMainWindowFactory*> rosterWindowFactories_; @@ -71,6 +74,7 @@ namespace Swift {  			QtChatTabs* tabs_;  			ApplicationPathProvider* applicationPathProvider_;  			StoragesFactory* storagesFactory_; +			CertificateStorageFactory* certificateStorageFactory_;  			AutoUpdater* autoUpdater_;  			Notifier* notifier_;  #if defined(SWIFTEN_PLATFORM_MACOSX) diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index 9e6db5d..13816d3 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -346,7 +346,7 @@ void ClientSession::handleTLSEncrypted() {  }  void ClientSession::checkTrustOrFinish(Certificate::ref certificate, boost::shared_ptr<CertificateVerificationError> error) { -	if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificate, localJID.getDomain())) { +	if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificate)) {  		continueAfterTLSEncrypted();  	}  	else { diff --git a/Swiften/TLS/BlindCertificateTrustChecker.h b/Swiften/TLS/BlindCertificateTrustChecker.h index fc7fbe8..d9db14c 100644 --- a/Swiften/TLS/BlindCertificateTrustChecker.h +++ b/Swiften/TLS/BlindCertificateTrustChecker.h @@ -19,7 +19,7 @@ namespace Swift {  	 */  	class BlindCertificateTrustChecker : public CertificateTrustChecker {  		public: -			virtual bool isCertificateTrusted(Certificate::ref, const String&) { +			virtual bool isCertificateTrusted(Certificate::ref) {  				return true;  			}  	}; diff --git a/Swiften/TLS/CertificateTrustChecker.h b/Swiften/TLS/CertificateTrustChecker.h index 7400dac..c248e4a 100644 --- a/Swiften/TLS/CertificateTrustChecker.h +++ b/Swiften/TLS/CertificateTrustChecker.h @@ -24,6 +24,6 @@ namespace Swift {  			 * trusted. This usually happens when a certificate's validation  			 * fails, to check whether to proceed with the connection or not.  			 */ -			virtual bool isCertificateTrusted(Certificate::ref certificate, const String& domain) = 0; +			virtual bool isCertificateTrusted(Certificate::ref certificate) = 0;  	};  } diff --git a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp index 347d6ef..6a3d688 100644 --- a/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp +++ b/Swiften/TLS/OpenSSL/OpenSSLCertificate.cpp @@ -4,9 +4,10 @@   * See Documentation/Licenses/GPLv3.txt for more information.   */ -#include "Swiften/TLS/OpenSSL/OpenSSLCertificate.h" +#include <Swiften/TLS/OpenSSL/OpenSSLCertificate.h> -#include "Swiften/Base/ByteArray.h" +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Log.h>  #undef X509_NAME // Windows.h defines this, and  for some reason, it doesn't get undeffed properly in x509.h  #include <openssl/x509v3.h> @@ -27,6 +28,9 @@ OpenSSLCertificate::OpenSSLCertificate(const ByteArray& der) {  	const unsigned char* p = reinterpret_cast<const unsigned char*>(der.getData());  #endif  	cert = boost::shared_ptr<X509>(d2i_X509(NULL, &p, der.getSize()), X509_free); +	if (!cert) { +		SWIFT_LOG(warning) << "Error creating certificate from DER data" << std::endl; +	}  	parse();  } | 
 Swift
 Swift