diff --git a/src/backend/corebackendmanager.cpp b/src/backend/corebackendmanager.cpp index cd228be..23c4060 100644 --- a/src/backend/corebackendmanager.cpp +++ b/src/backend/corebackendmanager.cpp @@ -21,12 +21,12 @@ #include "backend/corebackend.h" #include +#include #include #include #include #include #include -#include #include @@ -41,7 +41,6 @@ struct CoreBackendManagerPrivate KAuth::ExecuteJob *m_job; CoreBackend *m_Backend; - QString m_Uuid; QCA::Initializer init; QCA::PrivateKey privateKey; unsigned int counter = 0; @@ -104,8 +103,6 @@ bool CoreBackendManager::startExternalCommandHelper() action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand")); action.setTimeout(10 * 24 * 3600 * 1000); // 10 days QVariantMap arguments; - d->m_Uuid = QUuid::createUuid().toString(); - arguments.insert(QStringLiteral("callerUuid"), Uuid()); arguments.insert(QStringLiteral("pubkey"), pubkey.toDER()); action.setArguments(arguments); d->m_job = action.execute(); @@ -125,8 +122,12 @@ bool CoreBackendManager::startExternalCommandHelper() void CoreBackendManager::stopExternalCommandHelper() { QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); - if (iface.isValid()) - iface.call(QStringLiteral("exit"), CoreBackendManager::self()->Uuid()); + if (iface.isValid()) { + QByteArray request; + request.setNum(++CoreBackendManager::self()->counter()); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + iface.call(QStringLiteral("exit"), d->privateKey.signMessage(hash, QCA::EMSA3_Raw)); + } } KAuth::ExecuteJob* CoreBackendManager::job() @@ -134,11 +135,6 @@ KAuth::ExecuteJob* CoreBackendManager::job() return d->m_job; } -QString& CoreBackendManager::Uuid() -{ - return d->m_Uuid; -} - bool CoreBackendManager::load(const QString& name) { if (backend()) diff --git a/src/backend/corebackendmanager.h b/src/backend/corebackendmanager.h index 70476d7..07c56eb 100644 --- a/src/backend/corebackendmanager.h +++ b/src/backend/corebackendmanager.h @@ -82,11 +82,6 @@ public: */ CoreBackend* backend(); - /** - * @return a pointer to the currently loaded backend - */ - QString& Uuid(); - /** * @return a pointer to the KAuth job */ @@ -95,7 +90,7 @@ public: /** * stop ExternalCommand Helper */ - static void stopExternalCommandHelper(); + void stopExternalCommandHelper(); /**< @return RSA private key used for signing External Command requests. */ QCA::PrivateKey privateKey(); diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index caa4c2c..a560b30 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -129,12 +129,13 @@ bool ExternalCommand::start(int timeout) bool rval = false; if (iface.isValid()) { QByteArray request; - request.setNum(++CoreBackendManager::self()->counter()); + request.setNum(++CoreBackendManager::self()->counter()); request.append(cmd.toUtf8()); for (const auto &argument : qAsConst(d->m_Args)) - request.append(argument.toLocal8Bit()); + request.append(argument.toUtf8()); request.append(d->m_Input); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), @@ -185,9 +186,21 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days if (iface.isValid()) { + QByteArray request; + + request.setNum(++CoreBackendManager::self()->counter()); + request.append(source.path().toUtf8()); + request.append(QByteArray::number(source.firstByte())); + request.append(QByteArray::number(source.length())); + request.append(target.path().toUtf8()); + request.append(QByteArray::number(target.firstByte())); + request.append(QByteArray::number(blockSize)); + + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + // Use asynchronous DBus calls, so that we can process reports and progress QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"), - CoreBackendManager::self()->Uuid(), + CoreBackendManager::self()->privateKey().signMessage(hash, QCA::EMSA3_Raw), source.path(), source.firstByte(), source.length(), target.path(), target.firstByte(), blockSize); diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 02b388c..713167c 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -36,7 +36,6 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) reply.addData(QStringLiteral("success"), false); return reply; } - m_callerUuid = args[QStringLiteral("callerUuid")].toString(); m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); m_Counter = 0; @@ -111,10 +110,23 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr return true; } -bool ExternalCommandHelper::copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) +bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) { - if (!isCallerAuthorized(Uuid)) + QByteArray request; + + request.setNum(++m_Counter); + request.append(sourceDevice.toUtf8()); + request.append(QByteArray::number(sourceFirstByte)); + request.append(QByteArray::number(sourceLength)); + request.append(targetDevice.toUtf8()); + request.append(QByteArray::number(targetFirstByte)); + request.append(QByteArray::number(blockSize)); + + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { + qCritical() << xi18n("Invalid cryptographic signature"); return false; + } const qint64 blocksToCopy = sourceLength / blockSize; qint64 readOffset = sourceFirstByte; @@ -202,7 +214,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr QByteArray request; request.setNum(++m_Counter); - request.append(command.toLocal8Bit()); + request.append(command.toUtf8()); for (const auto &argument : arguments) request.append(argument.toUtf8()); request.append(input); @@ -227,20 +239,15 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr return reply; } -bool ExternalCommandHelper::isCallerAuthorized(const QString& Uuid) +void ExternalCommandHelper::exit(const QByteArray& signature) { - if (Uuid != m_callerUuid) { - qWarning() << "Caller is not authorized"; - return false; + QByteArray request; + request.setNum(++m_Counter); + QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); + if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { + return; } - return true; -} - -void ExternalCommandHelper::exit(const QString& Uuid) -{ - if (!isCallerAuthorized(Uuid)) - return; m_loop.exit(); if (QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface"))) diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index 4795399..818c76c 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -44,15 +44,13 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input); - Q_SCRIPTABLE bool copyblocks(const QString& Uuid, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); - Q_SCRIPTABLE void exit(const QString& Uuid); + Q_SCRIPTABLE bool copyblocks(const QByteArray& signature, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); + Q_SCRIPTABLE void exit(const QByteArray& signature); private: void onReadOutput(); - bool isCallerAuthorized(const QString& Uuid); QEventLoop m_loop; - QString m_callerUuid; QCA::Initializer initializer; QCA::PublicKey m_publicKey; unsigned int m_Counter; diff --git a/test/helpers.cpp b/test/helpers.cpp index e562fce..b89bdd8 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -59,5 +59,5 @@ KPMCoreInitializer::KPMCoreInitializer( const char* backend ) : KPMCoreInitializ KPMCoreInitializer::~KPMCoreInitializer() { - CoreBackendManager::stopExternalCommandHelper(); + CoreBackendManager::self()->stopExternalCommandHelper(); }