Cryptographically sign copyblocks and exit KAuth helper calls.
This commit is contained in:
parent
6b558f49d8
commit
231bfbd331
|
@ -21,12 +21,12 @@
|
||||||
#include "backend/corebackend.h"
|
#include "backend/corebackend.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QCryptographicHash>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDBusInterface>
|
#include <QDBusInterface>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QUuid>
|
|
||||||
|
|
||||||
#include <QtCrypto>
|
#include <QtCrypto>
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ struct CoreBackendManagerPrivate
|
||||||
KAuth::ExecuteJob *m_job;
|
KAuth::ExecuteJob *m_job;
|
||||||
CoreBackend *m_Backend;
|
CoreBackend *m_Backend;
|
||||||
|
|
||||||
QString m_Uuid;
|
|
||||||
QCA::Initializer init;
|
QCA::Initializer init;
|
||||||
QCA::PrivateKey privateKey;
|
QCA::PrivateKey privateKey;
|
||||||
unsigned int counter = 0;
|
unsigned int counter = 0;
|
||||||
|
@ -104,8 +103,6 @@ bool CoreBackendManager::startExternalCommandHelper()
|
||||||
action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand"));
|
action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand"));
|
||||||
action.setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
action.setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
||||||
QVariantMap arguments;
|
QVariantMap arguments;
|
||||||
d->m_Uuid = QUuid::createUuid().toString();
|
|
||||||
arguments.insert(QStringLiteral("callerUuid"), Uuid());
|
|
||||||
arguments.insert(QStringLiteral("pubkey"), pubkey.toDER());
|
arguments.insert(QStringLiteral("pubkey"), pubkey.toDER());
|
||||||
action.setArguments(arguments);
|
action.setArguments(arguments);
|
||||||
d->m_job = action.execute();
|
d->m_job = action.execute();
|
||||||
|
@ -125,8 +122,12 @@ bool CoreBackendManager::startExternalCommandHelper()
|
||||||
void CoreBackendManager::stopExternalCommandHelper()
|
void CoreBackendManager::stopExternalCommandHelper()
|
||||||
{
|
{
|
||||||
QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus());
|
QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus());
|
||||||
if (iface.isValid())
|
if (iface.isValid()) {
|
||||||
iface.call(QStringLiteral("exit"), CoreBackendManager::self()->Uuid());
|
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()
|
KAuth::ExecuteJob* CoreBackendManager::job()
|
||||||
|
@ -134,11 +135,6 @@ KAuth::ExecuteJob* CoreBackendManager::job()
|
||||||
return d->m_job;
|
return d->m_job;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString& CoreBackendManager::Uuid()
|
|
||||||
{
|
|
||||||
return d->m_Uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CoreBackendManager::load(const QString& name)
|
bool CoreBackendManager::load(const QString& name)
|
||||||
{
|
{
|
||||||
if (backend())
|
if (backend())
|
||||||
|
|
|
@ -82,11 +82,6 @@ public:
|
||||||
*/
|
*/
|
||||||
CoreBackend* backend();
|
CoreBackend* backend();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a pointer to the currently loaded backend
|
|
||||||
*/
|
|
||||||
QString& Uuid();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a pointer to the KAuth job
|
* @return a pointer to the KAuth job
|
||||||
*/
|
*/
|
||||||
|
@ -95,7 +90,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* stop ExternalCommand Helper
|
* stop ExternalCommand Helper
|
||||||
*/
|
*/
|
||||||
static void stopExternalCommandHelper();
|
void stopExternalCommandHelper();
|
||||||
|
|
||||||
/**< @return RSA private key used for signing External Command requests. */
|
/**< @return RSA private key used for signing External Command requests. */
|
||||||
QCA::PrivateKey privateKey();
|
QCA::PrivateKey privateKey();
|
||||||
|
|
|
@ -129,12 +129,13 @@ bool ExternalCommand::start(int timeout)
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
if (iface.isValid()) {
|
if (iface.isValid()) {
|
||||||
QByteArray request;
|
QByteArray request;
|
||||||
request.setNum(++CoreBackendManager::self()->counter());
|
|
||||||
|
|
||||||
|
request.setNum(++CoreBackendManager::self()->counter());
|
||||||
request.append(cmd.toUtf8());
|
request.append(cmd.toUtf8());
|
||||||
for (const auto &argument : qAsConst(d->m_Args))
|
for (const auto &argument : qAsConst(d->m_Args))
|
||||||
request.append(argument.toLocal8Bit());
|
request.append(argument.toUtf8());
|
||||||
request.append(d->m_Input);
|
request.append(d->m_Input);
|
||||||
|
|
||||||
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512);
|
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512);
|
||||||
|
|
||||||
QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"),
|
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());
|
QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus());
|
||||||
iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
iface.setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
||||||
if (iface.isValid()) {
|
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
|
// Use asynchronous DBus calls, so that we can process reports and progress
|
||||||
QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"),
|
QDBusPendingCall pcall= iface.asyncCall(QStringLiteral("copyblocks"),
|
||||||
CoreBackendManager::self()->Uuid(),
|
CoreBackendManager::self()->privateKey().signMessage(hash, QCA::EMSA3_Raw),
|
||||||
source.path(), source.firstByte(), source.length(),
|
source.path(), source.firstByte(), source.length(),
|
||||||
target.path(), target.firstByte(), blockSize);
|
target.path(), target.firstByte(), blockSize);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args)
|
||||||
reply.addData(QStringLiteral("success"), false);
|
reply.addData(QStringLiteral("success"), false);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
m_callerUuid = args[QStringLiteral("callerUuid")].toString();
|
|
||||||
m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray());
|
m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray());
|
||||||
m_Counter = 0;
|
m_Counter = 0;
|
||||||
|
|
||||||
|
@ -111,10 +110,23 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr
|
||||||
return true;
|
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;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const qint64 blocksToCopy = sourceLength / blockSize;
|
const qint64 blocksToCopy = sourceLength / blockSize;
|
||||||
qint64 readOffset = sourceFirstByte;
|
qint64 readOffset = sourceFirstByte;
|
||||||
|
@ -202,7 +214,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr
|
||||||
|
|
||||||
QByteArray request;
|
QByteArray request;
|
||||||
request.setNum(++m_Counter);
|
request.setNum(++m_Counter);
|
||||||
request.append(command.toLocal8Bit());
|
request.append(command.toUtf8());
|
||||||
for (const auto &argument : arguments)
|
for (const auto &argument : arguments)
|
||||||
request.append(argument.toUtf8());
|
request.append(argument.toUtf8());
|
||||||
request.append(input);
|
request.append(input);
|
||||||
|
@ -227,20 +239,15 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalCommandHelper::isCallerAuthorized(const QString& Uuid)
|
void ExternalCommandHelper::exit(const QByteArray& signature)
|
||||||
{
|
{
|
||||||
if (Uuid != m_callerUuid) {
|
QByteArray request;
|
||||||
qWarning() << "Caller is not authorized";
|
request.setNum(++m_Counter);
|
||||||
return false;
|
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();
|
m_loop.exit();
|
||||||
|
|
||||||
if (QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface")))
|
if (QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface")))
|
||||||
|
|
|
@ -44,15 +44,13 @@ public:
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
ActionReply init(const QVariantMap& args);
|
ActionReply init(const QVariantMap& args);
|
||||||
Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input);
|
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 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 QString& Uuid);
|
Q_SCRIPTABLE void exit(const QByteArray& signature);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onReadOutput();
|
void onReadOutput();
|
||||||
bool isCallerAuthorized(const QString& Uuid);
|
|
||||||
|
|
||||||
QEventLoop m_loop;
|
QEventLoop m_loop;
|
||||||
QString m_callerUuid;
|
|
||||||
QCA::Initializer initializer;
|
QCA::Initializer initializer;
|
||||||
QCA::PublicKey m_publicKey;
|
QCA::PublicKey m_publicKey;
|
||||||
unsigned int m_Counter;
|
unsigned int m_Counter;
|
||||||
|
|
|
@ -59,5 +59,5 @@ KPMCoreInitializer::KPMCoreInitializer( const char* backend ) : KPMCoreInitializ
|
||||||
|
|
||||||
KPMCoreInitializer::~KPMCoreInitializer()
|
KPMCoreInitializer::~KPMCoreInitializer()
|
||||||
{
|
{
|
||||||
CoreBackendManager::stopExternalCommandHelper();
|
CoreBackendManager::self()->stopExternalCommandHelper();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue