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 | |
parent | fc585cd8313fec545b4cdae4fe4fed1f75626409 (diff) | |
download | swift-contrib-f32492bec456866fb5101274e6789efc59a47bdc.zip swift-contrib-f32492bec456866fb5101274e6789efc59a47bdc.tar.bz2 |
Added plumbing for persistent certificate trust checking.
Diffstat (limited to 'Swift')
-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 |
13 files changed, 257 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 = [ 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) |