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 <QCoreApplication>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
#include <QDBusInterface>
|
||||
#include <QStringList>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QUuid>
|
||||
|
||||
#include <QtCrypto>
|
||||
|
||||
|
@ -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())
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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")))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -59,5 +59,5 @@ KPMCoreInitializer::KPMCoreInitializer( const char* backend ) : KPMCoreInitializ
|
|||
|
||||
KPMCoreInitializer::~KPMCoreInitializer()
|
||||
{
|
||||
CoreBackendManager::stopExternalCommandHelper();
|
||||
CoreBackendManager::self()->stopExternalCommandHelper();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue