summaryrefslogtreecommitdiffstats
path: root/Swift
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2010-12-05 18:06:41 (GMT)
committerRemko Tronçon <git@el-tramo.be>2010-12-05 18:06:41 (GMT)
commitf32492bec456866fb5101274e6789efc59a47bdc (patch)
tree5fad08517a769afe3943a7dcbfef2c4c2b3ea850 /Swift
parentfc585cd8313fec545b4cdae4fe4fed1f75626409 (diff)
downloadswift-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.cpp61
-rw-r--r--Swift/Controllers/CertificateFileStorage.h31
-rw-r--r--Swift/Controllers/CertificateFileStorageFactory.h28
-rw-r--r--Swift/Controllers/CertificateStorage.cpp14
-rw-r--r--Swift/Controllers/CertificateStorage.h22
-rw-r--r--Swift/Controllers/CertificateStorageFactory.cpp14
-rw-r--r--Swift/Controllers/CertificateStorageFactory.h19
-rw-r--r--Swift/Controllers/CertificateStorageTrustChecker.h34
-rw-r--r--Swift/Controllers/MainController.cpp18
-rw-r--r--Swift/Controllers/MainController.h7
-rw-r--r--Swift/Controllers/SConscript3
-rw-r--r--Swift/QtUI/QtSwift.cpp4
-rw-r--r--Swift/QtUI/QtSwift.h4
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)