wps_dev_attr.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * Wi-Fi Protected Setup - device attributes
  3. * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #include "common.h"
  10. #include "wps_i.h"
  11. #include "wps_dev_attr.h"
  12. int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg)
  13. {
  14. size_t len;
  15. wpa_printf(MSG_DEBUG, "WPS: * Manufacturer");
  16. wpabuf_put_be16(msg, ATTR_MANUFACTURER);
  17. len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0;
  18. #ifndef CONFIG_WPS_STRICT
  19. if (len == 0) {
  20. /*
  21. * Some deployed WPS implementations fail to parse zero-length
  22. * attributes. As a workaround, send a space character if the
  23. * device attribute string is empty.
  24. */
  25. wpabuf_put_be16(msg, 1);
  26. wpabuf_put_u8(msg, ' ');
  27. return 0;
  28. }
  29. #endif /* CONFIG_WPS_STRICT */
  30. wpabuf_put_be16(msg, len);
  31. wpabuf_put_data(msg, dev->manufacturer, len);
  32. return 0;
  33. }
  34. int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg)
  35. {
  36. size_t len;
  37. wpa_printf(MSG_DEBUG, "WPS: * Model Name");
  38. wpabuf_put_be16(msg, ATTR_MODEL_NAME);
  39. len = dev->model_name ? os_strlen(dev->model_name) : 0;
  40. #ifndef CONFIG_WPS_STRICT
  41. if (len == 0) {
  42. /*
  43. * Some deployed WPS implementations fail to parse zero-length
  44. * attributes. As a workaround, send a space character if the
  45. * device attribute string is empty.
  46. */
  47. wpabuf_put_be16(msg, 1);
  48. wpabuf_put_u8(msg, ' ');
  49. return 0;
  50. }
  51. #endif /* CONFIG_WPS_STRICT */
  52. wpabuf_put_be16(msg, len);
  53. wpabuf_put_data(msg, dev->model_name, len);
  54. return 0;
  55. }
  56. int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg)
  57. {
  58. size_t len;
  59. wpa_printf(MSG_DEBUG, "WPS: * Model Number");
  60. wpabuf_put_be16(msg, ATTR_MODEL_NUMBER);
  61. len = dev->model_number ? os_strlen(dev->model_number) : 0;
  62. #ifndef CONFIG_WPS_STRICT
  63. if (len == 0) {
  64. /*
  65. * Some deployed WPS implementations fail to parse zero-length
  66. * attributes. As a workaround, send a space character if the
  67. * device attribute string is empty.
  68. */
  69. wpabuf_put_be16(msg, 1);
  70. wpabuf_put_u8(msg, ' ');
  71. return 0;
  72. }
  73. #endif /* CONFIG_WPS_STRICT */
  74. wpabuf_put_be16(msg, len);
  75. wpabuf_put_data(msg, dev->model_number, len);
  76. return 0;
  77. }
  78. int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg)
  79. {
  80. size_t len;
  81. wpa_printf(MSG_DEBUG, "WPS: * Serial Number");
  82. wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER);
  83. len = dev->serial_number ? os_strlen(dev->serial_number) : 0;
  84. #ifndef CONFIG_WPS_STRICT
  85. if (len == 0) {
  86. /*
  87. * Some deployed WPS implementations fail to parse zero-length
  88. * attributes. As a workaround, send a space character if the
  89. * device attribute string is empty.
  90. */
  91. wpabuf_put_be16(msg, 1);
  92. wpabuf_put_u8(msg, ' ');
  93. return 0;
  94. }
  95. #endif /* CONFIG_WPS_STRICT */
  96. wpabuf_put_be16(msg, len);
  97. wpabuf_put_data(msg, dev->serial_number, len);
  98. return 0;
  99. }
  100. int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg)
  101. {
  102. wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type");
  103. wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE);
  104. wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
  105. wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN);
  106. return 0;
  107. }
  108. int wps_build_secondary_dev_type(struct wps_device_data *dev,
  109. struct wpabuf *msg)
  110. {
  111. if (!dev->num_sec_dev_types)
  112. return 0;
  113. wpa_printf(MSG_DEBUG, "WPS: * Secondary Device Type");
  114. wpabuf_put_be16(msg, ATTR_SECONDARY_DEV_TYPE_LIST);
  115. wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
  116. wpabuf_put_data(msg, dev->sec_dev_type,
  117. WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
  118. return 0;
  119. }
  120. int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg,
  121. unsigned int num_req_dev_types,
  122. const u8 *req_dev_types)
  123. {
  124. unsigned int i;
  125. for (i = 0; i < num_req_dev_types; i++) {
  126. wpa_hexdump(MSG_DEBUG, "WPS: * Requested Device Type",
  127. req_dev_types + i * WPS_DEV_TYPE_LEN,
  128. WPS_DEV_TYPE_LEN);
  129. wpabuf_put_be16(msg, ATTR_REQUESTED_DEV_TYPE);
  130. wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
  131. wpabuf_put_data(msg, req_dev_types + i * WPS_DEV_TYPE_LEN,
  132. WPS_DEV_TYPE_LEN);
  133. }
  134. return 0;
  135. }
  136. int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg)
  137. {
  138. size_t len;
  139. wpa_printf(MSG_DEBUG, "WPS: * Device Name");
  140. wpabuf_put_be16(msg, ATTR_DEV_NAME);
  141. len = dev->device_name ? os_strlen(dev->device_name) : 0;
  142. #ifndef CONFIG_WPS_STRICT
  143. if (len == 0) {
  144. /*
  145. * Some deployed WPS implementations fail to parse zero-length
  146. * attributes. As a workaround, send a space character if the
  147. * device attribute string is empty.
  148. */
  149. wpabuf_put_be16(msg, 1);
  150. wpabuf_put_u8(msg, ' ');
  151. return 0;
  152. }
  153. #endif /* CONFIG_WPS_STRICT */
  154. wpabuf_put_be16(msg, len);
  155. wpabuf_put_data(msg, dev->device_name, len);
  156. return 0;
  157. }
  158. int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg)
  159. {
  160. if (wps_build_manufacturer(dev, msg) ||
  161. wps_build_model_name(dev, msg) ||
  162. wps_build_model_number(dev, msg) ||
  163. wps_build_serial_number(dev, msg) ||
  164. wps_build_primary_dev_type(dev, msg) ||
  165. wps_build_dev_name(dev, msg))
  166. return -1;
  167. return 0;
  168. }
  169. int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg)
  170. {
  171. wpa_printf(MSG_DEBUG, "WPS: * OS Version");
  172. wpabuf_put_be16(msg, ATTR_OS_VERSION);
  173. wpabuf_put_be16(msg, 4);
  174. wpabuf_put_be32(msg, 0x80000000 | dev->os_version);
  175. return 0;
  176. }
  177. int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg)
  178. {
  179. if (dev->vendor_ext_m1 != NULL) {
  180. wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension M1",
  181. wpabuf_head_u8(dev->vendor_ext_m1),
  182. wpabuf_len(dev->vendor_ext_m1));
  183. wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
  184. wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext_m1));
  185. wpabuf_put_buf(msg, dev->vendor_ext_m1);
  186. }
  187. return 0;
  188. }
  189. int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg,
  190. u8 rf_band)
  191. {
  192. return wps_build_rf_bands_attr(msg, rf_band ? rf_band : dev->rf_bands);
  193. }
  194. int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
  195. {
  196. int i;
  197. for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
  198. if (dev->vendor_ext[i] == NULL)
  199. continue;
  200. wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension",
  201. wpabuf_head_u8(dev->vendor_ext[i]),
  202. wpabuf_len(dev->vendor_ext[i]));
  203. wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
  204. wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i]));
  205. wpabuf_put_buf(msg, dev->vendor_ext[i]);
  206. }
  207. return 0;
  208. }
  209. static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
  210. size_t str_len)
  211. {
  212. if (str == NULL) {
  213. wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received");
  214. return -1;
  215. }
  216. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
  217. os_free(dev->manufacturer);
  218. dev->manufacturer = dup_binstr(str, str_len);
  219. if (dev->manufacturer == NULL)
  220. return -1;
  221. return 0;
  222. }
  223. static int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
  224. size_t str_len)
  225. {
  226. if (str == NULL) {
  227. wpa_printf(MSG_DEBUG, "WPS: No Model Name received");
  228. return -1;
  229. }
  230. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
  231. os_free(dev->model_name);
  232. dev->model_name = dup_binstr(str, str_len);
  233. if (dev->model_name == NULL)
  234. return -1;
  235. return 0;
  236. }
  237. static int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
  238. size_t str_len)
  239. {
  240. if (str == NULL) {
  241. wpa_printf(MSG_DEBUG, "WPS: No Model Number received");
  242. return -1;
  243. }
  244. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
  245. os_free(dev->model_number);
  246. dev->model_number = dup_binstr(str, str_len);
  247. if (dev->model_number == NULL)
  248. return -1;
  249. return 0;
  250. }
  251. static int wps_process_serial_number(struct wps_device_data *dev,
  252. const u8 *str, size_t str_len)
  253. {
  254. if (str == NULL) {
  255. wpa_printf(MSG_DEBUG, "WPS: No Serial Number received");
  256. return -1;
  257. }
  258. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
  259. os_free(dev->serial_number);
  260. dev->serial_number = dup_binstr(str, str_len);
  261. if (dev->serial_number == NULL)
  262. return -1;
  263. return 0;
  264. }
  265. static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
  266. size_t str_len)
  267. {
  268. if (str == NULL) {
  269. wpa_printf(MSG_DEBUG, "WPS: No Device Name received");
  270. return -1;
  271. }
  272. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
  273. os_free(dev->device_name);
  274. dev->device_name = dup_binstr(str, str_len);
  275. if (dev->device_name == NULL)
  276. return -1;
  277. return 0;
  278. }
  279. static int wps_process_primary_dev_type(struct wps_device_data *dev,
  280. const u8 *dev_type)
  281. {
  282. #ifndef CONFIG_NO_STDOUT_DEBUG
  283. char devtype[WPS_DEV_TYPE_BUFSIZE];
  284. #endif /* CONFIG_NO_STDOUT_DEBUG */
  285. if (dev_type == NULL) {
  286. wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received");
  287. return -1;
  288. }
  289. os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN);
  290. wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s",
  291. wps_dev_type_bin2str(dev->pri_dev_type, devtype,
  292. sizeof(devtype)));
  293. return 0;
  294. }
  295. int wps_process_device_attrs(struct wps_device_data *dev,
  296. struct wps_parse_attr *attr)
  297. {
  298. if (wps_process_manufacturer(dev, attr->manufacturer,
  299. attr->manufacturer_len) ||
  300. wps_process_model_name(dev, attr->model_name,
  301. attr->model_name_len) ||
  302. wps_process_model_number(dev, attr->model_number,
  303. attr->model_number_len) ||
  304. wps_process_serial_number(dev, attr->serial_number,
  305. attr->serial_number_len) ||
  306. wps_process_primary_dev_type(dev, attr->primary_dev_type) ||
  307. wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len))
  308. return -1;
  309. return 0;
  310. }
  311. int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
  312. {
  313. if (ver == NULL) {
  314. wpa_printf(MSG_DEBUG, "WPS: No OS Version received");
  315. return -1;
  316. }
  317. dev->os_version = WPA_GET_BE32(ver);
  318. wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version);
  319. return 0;
  320. }
  321. int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
  322. {
  323. if (bands == NULL) {
  324. wpa_printf(MSG_DEBUG, "WPS: No RF Bands received");
  325. return -1;
  326. }
  327. dev->rf_bands = *bands;
  328. wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands);
  329. return 0;
  330. }
  331. void wps_device_data_free(struct wps_device_data *dev)
  332. {
  333. os_free(dev->device_name);
  334. dev->device_name = NULL;
  335. os_free(dev->manufacturer);
  336. dev->manufacturer = NULL;
  337. os_free(dev->model_name);
  338. dev->model_name = NULL;
  339. os_free(dev->model_number);
  340. dev->model_number = NULL;
  341. os_free(dev->serial_number);
  342. dev->serial_number = NULL;
  343. }