wps_dev_attr.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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. static int wps_build_serial_number(struct wps_device_data *dev,
  79. struct wpabuf *msg)
  80. {
  81. size_t len;
  82. wpa_printf(MSG_DEBUG, "WPS: * Serial Number");
  83. wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER);
  84. len = dev->serial_number ? os_strlen(dev->serial_number) : 0;
  85. #ifndef CONFIG_WPS_STRICT
  86. if (len == 0) {
  87. /*
  88. * Some deployed WPS implementations fail to parse zero-length
  89. * attributes. As a workaround, send a space character if the
  90. * device attribute string is empty.
  91. */
  92. wpabuf_put_be16(msg, 1);
  93. wpabuf_put_u8(msg, ' ');
  94. return 0;
  95. }
  96. #endif /* CONFIG_WPS_STRICT */
  97. wpabuf_put_be16(msg, len);
  98. wpabuf_put_data(msg, dev->serial_number, len);
  99. return 0;
  100. }
  101. int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg)
  102. {
  103. wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type");
  104. wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE);
  105. wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
  106. wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN);
  107. return 0;
  108. }
  109. int wps_build_secondary_dev_type(struct wps_device_data *dev,
  110. struct wpabuf *msg)
  111. {
  112. if (!dev->num_sec_dev_types)
  113. return 0;
  114. wpa_printf(MSG_DEBUG, "WPS: * Secondary Device Type");
  115. wpabuf_put_be16(msg, ATTR_SECONDARY_DEV_TYPE_LIST);
  116. wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
  117. wpabuf_put_data(msg, dev->sec_dev_type,
  118. WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
  119. return 0;
  120. }
  121. int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg,
  122. unsigned int num_req_dev_types,
  123. const u8 *req_dev_types)
  124. {
  125. unsigned int i;
  126. for (i = 0; i < num_req_dev_types; i++) {
  127. wpa_hexdump(MSG_DEBUG, "WPS: * Requested Device Type",
  128. req_dev_types + i * WPS_DEV_TYPE_LEN,
  129. WPS_DEV_TYPE_LEN);
  130. wpabuf_put_be16(msg, ATTR_REQUESTED_DEV_TYPE);
  131. wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
  132. wpabuf_put_data(msg, req_dev_types + i * WPS_DEV_TYPE_LEN,
  133. WPS_DEV_TYPE_LEN);
  134. }
  135. return 0;
  136. }
  137. int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg)
  138. {
  139. size_t len;
  140. wpa_printf(MSG_DEBUG, "WPS: * Device Name");
  141. wpabuf_put_be16(msg, ATTR_DEV_NAME);
  142. len = dev->device_name ? os_strlen(dev->device_name) : 0;
  143. #ifndef CONFIG_WPS_STRICT
  144. if (len == 0) {
  145. /*
  146. * Some deployed WPS implementations fail to parse zero-length
  147. * attributes. As a workaround, send a space character if the
  148. * device attribute string is empty.
  149. */
  150. wpabuf_put_be16(msg, 1);
  151. wpabuf_put_u8(msg, ' ');
  152. return 0;
  153. }
  154. #endif /* CONFIG_WPS_STRICT */
  155. wpabuf_put_be16(msg, len);
  156. wpabuf_put_data(msg, dev->device_name, len);
  157. return 0;
  158. }
  159. int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg)
  160. {
  161. if (wps_build_manufacturer(dev, msg) ||
  162. wps_build_model_name(dev, msg) ||
  163. wps_build_model_number(dev, msg) ||
  164. wps_build_serial_number(dev, msg) ||
  165. wps_build_primary_dev_type(dev, msg) ||
  166. wps_build_dev_name(dev, msg))
  167. return -1;
  168. return 0;
  169. }
  170. int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg)
  171. {
  172. wpa_printf(MSG_DEBUG, "WPS: * OS Version");
  173. wpabuf_put_be16(msg, ATTR_OS_VERSION);
  174. wpabuf_put_be16(msg, 4);
  175. wpabuf_put_be32(msg, 0x80000000 | dev->os_version);
  176. return 0;
  177. }
  178. int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg)
  179. {
  180. if (dev->vendor_ext_m1 != NULL) {
  181. wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension M1",
  182. wpabuf_head_u8(dev->vendor_ext_m1),
  183. wpabuf_len(dev->vendor_ext_m1));
  184. wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
  185. wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext_m1));
  186. wpabuf_put_buf(msg, dev->vendor_ext_m1);
  187. }
  188. return 0;
  189. }
  190. int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg)
  191. {
  192. wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands);
  193. wpabuf_put_be16(msg, ATTR_RF_BANDS);
  194. wpabuf_put_be16(msg, 1);
  195. wpabuf_put_u8(msg, dev->rf_bands);
  196. return 0;
  197. }
  198. int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
  199. {
  200. int i;
  201. for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
  202. if (dev->vendor_ext[i] == NULL)
  203. continue;
  204. wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension",
  205. wpabuf_head_u8(dev->vendor_ext[i]),
  206. wpabuf_len(dev->vendor_ext[i]));
  207. wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
  208. wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i]));
  209. wpabuf_put_buf(msg, dev->vendor_ext[i]);
  210. }
  211. return 0;
  212. }
  213. static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
  214. size_t str_len)
  215. {
  216. if (str == NULL) {
  217. wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received");
  218. return -1;
  219. }
  220. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
  221. os_free(dev->manufacturer);
  222. dev->manufacturer = os_malloc(str_len + 1);
  223. if (dev->manufacturer == NULL)
  224. return -1;
  225. os_memcpy(dev->manufacturer, str, str_len);
  226. dev->manufacturer[str_len] = '\0';
  227. return 0;
  228. }
  229. static int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
  230. size_t str_len)
  231. {
  232. if (str == NULL) {
  233. wpa_printf(MSG_DEBUG, "WPS: No Model Name received");
  234. return -1;
  235. }
  236. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
  237. os_free(dev->model_name);
  238. dev->model_name = os_malloc(str_len + 1);
  239. if (dev->model_name == NULL)
  240. return -1;
  241. os_memcpy(dev->model_name, str, str_len);
  242. dev->model_name[str_len] = '\0';
  243. return 0;
  244. }
  245. static int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
  246. size_t str_len)
  247. {
  248. if (str == NULL) {
  249. wpa_printf(MSG_DEBUG, "WPS: No Model Number received");
  250. return -1;
  251. }
  252. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
  253. os_free(dev->model_number);
  254. dev->model_number = os_malloc(str_len + 1);
  255. if (dev->model_number == NULL)
  256. return -1;
  257. os_memcpy(dev->model_number, str, str_len);
  258. dev->model_number[str_len] = '\0';
  259. return 0;
  260. }
  261. static int wps_process_serial_number(struct wps_device_data *dev,
  262. const u8 *str, size_t str_len)
  263. {
  264. if (str == NULL) {
  265. wpa_printf(MSG_DEBUG, "WPS: No Serial Number received");
  266. return -1;
  267. }
  268. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
  269. os_free(dev->serial_number);
  270. dev->serial_number = os_malloc(str_len + 1);
  271. if (dev->serial_number == NULL)
  272. return -1;
  273. os_memcpy(dev->serial_number, str, str_len);
  274. dev->serial_number[str_len] = '\0';
  275. return 0;
  276. }
  277. static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
  278. size_t str_len)
  279. {
  280. if (str == NULL) {
  281. wpa_printf(MSG_DEBUG, "WPS: No Device Name received");
  282. return -1;
  283. }
  284. wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
  285. os_free(dev->device_name);
  286. dev->device_name = os_malloc(str_len + 1);
  287. if (dev->device_name == NULL)
  288. return -1;
  289. os_memcpy(dev->device_name, str, str_len);
  290. dev->device_name[str_len] = '\0';
  291. return 0;
  292. }
  293. static int wps_process_primary_dev_type(struct wps_device_data *dev,
  294. const u8 *dev_type)
  295. {
  296. #ifndef CONFIG_NO_STDOUT_DEBUG
  297. char devtype[WPS_DEV_TYPE_BUFSIZE];
  298. #endif /* CONFIG_NO_STDOUT_DEBUG */
  299. if (dev_type == NULL) {
  300. wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received");
  301. return -1;
  302. }
  303. os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN);
  304. wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s",
  305. wps_dev_type_bin2str(dev->pri_dev_type, devtype,
  306. sizeof(devtype)));
  307. return 0;
  308. }
  309. int wps_process_device_attrs(struct wps_device_data *dev,
  310. struct wps_parse_attr *attr)
  311. {
  312. if (wps_process_manufacturer(dev, attr->manufacturer,
  313. attr->manufacturer_len) ||
  314. wps_process_model_name(dev, attr->model_name,
  315. attr->model_name_len) ||
  316. wps_process_model_number(dev, attr->model_number,
  317. attr->model_number_len) ||
  318. wps_process_serial_number(dev, attr->serial_number,
  319. attr->serial_number_len) ||
  320. wps_process_primary_dev_type(dev, attr->primary_dev_type) ||
  321. wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len))
  322. return -1;
  323. return 0;
  324. }
  325. int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
  326. {
  327. if (ver == NULL) {
  328. wpa_printf(MSG_DEBUG, "WPS: No OS Version received");
  329. return -1;
  330. }
  331. dev->os_version = WPA_GET_BE32(ver);
  332. wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version);
  333. return 0;
  334. }
  335. int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
  336. {
  337. if (bands == NULL) {
  338. wpa_printf(MSG_DEBUG, "WPS: No RF Bands received");
  339. return -1;
  340. }
  341. dev->rf_bands = *bands;
  342. wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands);
  343. return 0;
  344. }
  345. void wps_device_data_dup(struct wps_device_data *dst,
  346. const struct wps_device_data *src)
  347. {
  348. if (src->device_name)
  349. dst->device_name = os_strdup(src->device_name);
  350. if (src->manufacturer)
  351. dst->manufacturer = os_strdup(src->manufacturer);
  352. if (src->model_name)
  353. dst->model_name = os_strdup(src->model_name);
  354. if (src->model_number)
  355. dst->model_number = os_strdup(src->model_number);
  356. if (src->serial_number)
  357. dst->serial_number = os_strdup(src->serial_number);
  358. os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN);
  359. dst->os_version = src->os_version;
  360. dst->rf_bands = src->rf_bands;
  361. }
  362. void wps_device_data_free(struct wps_device_data *dev)
  363. {
  364. os_free(dev->device_name);
  365. dev->device_name = NULL;
  366. os_free(dev->manufacturer);
  367. dev->manufacturer = NULL;
  368. os_free(dev->model_name);
  369. dev->model_name = NULL;
  370. os_free(dev->model_number);
  371. dev->model_number = NULL;
  372. os_free(dev->serial_number);
  373. dev->serial_number = NULL;
  374. }