eapol_auth_sm.c 32 KB

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