PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel
C | 1780 lines | 1663 code | 41 blank | 76 comment | 68 complexity | 656349c2dff810d473178a27ab80cdd4 MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /*
  2. * WPA Supplicant / dbus-based control interface
  3. * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
  4. * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
  5. * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * Alternatively, this software may be distributed under the terms of BSD
  12. * license.
  13. *
  14. * See README and COPYING for more details.
  15. */
  16. #include "includes.h"
  17. #include "common.h"
  18. #include "common/ieee802_11_defs.h"
  19. #include "eap_peer/eap_methods.h"
  20. #include "eapol_supp/eapol_supp_sm.h"
  21. #include "rsn_supp/wpa.h"
  22. #include "../config.h"
  23. #include "../wpa_supplicant_i.h"
  24. #include "../driver_i.h"
  25. #include "../notify.h"
  26. #include "../wpas_glue.h"
  27. #include "../bss.h"
  28. #include "../scan.h"
  29. #include "dbus_new_helpers.h"
  30. #include "dbus_new.h"
  31. #include "dbus_new_handlers.h"
  32. #include "dbus_dict_helpers.h"
  33. extern int wpa_debug_level;
  34. extern int wpa_debug_show_keys;
  35. extern int wpa_debug_timestamp;
  36. static const char *debug_strings[] = {
  37. "msgdump", "debug", "info", "warning", "error", NULL
  38. };
  39. /**
  40. * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts
  41. * @path: The dbus object path
  42. * @network: (out) the configured network this object path refers to, if any
  43. * @bssid: (out) the scanned bssid this object path refers to, if any
  44. * Returns: The object path of the network interface this path refers to
  45. *
  46. * For a given object path, decomposes the object path into object id, network,
  47. * and BSSID parts, if those parts exist.
  48. */
  49. static char * wpas_dbus_new_decompose_object_path(const char *path,
  50. char **network,
  51. char **bssid)
  52. {
  53. const unsigned int dev_path_prefix_len =
  54. strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/");
  55. char *obj_path_only;
  56. char *next_sep;
  57. /* Be a bit paranoid about path */
  58. if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/",
  59. dev_path_prefix_len))
  60. return NULL;
  61. /* Ensure there's something at the end of the path */
  62. if ((path + dev_path_prefix_len)[0] == '\0')
  63. return NULL;
  64. obj_path_only = os_strdup(path);
  65. if (obj_path_only == NULL)
  66. return NULL;
  67. next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/');
  68. if (next_sep != NULL) {
  69. const char *net_part = os_strstr(
  70. next_sep, WPAS_DBUS_NEW_NETWORKS_PART "/");
  71. const char *bssid_part = os_strstr(
  72. next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/");
  73. if (network && net_part) {
  74. /* Deal with a request for a configured network */
  75. const char *net_name = net_part +
  76. os_strlen(WPAS_DBUS_NEW_NETWORKS_PART "/");
  77. *network = NULL;
  78. if (os_strlen(net_name))
  79. *network = os_strdup(net_name);
  80. } else if (bssid && bssid_part) {
  81. /* Deal with a request for a scanned BSSID */
  82. const char *bssid_name = bssid_part +
  83. os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/");
  84. if (strlen(bssid_name))
  85. *bssid = os_strdup(bssid_name);
  86. else
  87. *bssid = NULL;
  88. }
  89. /* Cut off interface object path before "/" */
  90. *next_sep = '\0';
  91. }
  92. return obj_path_only;
  93. }
  94. /**
  95. * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
  96. * @message: Pointer to incoming dbus message this error refers to
  97. * @arg: Optional string appended to error message
  98. * Returns: a dbus error message
  99. *
  100. * Convenience function to create and return an UnknownError
  101. */
  102. DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
  103. const char *arg)
  104. {
  105. return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
  106. arg);
  107. }
  108. /**
  109. * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
  110. * @message: Pointer to incoming dbus message this error refers to
  111. * Returns: A dbus error message
  112. *
  113. * Convenience function to create and return an invalid interface error
  114. */
  115. static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
  116. {
  117. return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
  118. "wpa_supplicant knows nothing about "
  119. "this interface.");
  120. }
  121. /**
  122. * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
  123. * @message: Pointer to incoming dbus message this error refers to
  124. * Returns: a dbus error message
  125. *
  126. * Convenience function to create and return an invalid network error
  127. */
  128. static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
  129. {
  130. return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
  131. "There is no such a network in this "
  132. "interface.");
  133. }
  134. /**
  135. * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
  136. * @message: Pointer to incoming dbus message this error refers to
  137. * Returns: a dbus error message
  138. *
  139. * Convenience function to create and return an invalid options error
  140. */
  141. DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
  142. const char *arg)
  143. {
  144. DBusMessage *reply;
  145. reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
  146. "Did not receive correct message "
  147. "arguments.");
  148. if (arg != NULL)
  149. dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
  150. DBUS_TYPE_INVALID);
  151. return reply;
  152. }
  153. static const char *dont_quote[] = {
  154. "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
  155. "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
  156. "bssid", NULL
  157. };
  158. static dbus_bool_t should_quote_opt(const char *key)
  159. {
  160. int i = 0;
  161. while (dont_quote[i] != NULL) {
  162. if (os_strcmp(key, dont_quote[i]) == 0)
  163. return FALSE;
  164. i++;
  165. }
  166. return TRUE;
  167. }
  168. /**
  169. * get_iface_by_dbus_path - Get a new network interface
  170. * @global: Pointer to global data from wpa_supplicant_init()
  171. * @path: Pointer to a dbus object path representing an interface
  172. * Returns: Pointer to the interface or %NULL if not found
  173. */
  174. static struct wpa_supplicant * get_iface_by_dbus_path(
  175. struct wpa_global *global, const char *path)
  176. {
  177. struct wpa_supplicant *wpa_s;
  178. for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
  179. if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
  180. return wpa_s;
  181. }
  182. return NULL;
  183. }
  184. /**
  185. * set_network_properties - Set properties of a configured network
  186. * @message: Pointer to incoming dbus message
  187. * @wpa_s: wpa_supplicant structure for a network interface
  188. * @ssid: wpa_ssid structure for a configured network
  189. * @iter: DBus message iterator containing dictionary of network
  190. * properties to set.
  191. * Returns: NULL when succeed or DBus error on failure
  192. *
  193. * Sets network configuration with parameters given id DBus dictionary
  194. */
  195. static DBusMessage * set_network_properties(DBusMessage *message,
  196. struct wpa_supplicant *wpa_s,
  197. struct wpa_ssid *ssid,
  198. DBusMessageIter *iter)
  199. {
  200. struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
  201. DBusMessage *reply = NULL;
  202. DBusMessageIter iter_dict;
  203. if (!wpa_dbus_dict_open_read(iter, &iter_dict))
  204. return wpas_dbus_error_invalid_args(message, NULL);
  205. while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
  206. char *value = NULL;
  207. size_t size = 50;
  208. int ret;
  209. if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
  210. reply = wpas_dbus_error_invalid_args(message, NULL);
  211. break;
  212. }
  213. if (entry.type == DBUS_TYPE_ARRAY &&
  214. entry.array_type == DBUS_TYPE_BYTE) {
  215. if (entry.array_len <= 0)
  216. goto error;
  217. size = entry.array_len * 2 + 1;
  218. value = os_zalloc(size);
  219. if (value == NULL)
  220. goto error;
  221. ret = wpa_snprintf_hex(value, size,
  222. (u8 *) entry.bytearray_value,
  223. entry.array_len);
  224. if (ret <= 0)
  225. goto error;
  226. } else if (entry.type == DBUS_TYPE_STRING) {
  227. if (should_quote_opt(entry.key)) {
  228. size = os_strlen(entry.str_value);
  229. if (size <= 0)
  230. goto error;
  231. size += 3;
  232. value = os_zalloc(size);
  233. if (value == NULL)
  234. goto error;
  235. ret = os_snprintf(value, size, "\"%s\"",
  236. entry.str_value);
  237. if (ret < 0 || (size_t) ret != (size - 1))
  238. goto error;
  239. } else {
  240. value = os_strdup(entry.str_value);
  241. if (value == NULL)
  242. goto error;
  243. }
  244. } else if (entry.type == DBUS_TYPE_UINT32) {
  245. value = os_zalloc(size);
  246. if (value == NULL)
  247. goto error;
  248. ret = os_snprintf(value, size, "%u",
  249. entry.uint32_value);
  250. if (ret <= 0)
  251. goto error;
  252. } else if (entry.type == DBUS_TYPE_INT32) {
  253. value = os_zalloc(size);
  254. if (value == NULL)
  255. goto error;
  256. ret = os_snprintf(value, size, "%d",
  257. entry.int32_value);
  258. if (ret <= 0)
  259. goto error;
  260. } else
  261. goto error;
  262. if (wpa_config_set(ssid, entry.key, value, 0) < 0)
  263. goto error;
  264. if ((os_strcmp(entry.key, "psk") == 0 &&
  265. value[0] == '"' && ssid->ssid_len) ||
  266. (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
  267. wpa_config_update_psk(ssid);
  268. else if (os_strcmp(entry.key, "priority") == 0)
  269. wpa_config_update_prio_list(wpa_s->conf);
  270. os_free(value);
  271. wpa_dbus_dict_entry_clear(&entry);
  272. continue;
  273. error:
  274. os_free(value);
  275. reply = wpas_dbus_error_invalid_args(message, entry.key);
  276. wpa_dbus_dict_entry_clear(&entry);
  277. break;
  278. }
  279. return reply;
  280. }
  281. /**
  282. * wpas_dbus_simple_property_getter - Get basic type property
  283. * @message: Pointer to incoming dbus message
  284. * @type: DBus type of property (must be basic type)
  285. * @val: pointer to place holding property value
  286. * Returns: The DBus message containing response for Properties.Get call
  287. * or DBus error message if error occurred.
  288. *
  289. * Generic getter for basic type properties. Type is required to be basic.
  290. */
  291. DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message,
  292. const int type, const void *val)
  293. {
  294. DBusMessage *reply = NULL;
  295. DBusMessageIter iter, variant_iter;
  296. if (!dbus_type_is_basic(type)) {
  297. wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
  298. " given type is not basic");
  299. return wpas_dbus_error_unknown_error(message, NULL);
  300. }
  301. if (message == NULL)
  302. reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
  303. else
  304. reply = dbus_message_new_method_return(message);
  305. if (reply != NULL) {
  306. dbus_message_iter_init_append(reply, &iter);
  307. if (!dbus_message_iter_open_container(
  308. &iter, DBUS_TYPE_VARIANT,
  309. wpa_dbus_type_as_string(type), &variant_iter) ||
  310. !dbus_message_iter_append_basic(&variant_iter, type,
  311. val) ||
  312. !dbus_message_iter_close_container(&iter, &variant_iter)) {
  313. wpa_printf(MSG_ERROR, "dbus: "
  314. "wpas_dbus_simple_property_getter: out of "
  315. "memory to put property value into "
  316. "message");
  317. dbus_message_unref(reply);
  318. reply = dbus_message_new_error(message,
  319. DBUS_ERROR_NO_MEMORY,
  320. NULL);
  321. }
  322. } else {
  323. wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
  324. " out of memory to return property value");
  325. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  326. NULL);
  327. }
  328. return reply;
  329. }
  330. /**
  331. * wpas_dbus_simple_property_setter - Set basic type property
  332. * @message: Pointer to incoming dbus message
  333. * @type: DBus type of property (must be basic type)
  334. * @val: pointer to place where value being set will be stored
  335. * Returns: NULL or DBus error message if error occurred.
  336. *
  337. * Generic setter for basic type properties. Type is required to be basic.
  338. */
  339. DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message,
  340. const int type, void *val)
  341. {
  342. DBusMessageIter iter, variant_iter;
  343. if (!dbus_type_is_basic(type)) {
  344. wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
  345. " given type is not basic");
  346. return wpas_dbus_error_unknown_error(message, NULL);
  347. }
  348. if (!dbus_message_iter_init(message, &iter)) {
  349. wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
  350. " out of memory to return scanning state");
  351. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  352. NULL);
  353. }
  354. /* omit first and second argument and get value from third */
  355. dbus_message_iter_next(&iter);
  356. dbus_message_iter_next(&iter);
  357. dbus_message_iter_recurse(&iter, &variant_iter);
  358. if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
  359. wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:"
  360. " wrong property type");
  361. return wpas_dbus_error_invalid_args(message,
  362. "wrong property type");
  363. }
  364. dbus_message_iter_get_basic(&variant_iter, val);
  365. return NULL;
  366. }
  367. /**
  368. * wpas_dbus_simple_array_property_getter - Get array type property
  369. * @message: Pointer to incoming dbus message
  370. * @type: DBus type of property array elements (must be basic type)
  371. * @array: pointer to array of elements to put into response message
  372. * @array_len: length of above array
  373. * Returns: The DBus message containing response for Properties.Get call
  374. * or DBus error message if error occurred.
  375. *
  376. * Generic getter for array type properties. Array elements type is
  377. * required to be basic.
  378. */
  379. DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message,
  380. const int type,
  381. const void *array,
  382. size_t array_len)
  383. {
  384. DBusMessage *reply = NULL;
  385. DBusMessageIter iter, variant_iter, array_iter;
  386. char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
  387. const char *sub_type_str;
  388. size_t element_size, i;
  389. if (!dbus_type_is_basic(type)) {
  390. wpa_printf(MSG_ERROR, "dbus: "
  391. "wpas_dbus_simple_array_property_getter: given "
  392. "type is not basic");
  393. return wpas_dbus_error_unknown_error(message, NULL);
  394. }
  395. sub_type_str = wpa_dbus_type_as_string(type);
  396. type_str[1] = sub_type_str[0];
  397. if (message == NULL)
  398. reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
  399. else
  400. reply = dbus_message_new_method_return(message);
  401. if (reply == NULL) {
  402. wpa_printf(MSG_ERROR, "dbus: "
  403. "wpas_dbus_simple_array_property_getter: out of "
  404. "memory to create return message");
  405. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  406. NULL);
  407. }
  408. dbus_message_iter_init_append(reply, &iter);
  409. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
  410. type_str, &variant_iter) ||
  411. !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
  412. sub_type_str, &array_iter)) {
  413. wpa_printf(MSG_ERROR, "dbus: "
  414. "wpas_dbus_simple_array_property_getter: out of "
  415. "memory to open container");
  416. dbus_message_unref(reply);
  417. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  418. NULL);
  419. }
  420. switch(type) {
  421. case DBUS_TYPE_BYTE:
  422. case DBUS_TYPE_BOOLEAN:
  423. element_size = 1;
  424. break;
  425. case DBUS_TYPE_INT16:
  426. case DBUS_TYPE_UINT16:
  427. element_size = sizeof(uint16_t);
  428. break;
  429. case DBUS_TYPE_INT32:
  430. case DBUS_TYPE_UINT32:
  431. element_size = sizeof(uint32_t);
  432. break;
  433. case DBUS_TYPE_INT64:
  434. case DBUS_TYPE_UINT64:
  435. element_size = sizeof(uint64_t);
  436. break;
  437. case DBUS_TYPE_DOUBLE:
  438. element_size = sizeof(double);
  439. break;
  440. case DBUS_TYPE_STRING:
  441. case DBUS_TYPE_OBJECT_PATH:
  442. element_size = sizeof(char *);
  443. break;
  444. default:
  445. wpa_printf(MSG_ERROR, "dbus: "
  446. "wpas_dbus_simple_array_property_getter: "
  447. "fatal: unknown element type");
  448. element_size = 1;
  449. break;
  450. }
  451. for (i = 0; i < array_len; i++) {
  452. dbus_message_iter_append_basic(&array_iter, type,
  453. array + i * element_size);
  454. }
  455. if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
  456. !dbus_message_iter_close_container(&iter, &variant_iter)) {
  457. wpa_printf(MSG_ERROR, "dbus: "
  458. "wpas_dbus_simple_array_property_getter: out of "
  459. "memory to close container");
  460. dbus_message_unref(reply);
  461. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  462. NULL);
  463. }
  464. return reply;
  465. }
  466. /**
  467. * wpas_dbus_handler_create_interface - Request registration of a network iface
  468. * @message: Pointer to incoming dbus message
  469. * @global: %wpa_supplicant global data structure
  470. * Returns: The object path of the new interface object,
  471. * or a dbus error message with more information
  472. *
  473. * Handler function for "CreateInterface" method call. Handles requests
  474. * by dbus clients to register a network interface that wpa_supplicant
  475. * will manage.
  476. */
  477. DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
  478. struct wpa_global *global)
  479. {
  480. DBusMessageIter iter_dict;
  481. DBusMessage *reply = NULL;
  482. DBusMessageIter iter;
  483. struct wpa_dbus_dict_entry entry;
  484. char *driver = NULL;
  485. char *ifname = NULL;
  486. char *bridge_ifname = NULL;
  487. dbus_message_iter_init(message, &iter);
  488. if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
  489. goto error;
  490. while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
  491. if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
  492. goto error;
  493. if (!strcmp(entry.key, "Driver") &&
  494. (entry.type == DBUS_TYPE_STRING)) {
  495. driver = os_strdup(entry.str_value);
  496. wpa_dbus_dict_entry_clear(&entry);
  497. if (driver == NULL)
  498. goto error;
  499. } else if (!strcmp(entry.key, "Ifname") &&
  500. (entry.type == DBUS_TYPE_STRING)) {
  501. ifname = os_strdup(entry.str_value);
  502. wpa_dbus_dict_entry_clear(&entry);
  503. if (ifname == NULL)
  504. goto error;
  505. } else if (!strcmp(entry.key, "BridgeIfname") &&
  506. (entry.type == DBUS_TYPE_STRING)) {
  507. bridge_ifname = os_strdup(entry.str_value);
  508. wpa_dbus_dict_entry_clear(&entry);
  509. if (bridge_ifname == NULL)
  510. goto error;
  511. } else {
  512. wpa_dbus_dict_entry_clear(&entry);
  513. goto error;
  514. }
  515. }
  516. if (ifname == NULL)
  517. goto error; /* Required Ifname argument missing */
  518. /*
  519. * Try to get the wpa_supplicant record for this iface, return
  520. * an error if we already control it.
  521. */
  522. if (wpa_supplicant_get_iface(global, ifname) != NULL) {
  523. reply = dbus_message_new_error(message,
  524. WPAS_DBUS_ERROR_IFACE_EXISTS,
  525. "wpa_supplicant already "
  526. "controls this interface.");
  527. } else {
  528. struct wpa_supplicant *wpa_s;
  529. struct wpa_interface iface;
  530. os_memset(&iface, 0, sizeof(iface));
  531. iface.driver = driver;
  532. iface.ifname = ifname;
  533. iface.bridge_ifname = bridge_ifname;
  534. /* Otherwise, have wpa_supplicant attach to it. */
  535. if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
  536. const char *path = wpa_s->dbus_new_path;
  537. reply = dbus_message_new_method_return(message);
  538. dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
  539. &path, DBUS_TYPE_INVALID);
  540. } else {
  541. reply = wpas_dbus_error_unknown_error(
  542. message, "wpa_supplicant couldn't grab this "
  543. "interface.");
  544. }
  545. }
  546. out:
  547. os_free(driver);
  548. os_free(ifname);
  549. os_free(bridge_ifname);
  550. return reply;
  551. error:
  552. reply = wpas_dbus_error_invalid_args(message, NULL);
  553. goto out;
  554. }
  555. /**
  556. * wpas_dbus_handler_remove_interface - Request deregistration of an interface
  557. * @message: Pointer to incoming dbus message
  558. * @global: wpa_supplicant global data structure
  559. * Returns: a dbus message containing a UINT32 indicating success (1) or
  560. * failure (0), or returns a dbus error message with more information
  561. *
  562. * Handler function for "removeInterface" method call. Handles requests
  563. * by dbus clients to deregister a network interface that wpa_supplicant
  564. * currently manages.
  565. */
  566. DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
  567. struct wpa_global *global)
  568. {
  569. struct wpa_supplicant *wpa_s;
  570. char *path;
  571. DBusMessage *reply = NULL;
  572. dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
  573. DBUS_TYPE_INVALID);
  574. wpa_s = get_iface_by_dbus_path(global, path);
  575. if (wpa_s == NULL)
  576. reply = wpas_dbus_error_iface_unknown(message);
  577. else if (wpa_supplicant_remove_iface(global, wpa_s)) {
  578. reply = wpas_dbus_error_unknown_error(
  579. message, "wpa_supplicant couldn't remove this "
  580. "interface.");
  581. }
  582. return reply;
  583. }
  584. /**
  585. * wpas_dbus_handler_get_interface - Get the object path for an interface name
  586. * @message: Pointer to incoming dbus message
  587. * @global: %wpa_supplicant global data structure
  588. * Returns: The object path of the interface object,
  589. * or a dbus error message with more information
  590. *
  591. * Handler function for "getInterface" method call.
  592. */
  593. DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
  594. struct wpa_global *global)
  595. {
  596. DBusMessage *reply = NULL;
  597. const char *ifname;
  598. const char *path;
  599. struct wpa_supplicant *wpa_s;
  600. dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
  601. DBUS_TYPE_INVALID);
  602. wpa_s = wpa_supplicant_get_iface(global, ifname);
  603. if (wpa_s == NULL)
  604. return wpas_dbus_error_iface_unknown(message);
  605. path = wpa_s->dbus_new_path;
  606. reply = dbus_message_new_method_return(message);
  607. if (reply == NULL)
  608. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  609. NULL);
  610. if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
  611. DBUS_TYPE_INVALID)) {
  612. dbus_message_unref(reply);
  613. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  614. NULL);
  615. }
  616. return reply;
  617. }
  618. /**
  619. * wpas_dbus_getter_debug_level - Get debug level
  620. * @message: Pointer to incoming dbus message
  621. * @global: %wpa_supplicant global data structure
  622. * Returns: DBus message with value of debug level
  623. *
  624. * Getter for "DebugLevel" property.
  625. */
  626. DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message,
  627. struct wpa_global *global)
  628. {
  629. const char *str;
  630. int idx = wpa_debug_level;
  631. if (idx < 0)
  632. idx = 0;
  633. if (idx > 4)
  634. idx = 4;
  635. str = debug_strings[idx];
  636. return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
  637. &str);
  638. }
  639. /**
  640. * wpas_dbus_getter_debug_timestamp - Get debug timestamp
  641. * @message: Pointer to incoming dbus message
  642. * @global: %wpa_supplicant global data structure
  643. * Returns: DBus message with value of debug timestamp
  644. *
  645. * Getter for "DebugTimestamp" property.
  646. */
  647. DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message,
  648. struct wpa_global *global)
  649. {
  650. return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
  651. &wpa_debug_timestamp);
  652. }
  653. /**
  654. * wpas_dbus_getter_debug_show_keys - Get debug show keys
  655. * @message: Pointer to incoming dbus message
  656. * @global: %wpa_supplicant global data structure
  657. * Returns: DBus message with value of debug show_keys
  658. *
  659. * Getter for "DebugShowKeys" property.
  660. */
  661. DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message,
  662. struct wpa_global *global)
  663. {
  664. return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
  665. &wpa_debug_show_keys);
  666. }
  667. /**
  668. * wpas_dbus_setter_debug_level - Set debug level
  669. * @message: Pointer to incoming dbus message
  670. * @global: %wpa_supplicant global data structure
  671. * Returns: %NULL or DBus error message
  672. *
  673. * Setter for "DebugLevel" property.
  674. */
  675. DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message,
  676. struct wpa_global *global)
  677. {
  678. DBusMessage *reply;
  679. const char *str = NULL;
  680. int i, val = -1;
  681. reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
  682. &str);
  683. if (reply)
  684. return reply;
  685. for (i = 0; debug_strings[i]; i++)
  686. if (os_strcmp(debug_strings[i], str) == 0) {
  687. val = i;
  688. break;
  689. }
  690. if (val < 0 ||
  691. wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
  692. wpa_debug_show_keys)) {
  693. dbus_message_unref(reply);
  694. return wpas_dbus_error_invalid_args(
  695. message, "Wrong debug level value");
  696. }
  697. return NULL;
  698. }
  699. /**
  700. * wpas_dbus_setter_debug_timestamp - Set debug timestamp
  701. * @message: Pointer to incoming dbus message
  702. * @global: %wpa_supplicant global data structure
  703. * Returns: %NULL or DBus error message
  704. *
  705. * Setter for "DebugTimestamp" property.
  706. */
  707. DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message,
  708. struct wpa_global *global)
  709. {
  710. DBusMessage *reply;
  711. dbus_bool_t val;
  712. reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
  713. &val);
  714. if (reply)
  715. return reply;
  716. wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
  717. wpa_debug_show_keys);
  718. return NULL;
  719. }
  720. /**
  721. * wpas_dbus_setter_debug_show_keys - Set debug show keys
  722. * @message: Pointer to incoming dbus message
  723. * @global: %wpa_supplicant global data structure
  724. * Returns: %NULL or DBus error message
  725. *
  726. * Setter for "DebugShowKeys" property.
  727. */
  728. DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message,
  729. struct wpa_global *global)
  730. {
  731. DBusMessage *reply;
  732. dbus_bool_t val;
  733. reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
  734. &val);
  735. if (reply)
  736. return reply;
  737. wpa_supplicant_set_debug_params(global, wpa_debug_level,
  738. wpa_debug_timestamp,
  739. val ? 1 : 0);
  740. return NULL;
  741. }
  742. /**
  743. * wpas_dbus_getter_interfaces - Request registered interfaces list
  744. * @message: Pointer to incoming dbus message
  745. * @global: %wpa_supplicant global data structure
  746. * Returns: The object paths array containing registered interfaces
  747. * objects paths or DBus error on failure
  748. *
  749. * Getter for "Interfaces" property. Handles requests
  750. * by dbus clients to return list of registered interfaces objects
  751. * paths
  752. */
  753. DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
  754. struct wpa_global *global)
  755. {
  756. DBusMessage *reply = NULL;
  757. struct wpa_supplicant *wpa_s;
  758. const char **paths;
  759. unsigned int i = 0, num = 0;
  760. for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
  761. num++;
  762. paths = os_zalloc(num * sizeof(char*));
  763. if (!paths) {
  764. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  765. NULL);
  766. }
  767. for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
  768. paths[i] = wpa_s->dbus_new_path;
  769. reply = wpas_dbus_simple_array_property_getter(message,
  770. DBUS_TYPE_OBJECT_PATH,
  771. paths, num);
  772. os_free(paths);
  773. return reply;
  774. }
  775. /**
  776. * wpas_dbus_getter_eap_methods - Request supported EAP methods list
  777. * @message: Pointer to incoming dbus message
  778. * @nothing: not used argument. may be NULL or anything else
  779. * Returns: The object paths array containing supported EAP methods
  780. * represented by strings or DBus error on failure
  781. *
  782. * Getter for "EapMethods" property. Handles requests
  783. * by dbus clients to return list of strings with supported EAP methods
  784. */
  785. DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
  786. {
  787. DBusMessage *reply = NULL;
  788. char **eap_methods;
  789. size_t num_items = 0;
  790. eap_methods = eap_get_names_as_string_array(&num_items);
  791. if (!eap_methods) {
  792. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  793. NULL);
  794. }
  795. reply = wpas_dbus_simple_array_property_getter(message,
  796. DBUS_TYPE_STRING,
  797. eap_methods, num_items);
  798. while (num_items)
  799. os_free(eap_methods[--num_items]);
  800. os_free(eap_methods);
  801. return reply;
  802. }
  803. static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
  804. char **type, DBusMessage **reply)
  805. {
  806. if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
  807. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  808. "Type must be a string");
  809. *reply = wpas_dbus_error_invalid_args(
  810. message, "Wrong Type value type. String required");
  811. return -1;
  812. }
  813. dbus_message_iter_get_basic(var, type);
  814. return 0;
  815. }
  816. static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
  817. struct wpa_driver_scan_params *params,
  818. DBusMessage **reply)
  819. {
  820. struct wpa_driver_scan_ssid *ssids = params->ssids;
  821. size_t ssids_num = 0;
  822. u8 *ssid;
  823. DBusMessageIter array_iter, sub_array_iter;
  824. char *val;
  825. int len;
  826. if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
  827. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
  828. "must be an array of arrays of bytes");
  829. *reply = wpas_dbus_error_invalid_args(
  830. message, "Wrong SSIDs value type. Array of arrays of "
  831. "bytes required");
  832. return -1;
  833. }
  834. dbus_message_iter_recurse(var, &array_iter);
  835. if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
  836. dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
  837. {
  838. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
  839. "must be an array of arrays of bytes");
  840. *reply = wpas_dbus_error_invalid_args(
  841. message, "Wrong SSIDs value type. Array of arrays of "
  842. "bytes required");
  843. return -1;
  844. }
  845. while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
  846. {
  847. if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
  848. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  849. "Too many ssids specified on scan dbus "
  850. "call");
  851. *reply = wpas_dbus_error_invalid_args(
  852. message, "Too many ssids specified. Specify "
  853. "at most four");
  854. return -1;
  855. }
  856. dbus_message_iter_recurse(&array_iter, &sub_array_iter);
  857. dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
  858. if (len == 0) {
  859. dbus_message_iter_next(&array_iter);
  860. continue;
  861. }
  862. ssid = os_malloc(len);
  863. if (ssid == NULL) {
  864. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  865. "out of memory. Cannot allocate memory for "
  866. "SSID");
  867. *reply = dbus_message_new_error(
  868. message, DBUS_ERROR_NO_MEMORY, NULL);
  869. return -1;
  870. }
  871. os_memcpy(ssid, val, len);
  872. ssids[ssids_num].ssid = ssid;
  873. ssids[ssids_num].ssid_len = len;
  874. dbus_message_iter_next(&array_iter);
  875. ssids_num++;
  876. }
  877. params->num_ssids = ssids_num;
  878. return 0;
  879. }
  880. static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
  881. struct wpa_driver_scan_params *params,
  882. DBusMessage **reply)
  883. {
  884. u8 *ies = NULL, *nies;
  885. int ies_len = 0;
  886. DBusMessageIter array_iter, sub_array_iter;
  887. char *val;
  888. int len;
  889. if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
  890. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
  891. "be an array of arrays of bytes");
  892. *reply = wpas_dbus_error_invalid_args(
  893. message, "Wrong IEs value type. Array of arrays of "
  894. "bytes required");
  895. return -1;
  896. }
  897. dbus_message_iter_recurse(var, &array_iter);
  898. if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
  899. dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
  900. {
  901. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
  902. "be an array of arrays of bytes");
  903. *reply = wpas_dbus_error_invalid_args(
  904. message, "Wrong IEs value type. Array required");
  905. return -1;
  906. }
  907. while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
  908. {
  909. dbus_message_iter_recurse(&array_iter, &sub_array_iter);
  910. dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
  911. if (len == 0) {
  912. dbus_message_iter_next(&array_iter);
  913. continue;
  914. }
  915. nies = os_realloc(ies, ies_len + len);
  916. if (nies == NULL) {
  917. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  918. "out of memory. Cannot allocate memory for "
  919. "IE");
  920. os_free(ies);
  921. *reply = dbus_message_new_error(
  922. message, DBUS_ERROR_NO_MEMORY, NULL);
  923. return -1;
  924. }
  925. ies = nies;
  926. os_memcpy(ies + ies_len, val, len);
  927. ies_len += len;
  928. dbus_message_iter_next(&array_iter);
  929. }
  930. params->extra_ies = ies;
  931. params->extra_ies_len = ies_len;
  932. return 0;
  933. }
  934. static int wpas_dbus_get_scan_channels(DBusMessage *message,
  935. DBusMessageIter *var,
  936. struct wpa_driver_scan_params *params,
  937. DBusMessage **reply)
  938. {
  939. DBusMessageIter array_iter, sub_array_iter;
  940. int *freqs = NULL, *nfreqs;
  941. int freqs_num = 0;
  942. if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
  943. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  944. "Channels must be an array of structs");
  945. *reply = wpas_dbus_error_invalid_args(
  946. message, "Wrong Channels value type. Array of structs "
  947. "required");
  948. return -1;
  949. }
  950. dbus_message_iter_recurse(var, &array_iter);
  951. if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
  952. wpa_printf(MSG_DEBUG,
  953. "wpas_dbus_handler_scan[dbus]: Channels must be an "
  954. "array of structs");
  955. *reply = wpas_dbus_error_invalid_args(
  956. message, "Wrong Channels value type. Array of structs "
  957. "required");
  958. return -1;
  959. }
  960. while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
  961. {
  962. int freq, width;
  963. dbus_message_iter_recurse(&array_iter, &sub_array_iter);
  964. if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
  965. DBUS_TYPE_UINT32) {
  966. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  967. "Channel must by specified by struct of "
  968. "two UINT32s %c",
  969. dbus_message_iter_get_arg_type(
  970. &sub_array_iter));
  971. *reply = wpas_dbus_error_invalid_args(
  972. message, "Wrong Channel struct. Two UINT32s "
  973. "required");
  974. os_free(freqs);
  975. return -1;
  976. }
  977. dbus_message_iter_get_basic(&sub_array_iter, &freq);
  978. if (!dbus_message_iter_next(&sub_array_iter) ||
  979. dbus_message_iter_get_arg_type(&sub_array_iter) !=
  980. DBUS_TYPE_UINT32) {
  981. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  982. "Channel must by specified by struct of "
  983. "two UINT32s");
  984. *reply = wpas_dbus_error_invalid_args(
  985. message,
  986. "Wrong Channel struct. Two UINT32s required");
  987. os_free(freqs);
  988. return -1;
  989. }
  990. dbus_message_iter_get_basic(&sub_array_iter, &width);
  991. #define FREQS_ALLOC_CHUNK 32
  992. if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
  993. nfreqs = os_realloc(freqs, sizeof(int) *
  994. (freqs_num + FREQS_ALLOC_CHUNK));
  995. if (nfreqs == NULL)
  996. os_free(freqs);
  997. freqs = nfreqs;
  998. }
  999. if (freqs == NULL) {
  1000. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  1001. "out of memory. can't allocate memory for "
  1002. "freqs");
  1003. *reply = dbus_message_new_error(
  1004. message, DBUS_ERROR_NO_MEMORY, NULL);
  1005. return -1;
  1006. }
  1007. freqs[freqs_num] = freq;
  1008. freqs_num++;
  1009. dbus_message_iter_next(&array_iter);
  1010. }
  1011. nfreqs = os_realloc(freqs,
  1012. sizeof(int) * (freqs_num + 1));
  1013. if (nfreqs == NULL)
  1014. os_free(freqs);
  1015. freqs = nfreqs;
  1016. if (freqs == NULL) {
  1017. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  1018. "out of memory. Can't allocate memory for freqs");
  1019. *reply = dbus_message_new_error(
  1020. message, DBUS_ERROR_NO_MEMORY, NULL);
  1021. return -1;
  1022. }
  1023. freqs[freqs_num] = 0;
  1024. params->freqs = freqs;
  1025. return 0;
  1026. }
  1027. /**
  1028. * wpas_dbus_handler_scan - Request a wireless scan on an interface
  1029. * @message: Pointer to incoming dbus message
  1030. * @wpa_s: wpa_supplicant structure for a network interface
  1031. * Returns: NULL indicating success or DBus error message on failure
  1032. *
  1033. * Handler function for "Scan" method call of a network device. Requests
  1034. * that wpa_supplicant perform a wireless scan as soon as possible
  1035. * on a particular wireless interface.
  1036. */
  1037. DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
  1038. struct wpa_supplicant *wpa_s)
  1039. {
  1040. DBusMessage *reply = NULL;
  1041. DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
  1042. char *key = NULL, *type = NULL;
  1043. struct wpa_driver_scan_params params;
  1044. size_t i;
  1045. os_memset(&params, 0, sizeof(params));
  1046. dbus_message_iter_init(message, &iter);
  1047. dbus_message_iter_recurse(&iter, &dict_iter);
  1048. while (dbus_message_iter_get_arg_type(&dict_iter) ==
  1049. DBUS_TYPE_DICT_ENTRY) {
  1050. dbus_message_iter_recurse(&dict_iter, &entry_iter);
  1051. dbus_message_iter_get_basic(&entry_iter, &key);
  1052. dbus_message_iter_next(&entry_iter);
  1053. dbus_message_iter_recurse(&entry_iter, &variant_iter);
  1054. if (os_strcmp(key, "Type") == 0) {
  1055. if (wpas_dbus_get_scan_type(message, &variant_iter,
  1056. &type, &reply) < 0)
  1057. goto out;
  1058. } else if (os_strcmp(key, "SSIDs") == 0) {
  1059. if (wpas_dbus_get_scan_ssids(message, &variant_iter,
  1060. &params, &reply) < 0)
  1061. goto out;
  1062. } else if (os_strcmp(key, "IEs") == 0) {
  1063. if (wpas_dbus_get_scan_ies(message, &variant_iter,
  1064. &params, &reply) < 0)
  1065. goto out;
  1066. } else if (os_strcmp(key, "Channels") == 0) {
  1067. if (wpas_dbus_get_scan_channels(message, &variant_iter,
  1068. &params, &reply) < 0)
  1069. goto out;
  1070. } else {
  1071. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  1072. "Unknown argument %s", key);
  1073. reply = wpas_dbus_error_invalid_args(message, key);
  1074. goto out;
  1075. }
  1076. dbus_message_iter_next(&dict_iter);
  1077. }
  1078. if (!type) {
  1079. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  1080. "Scan type not specified");
  1081. reply = wpas_dbus_error_invalid_args(message, key);
  1082. goto out;
  1083. }
  1084. if (!os_strcmp(type, "passive")) {
  1085. if (params.num_ssids || params.extra_ies_len) {
  1086. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  1087. "SSIDs or IEs specified for passive scan.");
  1088. reply = wpas_dbus_error_invalid_args(
  1089. message, "You can specify only Channels in "
  1090. "passive scan");
  1091. goto out;
  1092. } else if (params.freqs && params.freqs[0]) {
  1093. /* wildcard ssid */
  1094. params.num_ssids++;
  1095. wpa_supplicant_trigger_scan(wpa_s, &params);
  1096. } else {
  1097. wpa_s->scan_req = 2;
  1098. wpa_supplicant_req_scan(wpa_s, 0, 0);
  1099. }
  1100. } else if (!os_strcmp(type, "active")) {
  1101. wpa_supplicant_trigger_scan(wpa_s, &params);
  1102. } else {
  1103. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
  1104. "Unknown scan type: %s", type);
  1105. reply = wpas_dbus_error_invalid_args(message,
  1106. "Wrong scan type");
  1107. goto out;
  1108. }
  1109. out:
  1110. for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
  1111. os_free((u8 *) params.ssids[i].ssid);
  1112. os_free((u8 *) params.extra_ies);
  1113. os_free(params.freqs);
  1114. return reply;
  1115. }
  1116. /*
  1117. * wpas_dbus_handler_disconnect - Terminate the current connection
  1118. * @message: Pointer to incoming dbus message
  1119. * @wpa_s: wpa_supplicant structure for a network interface
  1120. * Returns: NotConnected DBus error message if already not connected
  1121. * or NULL otherwise.
  1122. *
  1123. * Handler function for "Disconnect" method call of network interface.
  1124. */
  1125. DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
  1126. struct wpa_supplicant *wpa_s)
  1127. {
  1128. if (wpa_s->current_ssid != NULL) {
  1129. wpa_s->disconnected = 1;
  1130. wpa_supplicant_deauthenticate(wpa_s,
  1131. WLAN_REASON_DEAUTH_LEAVING);
  1132. return NULL;
  1133. }
  1134. return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
  1135. "This interface is not connected");
  1136. }
  1137. /**
  1138. * wpas_dbus_new_iface_add_network - Add a new configured network
  1139. * @message: Pointer to incoming dbus message
  1140. * @wpa_s: wpa_supplicant structure for a network interface
  1141. * Returns: A dbus message containing the object path of the new network
  1142. *
  1143. * Handler function for "AddNetwork" method call of a network interface.
  1144. */
  1145. DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
  1146. struct wpa_supplicant *wpa_s)
  1147. {
  1148. DBusMessage *reply = NULL;
  1149. DBusMessageIter iter;
  1150. struct wpa_ssid *ssid = NULL;
  1151. char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
  1152. dbus_message_iter_init(message, &iter);
  1153. ssid = wpa_config_add_network(wpa_s->conf);
  1154. if (ssid == NULL) {
  1155. wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
  1156. "can't add new interface.");
  1157. reply = wpas_dbus_error_unknown_error(
  1158. message,
  1159. "wpa_supplicant could not add "
  1160. "a network on this interface.");
  1161. goto err;
  1162. }
  1163. wpas_notify_network_added(wpa_s, ssid);
  1164. ssid->disabled = 1;
  1165. wpa_config_set_network_defaults(ssid);
  1166. reply = set_network_properties(message, wpa_s, ssid, &iter);
  1167. if (reply) {
  1168. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
  1169. "control interface couldn't set network "
  1170. "properties");
  1171. goto err;
  1172. }
  1173. /* Construct the object path for this network. */
  1174. os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
  1175. "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
  1176. wpa_s->dbus_new_path, ssid->id);
  1177. reply = dbus_message_new_method_return(message);
  1178. if (reply == NULL) {
  1179. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1180. NULL);
  1181. goto err;
  1182. }
  1183. if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
  1184. DBUS_TYPE_INVALID)) {
  1185. dbus_message_unref(reply);
  1186. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1187. NULL);
  1188. goto err;
  1189. }
  1190. return reply;
  1191. err:
  1192. if (ssid) {
  1193. wpas_notify_network_removed(wpa_s, ssid);
  1194. wpa_config_remove_network(wpa_s->conf, ssid->id);
  1195. }
  1196. return reply;
  1197. }
  1198. /**
  1199. * wpas_dbus_handler_remove_network - Remove a configured network
  1200. * @message: Pointer to incoming dbus message
  1201. * @wpa_s: wpa_supplicant structure for a network interface
  1202. * Returns: NULL on success or dbus error on failure
  1203. *
  1204. * Handler function for "RemoveNetwork" method call of a network interface.
  1205. */
  1206. DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
  1207. struct wpa_supplicant *wpa_s)
  1208. {
  1209. DBusMessage *reply = NULL;
  1210. const char *op;
  1211. char *iface = NULL, *net_id = NULL;
  1212. int id;
  1213. struct wpa_ssid *ssid;
  1214. dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
  1215. DBUS_TYPE_INVALID);
  1216. /* Extract the network ID and ensure the network */
  1217. /* is actually a child of this interface */
  1218. iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
  1219. if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
  1220. reply = wpas_dbus_error_invalid_args(message, op);
  1221. goto out;
  1222. }
  1223. id = strtoul(net_id, NULL, 10);
  1224. if (errno == EINVAL) {
  1225. reply = wpas_dbus_error_invalid_args(message, op);
  1226. goto out;
  1227. }
  1228. ssid = wpa_config_get_network(wpa_s->conf, id);
  1229. if (ssid == NULL) {
  1230. reply = wpas_dbus_error_network_unknown(message);
  1231. goto out;
  1232. }
  1233. wpas_notify_network_removed(wpa_s, ssid);
  1234. if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
  1235. wpa_printf(MSG_ERROR,
  1236. "wpas_dbus_handler_remove_network[dbus]: "
  1237. "error occurred when removing network %d", id);
  1238. reply = wpas_dbus_error_unknown_error(
  1239. message, "error removing the specified network on "
  1240. "this interface.");
  1241. goto out;
  1242. }
  1243. if (ssid == wpa_s->current_ssid)
  1244. wpa_supplicant_deauthenticate(wpa_s,
  1245. WLAN_REASON_DEAUTH_LEAVING);
  1246. out:
  1247. os_free(iface);
  1248. os_free(net_id);
  1249. return reply;
  1250. }
  1251. /**
  1252. * wpas_dbus_handler_select_network - Attempt association with a network
  1253. * @message: Pointer to incoming dbus message
  1254. * @wpa_s: wpa_supplicant structure for a network interface
  1255. * Returns: NULL on success or dbus error on failure
  1256. *
  1257. * Handler function for "SelectNetwork" method call of network interface.
  1258. */
  1259. DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
  1260. struct wpa_supplicant *wpa_s)
  1261. {
  1262. DBusMessage *reply = NULL;
  1263. const char *op;
  1264. char *iface = NULL, *net_id = NULL;
  1265. int id;
  1266. struct wpa_ssid *ssid;
  1267. dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
  1268. DBUS_TYPE_INVALID);
  1269. /* Extract the network ID and ensure the network */
  1270. /* is actually a child of this interface */
  1271. iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
  1272. if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
  1273. reply = wpas_dbus_error_invalid_args(message, op);
  1274. goto out;
  1275. }
  1276. id = strtoul(net_id, NULL, 10);
  1277. if (errno == EINVAL) {
  1278. reply = wpas_dbus_error_invalid_args(message, op);
  1279. goto out;
  1280. }
  1281. ssid = wpa_config_get_network(wpa_s->conf, id);
  1282. if (ssid == NULL) {
  1283. reply = wpas_dbus_error_network_unknown(message);
  1284. goto out;
  1285. }
  1286. /* Finally, associate with the network */
  1287. wpa_supplicant_select_network(wpa_s, ssid);
  1288. out:
  1289. os_free(iface);
  1290. os_free(net_id);
  1291. return reply;
  1292. }
  1293. /**
  1294. * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
  1295. * @message: Pointer to incoming dbus message
  1296. * @wpa_s: %wpa_supplicant data structure
  1297. * Returns: A dbus message containing an error on failure or NULL on success
  1298. *
  1299. * Asks wpa_supplicant to internally store a binary blobs.
  1300. */
  1301. DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
  1302. struct wpa_supplicant *wpa_s)
  1303. {
  1304. DBusMessage *reply = NULL;
  1305. DBusMessageIter iter, array_iter;
  1306. char *blob_name;
  1307. u8 *blob_data;
  1308. int blob_len;
  1309. struct wpa_config_blob *blob = NULL;
  1310. dbus_message_iter_init(message, &iter);
  1311. dbus_message_iter_get_basic(&iter, &blob_name);
  1312. if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
  1313. return dbus_message_new_error(message,
  1314. WPAS_DBUS_ERROR_BLOB_EXISTS,
  1315. NULL);
  1316. }
  1317. dbus_message_iter_next(&iter);
  1318. dbus_message_iter_recurse(&iter, &array_iter);
  1319. dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
  1320. blob = os_zalloc(sizeof(*blob));
  1321. if (!blob) {
  1322. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1323. NULL);
  1324. goto err;
  1325. }
  1326. blob->data = os_malloc(blob_len);
  1327. if (!blob->data) {
  1328. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1329. NULL);
  1330. goto err;
  1331. }
  1332. os_memcpy(blob->data, blob_data, blob_len);
  1333. blob->len = blob_len;
  1334. blob->name = os_strdup(blob_name);
  1335. if (!blob->name) {
  1336. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1337. NULL);
  1338. goto err;
  1339. }
  1340. wpa_config_set_blob(wpa_s->conf, blob);
  1341. wpas_notify_blob_added(wpa_s, blob->name);
  1342. return reply;
  1343. err:
  1344. if (blob) {
  1345. os_free(blob->name);
  1346. os_free(blob->data);
  1347. os_free(blob);
  1348. }
  1349. return reply;
  1350. }
  1351. /**
  1352. * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
  1353. * @message: Pointer to incoming dbus message
  1354. * @wpa_s: %wpa_supplicant data structure
  1355. * Returns: A dbus message containing array of bytes (blob)
  1356. *
  1357. * Gets one wpa_supplicant's binary blobs.
  1358. */
  1359. DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
  1360. struct wpa_supplicant *wpa_s)
  1361. {
  1362. DBusMessage *reply = NULL;
  1363. DBusMessageIter iter, array_iter;
  1364. char *blob_name;
  1365. const struct wpa_config_blob *blob;
  1366. dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
  1367. DBUS_TYPE_INVALID);
  1368. blob = wpa_config_get_blob(wpa_s->conf, blob_name);
  1369. if (!blob) {
  1370. return dbus_message_new_error(message,
  1371. WPAS_DBUS_ERROR_BLOB_UNKNOWN,
  1372. "Blob id not set");
  1373. }
  1374. reply = dbus_message_new_method_return(message);
  1375. if (!reply) {
  1376. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1377. NULL);
  1378. goto out;
  1379. }
  1380. dbus_message_iter_init_append(reply, &iter);
  1381. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
  1382. DBUS_TYPE_BYTE_AS_STRING,
  1383. &array_iter)) {
  1384. dbus_message_unref(reply);
  1385. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1386. NULL);
  1387. goto out;
  1388. }
  1389. if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
  1390. &(blob->data), blob->len)) {
  1391. dbus_message_unref(reply);
  1392. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1393. NULL);
  1394. goto out;
  1395. }
  1396. if (!dbus_message_iter_close_container(&iter, &array_iter)) {
  1397. dbus_message_unref(reply);
  1398. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  1399. NULL);
  1400. goto out;
  1401. }
  1402. out:
  1403. return reply;
  1404. }
  1405. /**
  1406. * wpas_remove_handler_remove_blob - Remove named binary blob
  1407. * @message: Pointer to incoming dbus message
  1408. * @wpa_s: %wpa_supplicant data structure
  1409. * Returns: NULL on success or dbus error
  1410. *
  1411. * Asks wpa_supplicant to internally remove a binary blobs.
  1412. */
  1413. DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
  1414. struct wpa_supplicant *wpa_s)
  1415. {
  1416. DBusMessage *reply = NULL;
  1417. char *blob_name;
  1418. dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
  1419. DBUS_TYPE_INVALID);
  1420. if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
  1421. return dbus_message_new_error(message,
  1422. WPAS_DBUS_ERROR_BLOB_UNKNOWN,
  1423. "Blob id not set");
  1424. }
  1425. wpas_notify_blob_removed(wpa_s, blob_name);
  1426. return reply;
  1427. }
  1428. /**
  1429. * wpas_dbus_getter_capabilities - Return interface capabilities
  1430. * @message: Pointer to incoming dbus message
  1431. * @wpa_s: wpa_supplicant structure for a network interface
  1432. * Returns: A dbus message containing a dict of strings
  1433. *
  1434. * Getter for "Capabilities" property of an interface.
  1435. */
  1436. DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
  1437. struct wpa_supplicant *wpa_s)
  1438. {
  1439. DBusMessage *reply = NULL;
  1440. struct wpa_driver_capa capa;
  1441. int res;
  1442. DBusMessageIter iter, iter_dict;
  1443. DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
  1444. variant_iter;
  1445. const char *scans[] = { "active", "passive", "ssid" };
  1446. const char *modes[] = { "infrastructure", "ad-hoc", "ap" };
  1447. int n = sizeof(modes) / sizeof(char *);
  1448. if (message == NULL)
  1449. reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
  1450. else
  1451. reply = dbus_message_new_method_return(message);
  1452. if (!reply)
  1453. goto nomem;
  1454. dbus_message_iter_init_append(reply, &iter);
  1455. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
  1456. "a{sv}", &variant_iter))
  1457. goto nomem;
  1458. if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
  1459. goto nomem;
  1460. res = wpa_drv_get_capa(wpa_s, &capa);
  1461. /***** pairwise cipher */
  1462. if (res < 0) {
  1463. const char *args[] = {"ccmp", "tkip", "none"};
  1464. if (!wpa_dbus_dict_append_string_array(
  1465. &iter_dict, "Pairwise", args,
  1466. sizeof(args) / sizeof(char*)))
  1467. goto nomem;
  1468. } else {
  1469. if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
  1470. &iter_dict_entry,
  1471. &iter_dict_val,
  1472. &iter_array))
  1473. goto nomem;
  1474. if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
  1475. if (!wpa_dbus_dict_string_array_add_element(
  1476. &iter_array, "ccmp"))
  1477. goto nomem;
  1478. }
  1479. if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
  1480. if (!wpa_dbus_dict_string_array_add_element(
  1481. &iter_array, "tkip"))
  1482. goto nomem;
  1483. }
  1484. if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
  1485. if (!wpa_dbus_dict_string_array_add_element(
  1486. &iter_array, "none"))
  1487. goto nomem;
  1488. }
  1489. if (!wpa_dbus_dict_end_string_array(&iter_dict,
  1490. &iter_dict_entry,
  1491. &iter_dict_val,
  1492. &iter_array))
  1493. goto nomem;
  1494. }
  1495. /***** group cipher */
  1496. if (res < 0) {
  1497. const char *args[] = {
  1498. "ccmp", "tkip", "wep104", "wep40"
  1499. };
  1500. if (!wpa_dbus_dict_append_string_array(
  1501. &iter_dict, "Group", args,
  1502. sizeof(args) / sizeof(char*)))
  1503. goto nomem;
  1504. } else {
  1505. if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
  1506. &iter_dict_entry,
  1507. &iter_dict_val,
  1508. &iter_array))
  1509. goto nomem;
  1510. if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
  1511. if (!wpa_dbus_dict_string_array_add_element(
  1512. &iter_array, "ccmp"))
  1513. goto nomem;
  1514. }
  1515. if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
  1516. if (!wpa_dbus_dict_string_array_add_element(
  1517. &iter_array, "tkip"))
  1518. goto nomem;
  1519. }
  1520. if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
  1521. if (!wpa_dbus_dict_string_array_add_element(
  1522. &iter_array, "wep104"))
  1523. goto nomem;
  1524. }
  1525. if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
  1526. if (!wpa_dbus_dict_string_array_add_element(
  1527. &iter_array, "wep40"))
  1528. goto nomem;
  1529. }
  1530. if (!wpa_dbus_dict_end_string_array(&iter_dict,
  1531. &i