Stop KAuth helper if application crashes.
This is implemented by pinging application from KAuth helper via DBus. If it is busy then KAuth helper also waits for the current job to finish.
This commit is contained in:
parent
65ef6ab83d
commit
51780a6297
|
@ -34,6 +34,7 @@ target_link_libraries(kpmcore_externalcommand
|
||||||
|
|
||||||
install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR})
|
install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR})
|
||||||
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d )
|
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d )
|
||||||
|
install( FILES util/org.kde.kpmcore.applicationinterface.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d )
|
||||||
|
|
||||||
kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root)
|
kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root)
|
||||||
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
|
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
|
||||||
|
|
|
@ -22,10 +22,12 @@
|
||||||
#include "core/copytarget.h"
|
#include "core/copytarget.h"
|
||||||
#include "core/copysourcedevice.h"
|
#include "core/copysourcedevice.h"
|
||||||
#include "core/copytargetdevice.h"
|
#include "core/copytargetdevice.h"
|
||||||
|
#include "util/globallog.h"
|
||||||
#include "util/externalcommand.h"
|
#include "util/externalcommand.h"
|
||||||
#include "util/report.h"
|
#include "util/report.h"
|
||||||
|
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
#include <QDBusConnection>
|
||||||
#include <QDBusInterface>
|
#include <QDBusInterface>
|
||||||
#include <QDBusReply>
|
#include <QDBusReply>
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
|
@ -51,6 +53,7 @@ struct ExternalCommandPrivate
|
||||||
int m_ExitCode;
|
int m_ExitCode;
|
||||||
QByteArray m_Output;
|
QByteArray m_Output;
|
||||||
QByteArray m_Input;
|
QByteArray m_Input;
|
||||||
|
DBusThread *m_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int ExternalCommand::counter = 0;
|
unsigned int ExternalCommand::counter = 0;
|
||||||
|
@ -75,7 +78,8 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co
|
||||||
d->m_Output = QByteArray();
|
d->m_Output = QByteArray();
|
||||||
|
|
||||||
if (!helperStarted)
|
if (!helperStarted)
|
||||||
startHelper();
|
if(!startHelper())
|
||||||
|
Log(Log::Level::error) << xi18nc("@info:status", "Could not obtain administrator privileges.");
|
||||||
|
|
||||||
setup(processChannelMode);
|
setup(processChannelMode);
|
||||||
}
|
}
|
||||||
|
@ -346,6 +350,13 @@ void ExternalCommand::setExitCode(int i)
|
||||||
|
|
||||||
bool ExternalCommand::startHelper()
|
bool ExternalCommand::startHelper()
|
||||||
{
|
{
|
||||||
|
if (!QDBusConnection::systemBus().isConnected()) {
|
||||||
|
qWarning() << "Could not connect to DBus session bus";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
d->m_thread = new DBusThread;
|
||||||
|
d->m_thread->start();
|
||||||
|
|
||||||
init = new QCA::Initializer;
|
init = new QCA::Initializer;
|
||||||
// Generate RSA key pair for signing external command requests
|
// Generate RSA key pair for signing external command requests
|
||||||
if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA)) {
|
if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA)) {
|
||||||
|
@ -402,3 +413,18 @@ void ExternalCommand::stopHelper()
|
||||||
delete privateKey;
|
delete privateKey;
|
||||||
delete init;
|
delete init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DBusThread::run()
|
||||||
|
{
|
||||||
|
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface"))) {
|
||||||
|
qWarning() << QDBusConnection::systemBus().lastError().message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Application"), this, QDBusConnection::ExportAllSlots)) {
|
||||||
|
qWarning() << QDBusConnection::systemBus().lastError().message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QEventLoop loop;
|
||||||
|
loop.exec();
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
#include <QThread>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -38,6 +39,16 @@ class CopySource;
|
||||||
class CopyTarget;
|
class CopyTarget;
|
||||||
struct ExternalCommandPrivate;
|
struct ExternalCommandPrivate;
|
||||||
|
|
||||||
|
class DBusThread : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.ping")
|
||||||
|
void run() override;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
Q_SCRIPTABLE void ping() {return;};
|
||||||
|
};
|
||||||
|
|
||||||
/** An external command.
|
/** An external command.
|
||||||
|
|
||||||
Runs an external command as a child process.
|
Runs an external command as a child process.
|
||||||
|
@ -94,7 +105,7 @@ public:
|
||||||
|
|
||||||
// KAuth
|
// KAuth
|
||||||
/**< start ExternalCommand Helper */
|
/**< start ExternalCommand Helper */
|
||||||
static bool startHelper();
|
bool startHelper();
|
||||||
|
|
||||||
/**< stop ExternalCommand Helper */
|
/**< stop ExternalCommand Helper */
|
||||||
static void stopHelper();
|
static void stopHelper();
|
||||||
|
|
|
@ -27,6 +27,18 @@
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
/** Initialize ExternalCommandHelper Daemon and prepare DBus interface
|
/** Initialize ExternalCommandHelper Daemon and prepare DBus interface
|
||||||
|
*
|
||||||
|
* KAuth helper runs in the background until application exits.
|
||||||
|
* To avoid forever running helper in case of application crash
|
||||||
|
* ExternalCommand class opens DBus interface that we ping.
|
||||||
|
* If helper is not busy than it exits when ping fails. Otherwise,
|
||||||
|
* we wait for the current job to finish before exiting, so even in case
|
||||||
|
* of main application crash, we do not leave partially moved data.
|
||||||
|
*
|
||||||
|
* This helper also starts another DBus interface where it listens to
|
||||||
|
* command execution requests from the application that started the helper.
|
||||||
|
* These requests are validated using public key cryptography, to prevent
|
||||||
|
* other unprivileged applications from gaining root privileges.
|
||||||
*/
|
*/
|
||||||
ActionReply ExternalCommandHelper::init(const QVariantMap& args)
|
ActionReply ExternalCommandHelper::init(const QVariantMap& args)
|
||||||
{
|
{
|
||||||
|
@ -36,17 +48,42 @@ ActionReply ExternalCommandHelper::init(const QVariantMap& args)
|
||||||
reply.addData(QStringLiteral("success"), false);
|
reply.addData(QStringLiteral("success"), false);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray());
|
|
||||||
m_Counter = 0;
|
|
||||||
|
|
||||||
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) {
|
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) {
|
||||||
qWarning() << QDBusConnection::systemBus().lastError().message();
|
qWarning() << QDBusConnection::systemBus().lastError().message();
|
||||||
reply.addData(QStringLiteral("success"), false);
|
reply.addData(QStringLiteral("success"), false);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots);
|
if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots)) {
|
||||||
|
qWarning() << QDBusConnection::systemBus().lastError().message();
|
||||||
|
reply.addData(QStringLiteral("success"), false);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_publicKey = QCA::PublicKey::fromDER(args[QStringLiteral("pubkey")].toByteArray());
|
||||||
|
m_Counter = 0;
|
||||||
|
|
||||||
HelperSupport::progressStep(QVariantMap());
|
HelperSupport::progressStep(QVariantMap());
|
||||||
|
auto timeout = [this] () {
|
||||||
|
QDBusInterface iface(QStringLiteral("org.kde.kpmcore.applicationinterface"),
|
||||||
|
QStringLiteral("/Application"),
|
||||||
|
QStringLiteral("org.kde.kpmcore.ping"),
|
||||||
|
QDBusConnection::systemBus());
|
||||||
|
iface.setTimeout(5000); // 5 seconds;
|
||||||
|
auto pcall = iface.asyncCall(QStringLiteral("ping"));
|
||||||
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
|
||||||
|
auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) {
|
||||||
|
if (watcher->isError()) {
|
||||||
|
qWarning() << watcher->error();
|
||||||
|
m_loop.exit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop);
|
||||||
|
};
|
||||||
|
|
||||||
|
QTimer *timer = new QTimer(this);
|
||||||
|
connect(timer, &QTimer::timeout, this, timeout);
|
||||||
|
timer->start(5000); // 5 seconds
|
||||||
m_loop.exec();
|
m_loop.exec();
|
||||||
reply.addData(QStringLiteral("success"), true);
|
reply.addData(QStringLiteral("success"), true);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE busconfig PUBLIC
|
||||||
|
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||||
|
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||||
|
<busconfig>
|
||||||
|
|
||||||
|
<policy context="default">
|
||||||
|
<allow own="org.kde.kpmcore.applicationinterface"/>
|
||||||
|
</policy>
|
||||||
|
|
||||||
|
<policy user="root">
|
||||||
|
<allow send_destination="org.kde.kpmcore.applicationinterface"
|
||||||
|
send_interface="org.kde.kpmcore.ping"/>
|
||||||
|
</policy>
|
||||||
|
</busconfig>
|
Loading…
Reference in New Issue