dbus_new_handlers_wps.c 12 KB

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