Make ExternalCommandHelper::getNonce() reentrant.
Store previously generated values of nonce, and remove them from the container when they are used. BUG: 396312
This commit is contained in:
parent
c50e04c9d1
commit
938ec7fa8b
|
@ -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);
|
||||
|
|
|
@ -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<ExternalCommandPrivate> 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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#ifndef KPMCORE_EXTERNALCOMMANDHELPER_H
|
||||
#define KPMCORE_EXTERNALCOMMANDHELPER_H
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include <KAuth>
|
||||
|
||||
#include <QEventLoop>
|
||||
|
@ -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<quint64> m_Nonces;
|
||||
QString m_command;
|
||||
QString m_sourceDevice;
|
||||
QProcess m_cmd;
|
||||
|
|
Loading…
Reference in New Issue