dbus_new_handlers_wps.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. * WPA Supplicant / dbus-based control interface (WPS)
  3. * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
  4. * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
  5. *
  6. * This software may be distributed under the terms of the BSD license.
  7. * See README for more details.
  8. */
  9. #include "includes.h"
  10. #include "common.h"
  11. #include "../config.h"
  12. #include "../wpa_supplicant_i.h"
  13. #include "../wps_supplicant.h"
  14. #include "../driver_i.h"
  15. #include "../ap.h"
  16. #include "dbus_new_helpers.h"
  17. #include "dbus_new.h"
  18. #include "dbus_new_handlers.h"
  19. #include "dbus_dict_helpers.h"
  20. struct wps_start_params {
  21. int role; /* 0 - not set, 1 - enrollee, 2 - registrar */
  22. int type; /* 0 - not set, 1 - pin, 2 - pbc */
  23. u8 *bssid;
  24. char *pin;
  25. u8 *p2p_dev_addr;
  26. };
  27. static int wpas_dbus_handler_wps_role(DBusMessage *message,
  28. DBusMessageIter *entry_iter,
  29. struct wps_start_params *params,
  30. DBusMessage **reply)
  31. {
  32. DBusMessageIter variant_iter;
  33. char *val;
  34. dbus_message_iter_recurse(entry_iter, &variant_iter);
  35. if (dbus_message_iter_get_arg_type(&variant_iter) !=
  36. DBUS_TYPE_STRING) {
  37. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Role type, "
  38. "string required");
  39. *reply = wpas_dbus_error_invalid_args(message,
  40. "Role must be a string");
  41. return -1;
  42. }
  43. dbus_message_iter_get_basic(&variant_iter, &val);
  44. if (os_strcmp(val, "enrollee") == 0)
  45. params->role = 1;
  46. else if (os_strcmp(val, "registrar") == 0)
  47. params->role = 2;
  48. else {
  49. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Uknown role %s", val);
  50. *reply = wpas_dbus_error_invalid_args(message, val);
  51. return -1;
  52. }
  53. return 0;
  54. }
  55. static int wpas_dbus_handler_wps_type(DBusMessage *message,
  56. DBusMessageIter *entry_iter,
  57. struct wps_start_params *params,
  58. DBusMessage **reply)
  59. {
  60. DBusMessageIter variant_iter;
  61. char *val;
  62. dbus_message_iter_recurse(entry_iter, &variant_iter);
  63. if (dbus_message_iter_get_arg_type(&variant_iter) !=
  64. DBUS_TYPE_STRING) {
  65. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Type type, "
  66. "string required");
  67. *reply = wpas_dbus_error_invalid_args(message,
  68. "Type must be a string");
  69. return -1;
  70. }
  71. dbus_message_iter_get_basic(&variant_iter, &val);
  72. if (os_strcmp(val, "pin") == 0)
  73. params->type = 1;
  74. else if (os_strcmp(val, "pbc") == 0)
  75. params->type = 2;
  76. else {
  77. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown type %s",
  78. val);
  79. *reply = wpas_dbus_error_invalid_args(message, val);
  80. return -1;
  81. }
  82. return 0;
  83. }
  84. static int wpas_dbus_handler_wps_bssid(DBusMessage *message,
  85. DBusMessageIter *entry_iter,
  86. struct wps_start_params *params,
  87. DBusMessage **reply)
  88. {
  89. DBusMessageIter variant_iter, array_iter;
  90. int len;
  91. dbus_message_iter_recurse(entry_iter, &variant_iter);
  92. if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
  93. dbus_message_iter_get_element_type(&variant_iter) !=
  94. DBUS_TYPE_BYTE) {
  95. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Bssid type, "
  96. "byte array required");
  97. *reply = wpas_dbus_error_invalid_args(
  98. message, "Bssid must be a byte array");
  99. return -1;
  100. }
  101. dbus_message_iter_recurse(&variant_iter, &array_iter);
  102. dbus_message_iter_get_fixed_array(&array_iter, &params->bssid, &len);
  103. if (len != ETH_ALEN) {
  104. wpa_printf(MSG_DEBUG, "dbus: WPS.Stsrt - Wrong Bssid length "
  105. "%d", len);
  106. *reply = wpas_dbus_error_invalid_args(message,
  107. "Bssid is wrong length");
  108. return -1;
  109. }
  110. return 0;
  111. }
  112. static int wpas_dbus_handler_wps_pin(DBusMessage *message,
  113. DBusMessageIter *entry_iter,
  114. struct wps_start_params *params,
  115. DBusMessage **reply)
  116. {
  117. DBusMessageIter variant_iter;
  118. dbus_message_iter_recurse(entry_iter, &variant_iter);
  119. if (dbus_message_iter_get_arg_type(&variant_iter) !=
  120. DBUS_TYPE_STRING) {
  121. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Pin type, "
  122. "string required");
  123. *reply = wpas_dbus_error_invalid_args(message,
  124. "Pin must be a string");
  125. return -1;
  126. }
  127. dbus_message_iter_get_basic(&variant_iter, &params->pin);
  128. return 0;
  129. }
  130. #ifdef CONFIG_P2P
  131. static int wpas_dbus_handler_wps_p2p_dev_addr(DBusMessage *message,
  132. DBusMessageIter *entry_iter,
  133. struct wps_start_params *params,
  134. DBusMessage **reply)
  135. {
  136. DBusMessageIter variant_iter, array_iter;
  137. int len;
  138. dbus_message_iter_recurse(entry_iter, &variant_iter);
  139. if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
  140. dbus_message_iter_get_element_type(&variant_iter) !=
  141. DBUS_TYPE_BYTE) {
  142. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong "
  143. "P2PDeviceAddress type, byte array required");
  144. *reply = wpas_dbus_error_invalid_args(
  145. message, "P2PDeviceAddress must be a byte array");
  146. return -1;
  147. }
  148. dbus_message_iter_recurse(&variant_iter, &array_iter);
  149. dbus_message_iter_get_fixed_array(&array_iter, &params->p2p_dev_addr,
  150. &len);
  151. if (len != ETH_ALEN) {
  152. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong "
  153. "P2PDeviceAddress length %d", len);
  154. *reply = wpas_dbus_error_invalid_args(message,
  155. "P2PDeviceAddress "
  156. "has wrong length");
  157. return -1;
  158. }
  159. return 0;
  160. }
  161. #endif /* CONFIG_P2P */
  162. static int wpas_dbus_handler_wps_start_entry(DBusMessage *message, char *key,
  163. DBusMessageIter *entry_iter,
  164. struct wps_start_params *params,
  165. DBusMessage **reply)
  166. {
  167. if (os_strcmp(key, "Role") == 0)
  168. return wpas_dbus_handler_wps_role(message, entry_iter,
  169. params, reply);
  170. else if (os_strcmp(key, "Type") == 0)
  171. return wpas_dbus_handler_wps_type(message, entry_iter,
  172. params, reply);
  173. else if (os_strcmp(key, "Bssid") == 0)
  174. return wpas_dbus_handler_wps_bssid(message, entry_iter,
  175. params, reply);
  176. else if (os_strcmp(key, "Pin") == 0)
  177. return wpas_dbus_handler_wps_pin(message, entry_iter,
  178. params, reply);
  179. #ifdef CONFIG_P2P
  180. else if (os_strcmp(key, "P2PDeviceAddress") == 0)
  181. return wpas_dbus_handler_wps_p2p_dev_addr(message, entry_iter,
  182. params, reply);
  183. #endif /* CONFIG_P2P */
  184. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - unknown key %s", key);
  185. *reply = wpas_dbus_error_invalid_args(message, key);
  186. return -1;
  187. }
  188. /**
  189. * wpas_dbus_handler_wps_start - Start WPS configuration
  190. * @message: Pointer to incoming dbus message
  191. * @wpa_s: %wpa_supplicant data structure
  192. * Returns: DBus message dictionary on success or DBus error on failure
  193. *
  194. * Handler for "Start" method call. DBus dictionary argument contains
  195. * information about role (enrollee or registrar), authorization method
  196. * (pin or push button) and optionally pin and bssid. Returned message
  197. * has a dictionary argument which may contain newly generated pin (optional).
  198. */
  199. DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
  200. struct wpa_supplicant *wpa_s)
  201. {
  202. DBusMessage *reply = NULL;
  203. DBusMessageIter iter, dict_iter, entry_iter;
  204. struct wps_start_params params;
  205. char *key;
  206. char npin[9] = { '\0' };
  207. int ret;
  208. os_memset(&params, 0, sizeof(params));
  209. dbus_message_iter_init(message, &iter);
  210. dbus_message_iter_recurse(&iter, &dict_iter);
  211. while (dbus_message_iter_get_arg_type(&dict_iter) ==
  212. DBUS_TYPE_DICT_ENTRY) {
  213. dbus_message_iter_recurse(&dict_iter, &entry_iter);
  214. dbus_message_iter_get_basic(&entry_iter, &key);
  215. dbus_message_iter_next(&entry_iter);
  216. if (wpas_dbus_handler_wps_start_entry(message, key,
  217. &entry_iter,
  218. &params, &reply))
  219. return reply;
  220. dbus_message_iter_next(&dict_iter);
  221. }
  222. if (params.role == 0) {
  223. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Role not specified");
  224. return wpas_dbus_error_invalid_args(message,
  225. "Role not specified");
  226. } else if (params.role == 1 && params.type == 0) {
  227. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Type not specified");
  228. return wpas_dbus_error_invalid_args(message,
  229. "Type not specified");
  230. } else if (params.role == 2 && params.pin == NULL) {
  231. wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Pin required for "
  232. "registrar role");
  233. return wpas_dbus_error_invalid_args(
  234. message, "Pin required for registrar role.");
  235. }
  236. if (params.role == 2)
  237. ret = wpas_wps_start_reg(wpa_s, params.bssid, params.pin,
  238. NULL);
  239. else if (params.type == 1) {
  240. #ifdef CONFIG_AP
  241. if (wpa_s->ap_iface)
  242. ret = wpa_supplicant_ap_wps_pin(wpa_s,
  243. params.bssid,
  244. params.pin,
  245. npin, sizeof(npin), 0);
  246. else
  247. #endif /* CONFIG_AP */
  248. {
  249. ret = wpas_wps_start_pin(wpa_s, params.bssid,
  250. params.pin, 0,
  251. DEV_PW_DEFAULT);
  252. if (ret > 0)
  253. os_snprintf(npin, sizeof(npin), "%08d", ret);
  254. }
  255. } else {
  256. #ifdef CONFIG_AP
  257. if (wpa_s->ap_iface)
  258. ret = wpa_supplicant_ap_wps_pbc(wpa_s,
  259. params.bssid,
  260. params.p2p_dev_addr);
  261. else
  262. #endif /* CONFIG_AP */
  263. ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
  264. }
  265. if (ret < 0) {
  266. wpa_printf(MSG_DEBUG, "dbus: WPS.Start wpas_wps_failed in "
  267. "role %s and key %s",
  268. (params.role == 1 ? "enrollee" : "registrar"),
  269. (params.type == 0 ? "" :
  270. (params.type == 1 ? "pin" : "pbc")));
  271. return wpas_dbus_error_unknown_error(message,
  272. "WPS start failed");
  273. }
  274. reply = dbus_message_new_method_return(message);
  275. if (!reply) {
  276. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  277. NULL);
  278. }
  279. dbus_message_iter_init_append(reply, &iter);
  280. if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
  281. dbus_message_unref(reply);
  282. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  283. NULL);
  284. }
  285. if (os_strlen(npin) > 0) {
  286. if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) {
  287. dbus_message_unref(reply);
  288. return dbus_message_new_error(message,
  289. DBUS_ERROR_NO_MEMORY,
  290. NULL);
  291. }
  292. }
  293. if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
  294. dbus_message_unref(reply);
  295. return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  296. NULL);
  297. }
  298. return reply;
  299. }
  300. /**
  301. * wpas_dbus_getter_process_credentials - Check if credentials are processed
  302. * @message: Pointer to incoming dbus message
  303. * @wpa_s: %wpa_supplicant data structure
  304. * Returns: TRUE on success, FALSE on failure
  305. *
  306. * Getter for "ProcessCredentials" property. Returns returned boolean will be
  307. * true if wps_cred_processing configuration field is not equal to 1 or false
  308. * if otherwise.
  309. */
  310. dbus_bool_t wpas_dbus_getter_process_credentials(DBusMessageIter *iter,
  311. DBusError *error,
  312. void *user_data)
  313. {
  314. struct wpa_supplicant *wpa_s = user_data;
  315. dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1);
  316. return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
  317. &process, error);
  318. }
  319. /**
  320. * wpas_dbus_setter_process_credentials - Set credentials_processed conf param
  321. * @iter: Pointer to incoming dbus message iter
  322. * @error: Location to store error on failure
  323. * @user_data: Function specific data
  324. * Returns: TRUE on success, FALSE on failure
  325. *
  326. * Setter for "ProcessCredentials" property. Sets credentials_processed on 2
  327. * if boolean argument is true or on 1 if otherwise.
  328. */
  329. dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter,
  330. DBusError *error,
  331. void *user_data)
  332. {
  333. struct wpa_supplicant *wpa_s = user_data;
  334. dbus_bool_t process_credentials, old_pc;
  335. if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN,
  336. &process_credentials))
  337. return FALSE;
  338. old_pc = (wpa_s->conf->wps_cred_processing != 1);
  339. wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
  340. if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
  341. wpa_dbus_mark_property_changed(wpa_s->global->dbus,
  342. wpa_s->dbus_new_path,
  343. WPAS_DBUS_NEW_IFACE_WPS,
  344. "ProcessCredentials");
  345. return TRUE;
  346. }
  347. /**
  348. * wpas_dbus_getter_config_methods - Get current WPS configuration methods
  349. * @iter: Pointer to incoming dbus message iter
  350. * @error: Location to store error on failure
  351. * @user_data: Function specific data
  352. * Returns: TRUE on success, FALSE on failure
  353. *
  354. * Getter for "ConfigMethods" property. Returned boolean will be true if
  355. * providing the relevant string worked, or false otherwise.
  356. */
  357. dbus_bool_t wpas_dbus_getter_config_methods(DBusMessageIter *iter,
  358. DBusError *error,
  359. void *user_data)
  360. {
  361. struct wpa_supplicant *wpa_s = user_data;
  362. char *methods = wpa_s->conf->config_methods;
  363. return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
  364. &methods, error);
  365. }
  366. /**
  367. * wpas_dbus_setter_config_methods - Set WPS configuration methods
  368. * @iter: Pointer to incoming dbus message iter
  369. * @error: Location to store error on failure
  370. * @user_data: Function specific data
  371. * Returns: TRUE on success, FALSE on failure
  372. *
  373. * Setter for "ConfigMethods" property. Sets the methods string, apply such
  374. * change and returns true on success. Returns false otherwise.
  375. */
  376. dbus_bool_t wpas_dbus_setter_config_methods(DBusMessageIter *iter,
  377. DBusError *error,
  378. void *user_data)
  379. {
  380. struct wpa_supplicant *wpa_s = user_data;
  381. char *methods, *new_methods;
  382. if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
  383. &methods))
  384. return FALSE;
  385. new_methods = os_strdup(methods);
  386. if (!new_methods)
  387. return FALSE;
  388. os_free(wpa_s->conf->config_methods);
  389. wpa_s->conf->config_methods = new_methods;
  390. wpa_s->conf->changed_parameters |= CFG_CHANGED_CONFIG_METHODS;
  391. wpa_supplicant_update_config(wpa_s);
  392. return TRUE;
  393. }