<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                同EAP模塊類似,EAPOL模塊的實現參考了另外一個規范,即IEEE 802.1X。 >[info] 注意 參考IEEE 802.1X 2004版規范的主要原因是,WPAS中EAPOL模塊也基于該版本的規范。另外,筆者比較了2004版和2010版的802.1X,發現2004版的內容組織相對清晰易讀。 在介紹802.1X前,先來看其描述的EAP和EAPOL之間的關系,如圖4-25所示。 :-: ![](https://box.kancloud.cn/729597a80d4fc618dd4aaef3c9e0332d_697x645.jpg) 圖4-25 EAP和EAPOL的關系 根據上一節對EAP SUPP SM的介紹,讀者會發現圖4-25中所示的eapResp、eapSuccess等變量就是RFC4137中定義的用于LL層和EAP SUPP SM層交互的變量。很明顯,802.1X模塊(在WPAS中,它就是EAPOL模塊)是EAP SUPP的LL層(參考圖4-22)。 另外一個可能會讓讀者感到驚奇的是,802.1X規范為EAPOL Supplicant定義了5個不同的狀態機,分別如下。 1. **Port Timers SM**:Port超時控制狀態機。Port的概念請參考3.3.7節802.1X介紹。 2. **Supplicant PAE SM**:PAE是Port Access Entitiy的縮寫。該狀態機用于維護Port的狀態。 3. **Supplicant Backend SM**:規范并沒有明示該狀態機的作用。但筆者覺得它主要用于給Authenticator發送EAPOL回復消息。 4. **The Key Receiver SM**:用于處理Key(指EAPOL-Key幀)相關流程的狀態機。 5. **The Supplicant Key Transmit SM**:該狀態機非必選項,所以WPAS未實現它。 說實話,EAPOL Supplicant定義5個狀態機確實有些復雜。主要原因是這5個狀態機相互之間都有關聯,這些關聯體現在它們可能都受同一個變量的影響,從而導致各自的狀態發生變化。例如Port Timers SM修改了一些變量后,就有可能使得其他狀態機的狀態發生變化。規范中把這些變量成為全局變量(Global Varaibles)。 **規范閱讀提示** 1. 除了SUPP包含的這五個狀態機外,規范還為Authenticator定義了四個狀態機。Authenticator也需要實現Port Timers SM和The Key Receiver SM。 2. 規范中將這些狀態機統稱為PACP(Port Access Control Protocol)State Machine。 下面,先來認識這些全局變量。 **1. EAPOL SUPP全局變量** 802.1X定義了一些全局變量,它們被多個狀態機使用。這些全局變量的定義如表4-6所示。 :-: ![](https://box.kancloud.cn/95fd0665509d05110ca5adf5bcb5e051_892x694.jpg) 表 4-6 SUPP全局變量的定義 注意,表4-6省略了部分和Authenticator相關的全局變量。另外,規范還定義了一些全局超時變量,它們將在Port Timers SM中介紹。 **2. SUPP PACP狀態機** **①、Port Timers SM** Port Timers SM(PT SM)對應的狀態切換如圖4-26所示。 PT SM的功能比較簡單,就是每一秒觸發一次以從ONE_SECOND狀態進入TICK狀態。TICK狀態的EA中,它將遞減(圖4-26中的dec函數)某些變量的值。 :-: ![](https://box.kancloud.cn/88678b70d5da4ccedab663a712dbc0b6_1013x381.jpg) 圖4-26 PT SM狀態切換 注意,PT SM在SUPP和AUTH兩端都有。所以,圖4-26中的一些變量只用于AUTH端。這些變量的含義如表4-7所示。 :-: ![](https://box.kancloud.cn/49235273816921e5f941a3204bfc9775_1260x428.jpg) 表4-7 PT SM變量 雖然規范定義了PT SM,但WPAS中,PT SM的功能并不是通過狀態機宏來實現的,而僅僅是向eloop模塊注冊了一個超時時間為1秒的函數eapol_port_timers_tick,其代碼如下所示。 **eapol_supp_sm.c::eapol_port_timers_tick** ~~~ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) { struct eapol_sm *sm = timeout_ctx; if (sm->authWhile > 0) {// 處理authWhile sm->authWhile--; if (sm->authWhile == 0) wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0"); } // 處理heldWhile,startWhen,idleWhile(idleWhile見表4-1) ...... if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) { // 重新注冊超時處理函數,相當于切換到圖4-26中的ONE_SECOND狀態 eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, sm); } else { sm->timer_tick_enabled = 0; } eapol_sm_step(sm);// 處理其他狀態機的狀態切換,此函數內容下文會介紹 } ~~~ 上述代碼中,eapol_port_timers_tick除了遞減相關變量外,最后還需要調用eapol_sm_step函數以判斷其他狀態機是否需要切換狀態。這是PT SM和其他狀態機聯動的關鍵紐帶,而這個紐帶在規范中并不能直接體現出來(規范中,PT SM只是修改某些變量,至于其他狀態機到底怎么被觸發,則沒有說明。而eapol_port_timers_tick函數修改完變量后,直接調用eapol_sm_step 函數完成了對其他狀態機的檢查)。 下面來看第二個狀態機The Key Receiver SM。 **②、The Key Receiver SM** 圖4-27所示為The Key Receiver SM(以后簡稱TKR SM)狀態切換圖。主要有兩點值得關注。 :-: ![](https://box.kancloud.cn/6858cdc9b6b71b0c2639f8db2e03c83e_495x620.jpg) 圖4-27 TKR SM狀態切換 * TKR SM包含兩個狀態。第一個是NO_KEY_RECEIVE狀態。當rxKey(boolean型變量,當Supplicant收到EAPOL Key幀后,該值為TRUE)變為TRUE時,TKR進入KEY_RECEIVE狀態。 * TKR在KEY_RECEIVE狀態時需要調用processKey函數處理EAPOL Key消息。 WPAS中,TKR的代碼也非常簡單,如下所示。 **eapol_supp_sm.c::TRK SM相關函數** ~~~ SM_STATE(KEY_RX, NO_KEY_RECEIVE) { SM_ENTRY(KEY_RX, NO_KEY_RECEIVE); } SM_STATE(KEY_RX, KEY_RECEIVE) { SM_ENTRY(KEY_RX, KEY_RECEIVE); eapol_sm_processKey(sm); // 對應圖4-27所示的processKey函數 sm->rxKey = FALSE; } SM_STEP(KEY_RX) // TKR狀態機狀態切換函數 { if (sm->initialize || !sm->portEnabled) SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); // 直接進入NO_KEY_RECEIVE狀態 switch (sm->KEY_RX_state) { case KEY_RX_UNKNOWN: break; case KEY_RX_NO_KEY_RECEIVE: if (sm->rxKey) SM_ENTER(KEY_RX, KEY_RECEIVE); break; case KEY_RX_KEY_RECEIVE: if (sm->rxKey) SM_ENTER(KEY_RX, KEY_RECEIVE); break; } } ~~~ TKR SM的代碼非常簡單,此處不詳述。下面來看PAE SM。 **③、PAE SM** PAE SM比較復雜,其狀態切換如圖4-28所示。 :-: ![](https://box.kancloud.cn/8f9604bb5caa69f0e32a6df5e7ca22df_1099x1554.jpg) 圖4-28 PAE SM狀態切換 圖4-28中涉及的變量定義見表4-8。 :-: ![](https://box.kancloud.cn/8298200f37fda3d0405dc5acb9e14e14_1057x499.jpg) 表4-8 PAE SM 變量定義 圖4-28還包括兩個函數。 * txStart:用于發送EAPOL-Start消息給Authenticator。 * txLogoff:用于發送EAPOL-Logoff消息給Authenticator。 >[info] 提示 PAE SM中的狀態雖然較多,但筆者覺得它們的劃分似乎并無涇渭分明的根據。另外,規范對它們的描述也僅是說明滿足什么條件將進入什么狀態。至于為什么劃分這么多狀態也沒有太多可參考的依據。所以,讀者也不必拘泥于求根究底了,只要把握圖4-28即可。 WPAS中,PAE SM相關的代碼也比較簡單,此處僅看LOGOFF狀態的EA,如下所示。 **eapol_supp_sm.c::SM_STATE(SUPP_PAE,LOGOFF)** ~~~ SM_STATE(SUPP_PAE, LOGOFF) // 狀態機名為SUPP_PAE,狀態名為LOGOFF { SM_ENTRY(SUPP_PAE, LOGOFF); eapol_sm_txLogoff(sm); // 對應圖4-28中的txLogoff函數 sm->logoffSent = TRUE; sm->suppPortStatus = Unauthorized; // 這個函數內部將通過Nl80211 API設置WLAN Driver的狀態 // 屬于EAPOL模塊和WPAS中其他模塊的交互處理 eapol_sm_set_port_unauthorized(sm); } ~~~ **④、Backend SM** Backend SM(BE SM)的狀態轉換如圖4-29所示。 需要介紹和BE SM相關的變量authPeriod,它和authWhile(見表4-7)有關,默認值為30秒。 :-: ![](https://box.kancloud.cn/0bbd39bdcf354b971ea21aa4225d7a5b_651x816.jpg) 圖4-29 BE SM狀態切換 BE SM包含如下幾個重要函數。 * abortSupp:停止認證工作,釋放相關的資源。 * getSuppResp:這個函數本意是用來獲取EAP Response信息的,然后用txSuppResp函數發送出去。但WPAS中,該函數沒有包括任何有實質意義的內容。 * txSuppResp:發送EAPOL-Packet包給Authenticator。 BE SM的部分代碼如下所示。 **eapol_supp_sm.c::SM_STATE(SUPP_BE,REQUEST)** ~~~ SM_STATE(SUPP_BE, REQUEST) // REQUEST狀態對應的EA { SM_ENTRY(SUPP_BE, REQUEST); sm->authWhile = 0; sm->eapReq = TRUE; eapol_sm_getSuppRsp(sm); // 此函數內部并無任何有實質意義的內容,讀者不妨自行閱讀它 } ~~~ >[info] 提示 前面幾節介紹了802.1X中SUPP PACP幾個狀態機相關的知識。相比EAP SUPP SM而言,雖然PACP狀態機的個數增加了不少,但每個狀態機包含的狀態卻少了許多,所以PACP狀態機反而容易理解。 有了理論知識后,馬上來看EAPOL SUPP模塊中的幾個重要數據結構和函數。 **3.EAPOL SUPP代碼分析** 圖4-23和圖4-24介紹了EAPOL和EAP模塊的關系,那么EAPOL和WPAS其他模塊是什么關系呢?相關數據結構如圖4-30所示。 :-: ![](https://box.kancloud.cn/e8d2b83d7d27aebde5125bcec7e58923_913x669.jpg) 圖4-30 WPAS中EAPOL/EAP模塊數據結構 由圖4-30可知,WPAS定義了一個數據結構eapol_sm來存儲和PACP狀態機相關的內容。其內部定義了三個狀態機(TKR SM、PAE SM和BE SM)各自的狀態信息(由三個狀態枚舉值表達)、相關變量等。EAPOL模塊和WPAS中重要模塊wpa_supplicant的交互接口是通過結構體eapol_ctx來定義的。EAPOL模塊通過eap變量指向EAP模塊的代表eap_sm結構體。 >[info] 提示 eapol_sm和eapol_ctx實際包含的成員變量非常多,此處僅列舉其中一部分。 雖然WPAS包括EAPOL和EAP兩個模塊,但WPAS其他模塊一般只和EAPOL模塊交互。至于EAP模塊,它的操作(例如EAP的初始化以及EAP SUPP SM的運作)則由EAPOL模塊來觸發。 **①、EAPOL模塊的初始化** 先來看EAPOL和EAP模塊的初始化函數,由wpa_supplicant_init_eapol函數完成,代碼如下所示。 **wpas_glue.c::wpa_supplicant_init_eapol** ~~~ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) { #ifdef IEEE8021X_EAPOL struct eapol_ctx *ctx; ctx = os_zalloc(sizeof(*ctx)); ...... ctx->ctx = wpa_s; ctx->msg_ctx = wpa_s; ctx->eapol_send_ctx = wpa_s; ctx->preauth = 0; ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; ctx->eapol_send = wpa_supplicant_eapol_send; ......// 其他eapol_ctx成員變量的初始化 ctx->wps = wpa_s->wps; ctx->eap_param_needed = wpa_supplicant_eap_param_needed; ctx->port_cb = wpa_supplicant_port_cb; ctx->cb = wpa_supplicant_eapol_cb; ctx->cert_cb = wpa_supplicant_cert_cb; ctx->cb_ctx = wpa_s; wpa_s->eapol = eapol_sm_init(ctx); // 初始化EAPOL模塊 ...... #endif /* IEEE8021X_EAPOL */ return 0; } ~~~ wpa_supplicant_init_eapol首先設置eapol_ctx對象,然后調用eapol_sm_init來完成EAPOL模塊的初始化。eapol_sm_init的代碼如下所示。 **eapol_supp_sm.c::eapol_sm_init** ~~~ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) { struct eapol_sm *sm; struct eap_config conf; sm = os_zalloc(sizeof(*sm)); // EAPOL對應的狀態機信息 ...... sm->ctx = ctx;// eapol_ctx是WPAS中EAPOL模塊和其他模塊交互的接口 sm->portControl = Auto; sm->heldPeriod = 60; sm->startPeriod = 30; sm->maxStart = 3; sm->authPeriod = 30; os_memset(&conf, 0, sizeof(conf)); conf.opensc_engine_path = ctx->opensc_engine_path; ...... conf.wps = ctx->wps; // 初始化EAP Supplicant SM相關資源 sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf); ...... // 先設置initialize變量為TRUE,然后初始化相關狀態 sm->initialize = TRUE; eapol_sm_step(sm); sm->initialize = FALSE; // 設置為FALSE,再初始化相關狀態 eapol_sm_step(sm); sm->timer_tick_enabled = 1; eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); return sm; } ~~~ 在eapol_sm_init代碼中: 1. 先通過調用eap_peer_sm_init初始化EAP SUPP SM相關資源。 2. 然后完成EAPOL PACP三個狀態機的初始化工作。初始化的方法很簡單,即先設置initialize為TRUE,然后執行eapol_sm_step函數(該函數代碼見下文,其主要目的是根據條件以跳轉到下一個狀態。initialize為TRUE時,將觸發一些狀態的EA被調用,從而某些變量的初值將被設定)。然后設置initialize為FALSE后,再度執行eapol_sm_step函數(這樣,對應狀態的EA也將被執行,從而剩余變量的初值將被設定)。 3. 最后通過注冊一個eloop超時任務實現了PT SM。 **②、狀態機的聯動** 根據前面的介紹,EAPOL和EAP一共有四個狀態機,它們到底是怎么聯動的呢?答案就在eapol_sm_step中。eapol_sm_step的代碼如下所示。 **eapol_supp_sm.c::eapol_sm_step** ~~~ void eapol_sm_step(struct eapol_sm *sm) { int i; /* 筆者一直很好奇EAPOL和EAP中的四個狀態機是怎么聯動的。通過下面的代碼可知, 根據EAPOL和EAP的關系,首先要運行EAPOL中的三個狀態機(Port Timers SM由eloop定時任務 來實現),分別是SUPP_PAE、KEY_RX和SUPP_BE。然后執行EAP SUPP SM。如果changed變量 為TRUE,表示狀態發生了切換。由于每個狀態對應的EA又有可能改變其中一些變量從而引起其他狀 態機狀態發生變化,所以,這里有一個for語句來循環處理狀態切換,直到四個狀態機都沒有狀態切 換為止。一般情況下,for循環應該是一個無限循環,但此次通過100來控制循環次數,是為了防止 某些情況下狀態機陷入死循環而不能退出(這也說明規范中定義的SM在聯動時可能有邏輯錯誤)。 */ for (i = 0; i < 100; i++) { sm->changed = FALSE; SM_STEP_RUN(SUPP_PAE); SM_STEP_RUN(KEY_RX); SM_STEP_RUN(SUPP_BE); if (eap_peer_sm_step(sm->eap)) // eap_peer_sm_step返回非零,表示狀態有變化 sm->changed = TRUE; if (!sm->changed) break; // 如果沒有狀態變化,則跳出循環 } /* 運行超過100次,需要重新啟動EAPOL模塊狀態機運行,eapol_sm_step_timeout將重新調用 eapol_sm_step函數。 */ if (sm->changed) { eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm); } /* cb_status是一個枚舉類型的變量,可取值有EAPOL_CB_IN_PROGRESS, EAPOL_CB_SUCCESS和 EAPOL_CB_FAILURE。 */ if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) { int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0; /* 該值在PAE AUTHENTICATED狀態中被置為EAPOL_CB_SUCCESS,表示認證成功。在PAE HELD狀態被置為EAPOL_CB_FAILURE,表示認證還未成功。 */ sm->cb_status = EAPOL_CB_IN_PROGRESS; // 回調通知WPAS,真實的函數是wpa_supplicant_eapol_cb,這個函數以后介紹 sm->ctx->cb(sm, success, sm->ctx->cb_ctx); } } ~~~ WPAS中狀態機聯動代碼的實現非常巧妙,它通過循環來處理各個狀態機的狀態變換,直到四個狀態機都穩定為止。 >[info] 注意 初始化結束后,各個狀態機的狀態為:SUPP_PAE為DISCONNECTED狀態、KEY_RX為NO_KEY_RECEIVE狀態、SUPP_BE為IDLE狀態、EAP_SM為DISABLED狀態。 至此,對FRC4137和IEEE 802.1X-2004協議中EAP Supplicant和EAPOL Supplicant涉及的狀態機進行了詳細介紹。 在具體實現中,WPAS實現的EAPOL和EAP狀態機較為嚴格得遵循了這兩個文檔。所以,讀者只要理解了協議中的狀態切換和相關變量,則能輕松理解WPAS的實現。反之,如果僅單純從代碼入手,EAPOL/EAP狀態機的代碼將會非常難以理解。 關于EAPOL/EAP狀態機相關的知識就介紹到這,以后碰到具體代碼時,讀者根據狀態切換圖直接進入某個狀態中去看其處理函數(即EA)。 >[info] 提示 本章第二條分析路線使用的目標AP采用WPA2-PSK作為認證算法,故后續章節不會涉及太多和EAPOL及EAP相關的代碼分析。感興趣的讀者可在本節基礎上,自行搭建RAIDUS服務器來研究WPAS中EAPOL/EAP的工作過程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看