From f32492bec456866fb5101274e6789efc59a47bdc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 5 Dec 2010 19:06:41 +0100
Subject: Added plumbing for persistent certificate trust checking.


diff --git a/.project b/.project
index 0b4af0a..fcdfcdc 100644
--- a/.project
+++ b/.project
@@ -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();
 }
 
-- 
cgit v0.10.2-6-g49f6