diff options
author | VAUTRIN Emmanuel (Canal Plus Prestataire) <Emmanuel.VAUTRIN@cpexterne.org> | 2021-06-14 09:14:48 +0000 |
---|---|---|
committer | Daniel Wagner <wagi@monom.org> | 2021-08-29 21:16:40 +0200 |
commit | 416c9cd44131df98d0c57fe4f780419612795f90 (patch) | |
tree | 37f3cc5e4945519583a7953fd438cf47d049323e | |
parent | 9d7e55f40e807ea7d28a34b20e50af1b06ea2fda (diff) | |
download | connman-416c9cd44131df98d0c57fe4f780419612795f90.tar.gz |
service: Prevent auto connection during passphrase request
Avoid concurrent associations between a user connection to a secure
service, blocked by an agent passphrase input request, and a starting
auto connection on a different service of the same interface.
This issue happens when the end-user wants to connect to a new secure
Wifi network (W2) via an interface where another Wifi network (W1) is
already connected. When doing that, the following steps happen:
1. Disconnection of current network (W1).
2. User-connection to W2, held by the passphrase request.
3. Auto-connection to a known available Wifi network (W1) succeeding.
4. User-connection to W2, reactivated by the passphrase response,
failing, as another Wifi (W1) is already connected.
Wifi 2 will never be able, in this configuration, to connect.
-rw-r--r-- | src/service.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/service.c b/src/service.c index d87bc05c..a5a5cfde 100644 --- a/src/service.c +++ b/src/service.c @@ -49,6 +49,7 @@ static DBusConnection *connection = NULL; static GList *service_list = NULL; static GHashTable *service_hash = NULL; +static GHashTable *passphrase_requested = NULL; static GSList *counter_list = NULL; static unsigned int autoconnect_id = 0; static unsigned int vpn_autoconnect_id = 0; @@ -4209,6 +4210,7 @@ static bool auto_connect_service(GList *services, bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { }; bool autoconnecting = false; GList *list; + int index; DBG("preferred %d sessions %d reason %s", preferred, active_count, reason2string(reason)); @@ -4230,6 +4232,11 @@ static bool auto_connect_service(GList *services, continue; } + index = __connman_service_get_index(service); + if (g_hash_table_lookup(passphrase_requested, + GINT_TO_POINTER(index))) + return true; + if (service->pending || is_connecting(service->state) || is_connected(service->state)) { @@ -5790,6 +5797,7 @@ static void request_input_cb(struct connman_service *service, struct connman_device *device; const char *security; int err = 0; + int index; DBG("RequestInput return, %p", service); @@ -5852,6 +5860,10 @@ static void request_input_cb(struct connman_service *service, err = __connman_service_set_passphrase(service, passphrase); done: + index = __connman_service_get_index(service); + g_hash_table_remove(passphrase_requested, + GINT_TO_POINTER(index)); + if (err >= 0) { /* We forget any previous error. */ set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); @@ -6690,6 +6702,7 @@ static int service_connect(struct connman_service *service) int __connman_service_connect(struct connman_service *service, enum connman_service_connect_reason reason) { + int index; int err; DBG("service %p state %s connect reason %s -> %s", @@ -6777,6 +6790,13 @@ int __connman_service_connect(struct connman_service *service, if (service->hidden && err != -EINPROGRESS) service->pending = pending; + if (err == -EINPROGRESS) { + index = __connman_service_get_index(service); + g_hash_table_replace(passphrase_requested, + GINT_TO_POINTER(index), + GINT_TO_POINTER(true)); + } + return err; } } @@ -7748,6 +7768,8 @@ int __connman_service_init(void) service_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, service_free); + passphrase_requested = g_hash_table_new(g_direct_hash, g_direct_equal); + services_notify = g_new0(struct _services_notify, 1); services_notify->remove = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); @@ -7780,6 +7802,9 @@ void __connman_service_cleanup(void) g_hash_table_destroy(service_hash); service_hash = NULL; + g_hash_table_destroy(passphrase_requested); + passphrase_requested = NULL; + g_slist_free(counter_list); counter_list = NULL; |