eapol_supp_sm.c 54 KB

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