eap_wsc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * EAP-WSC server for Wi-Fi Protected Setup
  3. * Copyright (c) 2007-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 "eloop.h"
  17. #include "eap_i.h"
  18. #include "eap_common/eap_wsc_common.h"
  19. #include "wps/wps.h"
  20. struct eap_wsc_data {
  21. enum { START, MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
  22. int registrar;
  23. struct wpabuf *in_buf;
  24. struct wpabuf *out_buf;
  25. enum wsc_op_code in_op_code, out_op_code;
  26. size_t out_used;
  27. size_t fragment_size;
  28. struct wps_data *wps;
  29. int ext_reg_timeout;
  30. };
  31. static const char * eap_wsc_state_txt(int state)
  32. {
  33. switch (state) {
  34. case START:
  35. return "START";
  36. case MSG:
  37. return "MSG";
  38. case FRAG_ACK:
  39. return "FRAG_ACK";
  40. case WAIT_FRAG_ACK:
  41. return "WAIT_FRAG_ACK";
  42. case DONE:
  43. return "DONE";
  44. case FAIL:
  45. return "FAIL";
  46. default:
  47. return "?";
  48. }
  49. }
  50. static void eap_wsc_state(struct eap_wsc_data *data, int state)
  51. {
  52. wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s",
  53. eap_wsc_state_txt(data->state),
  54. eap_wsc_state_txt(state));
  55. data->state = state;
  56. }
  57. static void eap_wsc_ext_reg_timeout(void *eloop_ctx, void *timeout_ctx)
  58. {
  59. struct eap_sm *sm = eloop_ctx;
  60. struct eap_wsc_data *data = timeout_ctx;
  61. if (sm->method_pending != METHOD_PENDING_WAIT)
  62. return;
  63. wpa_printf(MSG_DEBUG, "EAP-WSC: Timeout while waiting for an External "
  64. "Registrar");
  65. data->ext_reg_timeout = 1;
  66. eap_sm_pending_cb(sm);
  67. }
  68. static void * eap_wsc_init(struct eap_sm *sm)
  69. {
  70. struct eap_wsc_data *data;
  71. int registrar;
  72. struct wps_config cfg;
  73. if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN &&
  74. os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) ==
  75. 0)
  76. registrar = 0; /* Supplicant is Registrar */
  77. else if (sm->identity && sm->identity_len == WSC_ID_ENROLLEE_LEN &&
  78. os_memcmp(sm->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)
  79. == 0)
  80. registrar = 1; /* Supplicant is Enrollee */
  81. else {
  82. wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity",
  83. sm->identity, sm->identity_len);
  84. return NULL;
  85. }
  86. data = os_zalloc(sizeof(*data));
  87. if (data == NULL)
  88. return NULL;
  89. data->state = registrar ? START : MSG;
  90. data->registrar = registrar;
  91. os_memset(&cfg, 0, sizeof(cfg));
  92. cfg.wps = sm->wps;
  93. cfg.registrar = registrar;
  94. if (registrar) {
  95. if (sm->wps == NULL || sm->wps->registrar == NULL) {
  96. wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not "
  97. "initialized");
  98. os_free(data);
  99. return NULL;
  100. }
  101. } else {
  102. if (sm->user == NULL || sm->user->password == NULL) {
  103. wpa_printf(MSG_INFO, "EAP-WSC: No AP PIN (password) "
  104. "configured for Enrollee functionality");
  105. os_free(data);
  106. return NULL;
  107. }
  108. cfg.pin = sm->user->password;
  109. cfg.pin_len = sm->user->password_len;
  110. }
  111. cfg.assoc_wps_ie = sm->assoc_wps_ie;
  112. cfg.peer_addr = sm->peer_addr;
  113. data->wps = wps_init(&cfg);
  114. if (data->wps == NULL) {
  115. os_free(data);
  116. return NULL;
  117. }
  118. data->fragment_size = WSC_FRAGMENT_SIZE;
  119. return data;
  120. }
  121. static void eap_wsc_reset(struct eap_sm *sm, void *priv)
  122. {
  123. struct eap_wsc_data *data = priv;
  124. eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
  125. wpabuf_free(data->in_buf);
  126. wpabuf_free(data->out_buf);
  127. wps_deinit(data->wps);
  128. os_free(data);
  129. }
  130. static struct wpabuf * eap_wsc_build_start(struct eap_sm *sm,
  131. struct eap_wsc_data *data, u8 id)
  132. {
  133. struct wpabuf *req;
  134. req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2,
  135. EAP_CODE_REQUEST, id);
  136. if (req == NULL) {
  137. wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for "
  138. "request");
  139. return NULL;
  140. }
  141. wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/Start");
  142. wpabuf_put_u8(req, WSC_Start); /* Op-Code */
  143. wpabuf_put_u8(req, 0); /* Flags */
  144. return req;
  145. }
  146. static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id)
  147. {
  148. struct wpabuf *req;
  149. u8 flags;
  150. size_t send_len, plen;
  151. flags = 0;
  152. send_len = wpabuf_len(data->out_buf) - data->out_used;
  153. if (2 + send_len > data->fragment_size) {
  154. send_len = data->fragment_size - 2;
  155. flags |= WSC_FLAGS_MF;
  156. if (data->out_used == 0) {
  157. flags |= WSC_FLAGS_LF;
  158. send_len -= 2;
  159. }
  160. }
  161. plen = 2 + send_len;
  162. if (flags & WSC_FLAGS_LF)
  163. plen += 2;
  164. req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen,
  165. EAP_CODE_REQUEST, id);
  166. if (req == NULL) {
  167. wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for "
  168. "request");
  169. return NULL;
  170. }
  171. wpabuf_put_u8(req, data->out_op_code); /* Op-Code */
  172. wpabuf_put_u8(req, flags); /* Flags */
  173. if (flags & WSC_FLAGS_LF)
  174. wpabuf_put_be16(req, wpabuf_len(data->out_buf));
  175. wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
  176. send_len);
  177. data->out_used += send_len;
  178. if (data->out_used == wpabuf_len(data->out_buf)) {
  179. wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
  180. "(message sent completely)",
  181. (unsigned long) send_len);
  182. wpabuf_free(data->out_buf);
  183. data->out_buf = NULL;
  184. data->out_used = 0;
  185. eap_wsc_state(data, MSG);
  186. } else {
  187. wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
  188. "(%lu more to send)", (unsigned long) send_len,
  189. (unsigned long) wpabuf_len(data->out_buf) -
  190. data->out_used);
  191. eap_wsc_state(data, WAIT_FRAG_ACK);
  192. }
  193. return req;
  194. }
  195. static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id)
  196. {
  197. struct eap_wsc_data *data = priv;
  198. switch (data->state) {
  199. case START:
  200. return eap_wsc_build_start(sm, data, id);
  201. case MSG:
  202. if (data->out_buf == NULL) {
  203. data->out_buf = wps_get_msg(data->wps,
  204. &data->out_op_code);
  205. if (data->out_buf == NULL) {
  206. wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to "
  207. "receive message from WPS");
  208. return NULL;
  209. }
  210. data->out_used = 0;
  211. }
  212. /* pass through */
  213. case WAIT_FRAG_ACK:
  214. return eap_wsc_build_msg(data, id);
  215. case FRAG_ACK:
  216. return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST);
  217. default:
  218. wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in "
  219. "buildReq", data->state);
  220. return NULL;
  221. }
  222. }
  223. static Boolean eap_wsc_check(struct eap_sm *sm, void *priv,
  224. struct wpabuf *respData)
  225. {
  226. const u8 *pos;
  227. size_t len;
  228. pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
  229. respData, &len);
  230. if (pos == NULL || len < 2) {
  231. wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame");
  232. return TRUE;
  233. }
  234. return FALSE;
  235. }
  236. static int eap_wsc_process_cont(struct eap_wsc_data *data,
  237. const u8 *buf, size_t len, u8 op_code)
  238. {
  239. /* Process continuation of a pending message */
  240. if (op_code != data->in_op_code) {
  241. wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in "
  242. "fragment (expected %d)",
  243. op_code, data->in_op_code);
  244. eap_wsc_state(data, FAIL);
  245. return -1;
  246. }
  247. if (len > wpabuf_tailroom(data->in_buf)) {
  248. wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow");
  249. eap_wsc_state(data, FAIL);
  250. return -1;
  251. }
  252. wpabuf_put_data(data->in_buf, buf, len);
  253. wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu "
  254. "bytes more", (unsigned long) len,
  255. (unsigned long) wpabuf_tailroom(data->in_buf));
  256. return 0;
  257. }
  258. static int eap_wsc_process_fragment(struct eap_wsc_data *data,
  259. u8 flags, u8 op_code, u16 message_length,
  260. const u8 *buf, size_t len)
  261. {
  262. /* Process a fragment that is not the last one of the message */
  263. if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) {
  264. wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length "
  265. "field in a fragmented packet");
  266. return -1;
  267. }
  268. if (data->in_buf == NULL) {
  269. /* First fragment of the message */
  270. data->in_buf = wpabuf_alloc(message_length);
  271. if (data->in_buf == NULL) {
  272. wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for "
  273. "message");
  274. return -1;
  275. }
  276. data->in_op_code = op_code;
  277. wpabuf_put_data(data->in_buf, buf, len);
  278. wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in "
  279. "first fragment, waiting for %lu bytes more",
  280. (unsigned long) len,
  281. (unsigned long) wpabuf_tailroom(data->in_buf));
  282. }
  283. return 0;
  284. }
  285. static void eap_wsc_process(struct eap_sm *sm, void *priv,
  286. struct wpabuf *respData)
  287. {
  288. struct eap_wsc_data *data = priv;
  289. const u8 *start, *pos, *end;
  290. size_t len;
  291. u8 op_code, flags;
  292. u16 message_length = 0;
  293. enum wps_process_res res;
  294. struct wpabuf tmpbuf;
  295. eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
  296. if (data->ext_reg_timeout) {
  297. eap_wsc_state(data, FAIL);
  298. return;
  299. }
  300. pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
  301. respData, &len);
  302. if (pos == NULL || len < 2)
  303. return; /* Should not happen; message already verified */
  304. start = pos;
  305. end = start + len;
  306. op_code = *pos++;
  307. flags = *pos++;
  308. if (flags & WSC_FLAGS_LF) {
  309. if (end - pos < 2) {
  310. wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow");
  311. return;
  312. }
  313. message_length = WPA_GET_BE16(pos);
  314. pos += 2;
  315. if (message_length < end - pos) {
  316. wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message "
  317. "Length");
  318. return;
  319. }
  320. }
  321. wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d "
  322. "Flags 0x%x Message Length %d",
  323. op_code, flags, message_length);
  324. if (data->state == WAIT_FRAG_ACK) {
  325. if (op_code != WSC_FRAG_ACK) {
  326. wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
  327. "in WAIT_FRAG_ACK state", op_code);
  328. eap_wsc_state(data, FAIL);
  329. return;
  330. }
  331. wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged");
  332. eap_wsc_state(data, MSG);
  333. return;
  334. }
  335. if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG &&
  336. op_code != WSC_Done) {
  337. wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d",
  338. op_code);
  339. eap_wsc_state(data, FAIL);
  340. return;
  341. }
  342. if (data->in_buf &&
  343. eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) {
  344. eap_wsc_state(data, FAIL);
  345. return;
  346. }
  347. if (flags & WSC_FLAGS_MF) {
  348. if (eap_wsc_process_fragment(data, flags, op_code,
  349. message_length, pos, end - pos) <
  350. 0)
  351. eap_wsc_state(data, FAIL);
  352. else
  353. eap_wsc_state(data, FRAG_ACK);
  354. return;
  355. }
  356. if (data->in_buf == NULL) {
  357. /* Wrap unfragmented messages as wpabuf without extra copy */
  358. wpabuf_set(&tmpbuf, pos, end - pos);
  359. data->in_buf = &tmpbuf;
  360. }
  361. res = wps_process_msg(data->wps, op_code, data->in_buf);
  362. switch (res) {
  363. case WPS_DONE:
  364. wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed "
  365. "successfully - report EAP failure");
  366. eap_wsc_state(data, FAIL);
  367. break;
  368. case WPS_CONTINUE:
  369. eap_wsc_state(data, MSG);
  370. break;
  371. case WPS_FAILURE:
  372. wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed");
  373. eap_wsc_state(data, FAIL);
  374. break;
  375. case WPS_PENDING:
  376. eap_wsc_state(data, MSG);
  377. sm->method_pending = METHOD_PENDING_WAIT;
  378. eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
  379. eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout,
  380. sm, data);
  381. break;
  382. }
  383. if (data->in_buf != &tmpbuf)
  384. wpabuf_free(data->in_buf);
  385. data->in_buf = NULL;
  386. }
  387. static Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv)
  388. {
  389. struct eap_wsc_data *data = priv;
  390. return data->state == FAIL;
  391. }
  392. static Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv)
  393. {
  394. /* EAP-WSC will always result in EAP-Failure */
  395. return FALSE;
  396. }
  397. static int eap_wsc_getTimeout(struct eap_sm *sm, void *priv)
  398. {
  399. /* Recommended retransmit times: retransmit timeout 5 seconds,
  400. * per-message timeout 15 seconds, i.e., 3 tries. */
  401. sm->MaxRetrans = 2; /* total 3 attempts */
  402. return 5;
  403. }
  404. int eap_server_wsc_register(void)
  405. {
  406. struct eap_method *eap;
  407. int ret;
  408. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  409. EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
  410. "WSC");
  411. if (eap == NULL)
  412. return -1;
  413. eap->init = eap_wsc_init;
  414. eap->reset = eap_wsc_reset;
  415. eap->buildReq = eap_wsc_buildReq;
  416. eap->check = eap_wsc_check;
  417. eap->process = eap_wsc_process;
  418. eap->isDone = eap_wsc_isDone;
  419. eap->isSuccess = eap_wsc_isSuccess;
  420. eap->getTimeout = eap_wsc_getTimeout;
  421. ret = eap_server_method_register(eap);
  422. if (ret)
  423. eap_server_method_free(eap);
  424. return ret;
  425. }