eapol_auth_sm.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151
  1. /*
  2. * IEEE 802.1X-2004 Authenticator - EAPOL state machine
  3. * Copyright (c) 2002-2009, 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 "eloop.h"
  11. #include "state_machine.h"
  12. #include "common/eapol_common.h"
  13. #include "eap_common/eap_defs.h"
  14. #include "eap_common/eap_common.h"
  15. #include "eap_server/eap.h"
  16. #include "eapol_auth_sm.h"
  17. #include "eapol_auth_sm_i.h"
  18. #define STATE_MACHINE_DATA struct eapol_state_machine
  19. #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
  20. #define STATE_MACHINE_ADDR sm->addr
  21. static struct eapol_callbacks eapol_cb;
  22. /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */
  23. #define setPortAuthorized() \
  24. sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1)
  25. #define setPortUnauthorized() \
  26. sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0)
  27. /* procedures */
  28. #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0)
  29. #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1)
  30. #define txReq() eapol_auth_tx_req(sm)
  31. #define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta)
  32. #define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta)
  33. #define processKey() do { } while (0)
  34. static void eapol_sm_step_run(struct eapol_state_machine *sm);
  35. static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
  36. static void eapol_auth_initialize(struct eapol_state_machine *sm);
  37. static void eapol_auth_logger(struct eapol_authenticator *eapol,
  38. const u8 *addr, eapol_logger_level level,
  39. const char *txt)
  40. {
  41. if (eapol->cb.logger == NULL)
  42. return;
  43. eapol->cb.logger(eapol->conf.ctx, addr, level, txt);
  44. }
  45. static void eapol_auth_vlogger(struct eapol_authenticator *eapol,
  46. const u8 *addr, eapol_logger_level level,
  47. const char *fmt, ...)
  48. {
  49. char *format;
  50. int maxlen;
  51. va_list ap;
  52. if (eapol->cb.logger == NULL)
  53. return;
  54. maxlen = os_strlen(fmt) + 100;
  55. format = os_malloc(maxlen);
  56. if (!format)
  57. return;
  58. va_start(ap, fmt);
  59. vsnprintf(format, maxlen, fmt, ap);
  60. va_end(ap);
  61. eapol_auth_logger(eapol, addr, level, format);
  62. os_free(format);
  63. }
  64. static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm,
  65. int success)
  66. {
  67. struct eap_hdr eap;
  68. os_memset(&eap, 0, sizeof(eap));
  69. eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
  70. eap.identifier = ++sm->last_eap_id;
  71. eap.length = host_to_be16(sizeof(eap));
  72. eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
  73. "Sending canned EAP packet %s (identifier %d)",
  74. success ? "SUCCESS" : "FAILURE", eap.identifier);
  75. sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
  76. IEEE802_1X_TYPE_EAP_PACKET,
  77. (u8 *) &eap, sizeof(eap));
  78. sm->dot1xAuthEapolFramesTx++;
  79. }
  80. static void eapol_auth_tx_req(struct eapol_state_machine *sm)
  81. {
  82. if (sm->eap_if->eapReqData == NULL ||
  83. wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) {
  84. eapol_auth_logger(sm->eapol, sm->addr,
  85. EAPOL_LOGGER_DEBUG,
  86. "TxReq called, but there is no EAP request "
  87. "from authentication server");
  88. return;
  89. }
  90. if (sm->flags & EAPOL_SM_WAIT_START) {
  91. wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR
  92. " while waiting for EAPOL-Start",
  93. MAC2STR(sm->addr));
  94. return;
  95. }
  96. sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData);
  97. eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
  98. "Sending EAP Packet (identifier %d)",
  99. sm->last_eap_id);
  100. sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
  101. IEEE802_1X_TYPE_EAP_PACKET,
  102. wpabuf_head(sm->eap_if->eapReqData),
  103. wpabuf_len(sm->eap_if->eapReqData));
  104. sm->dot1xAuthEapolFramesTx++;
  105. if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY)
  106. sm->dot1xAuthEapolReqIdFramesTx++;
  107. else
  108. sm->dot1xAuthEapolReqFramesTx++;
  109. }
  110. /**
  111. * eapol_port_timers_tick - Port Timers state machine
  112. * @eloop_ctx: struct eapol_state_machine *
  113. * @timeout_ctx: Not used
  114. *
  115. * This statemachine is implemented as a function that will be called
  116. * once a second as a registered event loop timeout.
  117. */
  118. static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
  119. {
  120. struct eapol_state_machine *state = timeout_ctx;
  121. if (state->aWhile > 0) {
  122. state->aWhile--;
  123. if (state->aWhile == 0) {
  124. wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
  125. " - aWhile --> 0",
  126. MAC2STR(state->addr));
  127. }
  128. }
  129. if (state->quietWhile > 0) {
  130. state->quietWhile--;
  131. if (state->quietWhile == 0) {
  132. wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
  133. " - quietWhile --> 0",
  134. MAC2STR(state->addr));
  135. }
  136. }
  137. if (state->reAuthWhen > 0) {
  138. state->reAuthWhen--;
  139. if (state->reAuthWhen == 0) {
  140. wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
  141. " - reAuthWhen --> 0",
  142. MAC2STR(state->addr));
  143. }
  144. }
  145. if (state->eap_if->retransWhile > 0) {
  146. state->eap_if->retransWhile--;
  147. if (state->eap_if->retransWhile == 0) {
  148. wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR
  149. " - (EAP) retransWhile --> 0",
  150. MAC2STR(state->addr));
  151. }
  152. }
  153. eapol_sm_step_run(state);
  154. eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state);
  155. }
  156. /* Authenticator PAE state machine */
  157. SM_STATE(AUTH_PAE, INITIALIZE)
  158. {
  159. SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae);
  160. sm->portMode = Auto;
  161. }
  162. SM_STATE(AUTH_PAE, DISCONNECTED)
  163. {
  164. int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE;
  165. if (sm->eapolLogoff) {
  166. if (sm->auth_pae_state == AUTH_PAE_CONNECTING)
  167. sm->authEapLogoffsWhileConnecting++;
  168. else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED)
  169. sm->authAuthEapLogoffWhileAuthenticated++;
  170. }
  171. SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae);
  172. sm->authPortStatus = Unauthorized;
  173. setPortUnauthorized();
  174. sm->reAuthCount = 0;
  175. sm->eapolLogoff = FALSE;
  176. if (!from_initialize) {
  177. sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
  178. sm->flags & EAPOL_SM_PREAUTH);
  179. }
  180. }
  181. SM_STATE(AUTH_PAE, RESTART)
  182. {
  183. if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) {
  184. if (sm->reAuthenticate)
  185. sm->authAuthReauthsWhileAuthenticated++;
  186. if (sm->eapolStart)
  187. sm->authAuthEapStartsWhileAuthenticated++;
  188. if (sm->eapolLogoff)
  189. sm->authAuthEapLogoffWhileAuthenticated++;
  190. }
  191. SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae);
  192. sm->eap_if->eapRestart = TRUE;
  193. }
  194. SM_STATE(AUTH_PAE, CONNECTING)
  195. {
  196. if (sm->auth_pae_state != AUTH_PAE_CONNECTING)
  197. sm->authEntersConnecting++;
  198. SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae);
  199. sm->reAuthenticate = FALSE;
  200. sm->reAuthCount++;
  201. }
  202. SM_STATE(AUTH_PAE, HELD)
  203. {
  204. if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail)
  205. sm->authAuthFailWhileAuthenticating++;
  206. SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae);
  207. sm->authPortStatus = Unauthorized;
  208. setPortUnauthorized();
  209. sm->quietWhile = sm->quietPeriod;
  210. sm->eapolLogoff = FALSE;
  211. eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING,
  212. "authentication failed - EAP type: %d (%s)",
  213. sm->eap_type_authsrv,
  214. eap_server_get_name(0, sm->eap_type_authsrv));
  215. if (sm->eap_type_authsrv != sm->eap_type_supp) {
  216. eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
  217. "Supplicant used different EAP type: "
  218. "%d (%s)", sm->eap_type_supp,
  219. eap_server_get_name(0, sm->eap_type_supp));
  220. }
  221. sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
  222. sm->flags & EAPOL_SM_PREAUTH);
  223. }
  224. SM_STATE(AUTH_PAE, AUTHENTICATED)
  225. {
  226. char *extra = "";
  227. if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess)
  228. sm->authAuthSuccessesWhileAuthenticating++;
  229. SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae);
  230. sm->authPortStatus = Authorized;
  231. setPortAuthorized();
  232. sm->reAuthCount = 0;
  233. if (sm->flags & EAPOL_SM_PREAUTH)
  234. extra = " (pre-authentication)";
  235. else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE)
  236. extra = " (PMKSA cache)";
  237. eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
  238. "authenticated - EAP type: %d (%s)%s",
  239. sm->eap_type_authsrv,
  240. eap_server_get_name(0, sm->eap_type_authsrv),
  241. extra);
  242. sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
  243. sm->flags & EAPOL_SM_PREAUTH);
  244. }
  245. SM_STATE(AUTH_PAE, AUTHENTICATING)
  246. {
  247. SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae);
  248. sm->eapolStart = FALSE;
  249. sm->authSuccess = FALSE;
  250. sm->authFail = FALSE;
  251. sm->authTimeout = FALSE;
  252. sm->authStart = TRUE;
  253. sm->keyRun = FALSE;
  254. sm->keyDone = FALSE;
  255. }
  256. SM_STATE(AUTH_PAE, ABORTING)
  257. {
  258. if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) {
  259. if (sm->authTimeout)
  260. sm->authAuthTimeoutsWhileAuthenticating++;
  261. if (sm->eapolStart)
  262. sm->authAuthEapStartsWhileAuthenticating++;
  263. if (sm->eapolLogoff)
  264. sm->authAuthEapLogoffWhileAuthenticating++;
  265. }
  266. SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae);
  267. sm->authAbort = TRUE;
  268. sm->keyRun = FALSE;
  269. sm->keyDone = FALSE;
  270. }
  271. SM_STATE(AUTH_PAE, FORCE_AUTH)
  272. {
  273. SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae);
  274. sm->authPortStatus = Authorized;
  275. setPortAuthorized();
  276. sm->portMode = ForceAuthorized;
  277. sm->eapolStart = FALSE;
  278. txCannedSuccess();
  279. }
  280. SM_STATE(AUTH_PAE, FORCE_UNAUTH)
  281. {
  282. SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae);
  283. sm->authPortStatus = Unauthorized;
  284. setPortUnauthorized();
  285. sm->portMode = ForceUnauthorized;
  286. sm->eapolStart = FALSE;
  287. txCannedFail();
  288. }
  289. SM_STEP(AUTH_PAE)
  290. {
  291. if ((sm->portControl == Auto && sm->portMode != sm->portControl) ||
  292. sm->initialize || !sm->eap_if->portEnabled)
  293. SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE);
  294. else if (sm->portControl == ForceAuthorized &&
  295. sm->portMode != sm->portControl &&
  296. !(sm->initialize || !sm->eap_if->portEnabled))
  297. SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH);
  298. else if (sm->portControl == ForceUnauthorized &&
  299. sm->portMode != sm->portControl &&
  300. !(sm->initialize || !sm->eap_if->portEnabled))
  301. SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH);
  302. else {
  303. switch (sm->auth_pae_state) {
  304. case AUTH_PAE_INITIALIZE:
  305. SM_ENTER(AUTH_PAE, DISCONNECTED);
  306. break;
  307. case AUTH_PAE_DISCONNECTED:
  308. SM_ENTER(AUTH_PAE, RESTART);
  309. break;
  310. case AUTH_PAE_RESTART:
  311. if (!sm->eap_if->eapRestart)
  312. SM_ENTER(AUTH_PAE, CONNECTING);
  313. break;
  314. case AUTH_PAE_HELD:
  315. if (sm->quietWhile == 0)
  316. SM_ENTER(AUTH_PAE, RESTART);
  317. break;
  318. case AUTH_PAE_CONNECTING:
  319. if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax)
  320. SM_ENTER(AUTH_PAE, DISCONNECTED);
  321. else if ((sm->eap_if->eapReq &&
  322. sm->reAuthCount <= sm->reAuthMax) ||
  323. sm->eap_if->eapSuccess || sm->eap_if->eapFail)
  324. SM_ENTER(AUTH_PAE, AUTHENTICATING);
  325. break;
  326. case AUTH_PAE_AUTHENTICATED:
  327. if (sm->eapolStart || sm->reAuthenticate)
  328. SM_ENTER(AUTH_PAE, RESTART);
  329. else if (sm->eapolLogoff || !sm->portValid)
  330. SM_ENTER(AUTH_PAE, DISCONNECTED);
  331. break;
  332. case AUTH_PAE_AUTHENTICATING:
  333. if (sm->authSuccess && sm->portValid)
  334. SM_ENTER(AUTH_PAE, AUTHENTICATED);
  335. else if (sm->authFail ||
  336. (sm->keyDone && !sm->portValid))
  337. SM_ENTER(AUTH_PAE, HELD);
  338. else if (sm->eapolStart || sm->eapolLogoff ||
  339. sm->authTimeout)
  340. SM_ENTER(AUTH_PAE, ABORTING);
  341. break;
  342. case AUTH_PAE_ABORTING:
  343. if (sm->eapolLogoff && !sm->authAbort)
  344. SM_ENTER(AUTH_PAE, DISCONNECTED);
  345. else if (!sm->eapolLogoff && !sm->authAbort)
  346. SM_ENTER(AUTH_PAE, RESTART);
  347. break;
  348. case AUTH_PAE_FORCE_AUTH:
  349. if (sm->eapolStart)
  350. SM_ENTER(AUTH_PAE, FORCE_AUTH);
  351. break;
  352. case AUTH_PAE_FORCE_UNAUTH:
  353. if (sm->eapolStart)
  354. SM_ENTER(AUTH_PAE, FORCE_UNAUTH);
  355. break;
  356. }
  357. }
  358. }
  359. /* Backend Authentication state machine */
  360. SM_STATE(BE_AUTH, INITIALIZE)
  361. {
  362. SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth);
  363. abortAuth();
  364. sm->eap_if->eapNoReq = FALSE;
  365. sm->authAbort = FALSE;
  366. }
  367. SM_STATE(BE_AUTH, REQUEST)
  368. {
  369. SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth);
  370. txReq();
  371. sm->eap_if->eapReq = FALSE;
  372. sm->backendOtherRequestsToSupplicant++;
  373. /*
  374. * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but
  375. * it looks like this would be logical thing to do there since the old
  376. * EAP response would not be valid anymore after the new EAP request
  377. * was sent out.
  378. *
  379. * A race condition has been reported, in which hostapd ended up
  380. * sending out EAP-Response/Identity as a response to the first
  381. * EAP-Request from the main EAP method. This can be avoided by
  382. * clearing eapolEap here.
  383. */
  384. sm->eapolEap = FALSE;
  385. }
  386. SM_STATE(BE_AUTH, RESPONSE)
  387. {
  388. SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth);
  389. sm->authTimeout = FALSE;
  390. sm->eapolEap = FALSE;
  391. sm->eap_if->eapNoReq = FALSE;
  392. sm->aWhile = sm->serverTimeout;
  393. sm->eap_if->eapResp = TRUE;
  394. /* sendRespToServer(); */
  395. sm->backendResponses++;
  396. }
  397. SM_STATE(BE_AUTH, SUCCESS)
  398. {
  399. SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth);
  400. txReq();
  401. sm->authSuccess = TRUE;
  402. sm->keyRun = TRUE;
  403. }
  404. SM_STATE(BE_AUTH, FAIL)
  405. {
  406. SM_ENTRY_MA(BE_AUTH, FAIL, be_auth);
  407. txReq();
  408. sm->authFail = TRUE;
  409. }
  410. SM_STATE(BE_AUTH, TIMEOUT)
  411. {
  412. SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth);
  413. sm->authTimeout = TRUE;
  414. }
  415. SM_STATE(BE_AUTH, IDLE)
  416. {
  417. SM_ENTRY_MA(BE_AUTH, IDLE, be_auth);
  418. sm->authStart = FALSE;
  419. }
  420. SM_STATE(BE_AUTH, IGNORE)
  421. {
  422. SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth);
  423. sm->eap_if->eapNoReq = FALSE;
  424. }
  425. SM_STEP(BE_AUTH)
  426. {
  427. if (sm->portControl != Auto || sm->initialize || sm->authAbort) {
  428. SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE);
  429. return;
  430. }
  431. switch (sm->be_auth_state) {
  432. case BE_AUTH_INITIALIZE:
  433. SM_ENTER(BE_AUTH, IDLE);
  434. break;
  435. case BE_AUTH_REQUEST:
  436. if (sm->eapolEap)
  437. SM_ENTER(BE_AUTH, RESPONSE);
  438. else if (sm->eap_if->eapReq)
  439. SM_ENTER(BE_AUTH, REQUEST);
  440. else if (sm->eap_if->eapTimeout)
  441. SM_ENTER(BE_AUTH, TIMEOUT);
  442. break;
  443. case BE_AUTH_RESPONSE:
  444. if (sm->eap_if->eapNoReq)
  445. SM_ENTER(BE_AUTH, IGNORE);
  446. if (sm->eap_if->eapReq) {
  447. sm->backendAccessChallenges++;
  448. SM_ENTER(BE_AUTH, REQUEST);
  449. } else if (sm->aWhile == 0)
  450. SM_ENTER(BE_AUTH, TIMEOUT);
  451. else if (sm->eap_if->eapFail) {
  452. sm->backendAuthFails++;
  453. SM_ENTER(BE_AUTH, FAIL);
  454. } else if (sm->eap_if->eapSuccess) {
  455. sm->backendAuthSuccesses++;
  456. SM_ENTER(BE_AUTH, SUCCESS);
  457. }
  458. break;
  459. case BE_AUTH_SUCCESS:
  460. SM_ENTER(BE_AUTH, IDLE);
  461. break;
  462. case BE_AUTH_FAIL:
  463. SM_ENTER(BE_AUTH, IDLE);
  464. break;
  465. case BE_AUTH_TIMEOUT:
  466. SM_ENTER(BE_AUTH, IDLE);
  467. break;
  468. case BE_AUTH_IDLE:
  469. if (sm->eap_if->eapFail && sm->authStart)
  470. SM_ENTER(BE_AUTH, FAIL);
  471. else if (sm->eap_if->eapReq && sm->authStart)
  472. SM_ENTER(BE_AUTH, REQUEST);
  473. else if (sm->eap_if->eapSuccess && sm->authStart)
  474. SM_ENTER(BE_AUTH, SUCCESS);
  475. break;
  476. case BE_AUTH_IGNORE:
  477. if (sm->eapolEap)
  478. SM_ENTER(BE_AUTH, RESPONSE);
  479. else if (sm->eap_if->eapReq)
  480. SM_ENTER(BE_AUTH, REQUEST);
  481. else if (sm->eap_if->eapTimeout)
  482. SM_ENTER(BE_AUTH, TIMEOUT);
  483. break;
  484. }
  485. }
  486. /* Reauthentication Timer state machine */
  487. SM_STATE(REAUTH_TIMER, INITIALIZE)
  488. {
  489. SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer);
  490. sm->reAuthWhen = sm->reAuthPeriod;
  491. }
  492. SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
  493. {
  494. SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
  495. sm->reAuthenticate = TRUE;
  496. sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
  497. EAPOL_AUTH_REAUTHENTICATE);
  498. }
  499. SM_STEP(REAUTH_TIMER)
  500. {
  501. if (sm->portControl != Auto || sm->initialize ||
  502. sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) {
  503. SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE);
  504. return;
  505. }
  506. switch (sm->reauth_timer_state) {
  507. case REAUTH_TIMER_INITIALIZE:
  508. if (sm->reAuthWhen == 0)
  509. SM_ENTER(REAUTH_TIMER, REAUTHENTICATE);
  510. break;
  511. case REAUTH_TIMER_REAUTHENTICATE:
  512. SM_ENTER(REAUTH_TIMER, INITIALIZE);
  513. break;
  514. }
  515. }
  516. /* Authenticator Key Transmit state machine */
  517. SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT)
  518. {
  519. SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx);
  520. }
  521. SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT)
  522. {
  523. SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx);
  524. txKey();
  525. sm->eap_if->eapKeyAvailable = FALSE;
  526. sm->keyDone = TRUE;
  527. }
  528. SM_STEP(AUTH_KEY_TX)
  529. {
  530. if (sm->initialize || sm->portControl != Auto) {
  531. SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT);
  532. return;
  533. }
  534. switch (sm->auth_key_tx_state) {
  535. case AUTH_KEY_TX_NO_KEY_TRANSMIT:
  536. if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable &&
  537. sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA))
  538. SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
  539. break;
  540. case AUTH_KEY_TX_KEY_TRANSMIT:
  541. if (!sm->keyTxEnabled || !sm->keyRun)
  542. SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT);
  543. else if (sm->eap_if->eapKeyAvailable)
  544. SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
  545. break;
  546. }
  547. }
  548. /* Key Receive state machine */
  549. SM_STATE(KEY_RX, NO_KEY_RECEIVE)
  550. {
  551. SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx);
  552. }
  553. SM_STATE(KEY_RX, KEY_RECEIVE)
  554. {
  555. SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx);
  556. processKey();
  557. sm->rxKey = FALSE;
  558. }
  559. SM_STEP(KEY_RX)
  560. {
  561. if (sm->initialize || !sm->eap_if->portEnabled) {
  562. SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE);
  563. return;
  564. }
  565. switch (sm->key_rx_state) {
  566. case KEY_RX_NO_KEY_RECEIVE:
  567. if (sm->rxKey)
  568. SM_ENTER(KEY_RX, KEY_RECEIVE);
  569. break;
  570. case KEY_RX_KEY_RECEIVE:
  571. if (sm->rxKey)
  572. SM_ENTER(KEY_RX, KEY_RECEIVE);
  573. break;
  574. }
  575. }
  576. /* Controlled Directions state machine */
  577. SM_STATE(CTRL_DIR, FORCE_BOTH)
  578. {
  579. SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir);
  580. sm->operControlledDirections = Both;
  581. }
  582. SM_STATE(CTRL_DIR, IN_OR_BOTH)
  583. {
  584. SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir);
  585. sm->operControlledDirections = sm->adminControlledDirections;
  586. }
  587. SM_STEP(CTRL_DIR)
  588. {
  589. if (sm->initialize) {
  590. SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH);
  591. return;
  592. }
  593. switch (sm->ctrl_dir_state) {
  594. case CTRL_DIR_FORCE_BOTH:
  595. if (sm->eap_if->portEnabled && sm->operEdge)
  596. SM_ENTER(CTRL_DIR, IN_OR_BOTH);
  597. break;
  598. case CTRL_DIR_IN_OR_BOTH:
  599. if (sm->operControlledDirections !=
  600. sm->adminControlledDirections)
  601. SM_ENTER(CTRL_DIR, IN_OR_BOTH);
  602. if (!sm->eap_if->portEnabled || !sm->operEdge)
  603. SM_ENTER(CTRL_DIR, FORCE_BOTH);
  604. break;
  605. }
  606. }
  607. struct eapol_state_machine *
  608. eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
  609. int flags, const struct wpabuf *assoc_wps_ie,
  610. const struct wpabuf *assoc_p2p_ie, void *sta_ctx,
  611. const char *identity, const char *radius_cui)
  612. {
  613. struct eapol_state_machine *sm;
  614. struct eap_config eap_conf;
  615. if (eapol == NULL)
  616. return NULL;
  617. sm = os_zalloc(sizeof(*sm));
  618. if (sm == NULL) {
  619. wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation "
  620. "failed");
  621. return NULL;
  622. }
  623. sm->radius_identifier = -1;
  624. os_memcpy(sm->addr, addr, ETH_ALEN);
  625. sm->flags = flags;
  626. sm->eapol = eapol;
  627. sm->sta = sta_ctx;
  628. /* Set default values for state machine constants */
  629. sm->auth_pae_state = AUTH_PAE_INITIALIZE;
  630. sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod;
  631. sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax;
  632. sm->be_auth_state = BE_AUTH_INITIALIZE;
  633. sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout;
  634. sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE;
  635. sm->reAuthPeriod = eapol->conf.eap_reauth_period;
  636. sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE;
  637. sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT;
  638. sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE;
  639. sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH;
  640. sm->portControl = Auto;
  641. if (!eapol->conf.wpa &&
  642. (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0))
  643. sm->keyTxEnabled = TRUE;
  644. else
  645. sm->keyTxEnabled = FALSE;
  646. if (eapol->conf.wpa)
  647. sm->portValid = FALSE;
  648. else
  649. sm->portValid = TRUE;
  650. os_memset(&eap_conf, 0, sizeof(eap_conf));
  651. eap_conf.eap_server = eapol->conf.eap_server;
  652. eap_conf.ssl_ctx = eapol->conf.ssl_ctx;
  653. eap_conf.msg_ctx = eapol->conf.msg_ctx;
  654. eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
  655. eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
  656. eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
  657. eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len;
  658. eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info;
  659. eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov;
  660. eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime;
  661. eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time;
  662. eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
  663. eap_conf.tnc = eapol->conf.tnc;
  664. eap_conf.wps = eapol->conf.wps;
  665. eap_conf.assoc_wps_ie = assoc_wps_ie;
  666. eap_conf.assoc_p2p_ie = assoc_p2p_ie;
  667. eap_conf.peer_addr = addr;
  668. eap_conf.fragment_size = eapol->conf.fragment_size;
  669. eap_conf.pwd_group = eapol->conf.pwd_group;
  670. eap_conf.pbc_in_m1 = eapol->conf.pbc_in_m1;
  671. sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
  672. if (sm->eap == NULL) {
  673. eapol_auth_free(sm);
  674. return NULL;
  675. }
  676. sm->eap_if = eap_get_interface(sm->eap);
  677. eapol_auth_initialize(sm);
  678. if (identity) {
  679. sm->identity = (u8 *) os_strdup(identity);
  680. if (sm->identity)
  681. sm->identity_len = os_strlen(identity);
  682. }
  683. if (radius_cui)
  684. sm->radius_cui = wpabuf_alloc_copy(radius_cui,
  685. os_strlen(radius_cui));
  686. return sm;
  687. }
  688. void eapol_auth_free(struct eapol_state_machine *sm)
  689. {
  690. if (sm == NULL)
  691. return;
  692. eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
  693. eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
  694. if (sm->eap)
  695. eap_server_sm_deinit(sm->eap);
  696. os_free(sm);
  697. }
  698. static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
  699. const u8 *addr)
  700. {
  701. return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr);
  702. }
  703. static void eapol_sm_step_run(struct eapol_state_machine *sm)
  704. {
  705. struct eapol_authenticator *eapol = sm->eapol;
  706. u8 addr[ETH_ALEN];
  707. unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer,
  708. prev_auth_key_tx, prev_key_rx, prev_ctrl_dir;
  709. int max_steps = 100;
  710. os_memcpy(addr, sm->addr, ETH_ALEN);
  711. /*
  712. * Allow EAPOL state machines to run as long as there are state
  713. * changes, but exit and return here through event loop if more than
  714. * 100 steps is needed as a precaution against infinite loops inside
  715. * eloop callback.
  716. */
  717. restart:
  718. prev_auth_pae = sm->auth_pae_state;
  719. prev_be_auth = sm->be_auth_state;
  720. prev_reauth_timer = sm->reauth_timer_state;
  721. prev_auth_key_tx = sm->auth_key_tx_state;
  722. prev_key_rx = sm->key_rx_state;
  723. prev_ctrl_dir = sm->ctrl_dir_state;
  724. SM_STEP_RUN(AUTH_PAE);
  725. if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
  726. SM_STEP_RUN(BE_AUTH);
  727. if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
  728. SM_STEP_RUN(REAUTH_TIMER);
  729. if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
  730. SM_STEP_RUN(AUTH_KEY_TX);
  731. if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
  732. SM_STEP_RUN(KEY_RX);
  733. if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr))
  734. SM_STEP_RUN(CTRL_DIR);
  735. if (prev_auth_pae != sm->auth_pae_state ||
  736. prev_be_auth != sm->be_auth_state ||
  737. prev_reauth_timer != sm->reauth_timer_state ||
  738. prev_auth_key_tx != sm->auth_key_tx_state ||
  739. prev_key_rx != sm->key_rx_state ||
  740. prev_ctrl_dir != sm->ctrl_dir_state) {
  741. if (--max_steps > 0)
  742. goto restart;
  743. /* Re-run from eloop timeout */
  744. eapol_auth_step(sm);
  745. return;
  746. }
  747. if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) {
  748. if (eap_server_sm_step(sm->eap)) {
  749. if (--max_steps > 0)
  750. goto restart;
  751. /* Re-run from eloop timeout */
  752. eapol_auth_step(sm);
  753. return;
  754. }
  755. /* TODO: find a better location for this */
  756. if (sm->eap_if->aaaEapResp) {
  757. sm->eap_if->aaaEapResp = FALSE;
  758. if (sm->eap_if->aaaEapRespData == NULL) {
  759. wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, "
  760. "but no aaaEapRespData available");
  761. return;
  762. }
  763. sm->eapol->cb.aaa_send(
  764. sm->eapol->conf.ctx, sm->sta,
  765. wpabuf_head(sm->eap_if->aaaEapRespData),
  766. wpabuf_len(sm->eap_if->aaaEapRespData));
  767. }
  768. }
  769. if (eapol_sm_sta_entry_alive(eapol, addr))
  770. sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
  771. EAPOL_AUTH_SM_CHANGE);
  772. }
  773. static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx)
  774. {
  775. struct eapol_state_machine *sm = eloop_ctx;
  776. eapol_sm_step_run(sm);
  777. }
  778. /**
  779. * eapol_auth_step - Advance EAPOL state machines
  780. * @sm: EAPOL state machine
  781. *
  782. * This function is called to advance EAPOL state machines after any change
  783. * that could affect their state.
  784. */
  785. void eapol_auth_step(struct eapol_state_machine *sm)
  786. {
  787. /*
  788. * Run eapol_sm_step_run from a registered timeout to make sure that
  789. * other possible timeouts/events are processed and to avoid long
  790. * function call chains.
  791. */
  792. eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL);
  793. }
  794. static void eapol_auth_initialize(struct eapol_state_machine *sm)
  795. {
  796. sm->initializing = TRUE;
  797. /* Initialize the state machines by asserting initialize and then
  798. * deasserting it after one step */
  799. sm->initialize = TRUE;
  800. eapol_sm_step_run(sm);
  801. sm->initialize = FALSE;
  802. eapol_sm_step_run(sm);
  803. sm->initializing = FALSE;
  804. /* Start one second tick for port timers state machine */
  805. eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
  806. eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm);
  807. }
  808. static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
  809. size_t identity_len, int phase2,
  810. struct eap_user *user)
  811. {
  812. struct eapol_state_machine *sm = ctx;
  813. return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity,
  814. identity_len, phase2, user);
  815. }
  816. static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
  817. {
  818. struct eapol_state_machine *sm = ctx;
  819. *len = sm->eapol->conf.eap_req_id_text_len;
  820. return sm->eapol->conf.eap_req_id_text;
  821. }
  822. static struct eapol_callbacks eapol_cb =
  823. {
  824. eapol_sm_get_eap_user,
  825. eapol_sm_get_eap_req_id_text
  826. };
  827. int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
  828. {
  829. if (sm == NULL || ctx == NULL || ctx != sm->eap)
  830. return -1;
  831. eap_sm_pending_cb(sm->eap);
  832. eapol_auth_step(sm);
  833. return 0;
  834. }
  835. static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
  836. struct eapol_auth_config *src)
  837. {
  838. dst->ctx = src->ctx;
  839. dst->eap_reauth_period = src->eap_reauth_period;
  840. dst->wpa = src->wpa;
  841. dst->individual_wep_key_len = src->individual_wep_key_len;
  842. dst->eap_server = src->eap_server;
  843. dst->ssl_ctx = src->ssl_ctx;
  844. dst->msg_ctx = src->msg_ctx;
  845. dst->eap_sim_db_priv = src->eap_sim_db_priv;
  846. os_free(dst->eap_req_id_text);
  847. dst->pwd_group = src->pwd_group;
  848. dst->pbc_in_m1 = src->pbc_in_m1;
  849. if (src->eap_req_id_text) {
  850. dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len);
  851. if (dst->eap_req_id_text == NULL)
  852. return -1;
  853. os_memcpy(dst->eap_req_id_text, src->eap_req_id_text,
  854. src->eap_req_id_text_len);
  855. dst->eap_req_id_text_len = src->eap_req_id_text_len;
  856. } else {
  857. dst->eap_req_id_text = NULL;
  858. dst->eap_req_id_text_len = 0;
  859. }
  860. if (src->pac_opaque_encr_key) {
  861. dst->pac_opaque_encr_key = os_malloc(16);
  862. os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
  863. 16);
  864. } else
  865. dst->pac_opaque_encr_key = NULL;
  866. if (src->eap_fast_a_id) {
  867. dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
  868. if (dst->eap_fast_a_id == NULL) {
  869. os_free(dst->eap_req_id_text);
  870. return -1;
  871. }
  872. os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
  873. src->eap_fast_a_id_len);
  874. dst->eap_fast_a_id_len = src->eap_fast_a_id_len;
  875. } else
  876. dst->eap_fast_a_id = NULL;
  877. if (src->eap_fast_a_id_info) {
  878. dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
  879. if (dst->eap_fast_a_id_info == NULL) {
  880. os_free(dst->eap_req_id_text);
  881. os_free(dst->eap_fast_a_id);
  882. return -1;
  883. }
  884. } else
  885. dst->eap_fast_a_id_info = NULL;
  886. dst->eap_fast_prov = src->eap_fast_prov;
  887. dst->pac_key_lifetime = src->pac_key_lifetime;
  888. dst->pac_key_refresh_time = src->pac_key_refresh_time;
  889. dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind;
  890. dst->tnc = src->tnc;
  891. dst->wps = src->wps;
  892. dst->fragment_size = src->fragment_size;
  893. return 0;
  894. }
  895. static void eapol_auth_conf_free(struct eapol_auth_config *conf)
  896. {
  897. os_free(conf->eap_req_id_text);
  898. conf->eap_req_id_text = NULL;
  899. os_free(conf->pac_opaque_encr_key);
  900. conf->pac_opaque_encr_key = NULL;
  901. os_free(conf->eap_fast_a_id);
  902. conf->eap_fast_a_id = NULL;
  903. os_free(conf->eap_fast_a_id_info);
  904. conf->eap_fast_a_id_info = NULL;
  905. }
  906. struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
  907. struct eapol_auth_cb *cb)
  908. {
  909. struct eapol_authenticator *eapol;
  910. eapol = os_zalloc(sizeof(*eapol));
  911. if (eapol == NULL)
  912. return NULL;
  913. if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) {
  914. os_free(eapol);
  915. return NULL;
  916. }
  917. if (conf->individual_wep_key_len > 0) {
  918. /* use key0 in individual key and key1 in broadcast key */
  919. eapol->default_wep_key_idx = 1;
  920. }
  921. eapol->cb.eapol_send = cb->eapol_send;
  922. eapol->cb.aaa_send = cb->aaa_send;
  923. eapol->cb.finished = cb->finished;
  924. eapol->cb.get_eap_user = cb->get_eap_user;
  925. eapol->cb.sta_entry_alive = cb->sta_entry_alive;
  926. eapol->cb.logger = cb->logger;
  927. eapol->cb.set_port_authorized = cb->set_port_authorized;
  928. eapol->cb.abort_auth = cb->abort_auth;
  929. eapol->cb.tx_key = cb->tx_key;
  930. eapol->cb.eapol_event = cb->eapol_event;
  931. return eapol;
  932. }
  933. void eapol_auth_deinit(struct eapol_authenticator *eapol)
  934. {
  935. if (eapol == NULL)
  936. return;
  937. eapol_auth_conf_free(&eapol->conf);
  938. os_free(eapol->default_wep_key);
  939. os_free(eapol);
  940. }