Merge "Add support for WPS2-PSK security type in Security property of service interfa...
[platform/upstream/connman.git] / gsupplicant / supplicant.c
old mode 100644 (file)
new mode 100755 (executable)
index cd91f95..806b4bd
@@ -224,6 +224,12 @@ struct _GSupplicantNetwork {
        unsigned int wps_capabilities;
        GHashTable *bss_table;
        GHashTable *config_table;
+#if defined TIZEN_EXT
+       unsigned int isHS20AP;
+       char *eap;
+       char *identity;
+       char *phase2;
+#endif
 };
 
 struct _GSupplicantPeer {
@@ -410,6 +416,7 @@ static void callback_interface_removed(GSupplicantInterface *interface)
        callbacks_pointer->interface_removed(interface);
 }
 
+#if !defined TIZEN_EXT
 static void callback_p2p_support(GSupplicantInterface *interface)
 {
        SUPPLICANT_DBG("");
@@ -420,6 +427,7 @@ static void callback_p2p_support(GSupplicantInterface *interface)
        if (callbacks_pointer && callbacks_pointer->p2p_support)
                callbacks_pointer->p2p_support(interface);
 }
+#endif
 
 static void callback_scan_started(GSupplicantInterface *interface)
 {
@@ -465,6 +473,19 @@ static void callback_network_removed(GSupplicantNetwork *network)
        callbacks_pointer->network_removed(network);
 }
 
+#if defined TIZEN_EXT
+static void callback_network_merged(GSupplicantNetwork *network)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->network_merged)
+               return;
+
+       callbacks_pointer->network_merged(network);
+}
+#endif
+
 static void callback_network_changed(GSupplicantNetwork *network,
                                        const char *property)
 {
@@ -565,6 +586,9 @@ static void remove_interface(gpointer data)
        g_free(interface->wps_cred.key);
        g_free(interface->path);
        g_free(interface->network_path);
+#if defined TIZEN_EXT
+       interface->network_path = NULL;
+#endif
        g_free(interface->ifname);
        g_free(interface->driver);
        g_free(interface->bridge);
@@ -584,6 +608,11 @@ static void remove_network(gpointer data)
        g_free(network->path);
        g_free(network->group);
        g_free(network->name);
+#if defined TIZEN_EXT
+       g_free(network->eap);
+       g_free(network->identity);
+       g_free(network->phase2);
+#endif
        g_free(network);
 }
 
@@ -897,6 +926,9 @@ unsigned int g_supplicant_interface_get_max_scan_ssids(
        if (!interface)
                return 0;
 
+       if (interface->max_scan_ssids == 0)
+               return WPAS_MAX_SCAN_SSIDS;
+
        return interface->max_scan_ssids;
 }
 
@@ -1097,6 +1129,40 @@ const char *g_supplicant_peer_get_name(GSupplicantPeer *peer)
        return peer->name;
 }
 
+#if defined TIZEN_EXT
+unsigned int g_supplicant_network_is_hs20AP(GSupplicantNetwork *network)
+{
+       if (!network)
+               return 0;
+
+       return network->isHS20AP;
+}
+
+const char *g_supplicant_network_get_eap(GSupplicantNetwork *network)
+{
+       if (!network || !network->eap)
+               return NULL;
+
+       return network->eap;
+}
+
+const char *g_supplicant_network_get_identity(GSupplicantNetwork *network)
+{
+       if (!network || !network->identity)
+               return NULL;
+
+       return network->identity;
+}
+
+const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
+{
+       if (!network || !network->phase2)
+               return NULL;
+
+       return network->phase2;
+}
+#endif
+
 const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
                                                                int *length)
 {
@@ -1179,16 +1245,89 @@ bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer)
        return peer->connection_requested;
 }
 
+#if defined TIZEN_EXT
+/*
+ * Description: Network client requires additional wifi specific info
+ */
+const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return NULL;
+
+       return (const unsigned char *)network->best_bss->bssid;
+}
+
+unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return 0;
+
+       return network->best_bss->maxrate;
+}
+
+const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return NULL;
+
+       if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
+           network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
+               unsigned int pairwise;
+
+               pairwise = network->best_bss->rsn_pairwise |
+                               network->best_bss->wpa_pairwise;
+
+               if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) &&
+                   (pairwise & G_SUPPLICANT_PAIRWISE_TKIP))
+                       return "mixed";
+               else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP)
+                       return "aes";
+               else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)
+                       return "tkip";
+
+       } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP)
+               return "wep";
+       else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE)
+               return "none";
+
+       return NULL;
+}
+
+bool g_supplicant_network_get_rsn_selected(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return 0;
+
+       if (network->best_bss->rsn_selected)
+               return true;
+       else
+               return false;
+}
+
+#endif
+
 static void merge_network(GSupplicantNetwork *network)
 {
        GString *str;
        const char *ssid, *mode, *key_mgmt;
+#if defined TIZEN_EXT
+       GSupplicantInterface *interface;
+       const char *isHS20AP;
+       const char *eap, *identity, *phase2;
+#endif
        unsigned int i, ssid_len;
        char *group;
 
        ssid = g_hash_table_lookup(network->config_table, "ssid");
        mode = g_hash_table_lookup(network->config_table, "mode");
        key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt");
+#if defined TIZEN_EXT
+       isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP");
+       eap = g_hash_table_lookup(network->config_table, "eap");
+       identity = g_hash_table_lookup(network->config_table, "identity");
+       phase2 = g_hash_table_lookup(network->config_table, "phase2");
+       interface = network->interface;
+#endif
 
        SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
 
@@ -1202,7 +1341,14 @@ static void merge_network(GSupplicantNetwork *network)
                return;
 
        for (i = 0; i < ssid_len; i++)
+#if defined TIZEN_EXT
+       {
+               if (ssid[i] != '"')
+#endif
                g_string_append_printf(str, "%02x", ssid[i]);
+#if defined TIZEN_EXT
+       }
+#endif
 
        if (g_strcmp0(mode, "0") == 0)
                g_string_append_printf(str, "_managed");
@@ -1211,11 +1357,41 @@ static void merge_network(GSupplicantNetwork *network)
 
        if (g_strcmp0(key_mgmt, "WPA-PSK") == 0)
                g_string_append_printf(str, "_psk");
+#if defined TIZEN_EXT
+       else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0)
+               g_string_append_printf(str, "_ieee8021x");
+       else
+               g_string_append_printf(str, "_none");
+#endif
 
        group = g_string_free(str, FALSE);
 
        SUPPLICANT_DBG("%s", group);
 
+#if defined TIZEN_EXT
+       if (g_strcmp0(isHS20AP, "1") == 0) {
+               network->isHS20AP = 1;
+               if (network->eap)
+                       g_free(network->eap);
+               network->eap = g_strdup(eap);
+
+               if (network->identity)
+                       g_free(network->identity);
+               network->identity = g_strdup(identity);
+
+               if (network->phase2)
+                       g_free(network->phase2);
+               network->phase2 = g_strdup(phase2);
+       } else
+               network->isHS20AP = 0;
+
+       if (interface)
+               interface->network_path = g_strdup(network->path);
+
+       network->group = g_strdup(group);
+       callback_network_merged(network);
+#endif
+
        g_free(group);
 
        g_hash_table_destroy(network->config_table);
@@ -1977,8 +2153,10 @@ static void interface_property(const char *key, DBusMessageIter *iter,
        if (g_strcmp0(key, "Capabilities") == 0) {
                supplicant_dbus_property_foreach(iter, interface_capability,
                                                                interface);
+#if !defined TIZEN_EXT
                if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P)
                        interface->p2p_support = true;
+#endif
        } else if (g_strcmp0(key, "State") == 0) {
                const char *str = NULL;
 
@@ -2450,8 +2628,23 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
                return;
        }
 
+#if defined TIZEN_EXT
+       if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
+               network->wps = TRUE;
+               network->wps_capabilities |= bss->wps_capabilities;
+       } else
+               network->wps = FALSE;
+#endif
+
        if (bss->signal == network->signal)
+#ifndef TIZEN_EXT
                return;
+#else
+       {
+               callback_network_changed(network, "");
+               return;
+       }
+#endif
 
        /*
         * If the new signal is lower than the SSID signal, we need
@@ -2459,7 +2652,14 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
         */
        if (bss->signal < network->signal) {
                if (bss != network->best_bss)
+#ifndef TIZEN_EXT
+                       return;
+#else
+               {
+                       callback_network_changed(network, "");
                        return;
+               }
+#endif
                network->signal = bss->signal;
                update_network_signal(network);
        } else {
@@ -2561,7 +2761,7 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter)
 
        if (g_strcmp0(name, "success") == 0)
                interface->wps_state = G_SUPPLICANT_WPS_STATE_SUCCESS;
-       else if (g_strcmp0(name, "fail") == 0)
+       else if (g_strcmp0(name, "failed") == 0)
                interface->wps_state = G_SUPPLICANT_WPS_STATE_FAIL;
        else
                interface->wps_state = G_SUPPLICANT_WPS_STATE_UNKNOWN;
@@ -2574,6 +2774,79 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter)
        supplicant_dbus_property_foreach(iter, wps_event_args, interface);
 }
 
+#if defined TIZEN_EXT
+static void signal_power_off(const char *path, DBusMessageIter *iter)
+{
+       int poweroff_state = 0;
+
+       dbus_message_iter_get_basic(iter, &poweroff_state);
+
+       SUPPLICANT_DBG("poweroff_state(%d)", poweroff_state);
+
+       /* POWER_OFF_DIRECT 2 && POWER_OFF_RESTART 3 */
+       if (poweroff_state != 2 && poweroff_state != 3)
+               return;
+
+       if (callbacks_pointer == NULL)
+               return;
+
+       if (callbacks_pointer->system_power_off == NULL)
+               return;
+
+       callbacks_pointer->system_power_off();
+}
+#endif
+
+static void signal_station_connected(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       const char *sta_mac = NULL;
+
+       SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
+
+       if (callbacks_pointer->add_station == NULL)
+               return;
+
+       if (g_strcmp0(path, "/") == 0)
+               return;
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (interface == NULL)
+               return;
+
+       dbus_message_iter_get_basic(iter, &sta_mac);
+       if (sta_mac == NULL)
+               return;
+
+       SUPPLICANT_DBG("New station %s connected", sta_mac);
+       callbacks_pointer->add_station(sta_mac);
+}
+
+static void signal_station_disconnected(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       const char *sta_mac = NULL;
+
+       SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
+
+       if (callbacks_pointer->remove_station == NULL)
+               return;
+
+       if (g_strcmp0(path, "/") == 0)
+               return;
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (interface == NULL)
+               return;
+
+       dbus_message_iter_get_basic(iter, &sta_mac);
+       if (sta_mac == NULL)
+               return;
+
+       SUPPLICANT_DBG("Station %s disconnected", sta_mac);
+       callbacks_pointer->remove_station(sta_mac);
+}
+
 static void create_peer_identifier(GSupplicantPeer *peer)
 {
        const unsigned char test[ETH_ALEN] = {};
@@ -3138,6 +3411,12 @@ static struct {
 
        { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
        { SUPPLICANT_INTERFACE ".Interface.WPS", "Event",       signal_wps_event       },
+#if defined TIZEN_EXT
+       { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
+#endif
+
+       { SUPPLICANT_INTERFACE".Interface", "StaAuthorized", signal_station_connected      },
+       { SUPPLICANT_INTERFACE".Interface", "StaDeauthorized", signal_station_disconnected },
 
        { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
        { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost",  signal_peer_lost  },
@@ -3478,7 +3757,9 @@ static void interface_create_property(const char *key, DBusMessageIter *iter,
        if (!key) {
                if (data->callback) {
                        data->callback(0, data->interface, data->user_data);
+#if !defined TIZEN_EXT
                        callback_p2p_support(interface);
+#endif
                }
 
                interface_create_data_free(data);
@@ -3588,7 +3869,9 @@ static void interface_get_result(const char *error,
 
        if (data->callback) {
                data->callback(0, interface, data->user_data);
+#if !defined TIZEN_EXT
                callback_p2p_support(interface);
+#endif
        }
 
        interface_create_data_free(data);
@@ -3945,8 +4228,13 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
 
        data->interface = interface;
        data->path = g_strdup(interface->path);
+#if defined TIZEN_EXT
+       data->interface->scan_callback = data->callback = callback;
+       data->interface->scan_data = data->user_data = user_data;
+#else
        data->callback = callback;
        data->user_data = user_data;
+#endif
        data->scan_params = scan_data;
 
         interface->scan_callback = callback;
@@ -4214,8 +4502,10 @@ static void add_network_security_tls(DBusMessageIter *dict,
        if (!ssid->private_key_path)
                return;
 
+#if !defined TIZEN_EXT
        if (!ssid->private_key_passphrase)
                return;
+#endif
 
        if (ssid->ca_cert_path)
                supplicant_dbus_dict_append_basic(dict, "ca_cert",
@@ -4224,9 +4514,11 @@ static void add_network_security_tls(DBusMessageIter *dict,
        supplicant_dbus_dict_append_basic(dict, "private_key",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_path);
+#if !defined TIZEN_EXT
        supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_passphrase);
+#endif
        supplicant_dbus_dict_append_basic(dict, "client_cert",
                                                DBUS_TYPE_STRING,
                                                &ssid->client_cert_path);
@@ -4258,8 +4550,10 @@ static void add_network_security_peap(DBusMessageIter *dict,
                if (!ssid->private_key_path)
                        return;
 
+#if !defined TIZEN_EXT
                if (!ssid->private_key_passphrase)
                        return;
+#endif
 
                supplicant_dbus_dict_append_basic(dict, "client_cert",
                                                DBUS_TYPE_STRING,
@@ -4269,9 +4563,11 @@ static void add_network_security_peap(DBusMessageIter *dict,
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_path);
 
+#if !defined TIZEN_EXT
                supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_passphrase);
+#endif
 
        }
 
@@ -4302,14 +4598,27 @@ static void add_network_security_eap(DBusMessageIter *dict,
 {
        char *eap_value;
 
+#if defined TIZEN_EXT
+       if (!ssid->eap)
+#else
        if (!ssid->eap || !ssid->identity)
+#endif
                return;
 
        if (g_strcmp0(ssid->eap, "tls") == 0) {
                add_network_security_tls(dict, ssid);
        } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
                                g_strcmp0(ssid->eap, "ttls") == 0) {
+#if defined TIZEN_EXT
+               if (!ssid->identity)
+                       return;
+#endif
                add_network_security_peap(dict, ssid);
+
+#if defined TIZEN_EXT
+       } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
+                       g_strcmp0(ssid->eap, "aka") == 0) {
+#endif
        } else
                return;
 
@@ -4318,9 +4627,16 @@ static void add_network_security_eap(DBusMessageIter *dict,
        supplicant_dbus_dict_append_basic(dict, "eap",
                                                DBUS_TYPE_STRING,
                                                &eap_value);
+#if defined TIZEN_EXT
+       if (ssid->identity != NULL)
+               supplicant_dbus_dict_append_basic(dict, "identity",
+                                                       DBUS_TYPE_STRING,
+                                                       &ssid->identity);
+#else
        supplicant_dbus_dict_append_basic(dict, "identity",
                                                DBUS_TYPE_STRING,
                                                &ssid->identity);
+#endif
 
        g_free(eap_value);
 }
@@ -4500,6 +4816,10 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
                                        DBUS_TYPE_BYTE, &ssid->ssid,
                                                ssid->ssid_len);
 
+       supplicant_dbus_dict_append_basic(&dict, "ignore_broadcast_ssid",
+                                       DBUS_TYPE_INT32,
+                                       &ssid->ignore_broadcast_ssid);
+
        supplicant_dbus_dict_close(iter, &dict);
 }
 
@@ -4507,10 +4827,18 @@ static void interface_wps_start_result(const char *error,
                                DBusMessageIter *iter, void *user_data)
 {
        struct interface_connect_data *data = user_data;
+       int err;
 
        SUPPLICANT_DBG("");
-       if (error)
+
+       err = 0;
+       if (error) {
                SUPPLICANT_DBG("error: %s", error);
+               err = parse_supplicant_error(iter);
+       }
+
+       if(data->callback)
+               data->callback(err, data->interface, data->user_data);
 
        g_free(data->path);
        g_free(data->ssid);
@@ -4541,6 +4869,12 @@ static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
        supplicant_dbus_dict_append_basic(&dict, "Type",
                                        DBUS_TYPE_STRING, &type);
 
+#if defined TIZEN_EXT
+       if (ssid->bssid)
+               supplicant_dbus_dict_append_fixed_array(&dict, "Bssid",
+                                               DBUS_TYPE_BYTE, &ssid->bssid, 6);
+#endif
+
        supplicant_dbus_dict_close(iter, &dict);
 }
 
@@ -4557,7 +4891,17 @@ static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
                dbus_free(data);
                return;
        }
-
+#if defined TIZEN_EXT
+       GSupplicantSSID *ssid = data->ssid;
+       if (ssid->pin_wps != NULL) {
+               if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) {
+                       SUPPLICANT_DBG("Invalid characters in WPS_PIN");
+                       g_free(data->ssid);
+                       dbus_free(data);
+                       return;
+               }
+       }
+#endif
        supplicant_dbus_method_call(data->interface->path,
                        SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
                        interface_add_wps_params,
@@ -4664,6 +5008,16 @@ static int network_remove(struct interface_data *data)
 
        SUPPLICANT_DBG("");
 
+#if defined TIZEN_EXT
+       GSupplicantInterface *intf = NULL;
+       /*
+        * Check if 'interface' is valid
+        */
+       intf = g_hash_table_lookup(interface_table, interface->path);
+       if (intf == NULL)
+               return -EINVAL;
+#endif
+
        return supplicant_dbus_method_call(interface->path,
                        SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
                        network_remove_params, network_remove_result, data,
@@ -5202,12 +5556,14 @@ static const char *g_supplicant_rule4 = "type=signal,"
                        "interface=" SUPPLICANT_INTERFACE ".BSS";
 static const char *g_supplicant_rule5 = "type=signal,"
                        "interface=" SUPPLICANT_INTERFACE ".Network";
+#if !defined TIZEN_EXT
 static const char *g_supplicant_rule6 = "type=signal,"
                "interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice";
 static const char *g_supplicant_rule7 = "type=signal,"
                "interface=" SUPPLICANT_INTERFACE ".Peer";
 static const char *g_supplicant_rule8 = "type=signal,"
                "interface=" SUPPLICANT_INTERFACE ".Group";
+#endif
 
 static void invoke_introspect_method(void)
 {
@@ -5262,9 +5618,16 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
        dbus_bus_add_match(connection, g_supplicant_rule3, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule4, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule5, NULL);
+#if defined TIZEN_EXT
+       dbus_bus_add_match(connection,
+                       "type=signal,interface=org.tizen.system.deviced.PowerOff,"
+                       "member=ChangeState", NULL);
+#endif
+#if !defined TIZEN_EXT
        dbus_bus_add_match(connection, g_supplicant_rule6, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule7, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule8, NULL);
+#endif
        dbus_connection_flush(connection);
 
        if (dbus_bus_name_has_owner(connection,
@@ -5306,9 +5669,11 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
        SUPPLICANT_DBG("");
 
        if (connection) {
+#if !defined TIZEN_EXT
                dbus_bus_remove_match(connection, g_supplicant_rule8, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule7, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule6, NULL);
+#endif
                dbus_bus_remove_match(connection, g_supplicant_rule5, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule4, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule3, NULL);