From 938ec7fa8b6084586dd8a006da36c46bff1508ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrius=20=C5=A0tikonas?= Date: Sat, 21 Jul 2018 11:03:25 +0100 Subject: [PATCH] Make ExternalCommandHelper::getNonce() reentrant. Store previously generated values of nonce, and remove them from the container when they are used. BUG: 396312 --- src/util/externalcommand.cpp | 18 +++++++++------ src/util/externalcommand.h | 6 ++--- src/util/externalcommandhelper.cpp | 35 +++++++++++++++++++++--------- src/util/externalcommandhelper.h | 12 +++++----- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index a1030c0..443e37e 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -142,8 +142,8 @@ bool ExternalCommand::start(int timeout) bool rval = false; if (iface.isValid()) { QByteArray request; - - request.setNum(getNonce(iface)); + const quint64 nonce = getNonce(iface); + request.setNum(nonce); request.append(cmd.toUtf8()); for (const auto &argument : qAsConst(d->m_Args)) request.append(argument.toUtf8()); @@ -154,6 +154,7 @@ bool ExternalCommand::start(int timeout) QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("start"), privateKey->signMessage(hash, QCA::EMSA3_Raw), + nonce, cmd, args(), d->m_Input, @@ -203,7 +204,8 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) if (iface.isValid()) { QByteArray request; - request.setNum(getNonce(iface)); + const quint64 nonce = getNonce(iface); + request.setNum(nonce); request.append(source.path().toUtf8()); request.append(QByteArray::number(source.firstByte())); request.append(QByteArray::number(source.length())); @@ -214,8 +216,9 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) 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"), + QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("copyblocks"), privateKey->signMessage(hash, QCA::EMSA3_Raw), + nonce, source.path(), source.firstByte(), source.length(), target.path(), target.firstByte(), blockSize); @@ -410,16 +413,17 @@ void ExternalCommand::stopHelper() QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus()); if (iface.isValid()) { QByteArray request; - request.setNum(getNonce(iface)); + const quint64 nonce = getNonce(iface); + request.setNum(nonce); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); - iface.call(QStringLiteral("exit"), privateKey->signMessage(hash, QCA::EMSA3_Raw)); + iface.call(QStringLiteral("exit"), privateKey->signMessage(hash, QCA::EMSA3_Raw), nonce); } delete privateKey; delete init; } -unsigned long long ExternalCommand::getNonce(QDBusInterface& iface) +quint64 ExternalCommand::getNonce(QDBusInterface& iface) { QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("getNonce")); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall); diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 8111a70..233df12 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -130,13 +130,13 @@ private: void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onReadOutput(); - static unsigned long long getNonce(QDBusInterface& iface); + static quint64 getNonce(QDBusInterface& iface); private: std::unique_ptr d; - // KAuth stuff - static unsigned long long m_Nonce; + // KAuth + static quint64 m_Nonce; static KAuth::ExecuteJob *m_job; static QCA::Initializer *init; static QCA::PrivateKey *privateKey; diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index 9078309..d542324 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -61,7 +61,6 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) } m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); - m_Nonce = m_Generator.generate(); HelperSupport::progressStep(QVariantMap()); auto timeout = [this] () { @@ -93,10 +92,11 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args) /** Generates cryptographic nonce * @return nonce */ -unsigned long long ExternalCommandHelper::getNonce() +quint64 ExternalCommandHelper::getNonce() { - m_Nonce = m_Generator.generate(); - return m_Nonce; + quint64 nonce = m_Generator.generate(); + m_Nonces.insert(nonce); + return nonce; } /** Reads the given number of bytes from the sourceDevice into the given buffer. @@ -156,11 +156,16 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr return true; } -bool ExternalCommandHelper::copyblocks(const QByteArray& signature, 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 quint64 nonce, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) { + if (m_Nonces.find(nonce) != m_Nonces.end()) + m_Nonces.erase( nonce ); + else + return false; + QByteArray request; - request.setNum(m_Nonce); + request.setNum(nonce); request.append(sourceDevice.toUtf8()); request.append(QByteArray::number(sourceFirstByte)); request.append(QByteArray::number(sourceLength)); @@ -253,14 +258,21 @@ bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QStrin return rval; } -QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode) +QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const quint64 nonce, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode) { QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); QVariantMap reply; reply[QStringLiteral("success")] = true; + if (m_Nonces.find(nonce) != m_Nonces.end()) + m_Nonces.erase( nonce ); + else { + reply[QStringLiteral("success")] = false; + return reply; + } + QByteArray request; - request.setNum(m_Nonce); + request.setNum(nonce); request.append(command.toUtf8()); for (const auto &argument : arguments) request.append(argument.toUtf8()); @@ -288,10 +300,13 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr return reply; } -void ExternalCommandHelper::exit(const QByteArray& signature) +void ExternalCommandHelper::exit(const QByteArray& signature, const quint64 nonce) { QByteArray request; - request.setNum(m_Nonce); + if (m_Nonces.find(nonce) == m_Nonces.end()) + return; + + request.setNum(nonce); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { qCritical() << xi18n("Invalid cryptographic signature"); diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index a2a309b..4f1cab7 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -18,6 +18,8 @@ #ifndef KPMCORE_EXTERNALCOMMANDHELPER_H #define KPMCORE_EXTERNALCOMMANDHELPER_H +#include + #include #include @@ -44,10 +46,10 @@ public: public Q_SLOTS: ActionReply init(const QVariantMap& args); - Q_SCRIPTABLE unsigned long long getNonce(); - Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode); - 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); + Q_SCRIPTABLE quint64 getNonce(); + Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const quint64 nonce, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode); + Q_SCRIPTABLE bool copyblocks(const QByteArray& signature, const quint64 nonce, 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, const quint64 nonce); private: void onReadOutput(); @@ -56,7 +58,7 @@ private: QCA::Initializer initializer; QCA::PublicKey m_publicKey; QRandomGenerator64 m_Generator; - unsigned long long m_Nonce; + std::unordered_set m_Nonces; QString m_command; QString m_sourceDevice; QProcess m_cmd;