Add setter/getter for handling MAC randomization policy
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index 36625d0..bb1bfa7 100755 (executable)
 #include "dbus.h"
 #include "gsupplicant.h"
 
+#if defined TIZEN_EXT
+#include "setting.h"
+#endif
+
 #define IEEE80211_CAP_ESS      0x0001
 #define IEEE80211_CAP_IBSS     0x0002
 #define IEEE80211_CAP_PRIVACY  0x0010
@@ -306,6 +310,10 @@ struct g_supplicant_bss {
        dbus_bool_t sae;
        dbus_bool_t owe;
        dbus_bool_t dpp;
+       dbus_bool_t owe_transition_mode;
+       unsigned int transition_mode_ssid_len;
+       unsigned char transition_mode_bssid[6];
+       unsigned char transition_mode_ssid[32];
 #endif
 };
 
@@ -334,8 +342,10 @@ struct _GSupplicantNetwork {
        GSList *vsie_list;
        unsigned char country_code[COUNTRY_CODE_LENGTH];
        GSupplicantPhy_mode phy_mode;
-#endif
-#if defined TIZEN_EXT
+       dbus_bool_t owe_transition_mode;
+       unsigned int transition_mode_ssid_len;
+       unsigned char transition_mode_bssid[6];
+       unsigned char transition_mode_ssid[32];
        unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
        GHashTable *assoc_reject_table;
 #endif
@@ -388,6 +398,11 @@ struct interface_create_data {
        char *ifname;
        char *driver;
        char *bridge;
+#if defined TIZEN_EXT
+       unsigned int mac_addr;
+       unsigned int preassoc_mac_addr;
+       unsigned int random_mac_lifetime;
+#endif /* TIZEN_EXT */
 #if defined TIZEN_EXT_WIFI_MESH
        char *parent_ifname;
        bool is_mesh_interface;
@@ -450,12 +465,9 @@ struct assoc_count_data {
 };
 
 static unsigned int last_connected_bss_timeout = 0;
+static bool simplified_log = true;
 #endif
 
-static void interface_get_params(DBusMessageIter *iter, void *user_data);
-static void interface_get_result(const char *error,
-                               DBusMessageIter *iter, void *user_data);
-
 static int network_remove(struct interface_data *data);
 
 #if defined TIZEN_EXT_WIFI_MESH
@@ -1131,7 +1143,9 @@ static void debug_strvalmap(const char *label, struct strvalmap *map,
                                                        unsigned int val)
 {
        int i;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        for (i = 0; map[i].str; i++) {
                if (val & map[i].val)
                        SUPPLICANT_DBG("%s: %s", label, map[i].str);
@@ -1306,6 +1320,24 @@ static void interface_capability(const char *key, DBusMessageIter *iter,
                                key, dbus_message_iter_get_arg_type(iter));
 }
 
+static void set_bss_expiration_age(DBusMessageIter *iter, void *user_data)
+{
+       unsigned int bss_expiration_age = GPOINTER_TO_UINT(user_data);
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
+                               &bss_expiration_age);
+}
+
+int g_supplicant_interface_set_bss_expiration_age(GSupplicantInterface *interface,
+                                       unsigned int bss_expiration_age)
+{
+       return supplicant_dbus_property_set(interface->path,
+                                      SUPPLICANT_INTERFACE ".Interface",
+                                      "BSSExpireAge", DBUS_TYPE_UINT32_AS_STRING,
+                                      set_bss_expiration_age, NULL,
+                                      GUINT_TO_POINTER(bss_expiration_age), NULL);
+}
+
 struct set_apscan_data
 {
        unsigned int ap_scan;
@@ -1819,6 +1851,34 @@ const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
 
        return (const unsigned char *)network->best_bss->bssid;
 }
+dbus_bool_t g_supplicant_network_get_transition_mode(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return FALSE;
+
+       return network->owe_transition_mode;
+}
+
+
+const unsigned char *g_supplicant_network_get_transition_mode_bssid(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return NULL;
+
+       return (const unsigned char *)network->transition_mode_bssid;
+}
+
+const void *g_supplicant_network_get_transition_mode_ssid(GSupplicantNetwork *network,
+                                               unsigned int *transition_mode_ssid_len)
+{
+       if (!network) {
+               *transition_mode_ssid_len = 0;
+               return NULL;
+       }
+
+       *transition_mode_ssid_len = network->transition_mode_ssid_len;
+       return network->transition_mode_ssid;
+}
 
 unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
 {
@@ -2458,7 +2518,7 @@ static char *create_group(struct g_supplicant_bss *bss)
 
        return g_string_free(str, FALSE);
 }
-
+#if defined TIZEN_EXT
 static void update_network_with_best_bss(GSupplicantNetwork *network,
                struct g_supplicant_bss *best_bss)
 {
@@ -2502,7 +2562,7 @@ static bool update_best_bss(GSupplicantNetwork *network,
 
        return false;
 }
-
+#endif
 static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
 {
        GSupplicantInterface *interface = bss->interface;
@@ -2552,6 +2612,10 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        }
 
 #if defined TIZEN_EXT
+       network->owe_transition_mode = bss->owe_transition_mode;
+       memcpy(network->transition_mode_ssid, bss->transition_mode_ssid, bss->transition_mode_ssid_len);
+       memcpy(network->transition_mode_bssid, bss->transition_mode_bssid, WIFI_BSSID_LEN_MAX);
+
        network->keymgmt = bss->keymgmt;
 
        if (g_slist_length(bss->vsie_list) > 0) {
@@ -2822,6 +2886,7 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        unsigned int value;
        int ie_len;
 #if defined TIZEN_EXT
+       const unsigned char OWE_WFA_OUI[] = { 0x50, 0x6f, 0x9a, 0x1c };
        int r_len, j;
        unsigned char *rates = NULL;
        unsigned char *ext_rates = NULL;
@@ -2860,8 +2925,41 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 #if defined TIZEN_EXT
                unsigned char *vsie;
                int vsie_len = 0;
+
+               if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, OWE_WFA_OUI, sizeof(OWE_WFA_OUI)) == 0) {
+                       SUPPLICANT_DBG("IE: match vendor specific data : OWE Transition Mode");
+
+/*
+               Tag: Vendor Specific: Wi-Fi Alliance: OWE Transition Mode
+                       Tag Number: Vendor Specific (221)    -> ie[0]
+                       Tag length: 26                       -> ie[1]
+                       OUI: 50:6f:9a (Wi-Fi Alliance)       -> ie[2]
+                       Vendor Specific OUI Type: 28         -> ie[5]
+                       BSSID: 92:fd:f0:20:2b:09             -> ie[6]
+                       SSID length: 15                      -> ie[12]
+                       SSID: Wi-Fi-5.2.3-owe                -> ie[13]
+
+0000   dd 1a 50 6f 9a 1c 92 fd f0 20 2b 09 0f 57 69 2d   ..Po..... +..Wi-
+0010   46 69 2d 35 2e 32 2e 33 2d 6f 77 65               Fi-5.2.3-owe
+
+*/
+                       bss->owe_transition_mode = TRUE;
+                       if (ie[1] >= 11) { // Tag length is at least up to ssid length position.
+                               memcpy(bss->transition_mode_bssid, ie+6, WIFI_BSSID_LEN_MAX);
+                               if (ie[12] > 0 && ie[12] < 32) {
+                                       memcpy(bss->transition_mode_ssid, ie+13, ie[12]);
+                                       bss->transition_mode_ssid_len = ie[12];
+                               } else
+                                       bss->transition_mode_ssid_len = 0;
+                       } else
+                               bss->owe_transition_mode = FALSE;
+                       continue;
+               }
+
                if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
-                       SUPPLICANT_DBG("IE: match vendor specific data");
+
+                       if (!simplified_log)
+                               SUPPLICANT_DBG("IE: match vendor specific data");
 
                        vsie_len = ie[1]+2;     // tag number size(1), tag length size(1)
                        vsie = (unsigned char *)g_try_malloc0(vsie_len);
@@ -3027,7 +3125,7 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
        else if (bss->sae)
                bss->security = G_SUPPLICANT_SECURITY_SAE;
-       else if (bss->owe)
+       else if (bss->owe || bss->owe_transition_mode)
                bss->security = G_SUPPLICANT_SECURITY_OWE;
        else if (bss->dpp)
                bss->security = G_SUPPLICANT_SECURITY_DPP;
@@ -3046,7 +3144,9 @@ static void bss_property(const char *key, DBusMessageIter *iter,
 
        if (!bss->interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("key %s", key);
 
        if (!key)
@@ -3153,7 +3253,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
        GSupplicantNetwork *network;
        struct g_supplicant_bss *bss;
        const char *path = NULL;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        dbus_message_iter_get_basic(iter, &path);
@@ -3162,7 +3264,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
 
        if (g_strcmp0(path, "/") == 0)
                return NULL;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("%s", path);
 
        network = g_hash_table_lookup(interface->bss_mapping, path);
@@ -3187,7 +3291,9 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter,
                                                void *user_data)
 {
        struct g_supplicant_bss *bss;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        bss = interface_bss_added(iter, user_data);
@@ -3218,7 +3324,9 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter,
                                                void *user_data)
 {
        struct g_supplicant_bss *bss;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        bss = interface_bss_added(iter, user_data);
@@ -3451,7 +3559,9 @@ static void wps_property(const char *key, DBusMessageIter *iter,
 
        if (!interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("key: %s", key);
 
        if (g_strcmp0(key, "ConfigMethods") == 0) {
@@ -3496,7 +3606,9 @@ static void interface_property(const char *key, DBusMessageIter *iter,
 
        if (!interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("%s", key);
 
        if (!key) {
@@ -3921,7 +4033,9 @@ static void signal_interface_removed(const char *path, DBusMessageIter *iter)
 static void signal_interface_changed(const char *path, DBusMessageIter *iter)
 {
        GSupplicantInterface *interface;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
@@ -3971,7 +4085,9 @@ static void signal_scan_done(const char *path, DBusMessageIter *iter)
 static void signal_bss_added(const char *path, DBusMessageIter *iter)
 {
        GSupplicantInterface *interface;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
@@ -4105,6 +4221,9 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        unsigned int old_wps_capabilities;
        struct g_supplicant_bss *bss;
 
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(bss_mapping, path);
@@ -5240,7 +5359,7 @@ static void country_result(const char *error,
                regdom->callback(result, regdom->alpha2,
                                        (void *) regdom->user_data);
 
-       g_free(regdom);
+       dbus_free(regdom);
 }
 
 static void country_params(DBusMessageIter *iter, void *user_data)
@@ -5500,29 +5619,11 @@ static void interface_create_result(const char *error,
        struct interface_create_data *data = user_data;
        const char *path = NULL;
        int err;
-#if defined TIZEN_EXT
-       int ret;
-#endif
 
        SUPPLICANT_DBG("");
 
        if (error) {
                g_message("error %s", error);
-#if defined TIZEN_EXT
-               SUPPLICANT_DBG("error %s", error);
-               if (strcmp(error, "fi.w1.wpa_supplicant1.InterfaceExists") == 0) {
-                       SUPPLICANT_DBG("Send method: GetInterface");
-                       ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
-                                       SUPPLICANT_INTERFACE,
-                                       "GetInterface",
-                                       interface_get_params,
-                                       interface_get_result, user_data,
-                                       NULL);
-                       if (ret < 0)
-                               interface_create_data_free(data);
-                       return;
-               }
-#endif
                err = -EIO;
                goto done;
        }
@@ -5590,6 +5691,19 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data)
                                        DBUS_TYPE_STRING, &config_file);
        }
 
+#ifdef TIZEN_EXT
+       if (!g_strcmp0(data->driver, "wifi")) {
+               supplicant_dbus_dict_append_basic(&dict, "MacAddr",
+                               DBUS_TYPE_UINT32, &data->mac_addr);
+
+               supplicant_dbus_dict_append_basic(&dict, "PreassocMacAddr",
+                               DBUS_TYPE_UINT32, &data->preassoc_mac_addr);
+
+               supplicant_dbus_dict_append_basic(&dict, "RandAddrLifetime",
+                               DBUS_TYPE_UINT32, &data->random_mac_lifetime);
+       }
+#endif /* TIZEN_EXT */
+
 #if defined TIZEN_EXT_WIFI_MESH
        if (data->is_mesh_interface) {
                if (data->parent_ifname)
@@ -5659,6 +5773,9 @@ static void interface_get_result(const char *error,
        const char *path = NULL;
        int err;
 
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        if (error) {
@@ -5729,7 +5846,9 @@ done:
 static void interface_get_params(DBusMessageIter *iter, void *user_data)
 {
        struct interface_create_data *data = user_data;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
@@ -5872,7 +5991,6 @@ int g_supplicant_interface_create(const char *ifname, const char *driver,
        data->callback = callback;
        data->user_data = user_data;
 
-#if !defined TIZEN_EXT
        ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
                                                SUPPLICANT_INTERFACE,
                                                "GetInterface",
@@ -5881,16 +5999,6 @@ int g_supplicant_interface_create(const char *ifname, const char *driver,
                                                NULL);
        if (ret < 0)
                interface_create_data_free(data);
-#else
-       ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
-                                               SUPPLICANT_INTERFACE,
-                                               "CreateInterface",
-                                               interface_create_params,
-                                               interface_create_result, data,
-                                               NULL);
-       if (ret < 0)
-               interface_create_data_free(data);
-#endif
 
        return ret;
 }
@@ -7076,7 +7184,10 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
                add_network_security_proto(dict, ssid);
                break;
        case G_SUPPLICANT_SECURITY_SAE:
-               key_mgmt = "SAE";
+               if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK)
+                       key_mgmt = "SAE WPA-PSK"; // WFA (WPA3 & WPA2 Mixed -> WPA2 only)
+               else
+                       key_mgmt = "SAE";
                add_network_security_psk(dict, ssid);
                break;
        case G_SUPPLICANT_SECURITY_OWE:
@@ -7159,7 +7270,11 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
                                                ssid->ssid_len);
 
 #if defined TIZEN_EXT
-       if (ssid->bssid) {
+       bool owe_transition_mode = FALSE;
+       if ((ssid->security == G_SUPPLICANT_SECURITY_OWE) && !(ssid->keymgmt & G_SUPPLICANT_KEYMGMT_OWE))
+               owe_transition_mode = TRUE;
+
+       if (ssid->bssid && !owe_transition_mode) {
                char *bssid = NULL;
                bssid = g_try_malloc0(18);
                if (bssid == NULL) {
@@ -7388,8 +7503,16 @@ static int send_decryption_request(const char *passphrase,
        if (!msg)
                return -EINVAL;
 
+#if defined TIZEN_EXT
+       if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
+                                                       DBUS_TYPE_INVALID)) {
+               SUPPLICANT_DBG("Could not fulfill decryption request");
+               return -ENOMEM;
+       }
+#else
        dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
                                                        DBUS_TYPE_INVALID);
+#endif
 
        if (!dbus_connection_send_with_reply(connection, msg,
                                &call, DBUS_TIMEOUT_USE_DEFAULT)) {
@@ -8434,7 +8557,9 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
                connection = NULL;
                return -EIO;
        }
-
+#if defined TIZEN_EXT
+       simplified_log = connman_setting_get_bool("SimplifiedLog");
+#endif
        callbacks_pointer = callbacks;
        eap_methods = 0;
 
@@ -8573,3 +8698,176 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
        callbacks_pointer = NULL;
        eap_methods = 0;
 }
+
+#ifdef TIZEN_EXT
+struct supplicant_mac_policy {
+       GSupplicantMacPolicyCallback callback;
+       dbus_uint32_t policy;
+       const void *user_data;
+};
+
+static void mac_policy_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_mac_policy *data = user_data;
+       int result = 0;
+
+       if (!user_data)
+               return;
+
+       if (error) {
+               SUPPLICANT_DBG("Mac policy setting failure %s", error);
+               result = -EINVAL;
+       }
+
+       if (data->callback)
+               data->callback(result, data->policy,
+                                       (void *) data->user_data);
+
+       dbus_free(data);
+}
+
+static void mac_policy_params(DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_mac_policy *data = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &(data->policy));
+}
+
+int g_supplicant_interface_set_mac_policy(GSupplicantInterface *interface,
+                                       GSupplicantMacPolicyCallback callback,
+                                                       unsigned int policy,
+                                                       void *user_data)
+{
+       struct supplicant_mac_policy *data = NULL;
+       int ret;
+
+       if (!system_available)
+               return -EFAULT;
+
+       if (!interface)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->callback = callback;
+       data->policy = policy;
+       data->user_data = user_data;
+
+       ret =  supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface",
+                               "MacAddr", DBUS_TYPE_INT32_AS_STRING,
+                               mac_policy_params, mac_policy_result, data, NULL);
+       if (ret < 0) {
+               SUPPLICANT_DBG("Unable to set MacAddr configuration");
+               dbus_free(data);
+       }
+
+       return ret;
+}
+
+int g_supplicant_interface_set_preassoc_mac_policy(GSupplicantInterface *interface,
+                                       GSupplicantMacPolicyCallback callback,
+                                                       unsigned int policy,
+                                                       void *user_data)
+{
+       struct supplicant_mac_policy *data;
+       int ret;
+
+       if (!system_available)
+               return -EFAULT;
+
+       if (!interface)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->callback = callback;
+       data->policy = policy;
+       data->user_data = user_data;
+
+       ret =  supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface",
+                               "PreassocMacAddr", DBUS_TYPE_INT32_AS_STRING,
+                               mac_policy_params, mac_policy_result, data, NULL);
+       if (ret < 0) {
+               SUPPLICANT_DBG("Unable to set PreassocMacAddr configuration");
+               dbus_free(data);
+       }
+
+       return ret;
+}
+
+struct supplicant_random_mac_lifetime {
+       GSupplicantRandomMaclifetimeCallback callback;
+       dbus_uint32_t lifetime;
+       const void *user_data;
+};
+
+static void random_mac_lifetime_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_random_mac_lifetime *data = user_data;
+       int result = 0;
+
+       if (!user_data)
+               return;
+
+       if (error) {
+               SUPPLICANT_DBG("Random Mac lifetime setting failure %s", error);
+               result = -EINVAL;
+       }
+
+       if (data->callback)
+               data->callback(result, data->lifetime,
+                                       (void *) data->user_data);
+
+       dbus_free(data);
+}
+
+static void random_mac_lifetime_params(DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_random_mac_lifetime *data = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &(data->lifetime));
+}
+
+int g_supplicant_interface_set_random_mac_lifetime(GSupplicantInterface *interface,
+                                       GSupplicantRandomMaclifetimeCallback callback,
+                                                       unsigned int lifetime,
+                                                       void *user_data)
+{
+       struct supplicant_random_mac_lifetime *data;
+       int ret;
+
+       if (!system_available)
+               return -EFAULT;
+
+       if (!interface)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->callback = callback;
+       data->lifetime = lifetime;
+       data->user_data = user_data;
+
+       ret =  supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface",
+                               "RandAddrLifetime", DBUS_TYPE_UINT32_AS_STRING,
+                               random_mac_lifetime_params, random_mac_lifetime_result,
+                               data, NULL);
+       if (ret < 0) {
+               SUPPLICANT_DBG("Unable to set RandAddrLifetime configuration");
+               dbus_free(data);
+       }
+
+       return ret;
+}
+#endif