wps_attr_parse.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. /*
  2. * Wi-Fi Protected Setup - attribute parsing
  3. * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "wps_i.h"
  17. #ifndef CONFIG_WPS_STRICT
  18. #define WPS_WORKAROUNDS
  19. #endif /* CONFIG_WPS_STRICT */
  20. static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
  21. const u8 *pos, u16 len)
  22. {
  23. switch (type) {
  24. case ATTR_VERSION:
  25. if (len != 1) {
  26. wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
  27. len);
  28. return -1;
  29. }
  30. attr->version = pos;
  31. break;
  32. case ATTR_VERSION2:
  33. if (len != 1) {
  34. wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
  35. "%u", len);
  36. return -1;
  37. }
  38. attr->version2 = pos;
  39. break;
  40. case ATTR_MSG_TYPE:
  41. if (len != 1) {
  42. wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
  43. "length %u", len);
  44. return -1;
  45. }
  46. attr->msg_type = pos;
  47. break;
  48. case ATTR_ENROLLEE_NONCE:
  49. if (len != WPS_NONCE_LEN) {
  50. wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
  51. "length %u", len);
  52. return -1;
  53. }
  54. attr->enrollee_nonce = pos;
  55. break;
  56. case ATTR_REGISTRAR_NONCE:
  57. if (len != WPS_NONCE_LEN) {
  58. wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
  59. "length %u", len);
  60. return -1;
  61. }
  62. attr->registrar_nonce = pos;
  63. break;
  64. case ATTR_UUID_E:
  65. if (len != WPS_UUID_LEN) {
  66. wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
  67. len);
  68. return -1;
  69. }
  70. attr->uuid_e = pos;
  71. break;
  72. case ATTR_UUID_R:
  73. if (len != WPS_UUID_LEN) {
  74. wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
  75. len);
  76. return -1;
  77. }
  78. attr->uuid_r = pos;
  79. break;
  80. case ATTR_AUTH_TYPE_FLAGS:
  81. if (len != 2) {
  82. wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
  83. "Type Flags length %u", len);
  84. return -1;
  85. }
  86. attr->auth_type_flags = pos;
  87. break;
  88. case ATTR_ENCR_TYPE_FLAGS:
  89. if (len != 2) {
  90. wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
  91. "Flags length %u", len);
  92. return -1;
  93. }
  94. attr->encr_type_flags = pos;
  95. break;
  96. case ATTR_CONN_TYPE_FLAGS:
  97. if (len != 1) {
  98. wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
  99. "Flags length %u", len);
  100. return -1;
  101. }
  102. attr->conn_type_flags = pos;
  103. break;
  104. case ATTR_CONFIG_METHODS:
  105. if (len != 2) {
  106. wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
  107. "length %u", len);
  108. return -1;
  109. }
  110. attr->config_methods = pos;
  111. break;
  112. case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
  113. if (len != 2) {
  114. wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
  115. "Registrar Config Methods length %u", len);
  116. return -1;
  117. }
  118. attr->sel_reg_config_methods = pos;
  119. break;
  120. case ATTR_PRIMARY_DEV_TYPE:
  121. if (len != WPS_DEV_TYPE_LEN) {
  122. wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
  123. "Type length %u", len);
  124. return -1;
  125. }
  126. attr->primary_dev_type = pos;
  127. break;
  128. case ATTR_RF_BANDS:
  129. if (len != 1) {
  130. wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
  131. "%u", len);
  132. return -1;
  133. }
  134. attr->rf_bands = pos;
  135. break;
  136. case ATTR_ASSOC_STATE:
  137. if (len != 2) {
  138. wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
  139. "length %u", len);
  140. return -1;
  141. }
  142. attr->assoc_state = pos;
  143. break;
  144. case ATTR_CONFIG_ERROR:
  145. if (len != 2) {
  146. wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
  147. "Error length %u", len);
  148. return -1;
  149. }
  150. attr->config_error = pos;
  151. break;
  152. case ATTR_DEV_PASSWORD_ID:
  153. if (len != 2) {
  154. wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
  155. "ID length %u", len);
  156. return -1;
  157. }
  158. attr->dev_password_id = pos;
  159. break;
  160. case ATTR_OOB_DEVICE_PASSWORD:
  161. if (len != WPS_OOB_DEVICE_PASSWORD_ATTR_LEN) {
  162. wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
  163. "Password length %u", len);
  164. return -1;
  165. }
  166. attr->oob_dev_password = pos;
  167. break;
  168. case ATTR_OS_VERSION:
  169. if (len != 4) {
  170. wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
  171. "%u", len);
  172. return -1;
  173. }
  174. attr->os_version = pos;
  175. break;
  176. case ATTR_WPS_STATE:
  177. if (len != 1) {
  178. wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
  179. "Setup State length %u", len);
  180. return -1;
  181. }
  182. attr->wps_state = pos;
  183. break;
  184. case ATTR_AUTHENTICATOR:
  185. if (len != WPS_AUTHENTICATOR_LEN) {
  186. wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
  187. "length %u", len);
  188. return -1;
  189. }
  190. attr->authenticator = pos;
  191. break;
  192. case ATTR_R_HASH1:
  193. if (len != WPS_HASH_LEN) {
  194. wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
  195. len);
  196. return -1;
  197. }
  198. attr->r_hash1 = pos;
  199. break;
  200. case ATTR_R_HASH2:
  201. if (len != WPS_HASH_LEN) {
  202. wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
  203. len);
  204. return -1;
  205. }
  206. attr->r_hash2 = pos;
  207. break;
  208. case ATTR_E_HASH1:
  209. if (len != WPS_HASH_LEN) {
  210. wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
  211. len);
  212. return -1;
  213. }
  214. attr->e_hash1 = pos;
  215. break;
  216. case ATTR_E_HASH2:
  217. if (len != WPS_HASH_LEN) {
  218. wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
  219. len);
  220. return -1;
  221. }
  222. attr->e_hash2 = pos;
  223. break;
  224. case ATTR_R_SNONCE1:
  225. if (len != WPS_SECRET_NONCE_LEN) {
  226. wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
  227. "%u", len);
  228. return -1;
  229. }
  230. attr->r_snonce1 = pos;
  231. break;
  232. case ATTR_R_SNONCE2:
  233. if (len != WPS_SECRET_NONCE_LEN) {
  234. wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
  235. "%u", len);
  236. return -1;
  237. }
  238. attr->r_snonce2 = pos;
  239. break;
  240. case ATTR_E_SNONCE1:
  241. if (len != WPS_SECRET_NONCE_LEN) {
  242. wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
  243. "%u", len);
  244. return -1;
  245. }
  246. attr->e_snonce1 = pos;
  247. break;
  248. case ATTR_E_SNONCE2:
  249. if (len != WPS_SECRET_NONCE_LEN) {
  250. wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
  251. "%u", len);
  252. return -1;
  253. }
  254. attr->e_snonce2 = pos;
  255. break;
  256. case ATTR_KEY_WRAP_AUTH:
  257. if (len != WPS_KWA_LEN) {
  258. wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
  259. "Authenticator length %u", len);
  260. return -1;
  261. }
  262. attr->key_wrap_auth = pos;
  263. break;
  264. case ATTR_AUTH_TYPE:
  265. if (len != 2) {
  266. wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
  267. "Type length %u", len);
  268. return -1;
  269. }
  270. attr->auth_type = pos;
  271. break;
  272. case ATTR_ENCR_TYPE:
  273. if (len != 2) {
  274. wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
  275. "Type length %u", len);
  276. return -1;
  277. }
  278. attr->encr_type = pos;
  279. break;
  280. case ATTR_NETWORK_INDEX:
  281. if (len != 1) {
  282. wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
  283. "length %u", len);
  284. return -1;
  285. }
  286. attr->network_idx = pos;
  287. break;
  288. case ATTR_NETWORK_KEY_INDEX:
  289. if (len != 1) {
  290. wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
  291. "length %u", len);
  292. return -1;
  293. }
  294. attr->network_key_idx = pos;
  295. break;
  296. case ATTR_MAC_ADDR:
  297. if (len != ETH_ALEN) {
  298. wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
  299. "length %u", len);
  300. return -1;
  301. }
  302. attr->mac_addr = pos;
  303. break;
  304. case ATTR_KEY_PROVIDED_AUTO:
  305. if (len != 1) {
  306. wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided "
  307. "Automatically length %u", len);
  308. return -1;
  309. }
  310. attr->key_prov_auto = pos;
  311. break;
  312. case ATTR_802_1X_ENABLED:
  313. if (len != 1) {
  314. wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled "
  315. "length %u", len);
  316. return -1;
  317. }
  318. attr->dot1x_enabled = pos;
  319. break;
  320. case ATTR_SELECTED_REGISTRAR:
  321. if (len != 1) {
  322. wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
  323. " length %u", len);
  324. return -1;
  325. }
  326. attr->selected_registrar = pos;
  327. break;
  328. case ATTR_REQUEST_TYPE:
  329. if (len != 1) {
  330. wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
  331. "length %u", len);
  332. return -1;
  333. }
  334. attr->request_type = pos;
  335. break;
  336. case ATTR_RESPONSE_TYPE:
  337. if (len != 1) {
  338. wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
  339. "length %u", len);
  340. return -1;
  341. }
  342. attr->response_type = pos;
  343. break;
  344. case ATTR_MANUFACTURER:
  345. attr->manufacturer = pos;
  346. attr->manufacturer_len = len;
  347. break;
  348. case ATTR_MODEL_NAME:
  349. attr->model_name = pos;
  350. attr->model_name_len = len;
  351. break;
  352. case ATTR_MODEL_NUMBER:
  353. attr->model_number = pos;
  354. attr->model_number_len = len;
  355. break;
  356. case ATTR_SERIAL_NUMBER:
  357. attr->serial_number = pos;
  358. attr->serial_number_len = len;
  359. break;
  360. case ATTR_DEV_NAME:
  361. attr->dev_name = pos;
  362. attr->dev_name_len = len;
  363. break;
  364. case ATTR_PUBLIC_KEY:
  365. attr->public_key = pos;
  366. attr->public_key_len = len;
  367. break;
  368. case ATTR_ENCR_SETTINGS:
  369. attr->encr_settings = pos;
  370. attr->encr_settings_len = len;
  371. break;
  372. case ATTR_CRED:
  373. if (attr->num_cred >= MAX_CRED_COUNT) {
  374. wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
  375. "attribute (max %d credentials)",
  376. MAX_CRED_COUNT);
  377. break;
  378. }
  379. attr->cred[attr->num_cred] = pos;
  380. attr->cred_len[attr->num_cred] = len;
  381. attr->num_cred++;
  382. break;
  383. case ATTR_SSID:
  384. attr->ssid = pos;
  385. attr->ssid_len = len;
  386. break;
  387. case ATTR_NETWORK_KEY:
  388. attr->network_key = pos;
  389. attr->network_key_len = len;
  390. break;
  391. case ATTR_EAP_TYPE:
  392. attr->eap_type = pos;
  393. attr->eap_type_len = len;
  394. break;
  395. case ATTR_EAP_IDENTITY:
  396. attr->eap_identity = pos;
  397. attr->eap_identity_len = len;
  398. break;
  399. case ATTR_AP_SETUP_LOCKED:
  400. if (len != 1) {
  401. wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
  402. "length %u", len);
  403. return -1;
  404. }
  405. attr->ap_setup_locked = pos;
  406. break;
  407. case ATTR_SETTINGS_DELAY_TIME:
  408. if (len != 1) {
  409. wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
  410. "Time length %u", len);
  411. return -1;
  412. }
  413. attr->settings_delay_time = pos;
  414. break;
  415. case ATTR_NETWORK_KEY_SHAREABLE:
  416. if (len != 1) {
  417. wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
  418. "Shareable length %u", len);
  419. return -1;
  420. }
  421. attr->network_key_shareable = pos;
  422. break;
  423. case ATTR_REQUEST_TO_ENROLL:
  424. if (len != 1) {
  425. wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
  426. "length %u", len);
  427. return -1;
  428. }
  429. attr->request_to_enroll = pos;
  430. break;
  431. case ATTR_AUTHORIZED_MACS:
  432. attr->authorized_macs = pos;
  433. attr->authorized_macs_len = len;
  434. break;
  435. case ATTR_REQUESTED_DEV_TYPE:
  436. if (len != WPS_DEV_TYPE_LEN) {
  437. wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
  438. "Type length %u", len);
  439. return -1;
  440. }
  441. if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
  442. wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
  443. "Type attribute (max %u types)",
  444. MAX_REQ_DEV_TYPE_COUNT);
  445. break;
  446. }
  447. attr->req_dev_type[attr->num_req_dev_type] = pos;
  448. attr->num_req_dev_type++;
  449. break;
  450. default:
  451. wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
  452. "len=%u", type, len);
  453. break;
  454. }
  455. return 0;
  456. }
  457. int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
  458. {
  459. const u8 *pos, *end;
  460. u16 type, len;
  461. os_memset(attr, 0, sizeof(*attr));
  462. pos = wpabuf_head(msg);
  463. end = pos + wpabuf_len(msg);
  464. while (pos < end) {
  465. if (end - pos < 4) {
  466. wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
  467. "%lu bytes remaining",
  468. (unsigned long) (end - pos));
  469. return -1;
  470. }
  471. type = WPA_GET_BE16(pos);
  472. pos += 2;
  473. len = WPA_GET_BE16(pos);
  474. pos += 2;
  475. wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u",
  476. type, len);
  477. if (len > end - pos) {
  478. wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
  479. return -1;
  480. }
  481. #ifdef WPS_WORKAROUNDS
  482. if (type == 0 && len == 0) {
  483. /*
  484. * Mac OS X 10.6 seems to be adding 0x00 padding to the
  485. * end of M1. Skip those to avoid interop issues.
  486. */
  487. int i;
  488. for (i = 0; i < end - pos; i++) {
  489. if (pos[i])
  490. break;
  491. }
  492. if (i == end - pos) {
  493. wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
  494. "unexpected message padding");
  495. break;
  496. }
  497. }
  498. #endif /* WPS_WORKAROUNDS */
  499. if (wps_set_attr(attr, type, pos, len) < 0)
  500. return -1;
  501. pos += len;
  502. }
  503. return 0;
  504. }