Use cryptographic nonce instead of counters.

This commit is contained in:
Andrius Štikonas 2018-07-20 21:12:13 +01:00
parent 48761e0e2b
commit c50e04c9d1
5 changed files with 47 additions and 11 deletions

View File

@ -196,7 +196,6 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode)
if (checkVG.run(-1) && checkVG.exitCode() == 0) if (checkVG.run(-1) && checkVG.exitCode() == 0)
{ {
qDebug() << "Trying to find LVM VG";
QList<Device *> availableDevices = scanDevices(); QList<Device *> availableDevices = scanDevices();
LvmDevice::scanSystemLVM(availableDevices); LvmDevice::scanSystemLVM(availableDevices);

View File

@ -57,7 +57,6 @@ struct ExternalCommandPrivate
QProcess::ProcessChannelMode processChannelMode; QProcess::ProcessChannelMode processChannelMode;
}; };
unsigned int ExternalCommand::counter = 0;
KAuth::ExecuteJob* ExternalCommand::m_job; KAuth::ExecuteJob* ExternalCommand::m_job;
QCA::PrivateKey* ExternalCommand::privateKey; QCA::PrivateKey* ExternalCommand::privateKey;
QCA::Initializer* ExternalCommand::init; QCA::Initializer* ExternalCommand::init;
@ -144,7 +143,7 @@ bool ExternalCommand::start(int timeout)
if (iface.isValid()) { if (iface.isValid()) {
QByteArray request; QByteArray request;
request.setNum(++counter); request.setNum(getNonce(iface));
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.toUtf8()); request.append(argument.toUtf8());
@ -204,7 +203,7 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target)
if (iface.isValid()) { if (iface.isValid()) {
QByteArray request; QByteArray request;
request.setNum(++counter); request.setNum(getNonce(iface));
request.append(source.path().toUtf8()); request.append(source.path().toUtf8());
request.append(QByteArray::number(source.firstByte())); request.append(QByteArray::number(source.firstByte()));
request.append(QByteArray::number(source.length())); request.append(QByteArray::number(source.length()));
@ -411,7 +410,7 @@ void ExternalCommand::stopHelper()
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()) {
QByteArray request; QByteArray request;
request.setNum(++counter); request.setNum(getNonce(iface));
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); 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));
} }
@ -420,6 +419,29 @@ void ExternalCommand::stopHelper()
delete init; delete init;
} }
unsigned long long ExternalCommand::getNonce(QDBusInterface& iface)
{
QDBusPendingCall pcall = iface.asyncCall(QStringLiteral("getNonce"));
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall);
QEventLoop loop;
unsigned long long rval = 0;
auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) {
loop.exit();
if (watcher->isError())
qWarning() << watcher->error();
else {
QDBusPendingReply<unsigned long long> reply = *watcher;
rval = reply;
}
};
connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop);
loop.exec();
return rval;
}
void DBusThread::run() void DBusThread::run()
{ {
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface"))) { if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface"))) {

View File

@ -37,6 +37,7 @@ namespace QCA { class PrivateKey; class Initializer; }
class Report; class Report;
class CopySource; class CopySource;
class CopyTarget; class CopyTarget;
class QDBusInterface;
struct ExternalCommandPrivate; struct ExternalCommandPrivate;
class DBusThread : public QThread class DBusThread : public QThread
@ -129,12 +130,13 @@ private:
void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onReadOutput(); void onReadOutput();
static unsigned long long getNonce(QDBusInterface& iface);
private: private:
std::unique_ptr<ExternalCommandPrivate> d; std::unique_ptr<ExternalCommandPrivate> d;
// KAuth stuff // KAuth stuff
static unsigned int counter; static unsigned long long m_Nonce;
static KAuth::ExecuteJob *m_job; static KAuth::ExecuteJob *m_job;
static QCA::Initializer *init; static QCA::Initializer *init;
static QCA::PrivateKey *privateKey; static QCA::PrivateKey *privateKey;

View File

@ -61,7 +61,7 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args)
} }
m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray()); m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray());
m_Counter = 0; m_Nonce = m_Generator.generate();
HelperSupport::progressStep(QVariantMap()); HelperSupport::progressStep(QVariantMap());
auto timeout = [this] () { auto timeout = [this] () {
@ -90,6 +90,15 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args)
return reply; return reply;
} }
/** Generates cryptographic nonce
* @return nonce
*/
unsigned long long ExternalCommandHelper::getNonce()
{
m_Nonce = m_Generator.generate();
return m_Nonce;
}
/** Reads the given number of bytes from the sourceDevice into the given buffer. /** Reads the given number of bytes from the sourceDevice into the given buffer.
@param sourceDevice device or file to read from @param sourceDevice device or file to read from
@param buffer buffer to store the bytes read in @param buffer buffer to store the bytes read in
@ -151,7 +160,7 @@ bool ExternalCommandHelper::copyblocks(const QByteArray& signature, const QStrin
{ {
QByteArray request; QByteArray request;
request.setNum(++m_Counter); request.setNum(m_Nonce);
request.append(sourceDevice.toUtf8()); request.append(sourceDevice.toUtf8());
request.append(QByteArray::number(sourceFirstByte)); request.append(QByteArray::number(sourceFirstByte));
request.append(QByteArray::number(sourceLength)); request.append(QByteArray::number(sourceLength));
@ -248,9 +257,10 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr
{ {
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QVariantMap reply; QVariantMap reply;
reply[QStringLiteral("success")] = true;
QByteArray request; QByteArray request;
request.setNum(++m_Counter); request.setNum(m_Nonce);
request.append(command.toUtf8()); request.append(command.toUtf8());
for (const auto &argument : arguments) for (const auto &argument : arguments)
request.append(argument.toUtf8()); request.append(argument.toUtf8());
@ -281,7 +291,7 @@ QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const QStr
void ExternalCommandHelper::exit(const QByteArray& signature) void ExternalCommandHelper::exit(const QByteArray& signature)
{ {
QByteArray request; QByteArray request;
request.setNum(++m_Counter); request.setNum(m_Nonce);
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512);
if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) {
qCritical() << xi18n("Invalid cryptographic signature"); qCritical() << xi18n("Invalid cryptographic signature");

View File

@ -21,6 +21,7 @@
#include <KAuth> #include <KAuth>
#include <QEventLoop> #include <QEventLoop>
#include <QRandomGenerator64>
#include <QString> #include <QString>
#include <QProcess> #include <QProcess>
@ -43,6 +44,7 @@ public:
public Q_SLOTS: public Q_SLOTS:
ActionReply init(const QVariantMap& args); 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 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 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 void exit(const QByteArray& signature);
@ -53,7 +55,8 @@ private:
QEventLoop m_loop; QEventLoop m_loop;
QCA::Initializer initializer; QCA::Initializer initializer;
QCA::PublicKey m_publicKey; QCA::PublicKey m_publicKey;
unsigned int m_Counter; QRandomGenerator64 m_Generator;
unsigned long long m_Nonce;
QString m_command; QString m_command;
QString m_sourceDevice; QString m_sourceDevice;
QProcess m_cmd; QProcess m_cmd;