<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### 一、預備知識(eap_sm、eap_method結構體) ~~~ struct eap_sm { //狀態機,存儲eap的狀態 enum { //枚舉eap的各種狀態 EAP_DISABLED, EAP_INITIALIZE, EAP_IDLE, EAP_RECEIVED, EAP_INTEGRITY_CHECK, EAP_METHOD_RESPONSE, EAP_METHOD_REQUEST, EAP_PROPOSE_METHOD, EAP_SELECT_ACTION, EAP_SEND_REQUEST, EAP_DISCARD, EAP_NAK, EAP_RETRANSMIT, EAP_SUCCESS, EAP_FAILURE, EAP_TIMEOUT_FAILURE, EAP_PICK_UP_METHOD, EAP_INITIALIZE_PASSTHROUGH, EAP_IDLE2, EAP_RETRANSMIT2, EAP_RECEIVED2, EAP_DISCARD2, EAP_SEND_REQUEST2, EAP_AAA_REQUEST, EAP_AAA_RESPONSE, EAP_AAA_IDLE, EAP_TIMEOUT_FAILURE2, EAP_FAILURE2, EAP_SUCCESS2 } EAP_state; /* Constants */ int MaxRetrans; //最大重傳次數,eap支持超時重發機制.eap_sm在初始化時賦值為5 struct eap_eapol_interface eap_if;//主要放些直接與消息相關的,如req及resp的數據,當前是req還是resp,是否到了重傳的時機(retransWhile)等 /* Full authenticator state machine local variables */ /* Long-term (maintained between packets) */ EapType currentMethod; //當前采用的Method,初始為EAP_TYPE_NONE,其后根據響應中的type定或自選 int currentId; //當前eap id,開始設為-1,作為backend_AAA時被設為響應消息eapid,需要發送eapreq的時候設為nextId enum { METHOD_PROPOSED, METHOD_CONTINUE, METHOD_END } methodState; int retransCount;//傳送次數 struct wpabuf *lastReqData;//記下已經發出的請求數據,如需要重傳時需要發此數據 int methodTimeout; /* Short-term (not maintained between packets) */ Boolean rxResp; //收到消息的id為resp時設置rxResp為TRUE int respId;//收到的resp消息的id EapType respMethod; int respVendor; u32 respVendorMethod; Boolean ignore; enum { DECISION_SUCCESS, DECISION_FAILURE, DECISION_CONTINUE, DECISION_PASSTHROUGH } decision; /* Miscellaneous variables */ const struct eap_method *m; /* selected EAP method,當前選定的eap method */ /* not defined in RFC 4137 */ Boolean changed;//狀態機是否改變,在不變時則退出狀態機運行,后續可能要發送eapreq,eapsuccess或eapfailure,或在pending時不做事情 void *eapol_ctx, *msg_ctx;//eapol_ctx:上下文信息,在狀態機初始化時指向session,之后不動;msg_ctx:尚未使用 struct eapol_callbacks *eapol_cb;//狀態機初始化時設置eapol_cb。struct eapol_callbacks為多個需要用到的回調函數如get_eap_user等組成的結構體 void *eap_method_priv;//由各個eap method定義的數據,在EAP_INITIALIZE是sm->eap_method_priv = sm->m->initPickUp(sm)?? 指向eap_identity_data //在具體EAP method階段則是具體eap_xxx_data u8 *identity; //在eap_identity_process內賦值,取自eap-resp/identity size_t identity_len; /* Whether Phase 2 method should validate identity match */ int require_identity_match; //EAP-GTC用到 int lastId; /* Identifier used in the last EAP-Packet */ struct eap_user *user; int user_eap_method_index; int init_phase2; //eap_ttls_phase2_eap_init? eap_peap_phase2_init兩個函數內設置為1 void *ssl_ctx; //在狀態機初始化eap_server_sm_init內設置為一個全局的g_ssl_context上下文。后者通過g_ssl_context = tls_init(NULL)實現初始化 struct eap_sim_db_data *eap_sim_db_priv;//指向系統配置的eap_sim/aka的配置信息,為eap_sim_db_data結構。主要含有與hlr的通信套接字信息,假名表, //重鑒權用戶信息,pending的用戶查詢等 Boolean backend_auth; //是否作為backend authentication server Boolean update_user; //sm->identity是否更新了的標志,如為true時可能需要重新獲取用戶信息 int eap_server; //是作為eapserver還是passthrough int num_rounds; //eap交互次數,最大允許EAP_MAX_AUTH_ROUNDS=50次 enum { METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT } method_pending; /*狀態機初始化時method_pending為METHOD_PENDING_NONE,因業務需要,可以將method_pending設置為METHOD_PENDING_WAIT。 eap狀態機在處理EAP_PROPOSE_METHOD或EAP_METHOD_RESPONSE時,如果為WAIT則什么不做,退出狀態機。 如果為CONT則設置method_pending = METHOD_PENDING_NONE并繼續執行EAP_METHOD_RESPONSE狀態。 eap具體method業務在收到響應等需要的時候調用eap_sm_pending_cb,他會設置method_pending為CONT,這樣再激活狀態機他會繼續執行*/ u8 *auth_challenge; u8 *peer_challenge; //均是eap-mschapv2鑒權過程中的參數,分別由server和peer生成的隨機數 u8 *pac_opaque_encr_key; u8 *eap_fast_a_id; size_t eap_fast_a_id_len; char *eap_fast_a_id_info; enum { NO_PROV, ANON_PROV, AUTH_PROV, BOTH_PROV } eap_fast_prov; int pac_key_lifetime; int pac_key_refresh_time; int eap_sim_aka_result_ind; int tnc; //以上均取自配置文件,eap server用不著這些,可以到配置文件中查看配置的這些變量的值 u16 pwd_group; struct wps_context *wps; struct wpabuf *assoc_wps_ie; struct wpabuf *assoc_p2p_ie; Boolean start_reauth; u8 peer_addr[ETH_ALEN]; /* Fragmentation size for EAP method init() handler */ int fragment_size; int pbc_in_m1; const u8 *server_id; size_t server_id_len; #ifdef CONFIG_TESTING_OPTIONS u32 tls_test_flags; #endif /* CONFIG_TESTING_OPTIONS */ }; ~~~ ~~~ struct eap_method { //這個結構體用來存放每種加密方法的各種操作函數和變量 int vendor; //存放eap vender ID EapType method; //EapType是一個枚舉類型,里面的值定義了method type const char *name; //存放method的名字,比如PSK void * (*init)(struct eap_sm *sm); //初始化eap method void * (*initPickUp)(struct eap_sm *sm); void (*reset)(struct eap_sm *sm, void *priv); struct wpabuf * (*buildReq)(struct eap_sm *sm, void *priv, u8 id); //處理一個eap request 請求包 int (*getTimeout)(struct eap_sm *sm, void *priv); Boolean (*check)(struct eap_sm *sm, void *priv, struct wpabuf *respData); void (*process)(struct eap_sm *sm, void *priv,struct wpabuf *respData); Boolean (*isDone)(struct eap_sm *sm, void *priv); u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); //從eap method中獲取秘鑰內容 Boolean (*isSuccess)(struct eap_sm *sm, void *priv); void (*free)(struct eap_method *method); //釋放eap method 數據 #define EAP_SERVER_METHOD_INTERFACE_VERSION 1 int version; //peer端EAP interface版本 struct eap_method *next; // 用于建立鏈表,指向下一個節點 u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len);//獲取擴展的秘鑰內容 }; ~~~ 上面兩個結構體封裝了很多參數和方法,顯得尤其重要,接下來,我們進入hostapd_global_init()函數。 ~~~ <span style="color:#000000;">static int hostapd_global_init(struct hapd_interfaces *interfaces,const char *entropy_file) { os_memset(&global, 0, sizeof(global));//重置global變量 hostapd_logger_register_cb(hostapd_logger_cb); if (eap_server_register_methods()) { //注冊eap server的加密方法 wpa_printf(MSG_ERROR, "Failed to register EAP methods"); return -1; } if (eloop_init()) { // wpa_printf(MSG_ERROR, "Failed to initialize event loop"); return -1; } random_init(entropy_file); #ifndef CONFIG_NATIVE_WINDOWS eloop_register_signal(SIGHUP, handle_reload, interfaces); eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); #endif /* CONFIG_NATIVE_WINDOWS */ eloop_register_signal_terminate(handle_term, interfaces); for (i = 0; wpa_drivers[i]; i++) global.drv_count++; if (global.drv_count == 0) { wpa_printf(MSG_ERROR, "No drivers enabled"); return -1; } global.drv_priv = os_calloc(global.drv_count, sizeof(void *)); if (global.drv_priv == NULL) return -1; return 0; }</span> ~~~ 1. 使用eap_server_register_methods函數注冊eap server支持的安全模式,并存放在一個鏈表里面,下圖是支持的安全模式。 ![](https://box.kancloud.cn/2016-04-15_57108d8dc08ea.jpg) ~~~ int eap_server_register_methods(void) { int ret = 0; #ifdef EAP_SERVER_IDENTITY if (ret == 0) ret = eap_server_identity_register(); #endif /* EAP_SERVER_IDENTITY */ #ifdef EAP_SERVER_MD5 if (ret == 0) ret = eap_server_md5_register(); #endif /* EAP_SERVER_MD5 */ #ifdef EAP_SERVER_TLS if (ret == 0) ret = eap_server_tls_register(); ....... ~~~ 根據宏開關來確認哪些安全模式是支持的,并調用相應協議的注冊函數,注冊一個加密安全模式放在struct eap_method鏈表中,因為這些安全模式注冊函數都差不多,所以只介紹其中一種模式eap_server_psk_register()。 ~~~ int eap_server_psk_register(void) { struct eap_method *eap; int ret; eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); if (eap == NULL) return -1; eap->init = eap_psk_init; eap->reset = eap_psk_reset; eap->buildReq = eap_psk_buildReq; eap->check = eap_psk_check; eap->process = eap_psk_process; eap->isDone = eap_psk_isDone; eap->getKey = eap_psk_getKey; eap->isSuccess = eap_psk_isSuccess; eap->get_emsk = eap_psk_get_emsk; ret = eap_server_method_register(eap); if (ret) eap_server_method_free(eap); return ret; } ~~~ 首先定義一個struct eap_method 對象,用eap_server_method_alloc給這個對象申請一塊空間,然后給這個對象根據不同的安全模式指向不同的操作函數,最后將這個eap對象通過eap_server_method_register函數添加到struct eap_method 結構體對象的鏈表里面。 2.使用eloop_init()對struct eloop_data eloop對象進行初始化,至于struct eloop_data的作用將在后面介紹。 ~~~ int eloop_init(void) { os_memset(&eloop, 0, sizeof(eloop)); dl_list_init(&eloop.timeout); #ifdef CONFIG_ELOOP_EPOLL eloop.epollfd = epoll_create1(0); if (eloop.epollfd < 0) { wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n", __func__, strerror(errno)); return -1; } eloop.readers.type = EVENT_TYPE_READ; eloop.writers.type = EVENT_TYPE_WRITE; eloop.exceptions.type = EVENT_TYPE_EXCEPTION; #endif /* CONFIG_ELOOP_EPOLL */ #ifdef WPA_TRACE signal(SIGSEGV, eloop_sigsegv_handler); #endif /* WPA_TRACE */ return 0; ~~~ 這個函數主要是重置eloop對象和初始化鏈表,然后對eloop成員的一些賦值等 3.random_init() ~~~ void random_init(const char *entropy_file) { os_free(random_entropy_file); if (entropy_file) random_entropy_file = os_strdup(entropy_file); else random_entropy_file = NULL; random_read_entropy(); #ifdef __linux__ if (random_fd >= 0) return; random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK); if (random_fd < 0) { #ifndef CONFIG_NO_STDOUT_DEBUG int error = errno; perror("open(/dev/random)"); wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", strerror(error)); #endif /* CONFIG_NO_STDOUT_DEBUG */ return; } wpa_printf(MSG_DEBUG, "random: Trying to read entropy from " "/dev/random"); eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL); #endif /* __linux__ */ random_write_entropy(); } ~~~ 這里面eloop_register_read_sock很重要,具體的需要用源代碼去深入跟蹤。 4.最后是中斷的注冊和global對像的賦值等操作。 這篇主要對初始化過程進行了介紹,功能的具體實現將在后面篇幅中講述。
                  <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>

                              哎呀哎呀视频在线观看