summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-09-18 11:40:41 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-09-18 11:40:45 +0200
commita7e7f7fdd2a9d38921476d57f305c9cd4459a556 (patch)
treed9ad3bdc3e275004a54f508025f0d52227ab18cb /common
parentea2e02ad656640c17d520b5a22c168c3c1faef56 (diff)
downloadsink-a7e7f7fdd2a9d38921476d57f305c9cd4459a556.tar.gz
sink-a7e7f7fdd2a9d38921476d57f305c9cd4459a556.zip
Avoid storing the password in the configuration
The password (or any other secret), is now cached in the client process (in-memory only), and delivered to the resource via command. The resource avoids doing any operations against the source until the secret is available.
Diffstat (limited to 'common')
-rw-r--r--common/CMakeLists.txt3
-rw-r--r--common/commands.h1
-rw-r--r--common/commands/secret.fbs7
-rw-r--r--common/domain/applicationdomaintype.h1
-rw-r--r--common/genericresource.cpp7
-rw-r--r--common/genericresource.h2
-rw-r--r--common/listener.cpp12
-rw-r--r--common/resource.cpp5
-rw-r--r--common/resource.h2
-rw-r--r--common/resourceaccess.cpp22
-rw-r--r--common/resourceaccess.h6
-rw-r--r--common/secretstore.cpp51
-rw-r--r--common/secretstore.h50
-rw-r--r--common/synchronizer.cpp18
-rw-r--r--common/synchronizer.h5
15 files changed, 192 insertions, 0 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 8421fc2..b0e0d04 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -33,6 +33,7 @@ set(storage_LIBS lmdb)
33 33
34set(command_SRCS 34set(command_SRCS
35 store.cpp 35 store.cpp
36 secretstore.cpp
36 notifier.cpp 37 notifier.cpp
37 resourcecontrol.cpp 38 resourcecontrol.cpp
38 modelresult.cpp 39 modelresult.cpp
@@ -97,6 +98,7 @@ generate_flatbuffers(
97 commands/revisionreplayed 98 commands/revisionreplayed
98 commands/inspection 99 commands/inspection
99 commands/flush 100 commands/flush
101 commands/secret
100 domain/contact 102 domain/contact
101 domain/addressbook 103 domain/addressbook
102 domain/event 104 domain/event
@@ -144,6 +146,7 @@ install(FILES
144 test.h 146 test.h
145 log.h 147 log.h
146 flush.h 148 flush.h
149 secretstore.h
147 ${CMAKE_CURRENT_BINARY_DIR}/sink_export.h 150 ${CMAKE_CURRENT_BINARY_DIR}/sink_export.h
148 DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME} COMPONENT Devel 151 DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME} COMPONENT Devel
149) 152)
diff --git a/common/commands.h b/common/commands.h
index 1548eac..8ced268 100644
--- a/common/commands.h
+++ b/common/commands.h
@@ -48,6 +48,7 @@ enum CommandIds
48 InspectionCommand, 48 InspectionCommand,
49 RemoveFromDiskCommand, 49 RemoveFromDiskCommand,
50 FlushCommand, 50 FlushCommand,
51 SecretCommand,
51 CustomCommand = 0xffff 52 CustomCommand = 0xffff
52}; 53};
53 54
diff --git a/common/commands/secret.fbs b/common/commands/secret.fbs
new file mode 100644
index 0000000..5bb2246
--- /dev/null
+++ b/common/commands/secret.fbs
@@ -0,0 +1,7 @@
1namespace Sink.Commands;
2
3table Secret {
4 secret: string;
5}
6
7root_type Secret;
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h
index f7fd07e..de2b5c9 100644
--- a/common/domain/applicationdomaintype.h
+++ b/common/domain/applicationdomaintype.h
@@ -102,6 +102,7 @@ enum SINK_EXPORT ErrorCode {
102 ConfigurationError, 102 ConfigurationError,
103 TransmissionError, 103 TransmissionError,
104 ConnectionLostError, 104 ConnectionLostError,
105 MissingCredentialsError
105}; 106};
106 107
107enum SINK_EXPORT SuccessCode { 108enum SINK_EXPORT SuccessCode {
diff --git a/common/genericresource.cpp b/common/genericresource.cpp
index 7178b3d..b6a8f62 100644
--- a/common/genericresource.cpp
+++ b/common/genericresource.cpp
@@ -45,6 +45,13 @@ GenericResource::~GenericResource()
45{ 45{
46} 46}
47 47
48void GenericResource::setSecret(const QString &s)
49{
50 if (mSynchronizer) {
51 mSynchronizer->setSecret(s);
52 }
53}
54
48void GenericResource::setupPreprocessors(const QByteArray &type, const QVector<Sink::Preprocessor *> &preprocessors) 55void GenericResource::setupPreprocessors(const QByteArray &type, const QVector<Sink::Preprocessor *> &preprocessors)
49{ 56{
50 mPipeline->setPreprocessors(type, preprocessors); 57 mPipeline->setPreprocessors(type, preprocessors);
diff --git a/common/genericresource.h b/common/genericresource.h
index bffc697..4e86b75 100644
--- a/common/genericresource.h
+++ b/common/genericresource.h
@@ -47,6 +47,8 @@ public:
47 static void removeFromDisk(const QByteArray &instanceIdentifier); 47 static void removeFromDisk(const QByteArray &instanceIdentifier);
48 static qint64 diskUsage(const QByteArray &instanceIdentifier); 48 static qint64 diskUsage(const QByteArray &instanceIdentifier);
49 49
50 virtual void setSecret(const QString &s) Q_DECL_OVERRIDE;
51
50 //TODO Remove this API, it's only used in tests 52 //TODO Remove this API, it's only used in tests
51 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query); 53 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query);
52 //TODO Remove this API, it's only used in tests 54 //TODO Remove this API, it's only used in tests
diff --git a/common/listener.cpp b/common/listener.cpp
index c9fd9d3..c6747cd 100644
--- a/common/listener.cpp
+++ b/common/listener.cpp
@@ -33,6 +33,7 @@
33#include "common/revisionupdate_generated.h" 33#include "common/revisionupdate_generated.h"
34#include "common/notification_generated.h" 34#include "common/notification_generated.h"
35#include "common/revisionreplayed_generated.h" 35#include "common/revisionreplayed_generated.h"
36#include "common/secret_generated.h"
36 37
37#include <QLocalServer> 38#include <QLocalServer>
38#include <QLocalSocket> 39#include <QLocalSocket>
@@ -240,6 +241,17 @@ void Listener::processCommand(int commandId, uint messageId, const QByteArray &c
240 } 241 }
241 break; 242 break;
242 } 243 }
244 case Sink::Commands::SecretCommand: {
245 flatbuffers::Verifier verifier((const uint8_t *)commandBuffer.constData(), commandBuffer.size());
246 if (Sink::Commands::VerifySecretBuffer(verifier)) {
247 auto buffer = Sink::Commands::GetSecret(commandBuffer.constData());
248 loadResource().setSecret(QString{buffer->secret()->c_str()});
249 } else {
250 SinkWarning() << "received invalid command";
251 }
252 break;
253 }
254
243 case Sink::Commands::SynchronizeCommand: 255 case Sink::Commands::SynchronizeCommand:
244 case Sink::Commands::InspectionCommand: 256 case Sink::Commands::InspectionCommand:
245 case Sink::Commands::DeleteEntityCommand: 257 case Sink::Commands::DeleteEntityCommand:
diff --git a/common/resource.cpp b/common/resource.cpp
index 804f0bf..78cc51b 100644
--- a/common/resource.cpp
+++ b/common/resource.cpp
@@ -51,6 +51,11 @@ void Resource::setLowerBoundRevision(qint64 revision)
51 Q_UNUSED(revision) 51 Q_UNUSED(revision)
52} 52}
53 53
54void Resource::setSecret(const QString &s)
55{
56 Q_UNUSED(s)
57}
58
54 59
55class ResourceFactory::Private 60class ResourceFactory::Private
56{ 61{
diff --git a/common/resource.h b/common/resource.h
index a50ffb5..938f267 100644
--- a/common/resource.h
+++ b/common/resource.h
@@ -47,6 +47,8 @@ public:
47 */ 47 */
48 virtual void setLowerBoundRevision(qint64 revision); 48 virtual void setLowerBoundRevision(qint64 revision);
49 49
50 virtual void setSecret(const QString &s);
51
50signals: 52signals:
51 void revisionUpdated(qint64); 53 void revisionUpdated(qint64);
52 void notify(Notification); 54 void notify(Notification);
diff --git a/common/resourceaccess.cpp b/common/resourceaccess.cpp
index 35fa46c..5ed3609 100644
--- a/common/resourceaccess.cpp
+++ b/common/resourceaccess.cpp
@@ -32,9 +32,11 @@
32#include "common/revisionreplayed_generated.h" 32#include "common/revisionreplayed_generated.h"
33#include "common/inspection_generated.h" 33#include "common/inspection_generated.h"
34#include "common/flush_generated.h" 34#include "common/flush_generated.h"
35#include "common/secret_generated.h"
35#include "common/entitybuffer.h" 36#include "common/entitybuffer.h"
36#include "common/bufferutils.h" 37#include "common/bufferutils.h"
37#include "common/test.h" 38#include "common/test.h"
39#include "common/secretstore.h"
38#include "log.h" 40#include "log.h"
39 41
40#include <QCoreApplication> 42#include <QCoreApplication>
@@ -234,6 +236,12 @@ ResourceAccess::ResourceAccess(const QByteArray &resourceInstanceIdentifier, con
234{ 236{
235 mResourceStatus = Sink::ApplicationDomain::NoStatus; 237 mResourceStatus = Sink::ApplicationDomain::NoStatus;
236 SinkTrace() << "Starting access"; 238 SinkTrace() << "Starting access";
239
240 QObject::connect(&SecretStore::instance(), &SecretStore::secretAvailable, this, [this] (const QByteArray &resourceId) {
241 if (resourceId == d->resourceInstanceIdentifier) {
242 sendSecret(SecretStore::instance().resourceSecret(d->resourceInstanceIdentifier)).exec();
243 }
244 });
237} 245}
238 246
239ResourceAccess::~ResourceAccess() 247ResourceAccess::~ResourceAccess()
@@ -387,6 +395,15 @@ KAsync::Job<void> ResourceAccess::sendFlushCommand(int flushType, const QByteArr
387 return sendCommand(Sink::Commands::FlushCommand, fbb); 395 return sendCommand(Sink::Commands::FlushCommand, fbb);
388} 396}
389 397
398KAsync::Job<void> ResourceAccess::sendSecret(const QString &secret)
399{
400 flatbuffers::FlatBufferBuilder fbb;
401 auto s = fbb.CreateString(secret.toStdString());
402 auto location = Sink::Commands::CreateSecret(fbb, s);
403 Sink::Commands::FinishSecretBuffer(fbb, location);
404 return sendCommand(Sink::Commands::SecretCommand, fbb);
405}
406
390void ResourceAccess::open() 407void ResourceAccess::open()
391{ 408{
392 if (d->socket && d->socket->isValid()) { 409 if (d->socket && d->socket->isValid()) {
@@ -483,6 +500,11 @@ void ResourceAccess::connected()
483 Commands::write(d->socket.data(), ++d->messageId, Commands::HandshakeCommand, fbb); 500 Commands::write(d->socket.data(), ++d->messageId, Commands::HandshakeCommand, fbb);
484 } 501 }
485 502
503 auto secret = SecretStore::instance().resourceSecret(d->resourceInstanceIdentifier);
504 if (!secret.isEmpty()) {
505 sendSecret(secret).exec();
506 }
507
486 // Reenqueue pending commands, we failed to send them 508 // Reenqueue pending commands, we failed to send them
487 processPendingCommandQueue(); 509 processPendingCommandQueue();
488 // Send queued commands 510 // Send queued commands
diff --git a/common/resourceaccess.h b/common/resourceaccess.h
index b6a0b34..890cc6d 100644
--- a/common/resourceaccess.h
+++ b/common/resourceaccess.h
@@ -80,6 +80,11 @@ public:
80 return KAsync::null<void>(); 80 return KAsync::null<void>();
81 } 81 }
82 82
83 virtual KAsync::Job<void> sendSecret(const QString &secret)
84 {
85 return KAsync::null<void>();
86 }
87
83 int getResourceStatus() const 88 int getResourceStatus() const
84 { 89 {
85 return mResourceStatus; 90 return mResourceStatus;
@@ -121,6 +126,7 @@ public:
121 KAsync::Job<void> 126 KAsync::Job<void>
122 sendInspectionCommand(int inspectionType,const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) Q_DECL_OVERRIDE; 127 sendInspectionCommand(int inspectionType,const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expecedValue) Q_DECL_OVERRIDE;
123 KAsync::Job<void> sendFlushCommand(int flushType, const QByteArray &flushId) Q_DECL_OVERRIDE; 128 KAsync::Job<void> sendFlushCommand(int flushType, const QByteArray &flushId) Q_DECL_OVERRIDE;
129 KAsync::Job<void> sendSecret(const QString &secret) Q_DECL_OVERRIDE;
124 /** 130 /**
125 * Tries to connect to server, and returns a connected socket on success. 131 * Tries to connect to server, and returns a connected socket on success.
126 */ 132 */
diff --git a/common/secretstore.cpp b/common/secretstore.cpp
new file mode 100644
index 0000000..39d5206
--- /dev/null
+++ b/common/secretstore.cpp
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "secretstore.h"
22
23#include <QGlobalStatic>
24#include <QMap>
25#include <QString>
26#include <QMutexLocker>
27
28using namespace Sink;
29
30QMutex SecretStore::sMutex;
31
32SecretStore &SecretStore::instance()
33{
34 static SecretStore s;
35 return s;
36}
37
38void SecretStore::insert(const QByteArray &resourceId, const QString &secret)
39{
40 QMutexLocker locker{&sMutex};
41 mCache.insert(resourceId, secret);
42 locker.unlock();
43 emit secretAvailable(resourceId);
44}
45
46QString SecretStore::resourceSecret(const QByteArray &resourceId)
47{
48 QMutexLocker locker{&sMutex};
49 return mCache.value(resourceId);
50}
51
diff --git a/common/secretstore.h b/common/secretstore.h
new file mode 100644
index 0000000..04fdaba
--- /dev/null
+++ b/common/secretstore.h
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#pragma once
22
23#include "sink_export.h"
24
25#include <QObject>
26#include <QString>
27#include <QMap>
28#include <QMutex>
29
30namespace Sink {
31
32class SINK_EXPORT SecretStore : public QObject
33{
34 Q_OBJECT
35public:
36 static SecretStore &instance();
37
38 void insert(const QByteArray &resourceId, const QString &secret);
39 QString resourceSecret(const QByteArray &resourceId);
40
41Q_SIGNALS:
42 void secretAvailable(const QByteArray &resourceId);
43
44private:
45 QMap<QByteArray, QString> mCache;
46 static QMutex sMutex;
47};
48
49}
50
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp
index 959cf48..4a0ac46 100644
--- a/common/synchronizer.cpp
+++ b/common/synchronizer.cpp
@@ -49,6 +49,20 @@ Synchronizer::~Synchronizer()
49 49
50} 50}
51 51
52void Synchronizer::setSecret(const QString &s)
53{
54 mSecret = s;
55
56 if (!mSyncRequestQueue.isEmpty()) {
57 processSyncQueue().exec();
58 }
59}
60
61QString Synchronizer::secret() const
62{
63 return mSecret;
64}
65
52void Synchronizer::setup(const std::function<void(int commandId, const QByteArray &data)> &enqueueCommandCallback, MessageQueue &mq) 66void Synchronizer::setup(const std::function<void(int commandId, const QByteArray &data)> &enqueueCommandCallback, MessageQueue &mq)
53{ 67{
54 mEnqueue = enqueueCommandCallback; 68 mEnqueue = enqueueCommandCallback;
@@ -474,6 +488,10 @@ void Synchronizer::setBusy(bool busy, const QString &reason, const QByteArray re
474 488
475KAsync::Job<void> Synchronizer::processSyncQueue() 489KAsync::Job<void> Synchronizer::processSyncQueue()
476{ 490{
491 if (secret().isEmpty()) {
492 SinkLogCtx(mLogCtx) << "Secret not available but required.";
493 return KAsync::null<void>();
494 }
477 if (mSyncRequestQueue.isEmpty()) { 495 if (mSyncRequestQueue.isEmpty()) {
478 SinkLogCtx(mLogCtx) << "All requests processed."; 496 SinkLogCtx(mLogCtx) << "All requests processed.";
479 return KAsync::null<void>(); 497 return KAsync::null<void>();
diff --git a/common/synchronizer.h b/common/synchronizer.h
index cc082be..bd03ba3 100644
--- a/common/synchronizer.h
+++ b/common/synchronizer.h
@@ -60,6 +60,8 @@ public:
60 bool allChangesReplayed() Q_DECL_OVERRIDE; 60 bool allChangesReplayed() Q_DECL_OVERRIDE;
61 void flushComplete(const QByteArray &flushId); 61 void flushComplete(const QByteArray &flushId);
62 62
63 void setSecret(const QString &s);
64
63signals: 65signals:
64 void notify(Notification); 66 void notify(Notification);
65 67
@@ -78,6 +80,8 @@ protected:
78 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 80 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
79 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); 81 virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &);
80protected: 82protected:
83 QString secret() const;
84
81 ///Calls the callback to enqueue the command 85 ///Calls the callback to enqueue the command
82 void enqueueCommand(int commandId, const QByteArray &data); 86 void enqueueCommand(int commandId, const QByteArray &data);
83 87
@@ -224,6 +228,7 @@ private:
224 MessageQueue *mMessageQueue; 228 MessageQueue *mMessageQueue;
225 bool mSyncInProgress; 229 bool mSyncInProgress;
226 QMultiHash<QByteArray, SyncRequest> mPendingSyncRequests; 230 QMultiHash<QByteArray, SyncRequest> mPendingSyncRequests;
231 QString mSecret;
227}; 232};
228 233
229} 234}