Make WiFi passphrase enc/dec routine async to prevent mutual synchronous call to... 67/165367/2 accepted/tizen/unified/20171229.070248 submit/tizen/20171229.034008
authorJaehyun Kim <jeik01.kim@samsung.com>
Thu, 28 Dec 2017 11:02:31 +0000 (20:02 +0900)
committerJaehyun Kim <jeik01.kim@samsung.com>
Thu, 28 Dec 2017 11:11:46 +0000 (20:11 +0900)
Change-Id: Ic7795b430e92b7ee81d4c65b39ef1aa914fccc1a
Signed-off-by: Jaehyun Kim <jeik01.kim@samsung.com>
gsupplicant/gsupplicant.h
gsupplicant/supplicant.c
packaging/connman.spec
plugins/wifi.c

index 9177275..612ab5a 100755 (executable)
@@ -399,6 +399,7 @@ struct _GSupplicantCallbacks {
                                        const char *property);
 #if defined TIZEN_EXT
        void (*system_power_off) (void);
+       void (*assoc_failed) (void *user_data);
 #endif
        void (*add_station) (const char *mac);
        void (*remove_station) (const char *mac);
index d84c893..9b7e003 100755 (executable)
@@ -503,6 +503,17 @@ static void callback_network_merged(GSupplicantNetwork *network)
 
        callbacks_pointer->network_merged(network);
 }
+
+static void callback_assoc_failed(void *user_data)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->assoc_failed)
+               return;
+
+       callbacks_pointer->assoc_failed(user_data);
+}
 #endif
 
 static void callback_network_changed(GSupplicantNetwork *network,
@@ -5173,6 +5184,135 @@ static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
        dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
 }
 
+#if defined TIZEN_EXT
+#define NETCONFIG_SERVICE "net.netconfig"
+#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
+#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
+
+struct dec_method_call_data {
+       struct interface_connect_data *data;
+       DBusPendingCall *pending_call;
+};
+
+static struct dec_method_call_data decrypt_request_data;
+
+static void crypt_method_call_cancel(void)
+{
+       if (decrypt_request_data.pending_call) {
+               dbus_pending_call_cancel(decrypt_request_data.pending_call);
+               dbus_pending_call_unref(decrypt_request_data.pending_call);
+               decrypt_request_data.pending_call = NULL;
+       }
+
+       g_free(decrypt_request_data.data->path);
+       g_free(decrypt_request_data.data->ssid);
+       dbus_free(decrypt_request_data.data);
+       decrypt_request_data.data = NULL;
+}
+
+static void decryption_request_reply(DBusPendingCall *call,
+                                               void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter args;
+       char *out_data;
+       int ret;
+       static gchar* origin_value = NULL;
+       struct interface_connect_data *data = user_data;
+
+       g_free(origin_value);
+       origin_value = NULL;
+
+       SUPPLICANT_DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, reply)) {
+               SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       if (dbus_message_iter_init(reply, &args) == FALSE) {
+               SUPPLICANT_DBG("dbus_message_iter_init() failed");
+               goto done;
+       }
+
+       dbus_message_iter_get_basic(&args, &out_data);
+
+       origin_value = g_strdup((const gchar *)out_data);
+       data->ssid->passphrase = origin_value;
+
+       ret = supplicant_dbus_method_call(data->interface->path,
+               SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
+               interface_add_network_params,
+               interface_add_network_result, data,
+               data->interface);
+
+       if (ret < 0) {
+               SUPPLICANT_DBG("AddNetwork failed %d", ret);
+               callback_assoc_failed(decrypt_request_data.data->user_data);
+               g_free(data->path);
+               g_free(data->ssid);
+               dbus_free(data);
+       }
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+
+       decrypt_request_data.pending_call = NULL;
+       decrypt_request_data.data = NULL;
+}
+
+static int send_decryption_request(const char *passphrase,
+                       struct interface_connect_data *data)
+{
+       DBusMessage *msg = NULL;
+       DBusPendingCall *call;
+
+       SUPPLICANT_DBG("Decryption request");
+
+       if (!passphrase) {
+               SUPPLICANT_DBG("Invalid parameter");
+               return -EINVAL;
+       }
+
+       if (!connection)
+               return -EINVAL;
+
+       msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
+                       NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase");
+       if (!msg)
+               return -EINVAL;
+
+       dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
+                                                       DBUS_TYPE_INVALID);
+
+       if (!dbus_connection_send_with_reply(connection, msg,
+                               &call, DBUS_TIMEOUT_USE_DEFAULT)) {
+               dbus_message_unref(msg);
+               return -EIO;
+       }
+
+       if (!call) {
+               dbus_message_unref(msg);
+               return -EIO;
+       }
+
+       decrypt_request_data.pending_call = call;
+       decrypt_request_data.data = data;
+
+       dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL);
+       dbus_message_unref(msg);
+
+       SUPPLICANT_DBG("Decryption request succeeded");
+
+       return 0;
+}
+#endif
 
 int g_supplicant_interface_connect(GSupplicantInterface *interface,
                                GSupplicantSSID *ssid,
@@ -5210,6 +5350,13 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface,
                        "ProcessCredentials", DBUS_TYPE_BOOLEAN_AS_STRING,
                        wps_process_credentials, wps_start, data, interface);
        } else
+#if defined TIZEN_EXT
+               if (ssid->passphrase && g_strcmp0(ssid->passphrase, "") != 0) {
+                       ret = send_decryption_request(ssid->passphrase, data);
+                       if (ret < 0)
+                               SUPPLICANT_DBG("Decryption request failed %d", ret);
+               } else
+#endif
                ret = supplicant_dbus_method_call(interface->path,
                        SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
                        interface_add_network_params,
@@ -5334,7 +5481,17 @@ int g_supplicant_interface_disconnect(GSupplicantInterface *interface,
 
        if (!system_available)
                return -EFAULT;
+#if defined TIZEN_EXT
+       if (decrypt_request_data.pending_call &&
+                       decrypt_request_data.data &&
+                       decrypt_request_data.data->user_data == user_data) {
 
+               callback_assoc_failed(decrypt_request_data.data->user_data);
+               crypt_method_call_cancel();
+
+               return 0;
+       }
+#endif
        data = dbus_malloc0(sizeof(*data));
        if (!data)
                return -ENOMEM;
index 3560de5..fee387e 100755 (executable)
@@ -5,7 +5,7 @@
 
 Name:           connman
 Version:        1.29
-Release:        25
+Release:        26
 License:        GPL-2.0+
 Summary:        Connection Manager
 Url:            http://connman.net
index 9c453b3..995fab4 100755 (executable)
@@ -163,65 +163,115 @@ static void start_autoscan(struct connman_device *device);
 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
 
-static gchar* send_cryptographic_request(const char *passphrase, const char *method)
+struct enc_method_call_data {
+       DBusConnection *connection;
+       struct connman_network *network;
+};
+
+static struct enc_method_call_data encrypt_request_data;
+
+static void encryption_request_reply(DBusPendingCall *call,
+                                               void *user_data)
 {
-       DBusConnection *connection = NULL;
-       DBusMessage *msg = NULL, *reply = NULL;
+       DBusMessage *reply;
        DBusError error;
-       gchar *result;
-       const char *out_data;
+       DBusMessageIter args;
+       char *out_data;
+       struct connman_service *service;
+       gchar* encrypted_value = NULL;
+       struct connman_network *network = encrypt_request_data.network;
 
-       if (!passphrase || !method) {
-               DBG("Invalid parameter");
-               return NULL;
-       }
+       DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
 
        dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, reply)) {
+               DBG("send_encryption_request() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       if (dbus_message_iter_init(reply, &args) == FALSE)
+               goto done;
+
+       dbus_message_iter_get_basic(&args, &out_data);
+
+       encrypted_value = g_strdup((const gchar *)out_data);
+       service = connman_service_lookup_from_network(network);
+
+       if (!service) {
+               DBG("encryption result: no service");
+               goto done;
+       }
+
+       if (connman_service_get_favorite(service)) {
+               __connman_service_set_passphrase(service, encrypted_value);
+               __connman_service_save(service);
+       } else
+               connman_network_set_string(network, "WiFi.Passphrase",
+                                                       encrypted_value);
+
+       DBG("encryption result: succeeded");
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+       dbus_connection_unref(encrypt_request_data.connection);
+       g_free(encrypted_value);
+
+       encrypt_request_data.connection = NULL;
+       encrypt_request_data.network = NULL;
+}
+
+static int send_encryption_request(const char *passphrase,
+                               struct connman_network *network)
+{
+       DBusConnection *connection = NULL;
+       DBusMessage *msg = NULL;
+       DBusPendingCall *call;
+
+       if (!passphrase) {
+               DBG("Invalid parameter");
+               return -EINVAL;
+       }
 
        connection = connman_dbus_get_connection();
        if (!connection) {
                DBG("dbus connection does not exist");
-               return NULL;
+               return -EINVAL;
        }
 
        msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
-                       NETCONFIG_WIFI_INTERFACE, method);
+                       NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
        if (!msg) {
                dbus_connection_unref(connection);
-               return NULL;
+               return -EINVAL;
        }
 
        dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
                                                        DBUS_TYPE_INVALID);
 
-       reply = dbus_connection_send_with_reply_and_block(connection, msg,
-                                       DBUS_TIMEOUT_USE_DEFAULT, &error);
-       if (reply == NULL) {
-               if (dbus_error_is_set(&error)) {
-                       DBG("%s", error.message);
-                       dbus_error_free(&error);
-               } else {
-                       DBG("Failed to request cryptographic request");
-               }
-               dbus_connection_unref(connection);
+       if (!dbus_connection_send_with_reply(connection, msg,
+                               &call, DBUS_TIMEOUT_USE_DEFAULT)) {
                dbus_message_unref(msg);
-               return NULL;
+               dbus_connection_unref(connection);
+               return -EIO;
        }
 
-       dbus_message_unref(msg);
-       dbus_connection_unref(connection);
-
-       if (!dbus_message_get_args(reply, NULL,
-                               DBUS_TYPE_STRING, &out_data,
-                               DBUS_TYPE_INVALID)) {
-               dbus_message_unref(reply);
-               return NULL;
+       if (!call) {
+               dbus_message_unref(msg);
+               dbus_connection_unref(connection);
+               return -EIO;
        }
 
-       result = g_strdup((const gchar *)out_data);
-       dbus_message_unref(reply);
+       encrypt_request_data.connection = connection;
+       encrypt_request_data.network = network;
+
+       dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
+       dbus_message_unref(msg);
 
-       return result;
+       return 0;
 }
 #endif
 
@@ -2349,28 +2399,6 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
        ssid->security = network_security(security);
        ssid->passphrase = connman_network_get_string(network,
                                                "WiFi.Passphrase");
-#if defined TIZEN_EXT
-       /* Decrypt the passphrase
-        */
-        static gchar* origin_value = NULL;
-        gchar *passphrase = g_strdup(ssid->passphrase);
-        g_free(origin_value);
-        origin_value = NULL;
-
-        if (passphrase && g_strcmp0(passphrase, "") != 0) {
-                origin_value = send_cryptographic_request(passphrase,
-                                                        "DecryptPassphrase");
-
-                if (!origin_value) {
-                        DBG("Decryption failed");
-                } else {
-                        DBG("Decryption succeeded");
-                        ssid->passphrase = origin_value;
-                }
-
-        }
-        g_free(passphrase);
-#endif
        ssid->eap = connman_network_get_string(network, "WiFi.EAP");
 
        /*
@@ -2707,7 +2735,7 @@ static bool handle_wps_completion(GSupplicantInterface *interface,
 #if defined TIZEN_EXT
                /* Check the passphrase and encrypt it
                 */
-                gchar *encrypted_value = NULL;
+                int ret;
                 gchar *passphrase = g_strdup(wps_key);
 
                 connman_network_set_string(network, "WiFi.PinWPS", NULL);
@@ -2718,18 +2746,14 @@ static bool handle_wps_completion(GSupplicantInterface *interface,
                         return true;
                 }
 
-                encrypted_value = send_cryptographic_request(passphrase, "EncryptPassphrase");
+                ret = send_encryption_request(passphrase, network);
 
                 g_free(passphrase);
 
-                if (!encrypted_value) {
-                        DBG("[WPS] Encryption failed");
-                        return true;
-                }
-                DBG("[WPS] Encryption succeeded");
-                connman_network_set_string(network, "WiFi.Passphrase",
-                                encrypted_value);
-                g_free(encrypted_value);
+                if (!ret)
+                        DBG("[WPS] Encryption request succeeded");
+                else
+                        DBG("[WPS] Encryption request failed %d", ret);
 
 #else
                connman_network_set_string(network, "WiFi.Passphrase",
@@ -3687,6 +3711,12 @@ static void network_merged(GSupplicantNetwork *network)
 
        wifi->network = connman_network;
 }
+
+static void assoc_failed(void *user_data)
+{
+       struct connman_network *network = user_data;
+       connman_network_set_associating(network, false);
+}
 #endif
 
 static void debug(const char *str)
@@ -3743,7 +3773,8 @@ static const GSupplicantCallbacks callbacks = {
        .peer_request           = peer_request,
 #if defined TIZEN_EXT
        .system_power_off       = system_power_off,
-       .network_merged = network_merged,
+       .network_merged         = network_merged,
+       .assoc_failed           = assoc_failed,
 #endif
        .disconnect_reasoncode  = disconnect_reasoncode,
        .assoc_status_code      = assoc_status_code,