eapol_supp_sm.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924
  1. /*
  2. * EAPOL supplicant state machines
  3. * Copyright (c) 2004-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 "state_machine.h"
  17. #include "wpabuf.h"
  18. #include "eloop.h"
  19. #include "crypto/crypto.h"
  20. #include "crypto/md5.h"
  21. #include "common/eapol_common.h"
  22. #include "eap_peer/eap.h"
  23. #include "eapol_supp_sm.h"
  24. #define STATE_MACHINE_DATA struct eapol_sm
  25. #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
  26. /* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */
  27. /**
  28. * struct eapol_sm - Internal data for EAPOL state machines
  29. */
  30. struct eapol_sm {
  31. /* Timers */
  32. unsigned int authWhile;
  33. unsigned int heldWhile;
  34. unsigned int startWhen;
  35. unsigned int idleWhile; /* for EAP state machine */
  36. int timer_tick_enabled;
  37. /* Global variables */
  38. Boolean eapFail;
  39. Boolean eapolEap;
  40. Boolean eapSuccess;
  41. Boolean initialize;
  42. Boolean keyDone;
  43. Boolean keyRun;
  44. PortControl portControl;
  45. Boolean portEnabled;
  46. PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */
  47. Boolean portValid;
  48. Boolean suppAbort;
  49. Boolean suppFail;
  50. Boolean suppStart;
  51. Boolean suppSuccess;
  52. Boolean suppTimeout;
  53. /* Supplicant PAE state machine */
  54. enum {
  55. SUPP_PAE_UNKNOWN = 0,
  56. SUPP_PAE_DISCONNECTED = 1,
  57. SUPP_PAE_LOGOFF = 2,
  58. SUPP_PAE_CONNECTING = 3,
  59. SUPP_PAE_AUTHENTICATING = 4,
  60. SUPP_PAE_AUTHENTICATED = 5,
  61. /* unused(6) */
  62. SUPP_PAE_HELD = 7,
  63. SUPP_PAE_RESTART = 8,
  64. SUPP_PAE_S_FORCE_AUTH = 9,
  65. SUPP_PAE_S_FORCE_UNAUTH = 10
  66. } SUPP_PAE_state; /* dot1xSuppPaeState */
  67. /* Variables */
  68. Boolean userLogoff;
  69. Boolean logoffSent;
  70. unsigned int startCount;
  71. Boolean eapRestart;
  72. PortControl sPortMode;
  73. /* Constants */
  74. unsigned int heldPeriod; /* dot1xSuppHeldPeriod */
  75. unsigned int startPeriod; /* dot1xSuppStartPeriod */
  76. unsigned int maxStart; /* dot1xSuppMaxStart */
  77. /* Key Receive state machine */
  78. enum {
  79. KEY_RX_UNKNOWN = 0,
  80. KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE
  81. } KEY_RX_state;
  82. /* Variables */
  83. Boolean rxKey;
  84. /* Supplicant Backend state machine */
  85. enum {
  86. SUPP_BE_UNKNOWN = 0,
  87. SUPP_BE_INITIALIZE = 1,
  88. SUPP_BE_IDLE = 2,
  89. SUPP_BE_REQUEST = 3,
  90. SUPP_BE_RECEIVE = 4,
  91. SUPP_BE_RESPONSE = 5,
  92. SUPP_BE_FAIL = 6,
  93. SUPP_BE_TIMEOUT = 7,
  94. SUPP_BE_SUCCESS = 8
  95. } SUPP_BE_state; /* dot1xSuppBackendPaeState */
  96. /* Variables */
  97. Boolean eapNoResp;
  98. Boolean eapReq;
  99. Boolean eapResp;
  100. /* Constants */
  101. unsigned int authPeriod; /* dot1xSuppAuthPeriod */
  102. /* Statistics */
  103. unsigned int dot1xSuppEapolFramesRx;
  104. unsigned int dot1xSuppEapolFramesTx;
  105. unsigned int dot1xSuppEapolStartFramesTx;
  106. unsigned int dot1xSuppEapolLogoffFramesTx;
  107. unsigned int dot1xSuppEapolRespFramesTx;
  108. unsigned int dot1xSuppEapolReqIdFramesRx;
  109. unsigned int dot1xSuppEapolReqFramesRx;
  110. unsigned int dot1xSuppInvalidEapolFramesRx;
  111. unsigned int dot1xSuppEapLengthErrorFramesRx;
  112. unsigned int dot1xSuppLastEapolFrameVersion;
  113. unsigned char dot1xSuppLastEapolFrameSource[6];
  114. /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */
  115. Boolean changed;
  116. struct eap_sm *eap;
  117. struct eap_peer_config *config;
  118. Boolean initial_req;
  119. u8 *last_rx_key;
  120. size_t last_rx_key_len;
  121. struct wpabuf *eapReqData; /* for EAP */
  122. Boolean altAccept; /* for EAP */
  123. Boolean altReject; /* for EAP */
  124. Boolean replay_counter_valid;
  125. u8 last_replay_counter[16];
  126. struct eapol_config conf;
  127. struct eapol_ctx *ctx;
  128. enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE }
  129. cb_status;
  130. Boolean cached_pmk;
  131. Boolean unicast_key_received, broadcast_key_received;
  132. };
  133. #define IEEE8021X_REPLAY_COUNTER_LEN 8
  134. #define IEEE8021X_KEY_SIGN_LEN 16
  135. #define IEEE8021X_KEY_IV_LEN 16
  136. #define IEEE8021X_KEY_INDEX_FLAG 0x80
  137. #define IEEE8021X_KEY_INDEX_MASK 0x03
  138. #ifdef _MSC_VER
  139. #pragma pack(push, 1)
  140. #endif /* _MSC_VER */
  141. struct ieee802_1x_eapol_key {
  142. u8 type;
  143. /* Note: key_length is unaligned */
  144. u8 key_length[2];
  145. /* does not repeat within the life of the keying material used to
  146. * encrypt the Key field; 64-bit NTP timestamp MAY be used here */
  147. u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
  148. u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */
  149. u8 key_index; /* key flag in the most significant bit:
  150. * 0 = broadcast (default key),
  151. * 1 = unicast (key mapping key); key index is in the
  152. * 7 least significant bits */
  153. /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as
  154. * the key */
  155. u8 key_signature[IEEE8021X_KEY_SIGN_LEN];
  156. /* followed by key: if packet body length = 44 + key length, then the
  157. * key field (of key_length bytes) contains the key in encrypted form;
  158. * if packet body length = 44, key field is absent and key_length
  159. * represents the number of least significant octets from
  160. * MS-MPPE-Send-Key attribute to be used as the keying material;
  161. * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
  162. } STRUCT_PACKED;
  163. #ifdef _MSC_VER
  164. #pragma pack(pop)
  165. #endif /* _MSC_VER */
  166. static void eapol_sm_txLogoff(struct eapol_sm *sm);
  167. static void eapol_sm_txStart(struct eapol_sm *sm);
  168. static void eapol_sm_processKey(struct eapol_sm *sm);
  169. static void eapol_sm_getSuppRsp(struct eapol_sm *sm);
  170. static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
  171. static void eapol_sm_abortSupp(struct eapol_sm *sm);
  172. static void eapol_sm_abort_cached(struct eapol_sm *sm);
  173. static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
  174. static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
  175. static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
  176. /* Port Timers state machine - implemented as a function that will be called
  177. * once a second as a registered event loop timeout */
  178. static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
  179. {
  180. struct eapol_sm *sm = timeout_ctx;
  181. if (sm->authWhile > 0) {
  182. sm->authWhile--;
  183. if (sm->authWhile == 0)
  184. wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0");
  185. }
  186. if (sm->heldWhile > 0) {
  187. sm->heldWhile--;
  188. if (sm->heldWhile == 0)
  189. wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0");
  190. }
  191. if (sm->startWhen > 0) {
  192. sm->startWhen--;
  193. if (sm->startWhen == 0)
  194. wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0");
  195. }
  196. if (sm->idleWhile > 0) {
  197. sm->idleWhile--;
  198. if (sm->idleWhile == 0)
  199. wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0");
  200. }
  201. if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) {
  202. eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx,
  203. sm);
  204. } else {
  205. wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick");
  206. sm->timer_tick_enabled = 0;
  207. }
  208. eapol_sm_step(sm);
  209. }
  210. static void eapol_enable_timer_tick(struct eapol_sm *sm)
  211. {
  212. if (sm->timer_tick_enabled)
  213. return;
  214. wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick");
  215. sm->timer_tick_enabled = 1;
  216. eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
  217. eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
  218. }
  219. SM_STATE(SUPP_PAE, LOGOFF)
  220. {
  221. SM_ENTRY(SUPP_PAE, LOGOFF);
  222. eapol_sm_txLogoff(sm);
  223. sm->logoffSent = TRUE;
  224. sm->suppPortStatus = Unauthorized;
  225. eapol_sm_set_port_unauthorized(sm);
  226. }
  227. SM_STATE(SUPP_PAE, DISCONNECTED)
  228. {
  229. SM_ENTRY(SUPP_PAE, DISCONNECTED);
  230. sm->sPortMode = Auto;
  231. sm->startCount = 0;
  232. sm->logoffSent = FALSE;
  233. sm->suppPortStatus = Unauthorized;
  234. eapol_sm_set_port_unauthorized(sm);
  235. sm->suppAbort = TRUE;
  236. sm->unicast_key_received = FALSE;
  237. sm->broadcast_key_received = FALSE;
  238. }
  239. SM_STATE(SUPP_PAE, CONNECTING)
  240. {
  241. int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING;
  242. SM_ENTRY(SUPP_PAE, CONNECTING);
  243. if (send_start) {
  244. sm->startWhen = sm->startPeriod;
  245. sm->startCount++;
  246. } else {
  247. /*
  248. * Do not send EAPOL-Start immediately since in most cases,
  249. * Authenticator is going to start authentication immediately
  250. * after association and an extra EAPOL-Start is just going to
  251. * delay authentication. Use a short timeout to send the first
  252. * EAPOL-Start if Authenticator does not start authentication.
  253. */
  254. #ifdef CONFIG_WPS
  255. /* Reduce latency on starting WPS negotiation. */
  256. sm->startWhen = 1;
  257. #else /* CONFIG_WPS */
  258. sm->startWhen = 3;
  259. #endif /* CONFIG_WPS */
  260. }
  261. eapol_enable_timer_tick(sm);
  262. sm->eapolEap = FALSE;
  263. if (send_start)
  264. eapol_sm_txStart(sm);
  265. }
  266. SM_STATE(SUPP_PAE, AUTHENTICATING)
  267. {
  268. SM_ENTRY(SUPP_PAE, AUTHENTICATING);
  269. sm->startCount = 0;
  270. sm->suppSuccess = FALSE;
  271. sm->suppFail = FALSE;
  272. sm->suppTimeout = FALSE;
  273. sm->keyRun = FALSE;
  274. sm->keyDone = FALSE;
  275. sm->suppStart = TRUE;
  276. }
  277. SM_STATE(SUPP_PAE, HELD)
  278. {
  279. SM_ENTRY(SUPP_PAE, HELD);
  280. sm->heldWhile = sm->heldPeriod;
  281. eapol_enable_timer_tick(sm);
  282. sm->suppPortStatus = Unauthorized;
  283. eapol_sm_set_port_unauthorized(sm);
  284. sm->cb_status = EAPOL_CB_FAILURE;
  285. }
  286. SM_STATE(SUPP_PAE, AUTHENTICATED)
  287. {
  288. SM_ENTRY(SUPP_PAE, AUTHENTICATED);
  289. sm->suppPortStatus = Authorized;
  290. eapol_sm_set_port_authorized(sm);
  291. sm->cb_status = EAPOL_CB_SUCCESS;
  292. }
  293. SM_STATE(SUPP_PAE, RESTART)
  294. {
  295. SM_ENTRY(SUPP_PAE, RESTART);
  296. sm->eapRestart = TRUE;
  297. }
  298. SM_STATE(SUPP_PAE, S_FORCE_AUTH)
  299. {
  300. SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
  301. sm->suppPortStatus = Authorized;
  302. eapol_sm_set_port_authorized(sm);
  303. sm->sPortMode = ForceAuthorized;
  304. }
  305. SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
  306. {
  307. SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
  308. sm->suppPortStatus = Unauthorized;
  309. eapol_sm_set_port_unauthorized(sm);
  310. sm->sPortMode = ForceUnauthorized;
  311. eapol_sm_txLogoff(sm);
  312. }
  313. SM_STEP(SUPP_PAE)
  314. {
  315. if ((sm->userLogoff && !sm->logoffSent) &&
  316. !(sm->initialize || !sm->portEnabled))
  317. SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF);
  318. else if (((sm->portControl == Auto) &&
  319. (sm->sPortMode != sm->portControl)) ||
  320. sm->initialize || !sm->portEnabled)
  321. SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED);
  322. else if ((sm->portControl == ForceAuthorized) &&
  323. (sm->sPortMode != sm->portControl) &&
  324. !(sm->initialize || !sm->portEnabled))
  325. SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH);
  326. else if ((sm->portControl == ForceUnauthorized) &&
  327. (sm->sPortMode != sm->portControl) &&
  328. !(sm->initialize || !sm->portEnabled))
  329. SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH);
  330. else switch (sm->SUPP_PAE_state) {
  331. case SUPP_PAE_UNKNOWN:
  332. break;
  333. case SUPP_PAE_LOGOFF:
  334. if (!sm->userLogoff)
  335. SM_ENTER(SUPP_PAE, DISCONNECTED);
  336. break;
  337. case SUPP_PAE_DISCONNECTED:
  338. SM_ENTER(SUPP_PAE, CONNECTING);
  339. break;
  340. case SUPP_PAE_CONNECTING:
  341. if (sm->startWhen == 0 && sm->startCount < sm->maxStart)
  342. SM_ENTER(SUPP_PAE, CONNECTING);
  343. else if (sm->startWhen == 0 &&
  344. sm->startCount >= sm->maxStart &&
  345. sm->portValid)
  346. SM_ENTER(SUPP_PAE, AUTHENTICATED);
  347. else if (sm->eapSuccess || sm->eapFail)
  348. SM_ENTER(SUPP_PAE, AUTHENTICATING);
  349. else if (sm->eapolEap)
  350. SM_ENTER(SUPP_PAE, RESTART);
  351. else if (sm->startWhen == 0 &&
  352. sm->startCount >= sm->maxStart &&
  353. !sm->portValid)
  354. SM_ENTER(SUPP_PAE, HELD);
  355. break;
  356. case SUPP_PAE_AUTHENTICATING:
  357. if (sm->eapSuccess && !sm->portValid &&
  358. sm->conf.accept_802_1x_keys &&
  359. sm->conf.required_keys == 0) {
  360. wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for "
  361. "plaintext connection; no EAPOL-Key frames "
  362. "required");
  363. sm->portValid = TRUE;
  364. if (sm->ctx->eapol_done_cb)
  365. sm->ctx->eapol_done_cb(sm->ctx->ctx);
  366. }
  367. if (sm->eapSuccess && sm->portValid)
  368. SM_ENTER(SUPP_PAE, AUTHENTICATED);
  369. else if (sm->eapFail || (sm->keyDone && !sm->portValid))
  370. SM_ENTER(SUPP_PAE, HELD);
  371. else if (sm->suppTimeout)
  372. SM_ENTER(SUPP_PAE, CONNECTING);
  373. break;
  374. case SUPP_PAE_HELD:
  375. if (sm->heldWhile == 0)
  376. SM_ENTER(SUPP_PAE, CONNECTING);
  377. else if (sm->eapolEap)
  378. SM_ENTER(SUPP_PAE, RESTART);
  379. break;
  380. case SUPP_PAE_AUTHENTICATED:
  381. if (sm->eapolEap && sm->portValid)
  382. SM_ENTER(SUPP_PAE, RESTART);
  383. else if (!sm->portValid)
  384. SM_ENTER(SUPP_PAE, DISCONNECTED);
  385. break;
  386. case SUPP_PAE_RESTART:
  387. if (!sm->eapRestart)
  388. SM_ENTER(SUPP_PAE, AUTHENTICATING);
  389. break;
  390. case SUPP_PAE_S_FORCE_AUTH:
  391. break;
  392. case SUPP_PAE_S_FORCE_UNAUTH:
  393. break;
  394. }
  395. }
  396. SM_STATE(KEY_RX, NO_KEY_RECEIVE)
  397. {
  398. SM_ENTRY(KEY_RX, NO_KEY_RECEIVE);
  399. }
  400. SM_STATE(KEY_RX, KEY_RECEIVE)
  401. {
  402. SM_ENTRY(KEY_RX, KEY_RECEIVE);
  403. eapol_sm_processKey(sm);
  404. sm->rxKey = FALSE;
  405. }
  406. SM_STEP(KEY_RX)
  407. {
  408. if (sm->initialize || !sm->portEnabled)
  409. SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
  410. switch (sm->KEY_RX_state) {
  411. case KEY_RX_UNKNOWN:
  412. break;
  413. case KEY_RX_NO_KEY_RECEIVE:
  414. if (sm->rxKey)
  415. SM_ENTER(KEY_RX, KEY_RECEIVE);
  416. break;
  417. case KEY_RX_KEY_RECEIVE:
  418. if (sm->rxKey)
  419. SM_ENTER(KEY_RX, KEY_RECEIVE);
  420. break;
  421. }
  422. }
  423. SM_STATE(SUPP_BE, REQUEST)
  424. {
  425. SM_ENTRY(SUPP_BE, REQUEST);
  426. sm->authWhile = 0;
  427. sm->eapReq = TRUE;
  428. eapol_sm_getSuppRsp(sm);
  429. }
  430. SM_STATE(SUPP_BE, RESPONSE)
  431. {
  432. SM_ENTRY(SUPP_BE, RESPONSE);
  433. eapol_sm_txSuppRsp(sm);
  434. sm->eapResp = FALSE;
  435. }
  436. SM_STATE(SUPP_BE, SUCCESS)
  437. {
  438. SM_ENTRY(SUPP_BE, SUCCESS);
  439. sm->keyRun = TRUE;
  440. sm->suppSuccess = TRUE;
  441. if (eap_key_available(sm->eap)) {
  442. /* New key received - clear IEEE 802.1X EAPOL-Key replay
  443. * counter */
  444. sm->replay_counter_valid = FALSE;
  445. }
  446. }
  447. SM_STATE(SUPP_BE, FAIL)
  448. {
  449. SM_ENTRY(SUPP_BE, FAIL);
  450. sm->suppFail = TRUE;
  451. }
  452. SM_STATE(SUPP_BE, TIMEOUT)
  453. {
  454. SM_ENTRY(SUPP_BE, TIMEOUT);
  455. sm->suppTimeout = TRUE;
  456. }
  457. SM_STATE(SUPP_BE, IDLE)
  458. {
  459. SM_ENTRY(SUPP_BE, IDLE);
  460. sm->suppStart = FALSE;
  461. sm->initial_req = TRUE;
  462. }
  463. SM_STATE(SUPP_BE, INITIALIZE)
  464. {
  465. SM_ENTRY(SUPP_BE, INITIALIZE);
  466. eapol_sm_abortSupp(sm);
  467. sm->suppAbort = FALSE;
  468. }
  469. SM_STATE(SUPP_BE, RECEIVE)
  470. {
  471. SM_ENTRY(SUPP_BE, RECEIVE);
  472. sm->authWhile = sm->authPeriod;
  473. eapol_enable_timer_tick(sm);
  474. sm->eapolEap = FALSE;
  475. sm->eapNoResp = FALSE;
  476. sm->initial_req = FALSE;
  477. }
  478. SM_STEP(SUPP_BE)
  479. {
  480. if (sm->initialize || sm->suppAbort)
  481. SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE);
  482. else switch (sm->SUPP_BE_state) {
  483. case SUPP_BE_UNKNOWN:
  484. break;
  485. case SUPP_BE_REQUEST:
  486. /*
  487. * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL
  488. * and SUCCESS based on eapFail and eapSuccess, respectively.
  489. * However, IEEE Std 802.1X-2004 is also specifying that
  490. * eapNoResp should be set in conjuction with eapSuccess and
  491. * eapFail which would mean that more than one of the
  492. * transitions here would be activated at the same time.
  493. * Skipping RESPONSE and/or RECEIVE states in these cases can
  494. * cause problems and the direct transitions to do not seem
  495. * correct. Because of this, the conditions for these
  496. * transitions are verified only after eapNoResp. They are
  497. * unlikely to be used since eapNoResp should always be set if
  498. * either of eapSuccess or eapFail is set.
  499. */
  500. if (sm->eapResp && sm->eapNoResp) {
  501. wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both "
  502. "eapResp and eapNoResp set?!");
  503. }
  504. if (sm->eapResp)
  505. SM_ENTER(SUPP_BE, RESPONSE);
  506. else if (sm->eapNoResp)
  507. SM_ENTER(SUPP_BE, RECEIVE);
  508. else if (sm->eapFail)
  509. SM_ENTER(SUPP_BE, FAIL);
  510. else if (sm->eapSuccess)
  511. SM_ENTER(SUPP_BE, SUCCESS);
  512. break;
  513. case SUPP_BE_RESPONSE:
  514. SM_ENTER(SUPP_BE, RECEIVE);
  515. break;
  516. case SUPP_BE_SUCCESS:
  517. SM_ENTER(SUPP_BE, IDLE);
  518. break;
  519. case SUPP_BE_FAIL:
  520. SM_ENTER(SUPP_BE, IDLE);
  521. break;
  522. case SUPP_BE_TIMEOUT:
  523. SM_ENTER(SUPP_BE, IDLE);
  524. break;
  525. case SUPP_BE_IDLE:
  526. if (sm->eapFail && sm->suppStart)
  527. SM_ENTER(SUPP_BE, FAIL);
  528. else if (sm->eapolEap && sm->suppStart)
  529. SM_ENTER(SUPP_BE, REQUEST);
  530. else if (sm->eapSuccess && sm->suppStart)
  531. SM_ENTER(SUPP_BE, SUCCESS);
  532. break;
  533. case SUPP_BE_INITIALIZE:
  534. SM_ENTER(SUPP_BE, IDLE);
  535. break;
  536. case SUPP_BE_RECEIVE:
  537. if (sm->eapolEap)
  538. SM_ENTER(SUPP_BE, REQUEST);
  539. else if (sm->eapFail)
  540. SM_ENTER(SUPP_BE, FAIL);
  541. else if (sm->authWhile == 0)
  542. SM_ENTER(SUPP_BE, TIMEOUT);
  543. else if (sm->eapSuccess)
  544. SM_ENTER(SUPP_BE, SUCCESS);
  545. break;
  546. }
  547. }
  548. static void eapol_sm_txLogoff(struct eapol_sm *sm)
  549. {
  550. wpa_printf(MSG_DEBUG, "EAPOL: txLogoff");
  551. sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
  552. IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0);
  553. sm->dot1xSuppEapolLogoffFramesTx++;
  554. sm->dot1xSuppEapolFramesTx++;
  555. }
  556. static void eapol_sm_txStart(struct eapol_sm *sm)
  557. {
  558. wpa_printf(MSG_DEBUG, "EAPOL: txStart");
  559. sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
  560. IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0);
  561. sm->dot1xSuppEapolStartFramesTx++;
  562. sm->dot1xSuppEapolFramesTx++;
  563. }
  564. #define IEEE8021X_ENCR_KEY_LEN 32
  565. #define IEEE8021X_SIGN_KEY_LEN 32
  566. struct eap_key_data {
  567. u8 encr_key[IEEE8021X_ENCR_KEY_LEN];
  568. u8 sign_key[IEEE8021X_SIGN_KEY_LEN];
  569. };
  570. static void eapol_sm_processKey(struct eapol_sm *sm)
  571. {
  572. struct ieee802_1x_hdr *hdr;
  573. struct ieee802_1x_eapol_key *key;
  574. struct eap_key_data keydata;
  575. u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32];
  576. u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN];
  577. int key_len, res, sign_key_len, encr_key_len;
  578. u16 rx_key_length;
  579. wpa_printf(MSG_DEBUG, "EAPOL: processKey");
  580. if (sm->last_rx_key == NULL)
  581. return;
  582. if (!sm->conf.accept_802_1x_keys) {
  583. wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key"
  584. " even though this was not accepted - "
  585. "ignoring this packet");
  586. return;
  587. }
  588. hdr = (struct ieee802_1x_hdr *) sm->last_rx_key;
  589. key = (struct ieee802_1x_eapol_key *) (hdr + 1);
  590. if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) {
  591. wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame");
  592. return;
  593. }
  594. rx_key_length = WPA_GET_BE16(key->key_length);
  595. wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d "
  596. "EAPOL-Key: type=%d key_length=%d key_index=0x%x",
  597. hdr->version, hdr->type, be_to_host16(hdr->length),
  598. key->type, rx_key_length, key->key_index);
  599. eapol_sm_notify_lower_layer_success(sm, 1);
  600. sign_key_len = IEEE8021X_SIGN_KEY_LEN;
  601. encr_key_len = IEEE8021X_ENCR_KEY_LEN;
  602. res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata));
  603. if (res < 0) {
  604. wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for "
  605. "decrypting EAPOL-Key keys");
  606. return;
  607. }
  608. if (res == 16) {
  609. /* LEAP derives only 16 bytes of keying material. */
  610. res = eapol_sm_get_key(sm, (u8 *) &keydata, 16);
  611. if (res) {
  612. wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP "
  613. "master key for decrypting EAPOL-Key keys");
  614. return;
  615. }
  616. sign_key_len = 16;
  617. encr_key_len = 16;
  618. os_memcpy(keydata.sign_key, keydata.encr_key, 16);
  619. } else if (res) {
  620. wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key "
  621. "data for decrypting EAPOL-Key keys (res=%d)", res);
  622. return;
  623. }
  624. /* The key replay_counter must increase when same master key */
  625. if (sm->replay_counter_valid &&
  626. os_memcmp(sm->last_replay_counter, key->replay_counter,
  627. IEEE8021X_REPLAY_COUNTER_LEN) >= 0) {
  628. wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did "
  629. "not increase - ignoring key");
  630. wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter",
  631. sm->last_replay_counter,
  632. IEEE8021X_REPLAY_COUNTER_LEN);
  633. wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter",
  634. key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN);
  635. return;
  636. }
  637. /* Verify key signature (HMAC-MD5) */
  638. os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN);
  639. os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN);
  640. hmac_md5(keydata.sign_key, sign_key_len,
  641. sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length),
  642. key->key_signature);
  643. if (os_memcmp(orig_key_sign, key->key_signature,
  644. IEEE8021X_KEY_SIGN_LEN) != 0) {
  645. wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in "
  646. "EAPOL-Key packet");
  647. os_memcpy(key->key_signature, orig_key_sign,
  648. IEEE8021X_KEY_SIGN_LEN);
  649. return;
  650. }
  651. wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified");
  652. key_len = be_to_host16(hdr->length) - sizeof(*key);
  653. if (key_len > 32 || rx_key_length > 32) {
  654. wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d",
  655. key_len ? key_len : rx_key_length);
  656. return;
  657. }
  658. if (key_len == rx_key_length) {
  659. os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN);
  660. os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key,
  661. encr_key_len);
  662. os_memcpy(datakey, key + 1, key_len);
  663. rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0,
  664. datakey, key_len);
  665. wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key",
  666. datakey, key_len);
  667. } else if (key_len == 0) {
  668. /*
  669. * IEEE 802.1X-2004 specifies that least significant Key Length
  670. * octets from MS-MPPE-Send-Key are used as the key if the key
  671. * data is not present. This seems to be meaning the beginning
  672. * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in
  673. * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator.
  674. * Anyway, taking the beginning of the keying material from EAP
  675. * seems to interoperate with Authenticators.
  676. */
  677. key_len = rx_key_length;
  678. os_memcpy(datakey, keydata.encr_key, key_len);
  679. wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying "
  680. "material data encryption key",
  681. datakey, key_len);
  682. } else {
  683. wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d "
  684. "(key_length=%d)", key_len, rx_key_length);
  685. return;
  686. }
  687. sm->replay_counter_valid = TRUE;
  688. os_memcpy(sm->last_replay_counter, key->replay_counter,
  689. IEEE8021X_REPLAY_COUNTER_LEN);
  690. wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d "
  691. "len %d",
  692. key->key_index & IEEE8021X_KEY_INDEX_FLAG ?
  693. "unicast" : "broadcast",
  694. key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len);
  695. if (sm->ctx->set_wep_key &&
  696. sm->ctx->set_wep_key(sm->ctx->ctx,
  697. key->key_index & IEEE8021X_KEY_INDEX_FLAG,
  698. key->key_index & IEEE8021X_KEY_INDEX_MASK,
  699. datakey, key_len) < 0) {
  700. wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the "
  701. " driver.");
  702. } else {
  703. if (key->key_index & IEEE8021X_KEY_INDEX_FLAG)
  704. sm->unicast_key_received = TRUE;
  705. else
  706. sm->broadcast_key_received = TRUE;
  707. if ((sm->unicast_key_received ||
  708. !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) &&
  709. (sm->broadcast_key_received ||
  710. !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST)))
  711. {
  712. wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key "
  713. "frames received");
  714. sm->portValid = TRUE;
  715. if (sm->ctx->eapol_done_cb)
  716. sm->ctx->eapol_done_cb(sm->ctx->ctx);
  717. }
  718. }
  719. }
  720. static void eapol_sm_getSuppRsp(struct eapol_sm *sm)
  721. {
  722. wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp");
  723. /* EAP layer processing; no special code is needed, since Supplicant
  724. * Backend state machine is waiting for eapNoResp or eapResp to be set
  725. * and these are only set in the EAP state machine when the processing
  726. * has finished. */
  727. }
  728. static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
  729. {
  730. struct wpabuf *resp;
  731. wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
  732. resp = eap_get_eapRespData(sm->eap);
  733. if (resp == NULL) {
  734. wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
  735. "not available");
  736. return;
  737. }
  738. /* Send EAP-Packet from the EAP layer to the Authenticator */
  739. sm->ctx->eapol_send(sm->ctx->eapol_send_ctx,
  740. IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp),
  741. wpabuf_len(resp));
  742. /* eapRespData is not used anymore, so free it here */
  743. wpabuf_free(resp);
  744. if (sm->initial_req)
  745. sm->dot1xSuppEapolReqIdFramesRx++;
  746. else
  747. sm->dot1xSuppEapolReqFramesRx++;
  748. sm->dot1xSuppEapolRespFramesTx++;
  749. sm->dot1xSuppEapolFramesTx++;
  750. }
  751. static void eapol_sm_abortSupp(struct eapol_sm *sm)
  752. {
  753. /* release system resources that may have been allocated for the
  754. * authentication session */
  755. os_free(sm->last_rx_key);
  756. sm->last_rx_key = NULL;
  757. wpabuf_free(sm->eapReqData);
  758. sm->eapReqData = NULL;
  759. eap_sm_abort(sm->eap);
  760. }
  761. static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
  762. {
  763. eapol_sm_step(timeout_ctx);
  764. }
  765. static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
  766. {
  767. if (sm->ctx->port_cb)
  768. sm->ctx->port_cb(sm->ctx->ctx, 1);
  769. }
  770. static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
  771. {
  772. if (sm->ctx->port_cb)
  773. sm->ctx->port_cb(sm->ctx->ctx, 0);
  774. }
  775. /**
  776. * eapol_sm_step - EAPOL state machine step function
  777. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  778. *
  779. * This function is called to notify the state machine about changed external
  780. * variables. It will step through the EAPOL state machines in loop to process
  781. * all triggered state changes.
  782. */
  783. void eapol_sm_step(struct eapol_sm *sm)
  784. {
  785. int i;
  786. /* In theory, it should be ok to run this in loop until !changed.
  787. * However, it is better to use a limit on number of iterations to
  788. * allow events (e.g., SIGTERM) to stop the program cleanly if the
  789. * state machine were to generate a busy loop. */
  790. for (i = 0; i < 100; i++) {
  791. sm->changed = FALSE;
  792. SM_STEP_RUN(SUPP_PAE);
  793. SM_STEP_RUN(KEY_RX);
  794. SM_STEP_RUN(SUPP_BE);
  795. if (eap_peer_sm_step(sm->eap))
  796. sm->changed = TRUE;
  797. if (!sm->changed)
  798. break;
  799. }
  800. if (sm->changed) {
  801. /* restart EAPOL state machine step from timeout call in order
  802. * to allow other events to be processed. */
  803. eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
  804. eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm);
  805. }
  806. if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) {
  807. int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0;
  808. sm->cb_status = EAPOL_CB_IN_PROGRESS;
  809. sm->ctx->cb(sm, success, sm->ctx->cb_ctx);
  810. }
  811. }
  812. #ifdef CONFIG_CTRL_IFACE
  813. static const char *eapol_supp_pae_state(int state)
  814. {
  815. switch (state) {
  816. case SUPP_PAE_LOGOFF:
  817. return "LOGOFF";
  818. case SUPP_PAE_DISCONNECTED:
  819. return "DISCONNECTED";
  820. case SUPP_PAE_CONNECTING:
  821. return "CONNECTING";
  822. case SUPP_PAE_AUTHENTICATING:
  823. return "AUTHENTICATING";
  824. case SUPP_PAE_HELD:
  825. return "HELD";
  826. case SUPP_PAE_AUTHENTICATED:
  827. return "AUTHENTICATED";
  828. case SUPP_PAE_RESTART:
  829. return "RESTART";
  830. default:
  831. return "UNKNOWN";
  832. }
  833. }
  834. static const char *eapol_supp_be_state(int state)
  835. {
  836. switch (state) {
  837. case SUPP_BE_REQUEST:
  838. return "REQUEST";
  839. case SUPP_BE_RESPONSE:
  840. return "RESPONSE";
  841. case SUPP_BE_SUCCESS:
  842. return "SUCCESS";
  843. case SUPP_BE_FAIL:
  844. return "FAIL";
  845. case SUPP_BE_TIMEOUT:
  846. return "TIMEOUT";
  847. case SUPP_BE_IDLE:
  848. return "IDLE";
  849. case SUPP_BE_INITIALIZE:
  850. return "INITIALIZE";
  851. case SUPP_BE_RECEIVE:
  852. return "RECEIVE";
  853. default:
  854. return "UNKNOWN";
  855. }
  856. }
  857. static const char * eapol_port_status(PortStatus status)
  858. {
  859. if (status == Authorized)
  860. return "Authorized";
  861. else
  862. return "Unauthorized";
  863. }
  864. #endif /* CONFIG_CTRL_IFACE */
  865. #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
  866. static const char * eapol_port_control(PortControl ctrl)
  867. {
  868. switch (ctrl) {
  869. case Auto:
  870. return "Auto";
  871. case ForceUnauthorized:
  872. return "ForceUnauthorized";
  873. case ForceAuthorized:
  874. return "ForceAuthorized";
  875. default:
  876. return "Unknown";
  877. }
  878. }
  879. #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
  880. /**
  881. * eapol_sm_configure - Set EAPOL variables
  882. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  883. * @heldPeriod: dot1xSuppHeldPeriod
  884. * @authPeriod: dot1xSuppAuthPeriod
  885. * @startPeriod: dot1xSuppStartPeriod
  886. * @maxStart: dot1xSuppMaxStart
  887. *
  888. * Set configurable EAPOL state machine variables. Each variable can be set to
  889. * the given value or ignored if set to -1 (to set only some of the variables).
  890. */
  891. void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod,
  892. int startPeriod, int maxStart)
  893. {
  894. if (sm == NULL)
  895. return;
  896. if (heldPeriod >= 0)
  897. sm->heldPeriod = heldPeriod;
  898. if (authPeriod >= 0)
  899. sm->authPeriod = authPeriod;
  900. if (startPeriod >= 0)
  901. sm->startPeriod = startPeriod;
  902. if (maxStart >= 0)
  903. sm->maxStart = maxStart;
  904. }
  905. /**
  906. * eapol_sm_get_method_name - Get EAPOL method name
  907. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  908. * Returns: Static string containing name of current eap method or NULL
  909. */
  910. const char * eapol_sm_get_method_name(struct eapol_sm *sm)
  911. {
  912. if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED ||
  913. sm->suppPortStatus != Authorized)
  914. return NULL;
  915. return eap_sm_get_method_name(sm->eap);
  916. }
  917. #ifdef CONFIG_CTRL_IFACE
  918. /**
  919. * eapol_sm_get_status - Get EAPOL state machine status
  920. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  921. * @buf: Buffer for status information
  922. * @buflen: Maximum buffer length
  923. * @verbose: Whether to include verbose status information
  924. * Returns: Number of bytes written to buf.
  925. *
  926. * Query EAPOL state machine for status information. This function fills in a
  927. * text area with current status information from the EAPOL state machine. If
  928. * the buffer (buf) is not large enough, status information will be truncated
  929. * to fit the buffer.
  930. */
  931. int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
  932. int verbose)
  933. {
  934. int len, ret;
  935. if (sm == NULL)
  936. return 0;
  937. len = os_snprintf(buf, buflen,
  938. "Supplicant PAE state=%s\n"
  939. "suppPortStatus=%s\n",
  940. eapol_supp_pae_state(sm->SUPP_PAE_state),
  941. eapol_port_status(sm->suppPortStatus));
  942. if (len < 0 || (size_t) len >= buflen)
  943. return 0;
  944. if (verbose) {
  945. ret = os_snprintf(buf + len, buflen - len,
  946. "heldPeriod=%u\n"
  947. "authPeriod=%u\n"
  948. "startPeriod=%u\n"
  949. "maxStart=%u\n"
  950. "portControl=%s\n"
  951. "Supplicant Backend state=%s\n",
  952. sm->heldPeriod,
  953. sm->authPeriod,
  954. sm->startPeriod,
  955. sm->maxStart,
  956. eapol_port_control(sm->portControl),
  957. eapol_supp_be_state(sm->SUPP_BE_state));
  958. if (ret < 0 || (size_t) ret >= buflen - len)
  959. return len;
  960. len += ret;
  961. }
  962. len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
  963. return len;
  964. }
  965. /**
  966. * eapol_sm_get_mib - Get EAPOL state machine MIBs
  967. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  968. * @buf: Buffer for MIB information
  969. * @buflen: Maximum buffer length
  970. * Returns: Number of bytes written to buf.
  971. *
  972. * Query EAPOL state machine for MIB information. This function fills in a
  973. * text area with current MIB information from the EAPOL state machine. If
  974. * the buffer (buf) is not large enough, MIB information will be truncated to
  975. * fit the buffer.
  976. */
  977. int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen)
  978. {
  979. size_t len;
  980. int ret;
  981. if (sm == NULL)
  982. return 0;
  983. ret = os_snprintf(buf, buflen,
  984. "dot1xSuppPaeState=%d\n"
  985. "dot1xSuppHeldPeriod=%u\n"
  986. "dot1xSuppAuthPeriod=%u\n"
  987. "dot1xSuppStartPeriod=%u\n"
  988. "dot1xSuppMaxStart=%u\n"
  989. "dot1xSuppSuppControlledPortStatus=%s\n"
  990. "dot1xSuppBackendPaeState=%d\n",
  991. sm->SUPP_PAE_state,
  992. sm->heldPeriod,
  993. sm->authPeriod,
  994. sm->startPeriod,
  995. sm->maxStart,
  996. sm->suppPortStatus == Authorized ?
  997. "Authorized" : "Unauthorized",
  998. sm->SUPP_BE_state);
  999. if (ret < 0 || (size_t) ret >= buflen)
  1000. return 0;
  1001. len = ret;
  1002. ret = os_snprintf(buf + len, buflen - len,
  1003. "dot1xSuppEapolFramesRx=%u\n"
  1004. "dot1xSuppEapolFramesTx=%u\n"
  1005. "dot1xSuppEapolStartFramesTx=%u\n"
  1006. "dot1xSuppEapolLogoffFramesTx=%u\n"
  1007. "dot1xSuppEapolRespFramesTx=%u\n"
  1008. "dot1xSuppEapolReqIdFramesRx=%u\n"
  1009. "dot1xSuppEapolReqFramesRx=%u\n"
  1010. "dot1xSuppInvalidEapolFramesRx=%u\n"
  1011. "dot1xSuppEapLengthErrorFramesRx=%u\n"
  1012. "dot1xSuppLastEapolFrameVersion=%u\n"
  1013. "dot1xSuppLastEapolFrameSource=" MACSTR "\n",
  1014. sm->dot1xSuppEapolFramesRx,
  1015. sm->dot1xSuppEapolFramesTx,
  1016. sm->dot1xSuppEapolStartFramesTx,
  1017. sm->dot1xSuppEapolLogoffFramesTx,
  1018. sm->dot1xSuppEapolRespFramesTx,
  1019. sm->dot1xSuppEapolReqIdFramesRx,
  1020. sm->dot1xSuppEapolReqFramesRx,
  1021. sm->dot1xSuppInvalidEapolFramesRx,
  1022. sm->dot1xSuppEapLengthErrorFramesRx,
  1023. sm->dot1xSuppLastEapolFrameVersion,
  1024. MAC2STR(sm->dot1xSuppLastEapolFrameSource));
  1025. if (ret < 0 || (size_t) ret >= buflen - len)
  1026. return len;
  1027. len += ret;
  1028. return len;
  1029. }
  1030. #endif /* CONFIG_CTRL_IFACE */
  1031. /**
  1032. * eapol_sm_rx_eapol - Process received EAPOL frames
  1033. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1034. * @src: Source MAC address of the EAPOL packet
  1035. * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
  1036. * @len: Length of the EAPOL frame
  1037. * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine,
  1038. * -1 failure
  1039. */
  1040. int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
  1041. size_t len)
  1042. {
  1043. const struct ieee802_1x_hdr *hdr;
  1044. const struct ieee802_1x_eapol_key *key;
  1045. int data_len;
  1046. int res = 1;
  1047. size_t plen;
  1048. if (sm == NULL)
  1049. return 0;
  1050. sm->dot1xSuppEapolFramesRx++;
  1051. if (len < sizeof(*hdr)) {
  1052. sm->dot1xSuppInvalidEapolFramesRx++;
  1053. return 0;
  1054. }
  1055. hdr = (const struct ieee802_1x_hdr *) buf;
  1056. sm->dot1xSuppLastEapolFrameVersion = hdr->version;
  1057. os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN);
  1058. if (hdr->version < EAPOL_VERSION) {
  1059. /* TODO: backwards compatibility */
  1060. }
  1061. plen = be_to_host16(hdr->length);
  1062. if (plen > len - sizeof(*hdr)) {
  1063. sm->dot1xSuppEapLengthErrorFramesRx++;
  1064. return 0;
  1065. }
  1066. #ifdef CONFIG_WPS
  1067. if (sm->conf.workaround &&
  1068. plen < len - sizeof(*hdr) &&
  1069. hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
  1070. len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
  1071. const struct eap_hdr *ehdr =
  1072. (const struct eap_hdr *) (hdr + 1);
  1073. u16 elen;
  1074. elen = be_to_host16(ehdr->length);
  1075. if (elen > plen && elen <= len - sizeof(*hdr)) {
  1076. /*
  1077. * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS
  1078. * packets with too short EAPOL header length field
  1079. * (14 octets). This is fixed in firmware Ver.1.49.
  1080. * As a workaround, fix the EAPOL header based on the
  1081. * correct length in the EAP packet.
  1082. */
  1083. wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL "
  1084. "payload length based on EAP header: "
  1085. "%d -> %d", (int) plen, elen);
  1086. plen = elen;
  1087. }
  1088. }
  1089. #endif /* CONFIG_WPS */
  1090. data_len = plen + sizeof(*hdr);
  1091. switch (hdr->type) {
  1092. case IEEE802_1X_TYPE_EAP_PACKET:
  1093. if (sm->cached_pmk) {
  1094. /* Trying to use PMKSA caching, but Authenticator did
  1095. * not seem to have a matching entry. Need to restart
  1096. * EAPOL state machines.
  1097. */
  1098. eapol_sm_abort_cached(sm);
  1099. }
  1100. wpabuf_free(sm->eapReqData);
  1101. sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen);
  1102. if (sm->eapReqData) {
  1103. wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
  1104. "frame");
  1105. sm->eapolEap = TRUE;
  1106. eapol_sm_step(sm);
  1107. }
  1108. break;
  1109. case IEEE802_1X_TYPE_EAPOL_KEY:
  1110. if (plen < sizeof(*key)) {
  1111. wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key "
  1112. "frame received");
  1113. break;
  1114. }
  1115. key = (const struct ieee802_1x_eapol_key *) (hdr + 1);
  1116. if (key->type == EAPOL_KEY_TYPE_WPA ||
  1117. key->type == EAPOL_KEY_TYPE_RSN) {
  1118. /* WPA Supplicant takes care of this frame. */
  1119. wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key "
  1120. "frame in EAPOL state machines");
  1121. res = 0;
  1122. break;
  1123. }
  1124. if (key->type != EAPOL_KEY_TYPE_RC4) {
  1125. wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown "
  1126. "EAPOL-Key type %d", key->type);
  1127. break;
  1128. }
  1129. os_free(sm->last_rx_key);
  1130. sm->last_rx_key = os_malloc(data_len);
  1131. if (sm->last_rx_key) {
  1132. wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key "
  1133. "frame");
  1134. os_memcpy(sm->last_rx_key, buf, data_len);
  1135. sm->last_rx_key_len = data_len;
  1136. sm->rxKey = TRUE;
  1137. eapol_sm_step(sm);
  1138. }
  1139. break;
  1140. default:
  1141. wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d",
  1142. hdr->type);
  1143. sm->dot1xSuppInvalidEapolFramesRx++;
  1144. break;
  1145. }
  1146. return res;
  1147. }
  1148. /**
  1149. * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet
  1150. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1151. *
  1152. * Notify EAPOL state machine about transmitted EAPOL packet from an external
  1153. * component, e.g., WPA. This will update the statistics.
  1154. */
  1155. void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm)
  1156. {
  1157. if (sm)
  1158. sm->dot1xSuppEapolFramesTx++;
  1159. }
  1160. /**
  1161. * eapol_sm_notify_portEnabled - Notification about portEnabled change
  1162. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1163. * @enabled: New portEnabled value
  1164. *
  1165. * Notify EAPOL state machine about new portEnabled value.
  1166. */
  1167. void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled)
  1168. {
  1169. if (sm == NULL)
  1170. return;
  1171. wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
  1172. "portEnabled=%d", enabled);
  1173. sm->portEnabled = enabled;
  1174. eapol_sm_step(sm);
  1175. }
  1176. /**
  1177. * eapol_sm_notify_portValid - Notification about portValid change
  1178. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1179. * @valid: New portValid value
  1180. *
  1181. * Notify EAPOL state machine about new portValid value.
  1182. */
  1183. void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid)
  1184. {
  1185. if (sm == NULL)
  1186. return;
  1187. wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
  1188. "portValid=%d", valid);
  1189. sm->portValid = valid;
  1190. eapol_sm_step(sm);
  1191. }
  1192. /**
  1193. * eapol_sm_notify_eap_success - Notification of external EAP success trigger
  1194. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1195. * @success: %TRUE = set success, %FALSE = clear success
  1196. *
  1197. * Notify the EAPOL state machine that external event has forced EAP state to
  1198. * success (success = %TRUE). This can be cleared by setting success = %FALSE.
  1199. *
  1200. * This function is called to update EAP state when WPA-PSK key handshake has
  1201. * been completed successfully since WPA-PSK does not use EAP state machine.
  1202. */
  1203. void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success)
  1204. {
  1205. if (sm == NULL)
  1206. return;
  1207. wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
  1208. "EAP success=%d", success);
  1209. sm->eapSuccess = success;
  1210. sm->altAccept = success;
  1211. if (success)
  1212. eap_notify_success(sm->eap);
  1213. eapol_sm_step(sm);
  1214. }
  1215. /**
  1216. * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger
  1217. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1218. * @fail: %TRUE = set failure, %FALSE = clear failure
  1219. *
  1220. * Notify EAPOL state machine that external event has forced EAP state to
  1221. * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE.
  1222. */
  1223. void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail)
  1224. {
  1225. if (sm == NULL)
  1226. return;
  1227. wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
  1228. "EAP fail=%d", fail);
  1229. sm->eapFail = fail;
  1230. sm->altReject = fail;
  1231. eapol_sm_step(sm);
  1232. }
  1233. /**
  1234. * eapol_sm_notify_config - Notification of EAPOL configuration change
  1235. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1236. * @config: Pointer to current network EAP configuration
  1237. * @conf: Pointer to EAPOL configuration data
  1238. *
  1239. * Notify EAPOL state machine that configuration has changed. config will be
  1240. * stored as a backpointer to network configuration. This can be %NULL to clear
  1241. * the stored pointed. conf will be copied to local EAPOL/EAP configuration
  1242. * data. If conf is %NULL, this part of the configuration change will be
  1243. * skipped.
  1244. */
  1245. void eapol_sm_notify_config(struct eapol_sm *sm,
  1246. struct eap_peer_config *config,
  1247. const struct eapol_config *conf)
  1248. {
  1249. if (sm == NULL)
  1250. return;
  1251. sm->config = config;
  1252. if (conf == NULL)
  1253. return;
  1254. sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys;
  1255. sm->conf.required_keys = conf->required_keys;
  1256. sm->conf.fast_reauth = conf->fast_reauth;
  1257. sm->conf.workaround = conf->workaround;
  1258. if (sm->eap) {
  1259. eap_set_fast_reauth(sm->eap, conf->fast_reauth);
  1260. eap_set_workaround(sm->eap, conf->workaround);
  1261. eap_set_force_disabled(sm->eap, conf->eap_disabled);
  1262. }
  1263. }
  1264. /**
  1265. * eapol_sm_get_key - Get master session key (MSK) from EAP
  1266. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1267. * @key: Pointer for key buffer
  1268. * @len: Number of bytes to copy to key
  1269. * Returns: 0 on success (len of key available), maximum available key len
  1270. * (>0) if key is available but it is shorter than len, or -1 on failure.
  1271. *
  1272. * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key
  1273. * is available only after a successful authentication.
  1274. */
  1275. int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
  1276. {
  1277. const u8 *eap_key;
  1278. size_t eap_len;
  1279. if (sm == NULL || !eap_key_available(sm->eap)) {
  1280. wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
  1281. return -1;
  1282. }
  1283. eap_key = eap_get_eapKeyData(sm->eap, &eap_len);
  1284. if (eap_key == NULL) {
  1285. wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
  1286. return -1;
  1287. }
  1288. if (len > eap_len) {
  1289. wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
  1290. "available (len=%lu)",
  1291. (unsigned long) len, (unsigned long) eap_len);
  1292. return eap_len;
  1293. }
  1294. os_memcpy(key, eap_key, len);
  1295. wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)",
  1296. (unsigned long) len);
  1297. return 0;
  1298. }
  1299. /**
  1300. * eapol_sm_notify_logoff - Notification of logon/logoff commands
  1301. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1302. * @logoff: Whether command was logoff
  1303. *
  1304. * Notify EAPOL state machines that user requested logon/logoff.
  1305. */
  1306. void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff)
  1307. {
  1308. if (sm) {
  1309. sm->userLogoff = logoff;
  1310. eapol_sm_step(sm);
  1311. }
  1312. }
  1313. /**
  1314. * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching
  1315. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1316. *
  1317. * Notify EAPOL state machines that PMKSA caching was successful. This is used
  1318. * to move EAPOL and EAP state machines into authenticated/successful state.
  1319. */
  1320. void eapol_sm_notify_cached(struct eapol_sm *sm)
  1321. {
  1322. if (sm == NULL)
  1323. return;
  1324. wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
  1325. sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED;
  1326. sm->suppPortStatus = Authorized;
  1327. eapol_sm_set_port_authorized(sm);
  1328. sm->portValid = TRUE;
  1329. eap_notify_success(sm->eap);
  1330. eapol_sm_step(sm);
  1331. }
  1332. /**
  1333. * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching
  1334. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1335. * @attempt: Whether PMKSA caching is tried
  1336. *
  1337. * Notify EAPOL state machines whether PMKSA caching is used.
  1338. */
  1339. void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt)
  1340. {
  1341. if (sm == NULL)
  1342. return;
  1343. if (attempt) {
  1344. wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA");
  1345. sm->cached_pmk = TRUE;
  1346. } else {
  1347. wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA");
  1348. sm->cached_pmk = FALSE;
  1349. }
  1350. }
  1351. static void eapol_sm_abort_cached(struct eapol_sm *sm)
  1352. {
  1353. wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, "
  1354. "doing full EAP authentication");
  1355. if (sm == NULL)
  1356. return;
  1357. sm->cached_pmk = FALSE;
  1358. sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
  1359. sm->suppPortStatus = Unauthorized;
  1360. eapol_sm_set_port_unauthorized(sm);
  1361. /* Make sure we do not start sending EAPOL-Start frames first, but
  1362. * instead move to RESTART state to start EAPOL authentication. */
  1363. sm->startWhen = 3;
  1364. eapol_enable_timer_tick(sm);
  1365. if (sm->ctx->aborted_cached)
  1366. sm->ctx->aborted_cached(sm->ctx->ctx);
  1367. }
  1368. /**
  1369. * eapol_sm_register_scard_ctx - Notification of smart card context
  1370. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1371. * @ctx: Context data for smart card operations
  1372. *
  1373. * Notify EAPOL state machines of context data for smart card operations. This
  1374. * context data will be used as a parameter for scard_*() functions.
  1375. */
  1376. void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx)
  1377. {
  1378. if (sm) {
  1379. sm->ctx->scard_ctx = ctx;
  1380. eap_register_scard_ctx(sm->eap, ctx);
  1381. }
  1382. }
  1383. /**
  1384. * eapol_sm_notify_portControl - Notification of portControl changes
  1385. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1386. * @portControl: New value for portControl variable
  1387. *
  1388. * Notify EAPOL state machines that portControl variable has changed.
  1389. */
  1390. void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl)
  1391. {
  1392. if (sm == NULL)
  1393. return;
  1394. wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
  1395. "portControl=%s", eapol_port_control(portControl));
  1396. sm->portControl = portControl;
  1397. eapol_sm_step(sm);
  1398. }
  1399. /**
  1400. * eapol_sm_notify_ctrl_attached - Notification of attached monitor
  1401. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1402. *
  1403. * Notify EAPOL state machines that a monitor was attached to the control
  1404. * interface to trigger re-sending of pending requests for user input.
  1405. */
  1406. void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm)
  1407. {
  1408. if (sm == NULL)
  1409. return;
  1410. eap_sm_notify_ctrl_attached(sm->eap);
  1411. }
  1412. /**
  1413. * eapol_sm_notify_ctrl_response - Notification of received user input
  1414. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1415. *
  1416. * Notify EAPOL state machines that a control response, i.e., user
  1417. * input, was received in order to trigger retrying of a pending EAP request.
  1418. */
  1419. void eapol_sm_notify_ctrl_response(struct eapol_sm *sm)
  1420. {
  1421. if (sm == NULL)
  1422. return;
  1423. if (sm->eapReqData && !sm->eapReq) {
  1424. wpa_printf(MSG_DEBUG, "EAPOL: received control response (user "
  1425. "input) notification - retrying pending EAP "
  1426. "Request");
  1427. sm->eapolEap = TRUE;
  1428. sm->eapReq = TRUE;
  1429. eapol_sm_step(sm);
  1430. }
  1431. }
  1432. /**
  1433. * eapol_sm_request_reauth - Request reauthentication
  1434. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1435. *
  1436. * This function can be used to request EAPOL reauthentication, e.g., when the
  1437. * current PMKSA entry is nearing expiration.
  1438. */
  1439. void eapol_sm_request_reauth(struct eapol_sm *sm)
  1440. {
  1441. if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED)
  1442. return;
  1443. eapol_sm_txStart(sm);
  1444. }
  1445. /**
  1446. * eapol_sm_notify_lower_layer_success - Notification of lower layer success
  1447. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1448. * @in_eapol_sm: Whether the caller is already running inside EAPOL state
  1449. * machine loop (eapol_sm_step())
  1450. *
  1451. * Notify EAPOL (and EAP) state machines that a lower layer has detected a
  1452. * successful authentication. This is used to recover from dropped EAP-Success
  1453. * messages.
  1454. */
  1455. void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm)
  1456. {
  1457. if (sm == NULL)
  1458. return;
  1459. eap_notify_lower_layer_success(sm->eap);
  1460. if (!in_eapol_sm)
  1461. eapol_sm_step(sm);
  1462. }
  1463. /**
  1464. * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid
  1465. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1466. */
  1467. void eapol_sm_invalidate_cached_session(struct eapol_sm *sm)
  1468. {
  1469. if (sm)
  1470. eap_invalidate_cached_session(sm->eap);
  1471. }
  1472. static struct eap_peer_config * eapol_sm_get_config(void *ctx)
  1473. {
  1474. struct eapol_sm *sm = ctx;
  1475. return sm ? sm->config : NULL;
  1476. }
  1477. static struct wpabuf * eapol_sm_get_eapReqData(void *ctx)
  1478. {
  1479. struct eapol_sm *sm = ctx;
  1480. if (sm == NULL || sm->eapReqData == NULL)
  1481. return NULL;
  1482. return sm->eapReqData;
  1483. }
  1484. static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable)
  1485. {
  1486. struct eapol_sm *sm = ctx;
  1487. if (sm == NULL)
  1488. return FALSE;
  1489. switch (variable) {
  1490. case EAPOL_eapSuccess:
  1491. return sm->eapSuccess;
  1492. case EAPOL_eapRestart:
  1493. return sm->eapRestart;
  1494. case EAPOL_eapFail:
  1495. return sm->eapFail;
  1496. case EAPOL_eapResp:
  1497. return sm->eapResp;
  1498. case EAPOL_eapNoResp:
  1499. return sm->eapNoResp;
  1500. case EAPOL_eapReq:
  1501. return sm->eapReq;
  1502. case EAPOL_portEnabled:
  1503. return sm->portEnabled;
  1504. case EAPOL_altAccept:
  1505. return sm->altAccept;
  1506. case EAPOL_altReject:
  1507. return sm->altReject;
  1508. }
  1509. return FALSE;
  1510. }
  1511. static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable,
  1512. Boolean value)
  1513. {
  1514. struct eapol_sm *sm = ctx;
  1515. if (sm == NULL)
  1516. return;
  1517. switch (variable) {
  1518. case EAPOL_eapSuccess:
  1519. sm->eapSuccess = value;
  1520. break;
  1521. case EAPOL_eapRestart:
  1522. sm->eapRestart = value;
  1523. break;
  1524. case EAPOL_eapFail:
  1525. sm->eapFail = value;
  1526. break;
  1527. case EAPOL_eapResp:
  1528. sm->eapResp = value;
  1529. break;
  1530. case EAPOL_eapNoResp:
  1531. sm->eapNoResp = value;
  1532. break;
  1533. case EAPOL_eapReq:
  1534. sm->eapReq = value;
  1535. break;
  1536. case EAPOL_portEnabled:
  1537. sm->portEnabled = value;
  1538. break;
  1539. case EAPOL_altAccept:
  1540. sm->altAccept = value;
  1541. break;
  1542. case EAPOL_altReject:
  1543. sm->altReject = value;
  1544. break;
  1545. }
  1546. }
  1547. static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable)
  1548. {
  1549. struct eapol_sm *sm = ctx;
  1550. if (sm == NULL)
  1551. return 0;
  1552. switch (variable) {
  1553. case EAPOL_idleWhile:
  1554. return sm->idleWhile;
  1555. }
  1556. return 0;
  1557. }
  1558. static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable,
  1559. unsigned int value)
  1560. {
  1561. struct eapol_sm *sm = ctx;
  1562. if (sm == NULL)
  1563. return;
  1564. switch (variable) {
  1565. case EAPOL_idleWhile:
  1566. sm->idleWhile = value;
  1567. eapol_enable_timer_tick(sm);
  1568. break;
  1569. }
  1570. }
  1571. static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob)
  1572. {
  1573. #ifndef CONFIG_NO_CONFIG_BLOBS
  1574. struct eapol_sm *sm = ctx;
  1575. if (sm && sm->ctx && sm->ctx->set_config_blob)
  1576. sm->ctx->set_config_blob(sm->ctx->ctx, blob);
  1577. #endif /* CONFIG_NO_CONFIG_BLOBS */
  1578. }
  1579. static const struct wpa_config_blob *
  1580. eapol_sm_get_config_blob(void *ctx, const char *name)
  1581. {
  1582. #ifndef CONFIG_NO_CONFIG_BLOBS
  1583. struct eapol_sm *sm = ctx;
  1584. if (sm && sm->ctx && sm->ctx->get_config_blob)
  1585. return sm->ctx->get_config_blob(sm->ctx->ctx, name);
  1586. else
  1587. return NULL;
  1588. #else /* CONFIG_NO_CONFIG_BLOBS */
  1589. return NULL;
  1590. #endif /* CONFIG_NO_CONFIG_BLOBS */
  1591. }
  1592. static void eapol_sm_notify_pending(void *ctx)
  1593. {
  1594. struct eapol_sm *sm = ctx;
  1595. if (sm == NULL)
  1596. return;
  1597. if (sm->eapReqData && !sm->eapReq) {
  1598. wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP "
  1599. "state machine - retrying pending EAP Request");
  1600. sm->eapolEap = TRUE;
  1601. sm->eapReq = TRUE;
  1602. eapol_sm_step(sm);
  1603. }
  1604. }
  1605. #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
  1606. static void eapol_sm_eap_param_needed(void *ctx, const char *field,
  1607. const char *txt)
  1608. {
  1609. struct eapol_sm *sm = ctx;
  1610. wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed");
  1611. if (sm->ctx->eap_param_needed)
  1612. sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt);
  1613. }
  1614. #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
  1615. #define eapol_sm_eap_param_needed NULL
  1616. #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
  1617. static void eapol_sm_notify_cert(void *ctx, int depth, const char *subject,
  1618. const char *cert_hash,
  1619. const struct wpabuf *cert)
  1620. {
  1621. struct eapol_sm *sm = ctx;
  1622. if (sm->ctx->cert_cb)
  1623. sm->ctx->cert_cb(sm->ctx->ctx, depth, subject,
  1624. cert_hash, cert);
  1625. }
  1626. static struct eapol_callbacks eapol_cb =
  1627. {
  1628. eapol_sm_get_config,
  1629. eapol_sm_get_bool,
  1630. eapol_sm_set_bool,
  1631. eapol_sm_get_int,
  1632. eapol_sm_set_int,
  1633. eapol_sm_get_eapReqData,
  1634. eapol_sm_set_config_blob,
  1635. eapol_sm_get_config_blob,
  1636. eapol_sm_notify_pending,
  1637. eapol_sm_eap_param_needed,
  1638. eapol_sm_notify_cert
  1639. };
  1640. /**
  1641. * eapol_sm_init - Initialize EAPOL state machine
  1642. * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer
  1643. * and EAPOL state machine will free it in eapol_sm_deinit()
  1644. * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure
  1645. *
  1646. * Allocate and initialize an EAPOL state machine.
  1647. */
  1648. struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
  1649. {
  1650. struct eapol_sm *sm;
  1651. struct eap_config conf;
  1652. sm = os_zalloc(sizeof(*sm));
  1653. if (sm == NULL)
  1654. return NULL;
  1655. sm->ctx = ctx;
  1656. sm->portControl = Auto;
  1657. /* Supplicant PAE state machine */
  1658. sm->heldPeriod = 60;
  1659. sm->startPeriod = 30;
  1660. sm->maxStart = 3;
  1661. /* Supplicant Backend state machine */
  1662. sm->authPeriod = 30;
  1663. os_memset(&conf, 0, sizeof(conf));
  1664. conf.opensc_engine_path = ctx->opensc_engine_path;
  1665. conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
  1666. conf.pkcs11_module_path = ctx->pkcs11_module_path;
  1667. conf.wps = ctx->wps;
  1668. conf.cert_in_cb = ctx->cert_in_cb;
  1669. sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
  1670. if (sm->eap == NULL) {
  1671. os_free(sm);
  1672. return NULL;
  1673. }
  1674. /* Initialize EAPOL state machines */
  1675. sm->initialize = TRUE;
  1676. eapol_sm_step(sm);
  1677. sm->initialize = FALSE;
  1678. eapol_sm_step(sm);
  1679. sm->timer_tick_enabled = 1;
  1680. eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
  1681. return sm;
  1682. }
  1683. /**
  1684. * eapol_sm_deinit - Deinitialize EAPOL state machine
  1685. * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
  1686. *
  1687. * Deinitialize and free EAPOL state machine.
  1688. */
  1689. void eapol_sm_deinit(struct eapol_sm *sm)
  1690. {
  1691. if (sm == NULL)
  1692. return;
  1693. eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
  1694. eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
  1695. eap_peer_sm_deinit(sm->eap);
  1696. os_free(sm->last_rx_key);
  1697. wpabuf_free(sm->eapReqData);
  1698. os_free(sm->ctx);
  1699. os_free(sm);
  1700. }