diff options
| author | Remko Tronçon <git@el-tramo.be> | 2010-12-05 18:06:41 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2010-12-05 18:06:41 (GMT) | 
| commit | f32492bec456866fb5101274e6789efc59a47bdc (patch) | |
| tree | 5fad08517a769afe3943a7dcbfef2c4c2b3ea850 /Swift/Controllers | |
| parent | fc585cd8313fec545b4cdae4fe4fed1f75626409 (diff) | |
| download | swift-f32492bec456866fb5101274e6789efc59a47bdc.zip swift-f32492bec456866fb5101274e6789efc59a47bdc.tar.bz2 | |
Added plumbing for persistent certificate trust checking.
Diffstat (limited to 'Swift/Controllers')
| -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 | 
11 files changed, 249 insertions, 2 deletions
| 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 = [ | 
 Swift
 Swift