preauth.c 14 KB

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