summaryrefslogtreecommitdiffstats
path: root/src/dbus
diff options
context:
space:
mode:
authorSteffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>2020-07-13 18:40:12 +0200
committerSteffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>2020-07-13 20:45:20 +0200
commit6d880185b1483b4efb3e358815060537d91b0de4 (patch)
tree8c669442c04ac693fa18ff570ad45bbaf58b4465 /src/dbus
parent2a5ad75ec88d4d3cf2a0903bbfd2ff4a6785dcde (diff)
Fix passing QDBusUnixFileDescriptors over peer-to-peer connections
Passing QDBusUnixFileDescriptors over peer-to-peer connections currently does not work, because QDBusConnectionPrivate::setPeer() does not set this->capabilities (unlike QDBusConnectionPrivate::setConnection() which is executed for bus connections). Keep track of whether the connection already has been authenticated, and once the connection does get authenticated, update this->capabilities. Note that sending a message directly after connecting (before any message has been received from the peer) might still fail if the message contains a QDBusUnixFileDescriptor. Pick-to: 5.15 Fixes: QTBUG-85396 Change-Id: Ib83213ebcd3255fb091c6faefb3618745b8d736c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/dbus')
-rw-r--r--src/dbus/qdbus_symbols_p.h2
-rw-r--r--src/dbus/qdbusconnection.cpp2
-rw-r--r--src/dbus/qdbusconnection_p.h9
-rw-r--r--src/dbus/qdbusintegrator.cpp36
-rw-r--r--src/dbus/qdbusmessage.cpp4
5 files changed, 41 insertions, 12 deletions
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index 7cce0d71aa..accaa4f5ed 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -213,6 +213,8 @@ DEFINEFUNC(DBusDispatchStatus , dbus_connection_dispatch, (DBusConnection
(connection), return)
DEFINEFUNC(DBusDispatchStatus , dbus_connection_get_dispatch_status, (DBusConnection *connection),
(connection), return)
+DEFINEFUNC(dbus_bool_t, dbus_connection_get_is_authenticated, (DBusConnection * connection),
+ (connection), return )
DEFINEFUNC(dbus_bool_t , dbus_connection_get_is_connected, (DBusConnection *connection),
(connection), return)
DEFINEFUNC(DBusConnection* , dbus_connection_open_private, (const char *address,
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index f690e52247..329a539e23 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -1119,7 +1119,7 @@ QString QDBusConnection::name() const
*/
QDBusConnection::ConnectionCapabilities QDBusConnection::connectionCapabilities() const
{
- return d ? d->capabilities : ConnectionCapabilities();
+ return d ? d->connectionCapabilities() : ConnectionCapabilities();
}
/*!
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index d3b46153cb..84c5aee3d7 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -277,6 +277,8 @@ private:
void _q_newConnection(QDBusConnectionPrivate *newConnection);
+ void handleAuthentication();
+
protected:
void timerEvent(QTimerEvent *e) override;
@@ -309,7 +311,11 @@ signals:
public:
QAtomicInt ref;
- QDBusConnection::ConnectionCapabilities capabilities;
+ QAtomicInt capabilities;
+ QDBusConnection::ConnectionCapabilities connectionCapabilities() const
+ {
+ return (QDBusConnection::ConnectionCapabilities)capabilities.loadRelaxed();
+ }
QString name; // this connection's name
QString baseService; // this connection's base service
QStringList serverConnectionNames;
@@ -342,6 +348,7 @@ public:
bool anonymousAuthenticationAllowed;
bool dispatchEnabled; // protected by the dispatch lock, not the main lock
+ bool isAuthenticated;
public:
// static methods
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 32521c85e7..07816568e5 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -526,7 +526,7 @@ qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data)
if (d->mode == QDBusConnectionPrivate::InvalidMode)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message, d->capabilities);
+ QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message, d->connectionCapabilities());
qDBusDebug() << d << "got message (signal):" << amsg;
return d->handleMessage(amsg) ?
@@ -1028,11 +1028,15 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
extern bool qDBusInitThreads();
QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
- : QObject(p), ref(1), mode(InvalidMode), busService(nullptr),
+ : QObject(p),
+ ref(1),
+ mode(InvalidMode),
+ busService(nullptr),
connection(nullptr),
rootNode(QString(QLatin1Char('/'))),
anonymousAuthenticationAllowed(false),
- dispatchEnabled(true)
+ dispatchEnabled(true),
+ isAuthenticated(false)
{
static const bool threads = q_dbus_threads_init_default();
if (::isDebugging == -1)
@@ -1218,6 +1222,9 @@ void QDBusConnectionPrivate::socketRead(qintptr fd)
}
++it;
}
+ if ((mode == ClientMode || mode == PeerMode) && !isAuthenticated
+ && q_dbus_connection_get_is_authenticated(connection))
+ handleAuthentication();
doDispatch();
}
@@ -1232,6 +1239,9 @@ void QDBusConnectionPrivate::socketWrite(qintptr fd)
}
++it;
}
+ if ((mode == ClientMode || mode == PeerMode) && !isAuthenticated
+ && q_dbus_connection_get_is_authenticated(connection))
+ handleAuthentication();
}
void QDBusConnectionPrivate::objectDestroyed(QObject *obj)
@@ -1274,7 +1284,8 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in
QDBusMessagePrivate::setParametersValidated(message, true);
message.setArguments(args);
QDBusError error;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error);
+ DBusMessage *msg =
+ QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
if (!msg) {
qWarning("QDBusConnection: Could not emit signal %s.%s: %s", qPrintable(interface), memberName.constData(),
qPrintable(error.message()));
@@ -1794,6 +1805,12 @@ static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnecti
return result;
}
+void QDBusConnectionPrivate::handleAuthentication()
+{
+ capabilities.storeRelaxed(connectionCapabilies(connection));
+ isAuthenticated = true;
+}
+
void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusErrorInternal &error)
{
mode = ClientMode;
@@ -1807,7 +1824,8 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
const char *service = q_dbus_bus_get_unique_name(connection);
Q_ASSERT(service);
baseService = QString::fromUtf8(service);
- capabilities = connectionCapabilies(connection);
+ // bus connections are already authenticated here because q_dbus_bus_register() has been called
+ handleAuthentication();
q_dbus_connection_set_exit_on_disconnect(connection, false);
q_dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
@@ -1876,7 +1894,7 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
if (q_dbus_pending_call_get_completed(call->pending)) {
// decode the message
DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending);
- msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities);
+ msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->connectionCapabilities());
q_dbus_message_unref(reply);
} else {
msg = QDBusMessage::createError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage());
@@ -1930,7 +1948,8 @@ bool QDBusConnectionPrivate::send(const QDBusMessage& message)
// through the d_ptr->localReply link
QDBusError error;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error);
+ DBusMessage *msg =
+ QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
if (!msg) {
if (message.type() == QDBusMessage::MethodCallMessage)
qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
@@ -2144,7 +2163,8 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
}
QDBusError error;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error);
+ DBusMessage *msg =
+ QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
if (!msg) {
qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
qPrintable(message.service()), qPrintable(message.path()),
diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp
index 1625dcdfea..01d55280d6 100644
--- a/src/dbus/qdbusmessage.cpp
+++ b/src/dbus/qdbusmessage.cpp
@@ -282,7 +282,7 @@ QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
// we must marshall and demarshall again so as to create QDBusArgument
// entries for the complex types
QDBusError error;
- DBusMessage *message = toDBusMessage(asSent, conn.capabilities, &error);
+ DBusMessage *message = toDBusMessage(asSent, conn.connectionCapabilities(), &error);
if (!message) {
// failed to marshall, so it's a call error
return QDBusMessage::createError(error);
@@ -290,7 +290,7 @@ QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
q_dbus_message_set_sender(message, conn.baseService.toUtf8());
- QDBusMessage retval = fromDBusMessage(message, conn.capabilities);
+ QDBusMessage retval = fromDBusMessage(message, conn.connectionCapabilities());
retval.d_ptr->localMessage = true;
q_dbus_message_unref(message);
if (retval.d_ptr->service.isEmpty())