From 6d880185b1483b4efb3e358815060537d91b0de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Kie=C3=9F?= Date: Mon, 13 Jul 2020 18:40:12 +0200 Subject: 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 --- src/dbus/qdbus_symbols_p.h | 2 ++ src/dbus/qdbusconnection.cpp | 2 +- src/dbus/qdbusconnection_p.h | 9 ++++++++- src/dbus/qdbusintegrator.cpp | 36 ++++++++++++++++++++++++++++-------- src/dbus/qdbusmessage.cpp | 4 ++-- 5 files changed, 41 insertions(+), 12 deletions(-) (limited to 'src') 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()) -- cgit v1.2.3