We need to give the original DBus sender to connman-vpnd
when connmand is proxying the connect request. Otherwise
the possible agent request goes to default vpn agent
instead of the correct agent that initiated the connect
request.

Reported by Jaakko Hannikainen.
---
 include/provider.h |  3 ++-
 plugins/vpn.c      | 37 +++++++++++++++++++++++++++++--------
 src/connman.h      |  3 ++-
 src/provider.c     |  5 +++--
 src/service.c      |  3 ++-
 vpn/vpn-provider.c | 25 +++++++++++++++++++++++--
 6 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/include/provider.h b/include/provider.h
index d1a8983..d28651a 100644
--- a/include/provider.h
+++ b/include/provider.h
@@ -124,7 +124,8 @@ struct connman_provider_driver {
        enum connman_provider_type type;
        int (*probe) (struct connman_provider *provider);
        int (*remove) (struct connman_provider *provider);
-       int (*connect) (struct connman_provider *provider);
+       int (*connect) (struct connman_provider *provider,
+                       const char *dbus_sender);
        int (*disconnect) (struct connman_provider *provider);
        int (*save) (struct connman_provider *provider, GKeyFile *keyfile);
        int (*set_property) (struct connman_provider *provider,
diff --git a/plugins/vpn.c b/plugins/vpn.c
index e6e4c8e..7202734 100644
--- a/plugins/vpn.c
+++ b/plugins/vpn.c
@@ -512,26 +512,39 @@ done:
        dbus_pending_call_unref(call);
 }
 
-static int connect_provider(struct connection_data *data, void *user_data)
+static int connect_provider(struct connection_data *data, void *user_data,
+                       const char *dbus_sender)
 {
        DBusPendingCall *call;
        DBusMessage *message;
        struct config_create_data *cb_data = user_data;
 
-       DBG("data %p user %p path %s", data, cb_data, data->path);
+       DBG("data %p user %p path %s sender %s", data, cb_data, data->path,
+                                                               dbus_sender);
 
        data->connect_pending = false;
 
+#define VPN_CONNECT2 "Connect2"
+
+       /* We need to pass original dbus sender to connman-vpnd,
+        * use a Connect2 method for that.
+        */
        message = dbus_message_new_method_call(VPN_SERVICE, data->path,
                                        VPN_CONNECTION_INTERFACE,
-                                       VPN_CONNECT);
+                                       VPN_CONNECT2);
        if (!message)
                return -ENOMEM;
 
+       if (dbus_sender)
+               dbus_message_append_args(message, DBUS_TYPE_STRING,
+                                       &dbus_sender, NULL);
+       else
+               dbus_sender = "";
+
        if (!dbus_connection_send_with_reply(connection, message,
                                                &call, DBUS_TIMEOUT)) {
                connman_error("Unable to call %s.%s()",
-                       VPN_CONNECTION_INTERFACE, VPN_CONNECT);
+                       VPN_CONNECTION_INTERFACE, VPN_CONNECT2);
                dbus_message_unref(message);
                return -EINVAL;
        }
@@ -658,8 +671,15 @@ static void add_connection(const char *path, 
DBusMessageIter *properties,
                connman_provider_set_domain(data->provider,
                                                data->domain);
 
-       if (data->connect_pending)
-               connect_provider(data, data->cb_data);
+       if (data->connect_pending) {
+               const char *dbus_sender = NULL;
+
+               if (data->cb_data && data->cb_data->message) {
+                       dbus_sender =
+                               dbus_message_get_sender(data->cb_data->message);
+               }
+               connect_provider(data, data->cb_data, dbus_sender);
+       }
 
        return;
 
@@ -857,7 +877,8 @@ static int provider_remove(struct connman_provider 
*provider)
        return 0;
 }
 
-static int provider_connect(struct connman_provider *provider)
+static int provider_connect(struct connman_provider *provider,
+                                       const char *dbus_sender)
 {
        struct connection_data *data;
 
@@ -865,7 +886,7 @@ static int provider_connect(struct connman_provider 
*provider)
        if (!data)
                return -EINVAL;
 
-       return connect_provider(data, NULL);
+       return connect_provider(data, NULL, dbus_sender);
 }
 
 static void disconnect_reply(DBusPendingCall *call, void *user_data)
diff --git a/src/connman.h b/src/connman.h
index aac6a0b..29151af 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -642,7 +642,8 @@ int __connman_provider_indicate_state(struct 
connman_provider *provider,
                                        enum connman_provider_state state);
 int __connman_provider_indicate_error(struct connman_provider *provider,
                                        enum connman_provider_error error);
-int __connman_provider_connect(struct connman_provider *provider);
+int __connman_provider_connect(struct connman_provider *provider,
+                                       const char *dbus_sender);
 int __connman_provider_remove_by_path(const char *path);
 void __connman_provider_cleanup(void);
 int __connman_provider_init(void);
diff --git a/src/provider.c b/src/provider.c
index 693552e..d5ce825 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -164,14 +164,15 @@ int connman_provider_remove(struct connman_provider 
*provider)
        return 0;
 }
 
-int __connman_provider_connect(struct connman_provider *provider)
+int __connman_provider_connect(struct connman_provider *provider,
+                                       const char *dbus_sender)
 {
        int err;
 
        DBG("provider %p", provider);
 
        if (provider->driver && provider->driver->connect)
-               err = provider->driver->connect(provider);
+               err = provider->driver->connect(provider, dbus_sender);
        else
                return -EOPNOTSUPP;
 
diff --git a/src/service.c b/src/service.c
index 9ac2fe4..8feb0f4 100644
--- a/src/service.c
+++ b/src/service.c
@@ -5963,7 +5963,8 @@ static int service_connect(struct connman_service 
*service)
                err = __connman_network_connect(service->network);
        } else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
                                        service->provider)
-               err = __connman_provider_connect(service->provider);
+               err = __connman_provider_connect(service->provider,
+                                               get_dbus_sender(service));
        else
                return -EOPNOTSUPP;
 
diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index b0aadcd..a8d05bf 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -501,6 +501,12 @@ static DBusMessage *do_connect(DBusConnection *conn, 
DBusMessage *msg,
        return NULL;
 }
 
+static DBusMessage *do_connect2(DBusConnection *conn, DBusMessage *msg,
+                                                               void *data)
+{
+       return do_connect(conn, msg, data);
+}
+
 static DBusMessage *do_disconnect(DBusConnection *conn, DBusMessage *msg,
                                                                void *data)
 {
@@ -527,6 +533,9 @@ static const GDBusMethodTable connection_methods[] = {
                        GDBUS_ARGS({ "name", "s" }), NULL,
                        clear_property) },
        { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, do_connect) },
+       { GDBUS_ASYNC_METHOD("Connect2",
+                       GDBUS_ARGS({ "dbus_sender", "s" }),
+                       NULL, do_connect2) },
        { GDBUS_METHOD("Disconnect", NULL, NULL, do_disconnect) },
        { },
 };
@@ -1087,10 +1096,22 @@ int __vpn_provider_connect(struct vpn_provider 
*provider, DBusMessage *msg)
        DBG("provider %p", provider);
 
        if (provider->driver && provider->driver->connect) {
+               const char *dbus_sender = dbus_message_get_sender(msg);
+
                dbus_message_ref(msg);
+
+               if (dbus_message_has_signature(msg,
+                                               DBUS_TYPE_STRING_AS_STRING)) {
+                       const char *sender = NULL;
+
+                       dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING,
+                                       &sender, DBUS_TYPE_INVALID);
+                       if (sender && sender[0])
+                               dbus_sender = sender;
+               }
+
                err = provider->driver->connect(provider, connect_cb,
-                                               dbus_message_get_sender(msg),
-                                               msg);
+                                               dbus_sender, msg);
        } else
                return -EOPNOTSUPP;
 
-- 
2.1.0

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to