Changeset View
Changeset View
Standalone View
Standalone View
src/backends/dbus/DBusHelperProxy.cpp
Show First 20 Lines • Show All 62 Lines • ▼ Show 20 Line(s) | 60 | { | |||
---|---|---|---|---|---|
63 | 63 | | |||
64 | QList<QVariant> args; | 64 | QList<QVariant> args; | ||
65 | args << action; | 65 | args << action; | ||
66 | message.setArguments(args); | 66 | message.setArguments(args); | ||
67 | 67 | | |||
68 | m_busConnection.asyncCall(message); | 68 | m_busConnection.asyncCall(message); | ||
69 | } | 69 | } | ||
70 | 70 | | |||
71 | void DBusHelperProxy::executeAction(const QString &action, const QString &helperID, const QVariantMap &arguments, int timeout) | 71 | void DBusHelperProxy::executeAction(const QString &action, const QString &helperID, const DetailsMap &details, const QVariantMap &arguments, int timeout) | ||
72 | { | 72 | { | ||
73 | QByteArray blob; | 73 | QByteArray blob; | ||
74 | { | 74 | { | ||
75 | QDataStream stream(&blob, QIODevice::WriteOnly); | 75 | QDataStream stream(&blob, QIODevice::WriteOnly); | ||
76 | stream << arguments; | 76 | stream << arguments; | ||
77 | } | 77 | } | ||
78 | 78 | | |||
79 | //on unit tests we won't have a service, but the service will already be running | 79 | //on unit tests we won't have a service, but the service will already be running | ||
Show All 14 Lines | 93 | errorReply.setErrorDescription(tr("DBus Backend error: connection to helper failed. %1\n(application: %2 helper: %3)").arg( | |||
94 | m_busConnection.lastError().message(), | 94 | m_busConnection.lastError().message(), | ||
95 | qApp->applicationName(), | 95 | qApp->applicationName(), | ||
96 | helperID)); | 96 | helperID)); | ||
97 | emit actionPerformed(action, errorReply); | 97 | emit actionPerformed(action, errorReply); | ||
98 | return; | 98 | return; | ||
99 | } | 99 | } | ||
100 | 100 | | |||
101 | QDBusMessage message; | 101 | QDBusMessage message; | ||
102 | message = QDBusMessage::createMethodCall(helperID, QLatin1String("/"), QLatin1String("org.kde.kf5auth"), QLatin1String("performAction")); | 102 | message = QDBusMessage::createMethodCall(helperID, QLatin1String("/"), QLatin1String("org.kde.kf5auth"), QLatin1String("performAction")); | ||
sitter: We need to be backwards compatible here. As far as I can tell this is where we call the actual… | |||||
Done as requested. Note three's a blocking call in the slot, but I'm assuming (for simplicity's sake) that's ok. LMK if otherwise. feverfew: Done as requested. Note three's a blocking call in the slot, but I'm assuming (for simplicity's… | |||||
103 | 103 | | |||
104 | QList<QVariant> args; | 104 | QList<QVariant> args; | ||
sitter: left over debugging? either remove or categorize | |||||
105 | args << action << BackendsManager::authBackend()->callerID() << blob; | 105 | args << action << BackendsManager::authBackend()->callerID() << BackendsManager::authBackend()->backendDetails(details) << blob; | ||
106 | message.setArguments(args); | 106 | message.setArguments(args); | ||
107 | 107 | | |||
108 | m_actionsInProgress.push_back(action); | 108 | m_actionsInProgress.push_back(action); | ||
109 | 109 | | |||
110 | QDBusPendingCall pendingCall = m_busConnection.asyncCall(message, timeout); | 110 | QDBusPendingCall pendingCall = m_busConnection.asyncCall(message, timeout); | ||
111 | 111 | | |||
112 | auto watcher = new QDBusPendingCallWatcher(pendingCall, this); | 112 | auto watcher = new QDBusPendingCallWatcher(pendingCall, this); | ||
113 | 113 | | |||
114 | connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, action, watcher]() { | 114 | connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] () mutable { | ||
115 | watcher->deleteLater(); | 115 | watcher->deleteLater(); | ||
116 | 116 | | |||
117 | const QDBusMessage reply = watcher->reply(); | 117 | QDBusMessage reply = watcher->reply(); | ||
118 | 118 | | |||
119 | if (reply.type() == QDBusMessage::ErrorMessage) { | 119 | if (reply.type() == QDBusMessage::ErrorMessage) { | ||
120 | if (watcher->error().type() == QDBusError::InvalidArgs) { | ||||
Probably better to us the abstraction enum if (watcher->error().type() == QDBusError::InvalidArgs) { sitter: Probably better to us the abstraction enum `if (watcher->error().type() == QDBusError… | |||||
121 | // For backwards compatibility if helper binary was built with older KAuth version. | ||||
122 | args.removeAt(args.count() - 2); // remove backend details | ||||
123 | message.setArguments(args); | ||||
124 | reply = m_busConnection.call(message, QDBus::Block, timeout); | ||||
125 | if (reply.type() != QDBusMessage::ErrorMessage) { | ||||
126 | return; | ||||
127 | } | ||||
128 | } | ||||
120 | ActionReply r = ActionReply::DBusErrorReply(); | 129 | ActionReply r = ActionReply::DBusErrorReply(); | ||
121 | r.setErrorDescription(tr("DBus Backend error: could not contact the helper. " | 130 | r.setErrorDescription(tr("DBus Backend error: could not contact the helper. " | ||
122 | "Connection error: %1. Message error: %2").arg(reply.errorMessage(), m_busConnection.lastError().message())); | 131 | "Connection error: %1. Message error: %2").arg(reply.errorMessage(), m_busConnection.lastError().message())); | ||
123 | qCWarning(KAUTH) << reply.errorMessage(); | 132 | qCWarning(KAUTH) << reply.errorMessage(); | ||
124 | 133 | | |||
125 | emit actionPerformed(action, r); | 134 | emit actionPerformed(action, r); | ||
126 | } | 135 | } | ||
127 | }); | 136 | }); | ||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Line(s) | |||||
193 | bool DBusHelperProxy::hasToStopAction() | 202 | bool DBusHelperProxy::hasToStopAction() | ||
194 | { | 203 | { | ||
195 | QEventLoop loop; | 204 | QEventLoop loop; | ||
196 | loop.processEvents(QEventLoop::AllEvents); | 205 | loop.processEvents(QEventLoop::AllEvents); | ||
197 | 206 | | |||
198 | return m_stopRequest; | 207 | return m_stopRequest; | ||
199 | } | 208 | } | ||
200 | 209 | | |||
201 | bool DBusHelperProxy::isCallerAuthorized(const QString &action, const QByteArray &callerID) | 210 | bool DBusHelperProxy::isCallerAuthorized(const QString &action, const QByteArray &callerID, const QVariantMap &details) | ||
202 | { | 211 | { | ||
203 | // Check the caller is really who it says it is | 212 | // Check the caller is really who it says it is | ||
204 | switch (BackendsManager::authBackend()->extraCallerIDVerificationMethod()) { | 213 | switch (BackendsManager::authBackend()->extraCallerIDVerificationMethod()) { | ||
205 | case AuthBackend::NoExtraCallerIDVerificationMethod: | 214 | case AuthBackend::NoExtraCallerIDVerificationMethod: | ||
206 | break; | 215 | break; | ||
207 | 216 | | |||
208 | case AuthBackend::VerifyAgainstDBusServiceName: | 217 | case AuthBackend::VerifyAgainstDBusServiceName: | ||
209 | if (message().service().toUtf8() != callerID) { | 218 | if (message().service().toUtf8() != callerID) { | ||
210 | return false; | 219 | return false; | ||
211 | } | 220 | } | ||
212 | break; | 221 | break; | ||
213 | 222 | | |||
214 | case AuthBackend::VerifyAgainstDBusServicePid: | 223 | case AuthBackend::VerifyAgainstDBusServicePid: | ||
215 | if (connection().interface()->servicePid(message().service()).value() != callerID.toUInt()) { | 224 | if (connection().interface()->servicePid(message().service()).value() != callerID.toUInt()) { | ||
216 | return false; | 225 | return false; | ||
217 | } | 226 | } | ||
218 | break; | 227 | break; | ||
219 | } | 228 | } | ||
220 | 229 | | |||
221 | return BackendsManager::authBackend()->isCallerAuthorized(action, callerID); | 230 | return BackendsManager::authBackend()->isCallerAuthorized(action, callerID, details); | ||
222 | } | 231 | } | ||
223 | 232 | | |||
224 | QByteArray DBusHelperProxy::performAction(const QString &action, const QByteArray &callerID, QByteArray arguments) | 233 | QByteArray DBusHelperProxy::performAction(const QString &action, const QByteArray &callerID, const QVariantMap &details, QByteArray arguments) | ||
225 | { | 234 | { | ||
226 | if (!responder) { | 235 | if (!responder) { | ||
227 | return ActionReply::NoResponderReply().serialized(); | 236 | return ActionReply::NoResponderReply().serialized(); | ||
228 | } | 237 | } | ||
229 | 238 | | |||
230 | if (!m_currentAction.isEmpty()) { | 239 | if (!m_currentAction.isEmpty()) { | ||
231 | return ActionReply::HelperBusyReply().serialized(); | 240 | return ActionReply::HelperBusyReply().serialized(); | ||
232 | } | 241 | } | ||
Show All 14 Lines | |||||
247 | QEventLoop e; | 256 | QEventLoop e; | ||
248 | e.processEvents(QEventLoop::AllEvents); | 257 | e.processEvents(QEventLoop::AllEvents); | ||
249 | 258 | | |||
250 | ActionReply retVal; | 259 | ActionReply retVal; | ||
251 | 260 | | |||
252 | QTimer *timer = responder->property("__KAuth_Helper_Shutdown_Timer").value<QTimer *>(); | 261 | QTimer *timer = responder->property("__KAuth_Helper_Shutdown_Timer").value<QTimer *>(); | ||
253 | timer->stop(); | 262 | timer->stop(); | ||
254 | 263 | | |||
255 | if (isCallerAuthorized(action, callerID)) { | 264 | if (isCallerAuthorized(action, callerID, details)) { | ||
256 | QString slotname = action; | 265 | QString slotname = action; | ||
257 | if (slotname.startsWith(m_name + QLatin1Char('.'))) { | 266 | if (slotname.startsWith(m_name + QLatin1Char('.'))) { | ||
258 | slotname = slotname.right(slotname.length() - m_name.length() - 1); | 267 | slotname = slotname.right(slotname.length() - m_name.length() - 1); | ||
259 | } | 268 | } | ||
260 | 269 | | |||
261 | slotname.replace(QLatin1Char('.'), QLatin1Char('_')); | 270 | slotname.replace(QLatin1Char('.'), QLatin1Char('_')); | ||
262 | 271 | | |||
263 | bool success = QMetaObject::invokeMethod(responder, slotname.toLatin1().data(), Qt::DirectConnection, | 272 | bool success = QMetaObject::invokeMethod(responder, slotname.toLatin1().data(), Qt::DirectConnection, | ||
▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines |
We need to be backwards compatible here. As far as I can tell this is where we call the actual helper binary. The helper binary may have been built with an older version of kauth, so it doesn't necessarily understand the new API.
You could call org.freedesktop.DBus.Introspectable to figure out which method arguments it supports, or possibly the simpler approach is to could with new arguments and if that results in org.freedesktop.DBus.Error.InvalidArgs try again with old arguments before giving up.