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>
This commit is contained in:
parent
2a5ad75ec8
commit
6d880185b1
@ -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,
|
||||
|
@ -1119,7 +1119,7 @@ QString QDBusConnection::name() const
|
||||
*/
|
||||
QDBusConnection::ConnectionCapabilities QDBusConnection::connectionCapabilities() const
|
||||
{
|
||||
return d ? d->capabilities : ConnectionCapabilities();
|
||||
return d ? d->connectionCapabilities() : ConnectionCapabilities();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -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
|
||||
|
@ -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()),
|
||||
|
@ -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())
|
||||
|
@ -1110,8 +1110,9 @@ void tst_QDBusMarshall::receiveUnknownType()
|
||||
QSKIP("Your session bus does not allow sending Unix file descriptors");
|
||||
|
||||
// make sure this QDBusConnection won't handle Unix file descriptors
|
||||
QDBusConnection::ConnectionCapabilities &capabRef = QDBusConnectionPrivate::d(con)->capabilities;
|
||||
SetResetValue<QDBusConnection::ConnectionCapabilities> resetter(capabRef, capabRef & ~QDBusConnection::UnixFileDescriptorPassing);
|
||||
QAtomicInt &capabRef = QDBusConnectionPrivate::d(con)->capabilities;
|
||||
SetResetValue<QAtomicInt> resetter(capabRef,
|
||||
capabRef & ~QDBusConnection::UnixFileDescriptorPassing);
|
||||
|
||||
if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) {
|
||||
// create a call back to us containing a file descriptor
|
||||
|
Loading…
Reference in New Issue
Block a user