139287Ssos/* 239643Syokota * WPA Supplicant / dbus-based control interface 339287Ssos * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 439287Ssos * 539287Ssos * This software may be distributed under the terms of the BSD license. 639287Ssos * See README for more details. 739287Ssos */ 839287Ssos 939643Syokota#include "includes.h" 1039643Syokota#include <dbus/dbus.h> 1139287Ssos 1239287Ssos#include "common.h" 1339287Ssos#include "eap_peer/eap_methods.h" 1439287Ssos#include "common/ieee802_11_defs.h" 1539643Syokota#include "eapol_supp/eapol_supp_sm.h" 1639643Syokota#include "rsn_supp/wpa.h" 1739643Syokota#include "../config.h" 1839643Syokota#include "../wpa_supplicant_i.h" 1939643Syokota#include "../driver_i.h" 2039643Syokota#include "../notify.h" 2139643Syokota#include "../wpas_glue.h" 2239643Syokota#include "../bss.h" 2339643Syokota#include "../scan.h" 2439643Syokota#include "dbus_old.h" 2539287Ssos#include "dbus_old_handlers.h" 2650477Speter#include "dbus_dict_helpers.h" 2739287Ssos 2839287Ssosextern int wpa_debug_level; 2942504Syokotaextern int wpa_debug_show_keys; 3066710Sjhbextern int wpa_debug_timestamp; 3139287Ssos 3256836Speter/** 3339287Ssos * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message 3439287Ssos * @message: Pointer to incoming dbus message this error refers to 3539287Ssos * Returns: a dbus error message 3639287Ssos * 3742179Syokota * Convenience function to create and return an invalid options error 3839287Ssos */ 3948104SyokotaDBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message, 4048104Syokota const char *arg) 4139287Ssos{ 4248104Syokota DBusMessage *reply; 4348104Syokota 4439287Ssos reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS, 4539287Ssos "Did not receive correct message " 4639287Ssos "arguments."); 4739287Ssos if (arg != NULL) 4839287Ssos dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg, 4939287Ssos DBUS_TYPE_INVALID); 5039287Ssos 5142504Syokota return reply; 5242504Syokota} 5339287Ssos 5442504Syokota 5542504Syokota/** 5642504Syokota * wpas_dbus_new_success_reply - Return a new success reply message 5742504Syokota * @message: Pointer to incoming dbus message this reply refers to 5842504Syokota * Returns: a dbus message containing a single UINT32 that indicates 5942504Syokota * success (ie, a value of 1) 6042504Syokota * 6142611Syokota * Convenience function to create and return a success reply message 6242504Syokota */ 6342504SyokotaDBusMessage * wpas_dbus_new_success_reply(DBusMessage *message) 6439287Ssos{ 6539287Ssos DBusMessage *reply; 6639287Ssos unsigned int success = 1; 6739287Ssos 6839287Ssos reply = dbus_message_new_method_return(message); 6939287Ssos dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success, 7039287Ssos DBUS_TYPE_INVALID); 7139287Ssos return reply; 7239287Ssos} 7339287Ssos 7439287Ssos 7539287Ssos/** 7639287Ssos * wpas_dbus_global_add_interface - Request registration of a network interface 7748399Speter * @message: Pointer to incoming dbus message 7842504Syokota * @global: %wpa_supplicant global data structure 7948399Speter * Returns: The object path of the new interface object, 8048104Syokota * or a dbus error message with more information 8142504Syokota * 8239287Ssos * Handler function for "addInterface" method call. Handles requests 8339287Ssos * by dbus clients to register a network interface that wpa_supplicant 8439287Ssos * will manage. 8539287Ssos */ 8639287SsosDBusMessage * wpas_dbus_global_add_interface(DBusMessage *message, 8739287Ssos struct wpa_global *global) 8839287Ssos{ 8939287Ssos char *ifname = NULL; 9039287Ssos char *driver = NULL; 9139287Ssos char *driver_param = NULL; 9239287Ssos char *confname = NULL; 9339287Ssos char *bridge_ifname = NULL; 9439287Ssos DBusMessage *reply = NULL; 9539287Ssos DBusMessageIter iter; 9639287Ssos 9742504Syokota dbus_message_iter_init(message, &iter); 9848104Syokota 9942504Syokota /* First argument: interface name (DBUS_TYPE_STRING) 10048104Syokota * Required; must be non-zero length 10148104Syokota */ 10248104Syokota if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 10348104Syokota goto error; 10439287Ssos dbus_message_iter_get_basic(&iter, &ifname); 10548104Syokota if (!os_strlen(ifname)) 10644846Sjlemon goto error; 10739287Ssos 10842504Syokota /* Second argument: dict of options */ 10942504Syokota if (dbus_message_iter_next(&iter)) { 11042504Syokota DBusMessageIter iter_dict; 11142504Syokota struct wpa_dbus_dict_entry entry; 11242504Syokota 11342504Syokota if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 11442504Syokota goto error; 11542504Syokota while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 11642504Syokota if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 11742504Syokota goto error; 11842504Syokota if (!strcmp(entry.key, "driver") && 11942504Syokota (entry.type == DBUS_TYPE_STRING)) { 12042504Syokota driver = os_strdup(entry.str_value); 12142504Syokota wpa_dbus_dict_entry_clear(&entry); 12242504Syokota if (driver == NULL) 12342504Syokota goto error; 12442504Syokota } else if (!strcmp(entry.key, "driver-params") && 12542504Syokota (entry.type == DBUS_TYPE_STRING)) { 12648104Syokota driver_param = os_strdup(entry.str_value); 12742504Syokota wpa_dbus_dict_entry_clear(&entry); 12848104Syokota if (driver_param == NULL) 12948104Syokota goto error; 13048104Syokota } else if (!strcmp(entry.key, "config-file") && 13148104Syokota (entry.type == DBUS_TYPE_STRING)) { 13248104Syokota confname = os_strdup(entry.str_value); 13348104Syokota wpa_dbus_dict_entry_clear(&entry); 13439287Ssos if (confname == NULL) 13539287Ssos goto error; 13639287Ssos } else if (!strcmp(entry.key, "bridge-ifname") && 13742504Syokota (entry.type == DBUS_TYPE_STRING)) { 13839287Ssos bridge_ifname = os_strdup(entry.str_value); 13939287Ssos wpa_dbus_dict_entry_clear(&entry); 14039287Ssos if (bridge_ifname == NULL) 14139287Ssos goto error; 14239287Ssos } else { 14339287Ssos wpa_dbus_dict_entry_clear(&entry); 14448104Syokota goto error; 14539287Ssos } 14648104Syokota } 14748104Syokota } 14848104Syokota 14948104Syokota /* 15039287Ssos * Try to get the wpa_supplicant record for this iface, return 15139287Ssos * an error if we already control it. 15239287Ssos */ 15339287Ssos if (wpa_supplicant_get_iface(global, ifname) != NULL) { 15439858Syokota reply = dbus_message_new_error(message, 15539858Syokota WPAS_ERROR_EXISTS_ERROR, 15639858Syokota "wpa_supplicant already " 15739858Syokota "controls this interface."); 15839287Ssos } else { 15939287Ssos struct wpa_supplicant *wpa_s; 16039287Ssos struct wpa_interface iface; 16139287Ssos os_memset(&iface, 0, sizeof(iface)); 16242504Syokota iface.ifname = ifname; 16339287Ssos iface.driver = driver; 16439287Ssos iface.driver_param = driver_param; 16545117Syokota iface.confname = confname; 16639287Ssos iface.bridge_ifname = bridge_ifname; 16742729Syokota /* Otherwise, have wpa_supplicant attach to it. */ 16842729Syokota if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) { 16948104Syokota const char *path = wpa_s->dbus_path; 17048104Syokota reply = dbus_message_new_method_return(message); 17142729Syokota dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 17242729Syokota &path, DBUS_TYPE_INVALID); 17348399Speter } else { 17448104Syokota reply = dbus_message_new_error(message, 17548104Syokota WPAS_ERROR_ADD_ERROR, 17648399Speter "wpa_supplicant " 17739287Ssos "couldn't grab this " 17839287Ssos "interface."); 17939287Ssos } 18039287Ssos } 18139287Ssos 18239287Ssosout: 18339287Ssos os_free(driver); 18439287Ssos os_free(driver_param); 18539287Ssos os_free(confname); 18639287Ssos os_free(bridge_ifname); 18739287Ssos return reply; 18843664Syokota 18950446Syokotaerror: 19048399Speter reply = wpas_dbus_new_invalid_opts_error(message, NULL); 19148104Syokota goto out; 19248399Speter} 19348104Syokota 19439591Syokota 19539591Syokota/** 19648104Syokota * wpas_dbus_global_remove_interface - Request deregistration of an interface 19739858Syokota * @message: Pointer to incoming dbus message 19839858Syokota * @global: wpa_supplicant global data structure 19939287Ssos * Returns: a dbus message containing a UINT32 indicating success (1) or 20039591Syokota * failure (0), or returns a dbus error message with more information 20148104Syokota * 20248104Syokota * Handler function for "removeInterface" method call. Handles requests 20339287Ssos * by dbus clients to deregister a network interface that wpa_supplicant 20448399Speter * currently manages. 20548104Syokota */ 20648399SpeterDBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message, 20748104Syokota struct wpa_global *global) 20839287Ssos{ 20939287Ssos struct wpa_supplicant *wpa_s; 21039287Ssos char *path; 21139287Ssos DBusMessage *reply = NULL; 21239287Ssos 21339287Ssos if (!dbus_message_get_args(message, NULL, 21439287Ssos DBUS_TYPE_OBJECT_PATH, &path, 21539287Ssos DBUS_TYPE_INVALID)) { 21639287Ssos reply = wpas_dbus_new_invalid_opts_error(message, NULL); 21739287Ssos goto out; 21839287Ssos } 21939287Ssos 22042504Syokota wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path); 22142504Syokota if (wpa_s == NULL) { 22242504Syokota reply = wpas_dbus_new_invalid_iface_error(message); 22342504Syokota goto out; 22442504Syokota } 22542504Syokota 22642504Syokota if (!wpa_supplicant_remove_iface(global, wpa_s, 0)) { 22742504Syokota reply = wpas_dbus_new_success_reply(message); 22842504Syokota } else { 22942504Syokota reply = dbus_message_new_error(message, 23042504Syokota WPAS_ERROR_REMOVE_ERROR, 23142504Syokota "wpa_supplicant couldn't " 23239287Ssos "remove this interface."); 23339287Ssos } 23439287Ssos 23539287Ssosout: 23639287Ssos return reply; 23744846Sjlemon} 23839287Ssos 23939287Ssos 24039287Ssos/** 24139287Ssos * wpas_dbus_global_get_interface - Get the object path for an interface name 24239287Ssos * @message: Pointer to incoming dbus message 24344846Sjlemon * @global: %wpa_supplicant global data structure 24444866Sjlemon * Returns: The object path of the interface object, 24544846Sjlemon * or a dbus error message with more information 24644846Sjlemon * 24750445Syokota * Handler function for "getInterface" method call. Handles requests 24839287Ssos * by dbus clients for the object path of an specific network interface. 24939287Ssos */ 25039287SsosDBusMessage * wpas_dbus_global_get_interface(DBusMessage *message, 25139287Ssos struct wpa_global *global) 25239287Ssos{ 25339287Ssos DBusMessage *reply = NULL; 25439287Ssos const char *ifname; 25539287Ssos const char *path; 25639287Ssos struct wpa_supplicant *wpa_s; 25739287Ssos 25839287Ssos if (!dbus_message_get_args(message, NULL, 25939287Ssos DBUS_TYPE_STRING, &ifname, 26039287Ssos DBUS_TYPE_INVALID)) { 26139287Ssos reply = wpas_dbus_new_invalid_opts_error(message, NULL); 26239287Ssos goto out; 26350445Syokota } 26439287Ssos 26539287Ssos wpa_s = wpa_supplicant_get_iface(global, ifname); 26639287Ssos if (wpa_s == NULL) { 26745117Syokota reply = wpas_dbus_new_invalid_iface_error(message); 26845117Syokota goto out; 26945117Syokota } 27045117Syokota 27145117Syokota path = wpa_s->dbus_path; 27245117Syokota reply = dbus_message_new_method_return(message); 27345117Syokota dbus_message_append_args(reply, 27445117Syokota DBUS_TYPE_OBJECT_PATH, &path, 27545117Syokota DBUS_TYPE_INVALID); 27650445Syokota 27745117Syokotaout: 27845117Syokota return reply; 27945117Syokota} 28045117Syokota 28145117Syokota 28239287Ssos/** 28339287Ssos * wpas_dbus_global_set_debugparams- Set the debug params 28439287Ssos * @message: Pointer to incoming dbus message 28539287Ssos * @global: %wpa_supplicant global data structure 28639287Ssos * Returns: a dbus message containing a UINT32 indicating success (1) or 28739287Ssos * failure (0), or returns a dbus error message with more information 28839287Ssos * 28939287Ssos * Handler function for "setDebugParams" method call. Handles requests 29039287Ssos * by dbus clients for the object path of an specific network interface. 29150445Syokota */ 29242729SyokotaDBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message, 29342729Syokota struct wpa_global *global) 29439287Ssos{ 29539287Ssos DBusMessage *reply = NULL; 29639287Ssos int debug_level; 29742729Syokota dbus_bool_t debug_timestamp; 29839287Ssos dbus_bool_t debug_show_keys; 29939287Ssos 30039287Ssos if (!dbus_message_get_args(message, NULL, 30139287Ssos DBUS_TYPE_INT32, &debug_level, 30239287Ssos DBUS_TYPE_BOOLEAN, &debug_timestamp, 30339287Ssos DBUS_TYPE_BOOLEAN, &debug_show_keys, 30439287Ssos DBUS_TYPE_INVALID)) { 30539287Ssos return wpas_dbus_new_invalid_opts_error(message, NULL); 30639287Ssos } 30739287Ssos 30839287Ssos if (wpa_supplicant_set_debug_params(global, debug_level, 30944846Sjlemon debug_timestamp ? 1 : 0, 31044866Sjlemon debug_show_keys ? 1 : 0)) { 31144846Sjlemon return wpas_dbus_new_invalid_opts_error(message, NULL); 31244846Sjlemon } 31350445Syokota 31439287Ssos reply = wpas_dbus_new_success_reply(message); 31539287Ssos 31642729Syokota return reply; 31739287Ssos} 31842729Syokota 31942729Syokota 32042729Syokota/** 32139287Ssos * wpas_dbus_iface_scan - Request a wireless scan on an interface 32239287Ssos * @message: Pointer to incoming dbus message 32339287Ssos * @wpa_s: wpa_supplicant structure for a network interface 32439287Ssos * Returns: a dbus message containing a UINT32 indicating success (1) or 32539287Ssos * failure (0) 32648104Syokota * 32748104Syokota * Handler function for "scan" method call of a network device. Requests 32848104Syokota * that wpa_supplicant perform a wireless scan as soon as possible 32948104Syokota * on a particular wireless interface. 33048104Syokota */ 33148104SyokotaDBusMessage * wpas_dbus_iface_scan(DBusMessage *message, 33248104Syokota struct wpa_supplicant *wpa_s) 33348104Syokota{ 33448104Syokota wpa_s->scan_req = MANUAL_SCAN_REQ; 33548104Syokota wpa_supplicant_req_scan(wpa_s, 0, 0); 33648104Syokota return wpas_dbus_new_success_reply(message); 33748104Syokota} 33848104Syokota 33948104Syokota 34048104Syokota/** 34148104Syokota * wpas_dbus_iface_scan_results - Get the results of a recent scan request 34248104Syokota * @message: Pointer to incoming dbus message 34350445Syokota * @wpa_s: wpa_supplicant structure for a network interface 34448104Syokota * Returns: a dbus message containing a dbus array of objects paths, or returns 34548104Syokota * a dbus error message if not scan results could be found 34648104Syokota * 34748104Syokota * Handler function for "scanResults" method call of a network device. Returns 34848104Syokota * a dbus message containing the object paths of wireless networks found. 34948104Syokota */ 35048104SyokotaDBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message, 35148104Syokota struct wpa_supplicant *wpa_s) 35248104Syokota{ 35348104Syokota DBusMessage *reply = NULL; 35448104Syokota DBusMessageIter iter; 35548104Syokota DBusMessageIter sub_iter; 35642729Syokota struct wpa_bss *bss; 35739287Ssos 35839287Ssos /* Create and initialize the return message */ 35939287Ssos reply = dbus_message_new_method_return(message); 36039287Ssos dbus_message_iter_init_append(reply, &iter); 36139287Ssos dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 36239287Ssos DBUS_TYPE_OBJECT_PATH_AS_STRING, 36344846Sjlemon &sub_iter); 36442729Syokota 36539287Ssos /* Loop through scan results and append each result's object path */ 36642729Syokota dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 36742729Syokota char path_buf[WPAS_DBUS_OBJECT_PATH_MAX]; 36842729Syokota char *path = path_buf; 36942729Syokota 37039287Ssos /* Construct the object path for this network. Note that ':' 37139287Ssos * is not a valid character in dbus object paths. 37239287Ssos */ 37339287Ssos os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 37439287Ssos "%s/" WPAS_DBUS_BSSIDS_PART "/" 37539287Ssos WPAS_DBUS_BSSID_FORMAT, 37639287Ssos wpa_s->dbus_path, MAC2STR(bss->bssid)); 37744866Sjlemon dbus_message_iter_append_basic(&sub_iter, 37844846Sjlemon DBUS_TYPE_OBJECT_PATH, &path); 37944846Sjlemon } 38050445Syokota 38139287Ssos dbus_message_iter_close_container(&iter, &sub_iter); 38239287Ssos 38348399Speter return reply; 38439287Ssos} 38548104Syokota 38648104Syokota 38748104Syokota/** 38848104Syokota * wpas_dbus_bssid_properties - Return the properties of a scanned network 38948104Syokota * @message: Pointer to incoming dbus message 39048104Syokota * @wpa_s: wpa_supplicant structure for a network interface 39148104Syokota * @res: wpa_supplicant scan result for which to get properties 39248104Syokota * Returns: a dbus message containing the properties for the requested network 39348104Syokota * 39448104Syokota * Handler function for "properties" method call of a scanned network. 39548104Syokota * Returns a dbus message containing the the properties. 39648104Syokota */ 39748104SyokotaDBusMessage * wpas_dbus_bssid_properties(DBusMessage *message, 39848104Syokota struct wpa_supplicant *wpa_s, 39948104Syokota struct wpa_bss *bss) 40048104Syokota{ 40148104Syokota DBusMessage *reply; 40248104Syokota DBusMessageIter iter, iter_dict; 40348104Syokota const u8 *ie; 40448104Syokota 40548104Syokota /* Dump the properties into a dbus message */ 40648104Syokota reply = dbus_message_new_method_return(message); 40748104Syokota 40848104Syokota dbus_message_iter_init_append(reply, &iter); 40948104Syokota if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 41050445Syokota goto error; 41148104Syokota 41248399Speter if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid", 41348104Syokota (const char *) bss->bssid, 41448104Syokota ETH_ALEN)) 41539287Ssos goto error; 41639287Ssos 41739287Ssos ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); 41839287Ssos if (ie) { 41939287Ssos if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid", 42039287Ssos (const char *) (ie + 2), 42139287Ssos ie[1])) 42239287Ssos goto error; 42339287Ssos } 42439287Ssos 42550445Syokota ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 42639287Ssos if (ie) { 42750445Syokota if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie", 42839287Ssos (const char *) ie, 42939287Ssos ie[1] + 2)) 43039287Ssos goto error; 43139287Ssos } 43239287Ssos 43339287Ssos ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); 43444846Sjlemon if (ie) { 43539287Ssos if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie", 43639287Ssos (const char *) ie, 43739287Ssos ie[1] + 2)) 43839287Ssos goto error; 43939287Ssos } 44039287Ssos 44144846Sjlemon ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE); 44244866Sjlemon if (ie) { 44344846Sjlemon if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie", 44444846Sjlemon (const char *) ie, 44544846Sjlemon ie[1] + 2)) 44650445Syokota goto error; 44739287Ssos } 44839287Ssos 44943664Syokota if (bss->freq) { 45043664Syokota if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency", 45143664Syokota bss->freq)) 45243664Syokota goto error; 45343664Syokota } 45443664Syokota if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities", 45543664Syokota bss->caps)) 45643664Syokota goto error; 45743664Syokota if (!(bss->flags & WPA_BSS_QUAL_INVALID) && 45843664Syokota !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual)) 45950445Syokota goto error; 46043664Syokota if (!(bss->flags & WPA_BSS_NOISE_INVALID) && 46143664Syokota !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise)) 46243664Syokota goto error; 46343664Syokota if (!(bss->flags & WPA_BSS_LEVEL_INVALID) && 46448104Syokota !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level)) 46550446Syokota goto error; 46648104Syokota if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", 46748104Syokota wpa_bss_get_max_rate(bss) * 500000)) 46848104Syokota goto error; 46948104Syokota 47048104Syokota if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 47148104Syokota goto error; 47248104Syokota 47348104Syokota return reply; 47448104Syokota 47548104Syokotaerror: 47648104Syokota if (reply) 47748104Syokota dbus_message_unref(reply); 47850446Syokota return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 47950446Syokota "an internal error occurred returning " 48050446Syokota "BSSID properties."); 48150446Syokota} 48250446Syokota 48350446Syokota 48450446Syokota/** 48548104Syokota * wpas_dbus_iface_capabilities - Return interface capabilities 48648104Syokota * @message: Pointer to incoming dbus message 48748399Speter * @wpa_s: wpa_supplicant structure for a network interface 48848104Syokota * Returns: A dbus message containing a dict of strings 48948104Syokota * 49048104Syokota * Handler function for "capabilities" method call of an interface. 49148104Syokota */ 49248104SyokotaDBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message, 49348104Syokota struct wpa_supplicant *wpa_s) 49448104Syokota{ 49548104Syokota DBusMessage *reply = NULL; 49648104Syokota struct wpa_driver_capa capa; 49748104Syokota int res; 49850445Syokota DBusMessageIter iter, iter_dict; 49948104Syokota char **eap_methods; 50048104Syokota size_t num_items; 50148104Syokota dbus_bool_t strict = FALSE; 50248104Syokota DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; 50348104Syokota 50448399Speter if (!dbus_message_get_args(message, NULL, 50548104Syokota DBUS_TYPE_BOOLEAN, &strict, 50648104Syokota DBUS_TYPE_INVALID)) 50748104Syokota strict = FALSE; 50848104Syokota 50948104Syokota reply = dbus_message_new_method_return(message); 51048104Syokota 51148104Syokota dbus_message_iter_init_append(reply, &iter); 51248104Syokota if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 51348104Syokota goto error; 51448104Syokota 51548104Syokota /* EAP methods */ 51648104Syokota eap_methods = eap_get_names_as_string_array(&num_items); 51748104Syokota if (eap_methods) { 51850445Syokota dbus_bool_t success = FALSE; 51948104Syokota size_t i = 0; 52048104Syokota 52139591Syokota success = wpa_dbus_dict_append_string_array( 52239287Ssos &iter_dict, "eap", (const char **) eap_methods, 52339591Syokota num_items); 52439287Ssos 52539591Syokota /* free returned method array */ 52639591Syokota while (eap_methods[i]) 52739591Syokota os_free(eap_methods[i++]); 52839591Syokota os_free(eap_methods); 52939591Syokota 53039591Syokota if (!success) 53139591Syokota goto error; 53239591Syokota } 53339591Syokota 53439591Syokota res = wpa_drv_get_capa(wpa_s, &capa); 53539591Syokota 53639591Syokota /***** pairwise cipher */ 53739591Syokota if (res < 0) { 53839591Syokota if (!strict) { 53939591Syokota const char *args[] = {"CCMP", "TKIP", "NONE"}; 54039591Syokota if (!wpa_dbus_dict_append_string_array( 54139591Syokota &iter_dict, "pairwise", args, 54239591Syokota sizeof(args) / sizeof(char*))) 54339591Syokota goto error; 54439591Syokota } 54539591Syokota } else { 54639287Ssos if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise", 54739287Ssos &iter_dict_entry, 54839287Ssos &iter_dict_val, 54939287Ssos &iter_array)) 55039287Ssos goto error; 55139287Ssos 55239287Ssos if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 55342235Sdes if (!wpa_dbus_dict_string_array_add_element( 55439287Ssos &iter_array, "CCMP")) 55539287Ssos goto error; 55639287Ssos } 55739287Ssos 55839287Ssos if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 55939287Ssos if (!wpa_dbus_dict_string_array_add_element( 56039287Ssos &iter_array, "TKIP")) 56139287Ssos goto error; 56239287Ssos } 56339287Ssos 56439287Ssos if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 56548104Syokota if (!wpa_dbus_dict_string_array_add_element( 56648104Syokota &iter_array, "NONE")) 56748104Syokota goto error; 56848104Syokota } 56948104Syokota 57048104Syokota if (!wpa_dbus_dict_end_string_array(&iter_dict, 57148104Syokota &iter_dict_entry, 57248104Syokota &iter_dict_val, 57348104Syokota &iter_array)) 57448104Syokota goto error; 57548104Syokota } 57648104Syokota 57748104Syokota /***** group cipher */ 57848104Syokota if (res < 0) { 57948104Syokota if (!strict) { 58048104Syokota const char *args[] = { 58148104Syokota "CCMP", "TKIP", "WEP104", "WEP40" 58248104Syokota }; 58348104Syokota if (!wpa_dbus_dict_append_string_array( 58448104Syokota &iter_dict, "group", args, 58548104Syokota sizeof(args) / sizeof(char*))) 58648104Syokota goto error; 58748104Syokota } 58839858Syokota } else { 58939858Syokota if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group", 59039858Syokota &iter_dict_entry, 59139858Syokota &iter_dict_val, 59239858Syokota &iter_array)) 59339858Syokota goto error; 59439858Syokota 59539858Syokota if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 59639858Syokota if (!wpa_dbus_dict_string_array_add_element( 59739858Syokota &iter_array, "CCMP")) 59839858Syokota goto error; 59939858Syokota } 60039858Syokota 60139287Ssos if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 60239287Ssos if (!wpa_dbus_dict_string_array_add_element( 60339287Ssos &iter_array, "TKIP")) 60445196Syokota goto error; 60539287Ssos } 60639287Ssos 60748104Syokota if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 60845196Syokota if (!wpa_dbus_dict_string_array_add_element( 60939287Ssos &iter_array, "WEP104")) 61039287Ssos goto error; 61139287Ssos } 61239287Ssos 61339287Ssos if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 61439287Ssos if (!wpa_dbus_dict_string_array_add_element( 61539287Ssos &iter_array, "WEP40")) 61639287Ssos goto error; 61739287Ssos } 61848104Syokota 61939287Ssos if (!wpa_dbus_dict_end_string_array(&iter_dict, 62039287Ssos &iter_dict_entry, 62145196Syokota &iter_dict_val, 62239287Ssos &iter_array)) 62345196Syokota goto error; 62439744Sache } 62545196Syokota 62644846Sjlemon /***** key management */ 62744846Sjlemon if (res < 0) { 62850445Syokota if (!strict) { 62939287Ssos const char *args[] = { 63045196Syokota "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE", 63139287Ssos "NONE" 63242504Syokota }; 63342504Syokota if (!wpa_dbus_dict_append_string_array( 63439287Ssos &iter_dict, "key_mgmt", args, 63542504Syokota sizeof(args) / sizeof(char*))) 63639287Ssos goto error; 63739287Ssos } 63848104Syokota } else { 63948104Syokota if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt", 64048104Syokota &iter_dict_entry, 64148104Syokota &iter_dict_val, 64248104Syokota &iter_array)) 64348104Syokota goto error; 64448104Syokota 64548104Syokota if (!wpa_dbus_dict_string_array_add_element(&iter_array, 64648104Syokota "NONE")) 64739287Ssos goto error; 64839858Syokota 64939858Syokota if (!wpa_dbus_dict_string_array_add_element(&iter_array, 65039858Syokota "IEEE8021X")) 65139858Syokota goto error; 65239858Syokota 65339858Syokota if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 65439858Syokota WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 65539858Syokota if (!wpa_dbus_dict_string_array_add_element( 65639858Syokota &iter_array, "WPA-EAP")) 65739858Syokota goto error; 65839858Syokota } 65939858Syokota 66039858Syokota if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 66139858Syokota WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 66239858Syokota if (!wpa_dbus_dict_string_array_add_element( 66339287Ssos &iter_array, "WPA-PSK")) 66439858Syokota goto error; 66539858Syokota } 66639858Syokota 66739858Syokota if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 66839858Syokota if (!wpa_dbus_dict_string_array_add_element( 66939858Syokota &iter_array, "WPA-NONE")) 67039858Syokota goto error; 67139287Ssos } 67239287Ssos 67339287Ssos if (!wpa_dbus_dict_end_string_array(&iter_dict, 67439287Ssos &iter_dict_entry, 67539287Ssos &iter_dict_val, 67639287Ssos &iter_array)) 67739287Ssos goto error; 67839287Ssos } 67939287Ssos 68039287Ssos /***** WPA protocol */ 68167816Sjhb if (res < 0) { 68266710Sjhb if (!strict) { 68366710Sjhb const char *args[] = { "RSN", "WPA" }; 68466710Sjhb if (!wpa_dbus_dict_append_string_array( 68566710Sjhb &iter_dict, "proto", args, 68666710Sjhb sizeof(args) / sizeof(char*))) 68766710Sjhb goto error; 68866710Sjhb } 68939287Ssos } else { 69066710Sjhb if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto", 69139287Ssos &iter_dict_entry, 69239287Ssos &iter_dict_val, 69348104Syokota &iter_array)) 69448104Syokota goto error; 69548104Syokota 69648104Syokota if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 69748104Syokota WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 69848104Syokota if (!wpa_dbus_dict_string_array_add_element( 69948104Syokota &iter_array, "RSN")) 70050445Syokota goto error; 70148104Syokota } 70248104Syokota 70348104Syokota if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 70448104Syokota WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 70548104Syokota if (!wpa_dbus_dict_string_array_add_element( 70648104Syokota &iter_array, "WPA")) 70748104Syokota goto error; 70848104Syokota } 70966710Sjhb 71066710Sjhb if (!wpa_dbus_dict_end_string_array(&iter_dict, 71166710Sjhb &iter_dict_entry, 71266710Sjhb &iter_dict_val, 71366710Sjhb &iter_array)) 71439287Ssos goto error; 71539287Ssos } 71639287Ssos 71739287Ssos /***** auth alg */ 71839287Ssos if (res < 0) { 71939287Ssos if (!strict) { 72039287Ssos const char *args[] = { "OPEN", "SHARED", "LEAP" }; 72139287Ssos if (!wpa_dbus_dict_append_string_array( 72239287Ssos &iter_dict, "auth_alg", args, 72339287Ssos sizeof(args) / sizeof(char*))) 72439287Ssos goto error; 72539858Syokota } 72639858Syokota } else { 72748104Syokota if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg", 72848104Syokota &iter_dict_entry, 72948104Syokota &iter_dict_val, 73048104Syokota &iter_array)) 73143664Syokota goto error; 73248104Syokota 73348104Syokota if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 73448104Syokota if (!wpa_dbus_dict_string_array_add_element( 73543664Syokota &iter_array, "OPEN")) 73643664Syokota goto error; 73748104Syokota } 73848104Syokota 73943664Syokota if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 74048104Syokota if (!wpa_dbus_dict_string_array_add_element( 74148104Syokota &iter_array, "SHARED")) 74248104Syokota goto error; 74348104Syokota } 74448104Syokota 74548104Syokota if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 74648104Syokota if (!wpa_dbus_dict_string_array_add_element( 74748104Syokota &iter_array, "LEAP")) 74848104Syokota goto error; 74948104Syokota } 75048104Syokota 75148104Syokota if (!wpa_dbus_dict_end_string_array(&iter_dict, 75248104Syokota &iter_dict_entry, 75348104Syokota &iter_dict_val, 75448104Syokota &iter_array)) 75548104Syokota goto error; 75648104Syokota } 75748104Syokota 75848104Syokota if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 75948104Syokota goto error; 76048104Syokota 76148104Syokota return reply; 76248104Syokota 76348104Syokotaerror: 76448104Syokota if (reply) 76548104Syokota dbus_message_unref(reply); 76648104Syokota return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 76748104Syokota "an internal error occurred returning " 76848104Syokota "interface capabilities."); 76948104Syokota} 77048104Syokota 77148104Syokota 77248104Syokota/** 77348104Syokota * wpas_dbus_iface_add_network - Add a new configured network 77448104Syokota * @message: Pointer to incoming dbus message 77548104Syokota * @wpa_s: wpa_supplicant structure for a network interface 77648104Syokota * Returns: A dbus message containing the object path of the new network 77739591Syokota * 77839591Syokota * Handler function for "addNetwork" method call of a network interface. 77939287Ssos */ 78039287SsosDBusMessage * wpas_dbus_iface_add_network(DBusMessage *message, 78139287Ssos struct wpa_supplicant *wpa_s) 78239287Ssos{ 78339287Ssos DBusMessage *reply = NULL; 78439287Ssos struct wpa_ssid *ssid; 78539858Syokota char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 78639858Syokota 78739287Ssos ssid = wpa_config_add_network(wpa_s->conf); 78839287Ssos if (ssid == NULL) { 78939287Ssos reply = dbus_message_new_error(message, 79039591Syokota WPAS_ERROR_ADD_NETWORK_ERROR, 79139287Ssos "wpa_supplicant could not add " 79239287Ssos "a network on this interface."); 79339287Ssos goto out; 79439287Ssos } 79539287Ssos wpas_notify_network_added(wpa_s, ssid); 79639287Ssos ssid->disabled = 1; 79739287Ssos wpa_config_set_network_defaults(ssid); 79839287Ssos 79948104Syokota /* Construct the object path for this network. */ 80048104Syokota os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 80148104Syokota "%s/" WPAS_DBUS_NETWORKS_PART "/%d", 80248104Syokota wpa_s->dbus_path, ssid->id); 80348104Syokota 80448104Syokota reply = dbus_message_new_method_return(message); 80548104Syokota dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 80648104Syokota &path, DBUS_TYPE_INVALID); 80748104Syokota 80848104Syokotaout: 80948104Syokota return reply; 81048104Syokota} 81148104Syokota 81248104Syokota 81348104Syokota/** 81448104Syokota * wpas_dbus_iface_remove_network - Remove a configured network 81548104Syokota * @message: Pointer to incoming dbus message 81648104Syokota * @wpa_s: wpa_supplicant structure for a network interface 81748104Syokota * Returns: A dbus message containing a UINT32 indicating success (1) or 81848104Syokota * failure (0) 81948104Syokota * 82048104Syokota * Handler function for "removeNetwork" method call of a network interface. 82148104Syokota */ 82248104SyokotaDBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message, 82342504Syokota struct wpa_supplicant *wpa_s) 82439287Ssos{ 82539287Ssos DBusMessage *reply = NULL; 82642504Syokota const char *op; 82739287Ssos char *iface = NULL, *net_id = NULL; 82842504Syokota int id; 82939287Ssos struct wpa_ssid *ssid; 83042504Syokota 83139287Ssos if (!dbus_message_get_args(message, NULL, 83239287Ssos DBUS_TYPE_OBJECT_PATH, &op, 83342504Syokota DBUS_TYPE_INVALID)) { 83442504Syokota reply = wpas_dbus_new_invalid_opts_error(message, NULL); 83542504Syokota goto out; 83642504Syokota } 83742504Syokota 83842504Syokota /* Extract the network ID */ 83942504Syokota iface = wpas_dbus_decompose_object_path(op, &net_id, NULL); 84042504Syokota if (iface == NULL) { 84142504Syokota reply = wpas_dbus_new_invalid_network_error(message); 84242504Syokota goto out; 84342504Syokota } 84442504Syokota 84542504Syokota /* Ensure the network is actually a child of this interface */ 84642504Syokota if (os_strcmp(iface, wpa_s->dbus_path) != 0) { 84739287Ssos reply = wpas_dbus_new_invalid_network_error(message); 84842504Syokota goto out; 84942504Syokota } 85042504Syokota 85142504Syokota id = strtoul(net_id, NULL, 10); 85242504Syokota ssid = wpa_config_get_network(wpa_s->conf, id); 85342504Syokota if (ssid == NULL) { 85442504Syokota reply = wpas_dbus_new_invalid_network_error(message); 85542504Syokota goto out; 85642504Syokota } 85742504Syokota 85842504Syokota wpas_notify_network_removed(wpa_s, ssid); 85942504Syokota 86042504Syokota if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 86142504Syokota reply = dbus_message_new_error(message, 86242504Syokota WPAS_ERROR_REMOVE_NETWORK_ERROR, 86342504Syokota "error removing the specified " 86442504Syokota "on this interface."); 86542504Syokota goto out; 86642504Syokota } 86742504Syokota 86842504Syokota if (ssid == wpa_s->current_ssid) 86942504Syokota wpa_supplicant_deauthenticate(wpa_s, 87042504Syokota WLAN_REASON_DEAUTH_LEAVING); 87142504Syokota reply = wpas_dbus_new_success_reply(message); 87242504Syokota 87342504Syokotaout: 87442504Syokota os_free(iface); 87542504Syokota os_free(net_id); 87642504Syokota return reply; 87742504Syokota} 87842504Syokota 87942504Syokota 88042504Syokotastatic const char *dont_quote[] = { 88142504Syokota "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", 88242504Syokota "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path", 88342504Syokota "bssid", NULL 88442504Syokota}; 88542504Syokota 88642504Syokota 88742504Syokotastatic dbus_bool_t should_quote_opt(const char *key) 88842504Syokota{ 88939287Ssos int i = 0; 89039287Ssos while (dont_quote[i] != NULL) { 89148399Speter if (strcmp(key, dont_quote[i]) == 0) 89242504Syokota return FALSE; 89342504Syokota i++; 89439287Ssos } 89542504Syokota return TRUE; 89639287Ssos} 89748399Speter 89839287Ssos 89939287Ssos/** 90048104Syokota * wpas_dbus_iface_set_network - Set options for a configured network 90148104Syokota * @message: Pointer to incoming dbus message 90248104Syokota * @wpa_s: wpa_supplicant structure for a network interface 90348104Syokota * @ssid: wpa_ssid structure for a configured network 90448104Syokota * Returns: a dbus message containing a UINT32 indicating success (1) or 90548104Syokota * failure (0) 90642504Syokota * 90739287Ssos * Handler function for "set" method call of a configured network. 90842504Syokota */ 90942504SyokotaDBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, 91042504Syokota struct wpa_supplicant *wpa_s, 91142504Syokota struct wpa_ssid *ssid) 91242504Syokota{ 91342504Syokota DBusMessage *reply = NULL; 91442504Syokota struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 91542504Syokota DBusMessageIter iter, iter_dict; 91642504Syokota 91742504Syokota dbus_message_iter_init(message, &iter); 91842504Syokota 91942504Syokota if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) { 92039287Ssos reply = wpas_dbus_new_invalid_opts_error(message, NULL); 92139287Ssos goto out; 92242504Syokota } 92339287Ssos 92439287Ssos while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 92542504Syokota char *value = NULL; 92639287Ssos size_t size = 50; 92739591Syokota int ret; 92839591Syokota 92939591Syokota if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 93039287Ssos reply = wpas_dbus_new_invalid_opts_error(message, 93139287Ssos NULL); 93239287Ssos goto out; 93339287Ssos } 93439287Ssos 93539287Ssos /* Type conversions, since wpa_supplicant wants strings */ 93639287Ssos if (entry.type == DBUS_TYPE_ARRAY && 93739287Ssos entry.array_type == DBUS_TYPE_BYTE) { 93839287Ssos if (entry.array_len <= 0) 93939287Ssos goto error; 94039287Ssos 94139287Ssos size = entry.array_len * 2 + 1; 94242504Syokota value = os_zalloc(size); 94339287Ssos if (value == NULL) 94439287Ssos goto error; 94539287Ssos ret = wpa_snprintf_hex(value, size, 94654258Syokota (u8 *) entry.bytearray_value, 94754258Syokota entry.array_len); 94842504Syokota if (ret <= 0) 94954258Syokota goto error; 95039287Ssos } else if (entry.type == DBUS_TYPE_STRING) { 95139287Ssos if (should_quote_opt(entry.key)) { 95239287Ssos size = os_strlen(entry.str_value); 95339287Ssos /* Zero-length option check */ 95439287Ssos if (size <= 0) 95539287Ssos goto error; 95639287Ssos size += 3; /* For quotes and terminator */ 95739287Ssos value = os_zalloc(size); 95839287Ssos if (value == NULL) 95939287Ssos goto error; 96039287Ssos ret = os_snprintf(value, size, "\"%s\"", 96139287Ssos entry.str_value); 96239287Ssos if (ret < 0 || (size_t) ret != (size - 1)) 96339287Ssos goto error; 96439287Ssos } else { 96539287Ssos value = os_strdup(entry.str_value); 96639287Ssos if (value == NULL) 96739287Ssos goto error; 96839287Ssos } 96939287Ssos } else if (entry.type == DBUS_TYPE_UINT32) { 97039287Ssos value = os_zalloc(size); 97139287Ssos if (value == NULL) 97239287Ssos goto error; 97339287Ssos ret = os_snprintf(value, size, "%u", 97454258Syokota entry.uint32_value); 97554258Syokota if (ret <= 0) 97639287Ssos goto error; 97754258Syokota } else if (entry.type == DBUS_TYPE_INT32) { 97839287Ssos value = os_zalloc(size); 97939287Ssos if (value == NULL) 98039287Ssos goto error; 98142504Syokota ret = os_snprintf(value, size, "%d", 98239287Ssos entry.int32_value); 98339287Ssos if (ret <= 0) 98448104Syokota goto error; 98539287Ssos } else 98642504Syokota goto error; 98742504Syokota 98839287Ssos if (wpa_config_set(ssid, entry.key, value, 0) < 0) 98948104Syokota goto error; 99048104Syokota 99142504Syokota if ((os_strcmp(entry.key, "psk") == 0 && 99239287Ssos value[0] == '"' && ssid->ssid_len) || 99348104Syokota (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) 99439287Ssos wpa_config_update_psk(ssid); 99539287Ssos else if (os_strcmp(entry.key, "priority") == 0) 99639287Ssos wpa_config_update_prio_list(wpa_s->conf); 99748104Syokota 99848104Syokota os_free(value); 99948104Syokota wpa_dbus_dict_entry_clear(&entry); 100048104Syokota continue; 100148104Syokota 100239287Ssos error: 100348104Syokota os_free(value); 100442504Syokota reply = wpas_dbus_new_invalid_opts_error(message, entry.key); 100548104Syokota wpa_dbus_dict_entry_clear(&entry); 100648104Syokota break; 100748104Syokota } 100848104Syokota 100948104Syokota if (!reply) 101048104Syokota reply = wpas_dbus_new_success_reply(message); 101148104Syokota 101248104Syokotaout: 101339287Ssos return reply; 101439287Ssos} 101539287Ssos 101639287Ssos 101742504Syokota/** 101839287Ssos * wpas_dbus_iface_enable_network - Mark a configured network as enabled 101939287Ssos * @message: Pointer to incoming dbus message 102039287Ssos * @wpa_s: wpa_supplicant structure for a network interface 102142504Syokota * @ssid: wpa_ssid structure for a configured network 102239287Ssos * Returns: A dbus message containing a UINT32 indicating success (1) or 102339287Ssos * failure (0) 102439287Ssos * 102542504Syokota * Handler function for "enable" method call of a configured network. 102639287Ssos */ 102739287SsosDBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message, 102848104Syokota struct wpa_supplicant *wpa_s, 102948104Syokota struct wpa_ssid *ssid) 103048104Syokota{ 103139287Ssos wpa_supplicant_enable_network(wpa_s, ssid); 103248104Syokota return wpas_dbus_new_success_reply(message); 103339287Ssos} 103439287Ssos 103548104Syokota 103648104Syokota/** 103748104Syokota * wpas_dbus_iface_disable_network - Mark a configured network as disabled 103848104Syokota * @message: Pointer to incoming dbus message 103942504Syokota * @wpa_s: wpa_supplicant structure for a network interface 104039287Ssos * @ssid: wpa_ssid structure for a configured network 104139287Ssos * Returns: A dbus message containing a UINT32 indicating success (1) or 104239287Ssos * failure (0) 104339287Ssos * 104439287Ssos * Handler function for "disable" method call of a configured network. 104539287Ssos */ 104639287SsosDBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message, 104742504Syokota struct wpa_supplicant *wpa_s, 104848104Syokota struct wpa_ssid *ssid) 104948104Syokota{ 105048104Syokota wpa_supplicant_disable_network(wpa_s, ssid); 105148104Syokota return wpas_dbus_new_success_reply(message); 105248104Syokota} 105348104Syokota 105448104Syokota 105548104Syokota/** 105648104Syokota * wpas_dbus_iface_select_network - Attempt association with a configured network 105748104Syokota * @message: Pointer to incoming dbus message 105848104Syokota * @wpa_s: wpa_supplicant structure for a network interface 105948104Syokota * Returns: A dbus message containing a UINT32 indicating success (1) or 106039287Ssos * failure (0) 106139287Ssos * 106248104Syokota * Handler function for "selectNetwork" method call of network interface. 106348104Syokota */ 106448104SyokotaDBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, 106539287Ssos struct wpa_supplicant *wpa_s) 106648104Syokota{ 106743664Syokota DBusMessage *reply = NULL; 106843674Syokota const char *op; 106943674Syokota struct wpa_ssid *ssid; 107043674Syokota char *iface_obj_path = NULL; 107143674Syokota char *network = NULL; 107243674Syokota 107343674Syokota if (os_strlen(dbus_message_get_signature(message)) == 0) { 107443674Syokota /* Any network */ 107543674Syokota ssid = NULL; 107643674Syokota } else { 107743674Syokota int nid; 107843674Syokota 107943674Syokota if (!dbus_message_get_args(message, NULL, 108043674Syokota DBUS_TYPE_OBJECT_PATH, &op, 108143674Syokota DBUS_TYPE_INVALID)) { 108243674Syokota reply = wpas_dbus_new_invalid_opts_error(message, 108343674Syokota NULL); 108443674Syokota goto out; 108543674Syokota } 108643674Syokota 108743674Syokota /* Extract the network number */ 108843674Syokota iface_obj_path = wpas_dbus_decompose_object_path(op, 108948104Syokota &network, 109048104Syokota NULL); 109143664Syokota if (iface_obj_path == NULL) { 109243664Syokota reply = wpas_dbus_new_invalid_iface_error(message); 109343674Syokota goto out; 109443664Syokota } 109543674Syokota /* Ensure the object path really points to this interface */ 109639287Ssos if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) { 109742504Syokota reply = wpas_dbus_new_invalid_network_error(message); 109843674Syokota goto out; 109942504Syokota } 110039287Ssos 110139287Ssos nid = strtoul(network, NULL, 10); 110239287Ssos if (errno == EINVAL) { 110339287Ssos reply = wpas_dbus_new_invalid_network_error(message); 110442504Syokota goto out; 110542504Syokota } 110639287Ssos 110742504Syokota ssid = wpa_config_get_network(wpa_s->conf, nid); 110839287Ssos if (ssid == NULL) { 110939287Ssos reply = wpas_dbus_new_invalid_network_error(message); 111039287Ssos goto out; 111142504Syokota } 111242504Syokota } 111339287Ssos 111442504Syokota /* Finally, associate with the network */ 111539287Ssos wpa_supplicant_select_network(wpa_s, ssid); 111639287Ssos 111739287Ssos reply = wpas_dbus_new_success_reply(message); 111842504Syokota 111939287Ssosout: 112042504Syokota os_free(iface_obj_path); 112139287Ssos os_free(network); 112239287Ssos return reply; 112339287Ssos} 112442504Syokota 112539287Ssos 112642729Syokota/** 112742729Syokota * wpas_dbus_iface_disconnect - Terminate the current connection 112839287Ssos * @message: Pointer to incoming dbus message 112945117Syokota * @wpa_s: wpa_supplicant structure for a network interface 113045117Syokota * Returns: A dbus message containing a UINT32 indicating success (1) or 113145117Syokota * failure (0) 113242729Syokota * 113342729Syokota * Handler function for "disconnect" method call of network interface. 113442729Syokota */ 113545117SyokotaDBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message, 113645117Syokota struct wpa_supplicant *wpa_s) 113742729Syokota{ 113842729Syokota wpa_s->disconnected = 1; 113942729Syokota wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 114039287Ssos 114139287Ssos return wpas_dbus_new_success_reply(message); 114239287Ssos} 114342504Syokota 114439287Ssos 114545117Syokota/** 114642729Syokota * wpas_dbus_iface_set_ap_scan - Control roaming mode 114742729Syokota * @message: Pointer to incoming dbus message 114839287Ssos * @wpa_s: wpa_supplicant structure for a network interface 114942729Syokota * Returns: A dbus message containing a UINT32 indicating success (1) or 115045117Syokota * failure (0) 115142729Syokota * 115242729Syokota * Handler function for "setAPScan" method call. 115342729Syokota */ 115445117SyokotaDBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message, 115545117Syokota struct wpa_supplicant *wpa_s) 115642729Syokota{ 115745117Syokota DBusMessage *reply = NULL; 115842729Syokota dbus_uint32_t ap_scan = 1; 115942729Syokota 116039287Ssos if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan, 116139287Ssos DBUS_TYPE_INVALID)) { 116239287Ssos reply = wpas_dbus_new_invalid_opts_error(message, NULL); 116342504Syokota goto out; 116439287Ssos } 116542504Syokota 116639287Ssos if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 116739287Ssos reply = wpas_dbus_new_invalid_opts_error(message, NULL); 116839287Ssos goto out; 116942504Syokota } 117039287Ssos 117142504Syokota reply = wpas_dbus_new_success_reply(message); 117242504Syokota 117339287Ssosout: 117439287Ssos return reply; 117539287Ssos} 117639287Ssos 117739287Ssos 117839287Ssos/** 117939287Ssos * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths 118039287Ssos * @message: Pointer to incoming dbus message 118139287Ssos * @wpa_s: wpa_supplicant structure for a network interface 118239287Ssos * Returns: A dbus message containing a UINT32 indicating success (1) or 118339287Ssos * failure (0) 118439287Ssos * 118539287Ssos * Handler function for "setSmartcardModules" method call. 118639287Ssos */ 118739287SsosDBusMessage * wpas_dbus_iface_set_smartcard_modules( 118842504Syokota DBusMessage *message, struct wpa_supplicant *wpa_s) 118939287Ssos{ 119042504Syokota DBusMessageIter iter, iter_dict; 119142504Syokota char *opensc_engine_path = NULL; 119239287Ssos char *pkcs11_engine_path = NULL; 119339287Ssos char *pkcs11_module_path = NULL; 119439287Ssos struct wpa_dbus_dict_entry entry; 119539287Ssos 119639287Ssos if (!dbus_message_iter_init(message, &iter)) 119748399Speter goto error; 119839287Ssos 119948104Syokota if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 120048104Syokota goto error; 120148104Syokota 120248104Syokota while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 120348104Syokota if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 120448104Syokota goto error; 120548104Syokota if (!strcmp(entry.key, "opensc_engine_path") && 120648104Syokota (entry.type == DBUS_TYPE_STRING)) { 120748104Syokota opensc_engine_path = os_strdup(entry.str_value); 120850445Syokota if (opensc_engine_path == NULL) 120948104Syokota goto error; 121048104Syokota } else if (!strcmp(entry.key, "pkcs11_engine_path") && 121148104Syokota (entry.type == DBUS_TYPE_STRING)) { 121248104Syokota pkcs11_engine_path = os_strdup(entry.str_value); 121348399Speter if (pkcs11_engine_path == NULL) 121448104Syokota goto error; 121548104Syokota } else if (!strcmp(entry.key, "pkcs11_module_path") && 121642504Syokota (entry.type == DBUS_TYPE_STRING)) { 121739287Ssos pkcs11_module_path = os_strdup(entry.str_value); 121839287Ssos if (pkcs11_module_path == NULL) 121939287Ssos goto error; 122039287Ssos } else { 122139287Ssos wpa_dbus_dict_entry_clear(&entry); 122239287Ssos goto error; 122339287Ssos } 122439287Ssos wpa_dbus_dict_entry_clear(&entry); 122539287Ssos } 122639287Ssos 122742504Syokota os_free(wpa_s->conf->opensc_engine_path); 122842504Syokota wpa_s->conf->opensc_engine_path = opensc_engine_path; 122939287Ssos os_free(wpa_s->conf->pkcs11_engine_path); 123048104Syokota wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path; 123148104Syokota os_free(wpa_s->conf->pkcs11_module_path); 123248104Syokota wpa_s->conf->pkcs11_module_path = pkcs11_module_path; 123348104Syokota 123448104Syokota wpa_sm_set_eapol(wpa_s->wpa, NULL); 123539287Ssos eapol_sm_deinit(wpa_s->eapol); 123648104Syokota wpa_s->eapol = NULL; 123739287Ssos wpa_supplicant_init_eapol(wpa_s); 123839287Ssos wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); 123939287Ssos 124048104Syokota return wpas_dbus_new_success_reply(message); 124139287Ssos 124250445Syokotaerror: 124343664Syokota os_free(opensc_engine_path); 124443664Syokota os_free(pkcs11_engine_path); 124543664Syokota os_free(pkcs11_module_path); 124643664Syokota return wpas_dbus_new_invalid_opts_error(message, NULL); 124748104Syokota} 124843664Syokota 124948104Syokota 125043664Syokota/** 125139287Ssos * wpas_dbus_iface_get_state - Get interface state 125239287Ssos * @message: Pointer to incoming dbus message 125339287Ssos * @wpa_s: wpa_supplicant structure for a network interface 125442504Syokota * Returns: A dbus message containing a STRING representing the current 125539287Ssos * interface state 125642504Syokota * 125739287Ssos * Handler function for "state" method call. 125839287Ssos */ 125939287SsosDBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, 126042504Syokota struct wpa_supplicant *wpa_s) 126139287Ssos{ 126242504Syokota DBusMessage *reply = NULL; 126339287Ssos const char *str_state; 126439287Ssos 126539287Ssos reply = dbus_message_new_method_return(message); 126642504Syokota if (reply != NULL) { 126742504Syokota str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 126839287Ssos dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state, 126942504Syokota DBUS_TYPE_INVALID); 127042504Syokota } 127142504Syokota 127242504Syokota return reply; 127342504Syokota} 127448104Syokota 127542504Syokota 127648104Syokota/** 127748104Syokota * wpas_dbus_iface_get_scanning - Get interface scanning state 127842504Syokota * @message: Pointer to incoming dbus message 127942504Syokota * @wpa_s: wpa_supplicant structure for a network interface 128042504Syokota * Returns: A dbus message containing whether the interface is scanning 128148104Syokota * 128242504Syokota * Handler function for "scanning" method call. 128348104Syokota */ 128448104SyokotaDBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message, 128548104Syokota struct wpa_supplicant *wpa_s) 128642504Syokota{ 128739287Ssos DBusMessage *reply = NULL; 128848104Syokota dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 128948104Syokota 129048104Syokota reply = dbus_message_new_method_return(message); 129148104Syokota if (reply != NULL) { 129248104Syokota dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning, 129348104Syokota DBUS_TYPE_INVALID); 129448104Syokota } else { 129548104Syokota wpa_printf(MSG_ERROR, "dbus: Not enough memory to return " 129648104Syokota "scanning state"); 129748104Syokota } 129848104Syokota 129948104Syokota return reply; 130048104Syokota} 130148104Syokota 130248104Syokota 130348104Syokota/** 130448104Syokota * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates) 130548104Syokota * @message: Pointer to incoming dbus message 130648104Syokota * @wpa_s: %wpa_supplicant data structure 130748104Syokota * Returns: A dbus message containing a UINT32 indicating success (1) or 130848104Syokota * failure (0) 130948104Syokota * 131048104Syokota * Asks wpa_supplicant to internally store a one or more binary blobs. 131148104Syokota */ 131248104SyokotaDBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, 131348104Syokota struct wpa_supplicant *wpa_s) 131448104Syokota{ 131548104Syokota DBusMessage *reply = NULL; 131648104Syokota struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 131748104Syokota DBusMessageIter iter, iter_dict; 131848104Syokota 131948104Syokota dbus_message_iter_init(message, &iter); 132048104Syokota 132148104Syokota if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 132248104Syokota return wpas_dbus_new_invalid_opts_error(message, NULL); 132348104Syokota 132448104Syokota while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 132548104Syokota struct wpa_config_blob *blob; 132648104Syokota 132748104Syokota if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 132848104Syokota reply = wpas_dbus_new_invalid_opts_error(message, 132948104Syokota NULL); 133048104Syokota break; 133148104Syokota } 133248104Syokota 133348104Syokota if (entry.type != DBUS_TYPE_ARRAY || 133448104Syokota entry.array_type != DBUS_TYPE_BYTE) { 133548104Syokota reply = wpas_dbus_new_invalid_opts_error( 133648104Syokota message, "Byte array expected."); 133748104Syokota break; 133848104Syokota } 133948104Syokota 134048104Syokota if ((entry.array_len <= 0) || (entry.array_len > 65536) || 134148104Syokota !strlen(entry.key)) { 134248104Syokota reply = wpas_dbus_new_invalid_opts_error( 134348104Syokota message, "Invalid array size."); 134448104Syokota break; 134548104Syokota } 134648104Syokota 134748104Syokota blob = os_zalloc(sizeof(*blob)); 134848104Syokota if (blob == NULL) { 134948104Syokota reply = dbus_message_new_error( 135048104Syokota message, WPAS_ERROR_ADD_ERROR, 135148104Syokota "Not enough memory to add blob."); 135248104Syokota break; 135348104Syokota } 135448104Syokota blob->data = os_zalloc(entry.array_len); 135548104Syokota if (blob->data == NULL) { 135648104Syokota reply = dbus_message_new_error( 135748104Syokota message, WPAS_ERROR_ADD_ERROR, 135848104Syokota "Not enough memory to add blob data."); 135948104Syokota os_free(blob); 136048104Syokota break; 136148104Syokota } 136248104Syokota 136348104Syokota blob->name = os_strdup(entry.key); 136448104Syokota blob->len = entry.array_len; 136548104Syokota os_memcpy(blob->data, (u8 *) entry.bytearray_value, 136648104Syokota entry.array_len); 136748104Syokota if (blob->name == NULL || blob->data == NULL) { 136848104Syokota wpa_config_free_blob(blob); 136948104Syokota reply = dbus_message_new_error( 137048104Syokota message, WPAS_ERROR_ADD_ERROR, 137148104Syokota "Error adding blob."); 137248104Syokota break; 137348104Syokota } 137448104Syokota 137548104Syokota /* Success */ 137648104Syokota if (!wpa_config_remove_blob(wpa_s->conf, blob->name)) 137748104Syokota wpas_notify_blob_removed(wpa_s, blob->name); 137848104Syokota wpa_config_set_blob(wpa_s->conf, blob); 137948104Syokota wpas_notify_blob_added(wpa_s, blob->name); 138048104Syokota 138148104Syokota wpa_dbus_dict_entry_clear(&entry); 138248104Syokota } 138348104Syokota wpa_dbus_dict_entry_clear(&entry); 138448104Syokota 138548104Syokota return reply ? reply : wpas_dbus_new_success_reply(message); 138648104Syokota} 138748104Syokota 138848104Syokota 138948104Syokota/** 139048104Syokota * wpas_dbus_iface_remove_blob - Remove named binary blobs 139148104Syokota * @message: Pointer to incoming dbus message 139248104Syokota * @wpa_s: %wpa_supplicant data structure 139348104Syokota * Returns: A dbus message containing a UINT32 indicating success (1) or 139448104Syokota * failure (0) 139548104Syokota * 139648104Syokota * Asks wpa_supplicant to remove one or more previously stored binary blobs. 139748104Syokota */ 139848104SyokotaDBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, 139948104Syokota struct wpa_supplicant *wpa_s) 140050446Syokota{ 140150446Syokota DBusMessageIter iter, array; 140242504Syokota char *err_msg = NULL; 140348104Syokota 140448104Syokota dbus_message_iter_init(message, &iter); 140548104Syokota 140648104Syokota if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) || 140750792Syokota (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)) 140850792Syokota return wpas_dbus_new_invalid_opts_error(message, NULL); 140948104Syokota 141048104Syokota dbus_message_iter_recurse(&iter, &array); 141148104Syokota while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { 141250792Syokota const char *name; 141350792Syokota 141448104Syokota dbus_message_iter_get_basic(&array, &name); 141548104Syokota if (!os_strlen(name)) 141648104Syokota err_msg = "Invalid blob name."; 141748104Syokota 141848104Syokota if (wpa_config_remove_blob(wpa_s->conf, name) != 0) 141948104Syokota err_msg = "Error removing blob."; 142048104Syokota else 142148104Syokota wpas_notify_blob_removed(wpa_s, name); 142250792Syokota dbus_message_iter_next(&array); 142350792Syokota } 142450446Syokota 142548104Syokota if (err_msg) 142650446Syokota return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR, 142750446Syokota err_msg); 142850446Syokota 142950446Syokota return wpas_dbus_new_success_reply(message); 143048104Syokota} 143148104Syokota 143248104Syokota 143348104Syokota/** 143448104Syokota * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries 143548104Syokota * @message: Pointer to incoming dbus message 143648104Syokota * @wpa_s: %wpa_supplicant data structure 143748104Syokota * Returns: a dbus message containing a UINT32 indicating success (1) or 143848104Syokota * failure (0), or returns a dbus error message with more information 143948104Syokota * 144048104Syokota * Handler function for "flush" method call. Handles requests for an 144148104Syokota * interface with an optional "age" parameter that specifies the minimum 144248104Syokota * age of a BSS to be flushed. 144348104Syokota */ 144448104SyokotaDBusMessage * wpas_dbus_iface_flush(DBusMessage *message, 144548104Syokota struct wpa_supplicant *wpa_s) 144648104Syokota{ 144748104Syokota int flush_age = 0; 144848104Syokota 144948104Syokota if (os_strlen(dbus_message_get_signature(message)) != 0 && 145048104Syokota !dbus_message_get_args(message, NULL, 145148104Syokota DBUS_TYPE_INT32, &flush_age, 145248104Syokota DBUS_TYPE_INVALID)) { 145348104Syokota return wpas_dbus_new_invalid_opts_error(message, NULL); 145448104Syokota } 145548104Syokota 145648104Syokota if (flush_age == 0) 145748104Syokota wpa_bss_flush(wpa_s); 145848104Syokota else 145948104Syokota wpa_bss_flush_by_age(wpa_s, flush_age); 146048104Syokota 146148104Syokota return wpas_dbus_new_success_reply(message); 146248104Syokota} 146348104Syokota