dbus_new_handlers_wps.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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 "dbus_new_helpers.h"
  21. #include "dbus_new.h"
  22. #include "dbus_new_handlers.h"
  23. #include "dbus_dict_helpers.h"
  24. /**
  25. * wpas_dbus_handler_wps_start - Start WPS configuration
  26. * @message: Pointer to incoming dbus message
  27. * @wpa_s: %wpa_supplicant data structure
  28. * Returns: DBus message dictionary on success or DBus error on failure
  29. *
  30. * Handler for "Start" method call. DBus dictionary argument contains
  31. * information about role (enrollee or registrar), authorization method
  32. * (pin or push button) and optionally pin and bssid. Returned message
  33. * has a dictionary argument which may contain newly generated pin (optional).
  34. */
  35. DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
  36. struct wpa_supplicant *wpa_s)
  37. {
  38. DBusMessage * reply = NULL;
  39. DBusMessageIter iter, dict_iter, entry_iter, variant_iter, array_iter;
  40. char *key, *val;
  41. int role = 0; /* 0 - not set, 1 - enrollee, 2 - registrar */
  42. int type = 0; /* 0 - not set, 1 - pin, 2 - pbc */
  43. u8 *bssid = NULL;
  44. char *pin = NULL, npin[9] = { '\0' };
  45. int len, ret;
  46. dbus_message_iter_init(message, &iter);
  47. dbus_message_iter_recurse(&iter, &dict_iter);
  48. while (dbus_message_iter_get_arg_type(&dict_iter) ==
  49. DBUS_TYPE_DICT_ENTRY) {
  50. dbus_message_iter_recurse(&dict_iter, &entry_iter);
  51. dbus_message_iter_get_basic(&entry_iter, &key);
  52. dbus_message_iter_next(&entry_iter);
  53. if (os_strcmp(key, "Role") == 0) {
  54. dbus_message_iter_recurse(&entry_iter, &variant_iter);
  55. if (dbus_message_iter_get_arg_type(&variant_iter) !=
  56. DBUS_TYPE_STRING) {
  57. wpa_printf(MSG_DEBUG,
  58. "wpas_dbus_handler_wps_start"
  59. "[dbus]: "
  60. "wrong Role type. string required");
  61. reply = wpas_dbus_error_invald_args(
  62. message, "Role must be a string");
  63. goto out;
  64. }
  65. dbus_message_iter_get_basic(&variant_iter, &val);
  66. if (os_strcmp(val, "enrollee") == 0)
  67. role = 1;
  68. else if (os_strcmp(val, "registrar") == 0)
  69. role = 2;
  70. else {
  71. wpa_printf(MSG_DEBUG,
  72. "wpas_dbus_handler_wps_start[dbus]: "
  73. "unknown role %s", val);
  74. reply = wpas_dbus_error_invald_args(message, val);
  75. goto out;
  76. }
  77. } else if (strcmp(key, "Type") == 0) {
  78. dbus_message_iter_recurse(&entry_iter, &variant_iter);
  79. if (dbus_message_iter_get_arg_type(&variant_iter) !=
  80. DBUS_TYPE_STRING) {
  81. wpa_printf(MSG_DEBUG,
  82. "wpas_dbus_handler_wps_start[dbus]: "
  83. "wrong Type type. string required");
  84. reply = wpas_dbus_error_invald_args(
  85. message, "Type must be a string");
  86. goto out;
  87. }
  88. dbus_message_iter_get_basic(&variant_iter, &val);
  89. if (os_strcmp(val, "pin") == 0)
  90. type = 1;
  91. else if (os_strcmp(val, "pbc") == 0)
  92. type = 2;
  93. else {
  94. wpa_printf(MSG_DEBUG,
  95. "wpas_dbus_handler_wps_start[dbus]: "
  96. "unknown type %s", val);
  97. reply = wpas_dbus_error_invald_args(message,
  98. val);
  99. goto out;
  100. }
  101. } else if (strcmp(key, "Bssid") == 0) {
  102. dbus_message_iter_recurse(&entry_iter, &variant_iter);
  103. if (dbus_message_iter_get_arg_type(&variant_iter) !=
  104. DBUS_TYPE_ARRAY ||
  105. dbus_message_iter_get_element_type(&variant_iter) !=
  106. DBUS_TYPE_ARRAY) {
  107. wpa_printf(MSG_DEBUG,
  108. "wpas_dbus_handler_wps_start[dbus]: "
  109. "wrong Bssid type. byte array required");
  110. reply = wpas_dbus_error_invald_args(
  111. message, "Bssid must be a byte array");
  112. goto out;
  113. }
  114. dbus_message_iter_recurse(&variant_iter, &array_iter);
  115. dbus_message_iter_get_fixed_array(&array_iter, &bssid,
  116. &len);
  117. if (len != ETH_ALEN) {
  118. wpa_printf(MSG_DEBUG,
  119. "wpas_dbus_handler_wps_start[dbus]: "
  120. "wrong Bssid length %d", len);
  121. reply = wpas_dbus_error_invald_args(
  122. message, "Bssid is wrong length");
  123. goto out;
  124. }
  125. }
  126. else if (os_strcmp(key, "Pin") == 0) {
  127. dbus_message_iter_recurse(&entry_iter, &variant_iter);
  128. if (dbus_message_iter_get_arg_type(&variant_iter) !=
  129. DBUS_TYPE_STRING) {
  130. wpa_printf(MSG_DEBUG,
  131. "wpas_dbus_handler_wps_start[dbus]: "
  132. "wrong Pin type. string required");
  133. reply = wpas_dbus_error_invald_args(
  134. message, "Pin must be a string");
  135. goto out;
  136. }
  137. dbus_message_iter_get_basic(&variant_iter, &pin);
  138. } else {
  139. wpa_printf(MSG_DEBUG,
  140. "wpas_dbus_handler_wps_start[dbus]: "
  141. "unknown key %s", key);
  142. reply = wpas_dbus_error_invald_args(message, key);
  143. goto out;
  144. }
  145. dbus_message_iter_next(&dict_iter);
  146. }
  147. if (role == 0) {
  148. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
  149. "Role not specified");
  150. reply = wpas_dbus_error_invald_args(message,
  151. "Role not specified");
  152. goto out;
  153. }
  154. else if (role == 1 && type == 0) {
  155. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
  156. "Type not specified");
  157. reply = wpas_dbus_error_invald_args(message,
  158. "Type not specified");
  159. goto out;
  160. }
  161. else if (role == 2 && pin == NULL) {
  162. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
  163. "Pin required for registrar role.");
  164. reply = wpas_dbus_error_invald_args(
  165. message, "Pin required for registrar role.");
  166. goto out;
  167. }
  168. if (role == 2)
  169. ret = wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
  170. else if (type == 1) {
  171. ret = wpas_wps_start_pin(wpa_s, bssid, pin);
  172. if (ret > 0)
  173. os_snprintf(npin, sizeof(npin), "%08d", ret);
  174. } else
  175. ret = wpas_wps_start_pbc(wpa_s, bssid);
  176. if (ret < 0) {
  177. wpa_printf(MSG_DEBUG, "wpas_dbus_handler_wps_start[dbus]: "
  178. "wpas_wps_failed in role %s and key %s.",
  179. (role == 1 ? "enrollee" : "registrar"),
  180. (type == 0 ? "" : (type == 1 ? "pin" : "pbc")));
  181. reply = wpas_dbus_error_unknown_error(message,
  182. "wps start failed");
  183. goto out;
  184. }
  185. reply = dbus_message_new_method_return(message);
  186. if (!reply) {
  187. perror("wpas_dbus_handler_wps_start[dbus]: out of memory "
  188. "when creating reply");
  189. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  190. NULL);
  191. goto out;
  192. }
  193. dbus_message_iter_init_append(reply, &iter);
  194. if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
  195. perror("wpas_dbus_handler_wps_start[dbus]: out of memory "
  196. "when opening dictionary");
  197. dbus_message_unref(reply);
  198. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  199. NULL);
  200. goto out;
  201. }
  202. if (os_strlen(npin) > 0) {
  203. if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) {
  204. perror("wpas_dbus_handler_wps_start[dbus]: "
  205. "out of memory when appending pin");
  206. dbus_message_unref(reply);
  207. reply = dbus_message_new_error(message,
  208. DBUS_ERROR_NO_MEMORY,
  209. NULL);
  210. goto out;
  211. }
  212. }
  213. if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
  214. perror("wpas_dbus_handler_wps_start[dbus]: out of memory "
  215. "when closing dictionary");
  216. dbus_message_unref(reply);
  217. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  218. NULL);
  219. goto out;
  220. }
  221. out:
  222. return reply;
  223. }
  224. /**
  225. * wpas_dbus_getter_process_credentials - Check if credentials are processed
  226. * @message: Pointer to incoming dbus message
  227. * @wpa_s: %wpa_supplicant data structure
  228. * Returns: DBus message with a boolean on success or DBus error on failure
  229. *
  230. * Getter for "ProcessCredentials" property. Returns returned boolean will be
  231. * true if wps_cred_processing configuration field is not equal to 1 or false
  232. * if otherwise.
  233. */
  234. DBusMessage * wpas_dbus_getter_process_credentials(
  235. DBusMessage *message, struct wpa_supplicant *wpa_s)
  236. {
  237. DBusMessage *reply = NULL;
  238. DBusMessageIter iter, variant_iter;
  239. dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1);
  240. if (message == NULL)
  241. reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
  242. else
  243. reply = dbus_message_new_method_return(message);
  244. if (reply != NULL) {
  245. dbus_message_iter_init_append(reply, &iter);
  246. if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
  247. "b", &variant_iter) ||
  248. !dbus_message_iter_append_basic(&variant_iter,
  249. DBUS_TYPE_BOOLEAN,
  250. &process) ||
  251. !dbus_message_iter_close_container(&iter, &variant_iter)) {
  252. perror("wpas_dbus_getter_process_credentials[dbus]: "
  253. "out of memory to put value into message.");
  254. dbus_message_unref(reply);
  255. reply = dbus_message_new_error(message,
  256. DBUS_ERROR_NO_MEMORY,
  257. NULL);
  258. }
  259. } else {
  260. perror("wpas_dbus_getter_process_credentials[dbus]: out of "
  261. "memory to create reply message.");
  262. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  263. NULL);
  264. }
  265. return reply;
  266. }
  267. /**
  268. * wpas_dbus_setter_process_credentials - Set credentials_processed conf param
  269. * @message: Pointer to incoming dbus message
  270. * @wpa_s: %wpa_supplicant data structure
  271. * Returns: NULL on success or DBus error on failure
  272. *
  273. * Setter for "ProcessCredentials" property. Sets credentials_processed on 2
  274. * if boolean argument is true or on 1 if otherwise.
  275. */
  276. DBusMessage * wpas_dbus_setter_process_credentials(
  277. DBusMessage *message, struct wpa_supplicant *wpa_s)
  278. {
  279. DBusMessage *reply = NULL;
  280. DBusMessageIter iter, variant_iter;
  281. dbus_bool_t process_credentials, old_pc;
  282. if (!dbus_message_iter_init(message, &iter)) {
  283. perror("wpas_dbus_getter_ap_scan[dbus]: out of "
  284. "memory to return scanning state.");
  285. reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
  286. NULL);
  287. goto out;
  288. }
  289. /* omit first and second argument and get value from third*/
  290. dbus_message_iter_next(&iter);
  291. dbus_message_iter_next(&iter);
  292. dbus_message_iter_recurse(&iter, &variant_iter);
  293. if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_BOOLEAN)
  294. {
  295. reply = wpas_dbus_error_invald_args(message,
  296. "BOOLEAN required");
  297. goto out;
  298. }
  299. dbus_message_iter_get_basic(&variant_iter, &process_credentials);
  300. old_pc = (wpa_s->conf->wps_cred_processing != 1);
  301. wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
  302. if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
  303. wpa_dbus_signal_property_changed(
  304. wpa_s->global->dbus_new_ctrl_iface,
  305. (WPADBusPropertyAccessor)
  306. wpas_dbus_getter_process_credentials,
  307. wpa_s, wpas_dbus_get_path(wpa_s),
  308. WPAS_DBUS_NEW_IFACE_WPS,
  309. "ProcessCredentials");
  310. out:
  311. return reply;
  312. }