preauth.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /*
  2. * RSN pre-authentication (supplicant)
  3. * Copyright (c) 2003-2010, 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 "wpa.h"
  17. #include "eloop.h"
  18. #include "l2_packet/l2_packet.h"
  19. #include "eapol_supp/eapol_supp_sm.h"
  20. #include "preauth.h"
  21. #include "pmksa_cache.h"
  22. #include "wpa_i.h"
  23. #include "common/ieee802_11_defs.h"
  24. #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
  25. #define PMKID_CANDIDATE_PRIO_SCAN 1000
  26. struct rsn_pmksa_candidate {
  27. struct dl_list list;
  28. u8 bssid[ETH_ALEN];
  29. int priority;
  30. };
  31. /**
  32. * pmksa_candidate_free - Free all entries in PMKSA candidate list
  33. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  34. */
  35. void pmksa_candidate_free(struct wpa_sm *sm)
  36. {
  37. struct rsn_pmksa_candidate *entry, *n;
  38. if (sm == NULL)
  39. return;
  40. dl_list_for_each_safe(entry, n, &sm->pmksa_candidates,
  41. struct rsn_pmksa_candidate, list)
  42. os_free(entry);
  43. }
  44. static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
  45. const u8 *buf, size_t len)
  46. {
  47. struct wpa_sm *sm = ctx;
  48. wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr));
  49. wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len);
  50. if (sm->preauth_eapol == NULL ||
  51. is_zero_ether_addr(sm->preauth_bssid) ||
  52. os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) {
  53. wpa_printf(MSG_WARNING, "RSN pre-auth frame received from "
  54. "unexpected source " MACSTR " - dropped",
  55. MAC2STR(src_addr));
  56. return;
  57. }
  58. eapol_sm_rx_eapol(sm->preauth_eapol, src_addr, buf, len);
  59. }
  60. static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success,
  61. void *ctx)
  62. {
  63. struct wpa_sm *sm = ctx;
  64. u8 pmk[PMK_LEN];
  65. if (success) {
  66. int res, pmk_len;
  67. pmk_len = PMK_LEN;
  68. res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
  69. if (res) {
  70. /*
  71. * EAP-LEAP is an exception from other EAP methods: it
  72. * uses only 16-byte PMK.
  73. */
  74. res = eapol_sm_get_key(eapol, pmk, 16);
  75. pmk_len = 16;
  76. }
  77. if (res == 0) {
  78. wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
  79. pmk, pmk_len);
  80. sm->pmk_len = pmk_len;
  81. pmksa_cache_add(sm->pmksa, pmk, pmk_len,
  82. sm->preauth_bssid, sm->own_addr,
  83. sm->network_ctx,
  84. WPA_KEY_MGMT_IEEE8021X);
  85. } else {
  86. wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
  87. "RSN: failed to get master session key from "
  88. "pre-auth EAPOL state machines");
  89. success = 0;
  90. }
  91. }
  92. wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
  93. MACSTR " %s", MAC2STR(sm->preauth_bssid),
  94. success ? "completed successfully" : "failed");
  95. rsn_preauth_deinit(sm);
  96. rsn_preauth_candidate_process(sm);
  97. }
  98. static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx)
  99. {
  100. struct wpa_sm *sm = eloop_ctx;
  101. wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
  102. MACSTR " timed out", MAC2STR(sm->preauth_bssid));
  103. rsn_preauth_deinit(sm);
  104. rsn_preauth_candidate_process(sm);
  105. }
  106. static int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf,
  107. size_t len)
  108. {
  109. struct wpa_sm *sm = ctx;
  110. u8 *msg;
  111. size_t msglen;
  112. int res;
  113. /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
  114. * extra copy here */
  115. if (sm->l2_preauth == NULL)
  116. return -1;
  117. msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL);
  118. if (msg == NULL)
  119. return -1;
  120. wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen);
  121. res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid,
  122. ETH_P_RSN_PREAUTH, msg, msglen);
  123. os_free(msg);
  124. return res;
  125. }
  126. /**
  127. * rsn_preauth_init - Start new RSN pre-authentication
  128. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  129. * @dst: Authenticator address (BSSID) with which to preauthenticate
  130. * @eap_conf: Current EAP configuration
  131. * Returns: 0 on success, -1 on another pre-authentication is in progress,
  132. * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine
  133. * initialization failure, -4 on memory allocation failure
  134. *
  135. * This function request an RSN pre-authentication with a given destination
  136. * address. This is usually called for PMKSA candidates found from scan results
  137. * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger
  138. * pre-authentication.
  139. */
  140. int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
  141. struct eap_peer_config *eap_conf)
  142. {
  143. struct eapol_config eapol_conf;
  144. struct eapol_ctx *ctx;
  145. if (sm->preauth_eapol)
  146. return -1;
  147. wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
  148. "RSN: starting pre-authentication with " MACSTR, MAC2STR(dst));
  149. sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr,
  150. ETH_P_RSN_PREAUTH,
  151. rsn_preauth_receive, sm, 0);
  152. if (sm->l2_preauth == NULL) {
  153. wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet "
  154. "processing for pre-authentication");
  155. return -2;
  156. }
  157. if (sm->bridge_ifname) {
  158. sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname,
  159. sm->own_addr,
  160. ETH_P_RSN_PREAUTH,
  161. rsn_preauth_receive, sm, 0);
  162. if (sm->l2_preauth_br == NULL) {
  163. wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 "
  164. "packet processing (bridge) for "
  165. "pre-authentication");
  166. return -2;
  167. }
  168. }
  169. ctx = os_zalloc(sizeof(*ctx));
  170. if (ctx == NULL) {
  171. wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context.");
  172. return -4;
  173. }
  174. ctx->ctx = sm->ctx->ctx;
  175. ctx->msg_ctx = sm->ctx->ctx;
  176. ctx->preauth = 1;
  177. ctx->cb = rsn_preauth_eapol_cb;
  178. ctx->cb_ctx = sm;
  179. ctx->scard_ctx = sm->scard_ctx;
  180. ctx->eapol_send = rsn_preauth_eapol_send;
  181. ctx->eapol_send_ctx = sm;
  182. ctx->set_config_blob = sm->ctx->set_config_blob;
  183. ctx->get_config_blob = sm->ctx->get_config_blob;
  184. sm->preauth_eapol = eapol_sm_init(ctx);
  185. if (sm->preauth_eapol == NULL) {
  186. os_free(ctx);
  187. wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL "
  188. "state machines for pre-authentication");
  189. return -3;
  190. }
  191. os_memset(&eapol_conf, 0, sizeof(eapol_conf));
  192. eapol_conf.accept_802_1x_keys = 0;
  193. eapol_conf.required_keys = 0;
  194. eapol_conf.fast_reauth = sm->fast_reauth;
  195. eapol_conf.workaround = sm->eap_workaround;
  196. eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf);
  197. /*
  198. * Use a shorter startPeriod with preauthentication since the first
  199. * preauth EAPOL-Start frame may end up being dropped due to race
  200. * condition in the AP between the data receive and key configuration
  201. * after the 4-Way Handshake.
  202. */
  203. eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6);
  204. os_memcpy(sm->preauth_bssid, dst, ETH_ALEN);
  205. eapol_sm_notify_portValid(sm->preauth_eapol, TRUE);
  206. /* 802.1X::portControl = Auto */
  207. eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE);
  208. eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0,
  209. rsn_preauth_timeout, sm, NULL);
  210. return 0;
  211. }
  212. /**
  213. * rsn_preauth_deinit - Abort RSN pre-authentication
  214. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  215. *
  216. * This function aborts the current RSN pre-authentication (if one is started)
  217. * and frees resources allocated for it.
  218. */
  219. void rsn_preauth_deinit(struct wpa_sm *sm)
  220. {
  221. if (sm == NULL || !sm->preauth_eapol)
  222. return;
  223. eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL);
  224. eapol_sm_deinit(sm->preauth_eapol);
  225. sm->preauth_eapol = NULL;
  226. os_memset(sm->preauth_bssid, 0, ETH_ALEN);
  227. l2_packet_deinit(sm->l2_preauth);
  228. sm->l2_preauth = NULL;
  229. if (sm->l2_preauth_br) {
  230. l2_packet_deinit(sm->l2_preauth_br);
  231. sm->l2_preauth_br = NULL;
  232. }
  233. }
  234. /**
  235. * rsn_preauth_candidate_process - Process PMKSA candidates
  236. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  237. *
  238. * Go through the PMKSA candidates and start pre-authentication if a candidate
  239. * without an existing PMKSA cache entry is found. Processed candidates will be
  240. * removed from the list.
  241. */
  242. void rsn_preauth_candidate_process(struct wpa_sm *sm)
  243. {
  244. struct rsn_pmksa_candidate *candidate, *n;
  245. if (dl_list_empty(&sm->pmksa_candidates))
  246. return;
  247. /* TODO: drop priority for old candidate entries */
  248. wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate "
  249. "list");
  250. if (sm->preauth_eapol ||
  251. sm->proto != WPA_PROTO_RSN ||
  252. wpa_sm_get_state(sm) != WPA_COMPLETED ||
  253. (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
  254. sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) {
  255. wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable "
  256. "state for new pre-authentication");
  257. return; /* invalid state for new pre-auth */
  258. }
  259. dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
  260. struct rsn_pmksa_candidate, list) {
  261. struct rsn_pmksa_cache_entry *p = NULL;
  262. p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL);
  263. if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
  264. (p == NULL || p->opportunistic)) {
  265. wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
  266. "candidate " MACSTR
  267. " selected for pre-authentication",
  268. MAC2STR(candidate->bssid));
  269. dl_list_del(&candidate->list);
  270. rsn_preauth_init(sm, candidate->bssid,
  271. sm->eap_conf_ctx);
  272. os_free(candidate);
  273. return;
  274. }
  275. wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate "
  276. MACSTR " does not need pre-authentication anymore",
  277. MAC2STR(candidate->bssid));
  278. /* Some drivers (e.g., NDIS) expect to get notified about the
  279. * PMKIDs again, so report the existing data now. */
  280. if (p) {
  281. wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid);
  282. }
  283. dl_list_del(&candidate->list);
  284. os_free(candidate);
  285. }
  286. wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
  287. "candidates");
  288. }
  289. /**
  290. * pmksa_candidate_add - Add a new PMKSA candidate
  291. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  292. * @bssid: BSSID (authenticator address) of the candidate
  293. * @prio: Priority (the smaller number, the higher priority)
  294. * @preauth: Whether the candidate AP advertises support for pre-authentication
  295. *
  296. * This function is used to add PMKSA candidates for RSN pre-authentication. It
  297. * is called from scan result processing and from driver events for PMKSA
  298. * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event().
  299. */
  300. void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
  301. int prio, int preauth)
  302. {
  303. struct rsn_pmksa_candidate *cand, *pos;
  304. if (sm->network_ctx && sm->proactive_key_caching)
  305. pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
  306. bssid);
  307. if (!preauth) {
  308. wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
  309. "preauth flag");
  310. return;
  311. }
  312. /* If BSSID already on candidate list, update the priority of the old
  313. * entry. Do not override priority based on normal scan results. */
  314. cand = NULL;
  315. dl_list_for_each(pos, &sm->pmksa_candidates,
  316. struct rsn_pmksa_candidate, list) {
  317. if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) {
  318. cand = pos;
  319. break;
  320. }
  321. }
  322. if (cand) {
  323. if (prio < PMKID_CANDIDATE_PRIO_SCAN)
  324. cand->priority = prio;
  325. } else {
  326. cand = os_zalloc(sizeof(*cand));
  327. if (cand == NULL)
  328. return;
  329. os_memcpy(cand->bssid, bssid, ETH_ALEN);
  330. cand->priority = prio;
  331. }
  332. /* Add candidate to the list; order by increasing priority value. i.e.,
  333. * highest priority (smallest value) first. */
  334. dl_list_for_each(pos, &sm->pmksa_candidates,
  335. struct rsn_pmksa_candidate, list) {
  336. if (cand->priority <= pos->priority) {
  337. dl_list_add(pos->list.prev, &cand->list);
  338. cand = NULL;
  339. break;
  340. }
  341. }
  342. if (cand)
  343. dl_list_add_tail(&sm->pmksa_candidates, &cand->list);
  344. wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache "
  345. "candidate " MACSTR " prio %d", MAC2STR(bssid), prio);
  346. rsn_preauth_candidate_process(sm);
  347. }
  348. /* TODO: schedule periodic scans if current AP supports preauth */
  349. /**
  350. * rsn_preauth_scan_results - Start processing scan results for canditates
  351. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  352. * Returns: 0 if ready to process results or -1 to skip processing
  353. *
  354. * This functions is used to notify RSN code about start of new scan results
  355. * processing. The actual scan results will be provided by calling
  356. * rsn_preauth_scan_result() for each BSS if this function returned 0.
  357. */
  358. int rsn_preauth_scan_results(struct wpa_sm *sm)
  359. {
  360. if (sm->ssid_len == 0)
  361. return -1;
  362. /*
  363. * TODO: is it ok to free all candidates? What about the entries
  364. * received from EVENT_PMKID_CANDIDATE?
  365. */
  366. pmksa_candidate_free(sm);
  367. return 0;
  368. }
  369. /**
  370. * rsn_preauth_scan_result - Processing scan result for PMKSA canditates
  371. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  372. *
  373. * Add all suitable APs (Authenticators) from scan results into PMKSA
  374. * candidate list.
  375. */
  376. void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
  377. const u8 *ssid, const u8 *rsn)
  378. {
  379. struct wpa_ie_data ie;
  380. struct rsn_pmksa_cache_entry *pmksa;
  381. if (ssid[1] != sm->ssid_len ||
  382. os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0)
  383. return; /* Not for the current SSID */
  384. if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0)
  385. return; /* Ignore current AP */
  386. if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
  387. return;
  388. pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL);
  389. if (pmksa && (!pmksa->opportunistic ||
  390. !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
  391. return;
  392. /* Give less priority to candidates found from normal scan results. */
  393. pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN,
  394. ie.capabilities & WPA_CAPABILITY_PREAUTH);
  395. }
  396. #ifdef CONFIG_CTRL_IFACE
  397. /**
  398. * rsn_preauth_get_status - Get pre-authentication status
  399. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  400. * @buf: Buffer for status information
  401. * @buflen: Maximum buffer length
  402. * @verbose: Whether to include verbose status information
  403. * Returns: Number of bytes written to buf.
  404. *
  405. * Query WPA2 pre-authentication for status information. This function fills in
  406. * a text area with current status information. If the buffer (buf) is not
  407. * large enough, status information will be truncated to fit the buffer.
  408. */
  409. int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
  410. int verbose)
  411. {
  412. char *pos = buf, *end = buf + buflen;
  413. int res, ret;
  414. if (sm->preauth_eapol) {
  415. ret = os_snprintf(pos, end - pos, "Pre-authentication "
  416. "EAPOL state machines:\n");
  417. if (ret < 0 || ret >= end - pos)
  418. return pos - buf;
  419. pos += ret;
  420. res = eapol_sm_get_status(sm->preauth_eapol,
  421. pos, end - pos, verbose);
  422. if (res >= 0)
  423. pos += res;
  424. }
  425. return pos - buf;
  426. }
  427. #endif /* CONFIG_CTRL_IFACE */
  428. /**
  429. * rsn_preauth_in_progress - Verify whether pre-authentication is in progress
  430. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  431. */
  432. int rsn_preauth_in_progress(struct wpa_sm *sm)
  433. {
  434. return sm->preauth_eapol != NULL;
  435. }
  436. #endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */