📄 eapol_supp_sm.c
字号:
}static const char *eapol_supp_be_state(int state){ switch (state) { case SUPP_BE_REQUEST: return "REQUEST"; case SUPP_BE_RESPONSE: return "RESPONSE"; case SUPP_BE_SUCCESS: return "SUCCESS"; case SUPP_BE_FAIL: return "FAIL"; case SUPP_BE_TIMEOUT: return "TIMEOUT"; case SUPP_BE_IDLE: return "IDLE"; case SUPP_BE_INITIALIZE: return "INITIALIZE"; case SUPP_BE_RECEIVE: return "RECEIVE"; default: return "UNKNOWN"; }}static const char * eapol_port_status(PortStatus status){ if (status == Authorized) return "Authorized"; else return "Unauthorized";}#endif /* CONFIG_CTRL_IFACE */#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)static const char * eapol_port_control(PortControl ctrl){ switch (ctrl) { case Auto: return "Auto"; case ForceUnauthorized: return "ForceUnauthorized"; case ForceAuthorized: return "ForceAuthorized"; default: return "Unknown"; }}#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG *//** * eapol_sm_configure - Set EAPOL variables * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @heldPeriod: dot1xSuppHeldPeriod * @authPeriod: dot1xSuppAuthPeriod * @startPeriod: dot1xSuppStartPeriod * @maxStart: dot1xSuppMaxStart * * Set configurable EAPOL state machine variables. Each variable can be set to * the given value or ignored if set to -1 (to set only some of the variables). */void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, int startPeriod, int maxStart){ if (sm == NULL) return; if (heldPeriod >= 0) sm->heldPeriod = heldPeriod; if (authPeriod >= 0) sm->authPeriod = authPeriod; if (startPeriod >= 0) sm->startPeriod = startPeriod; if (maxStart >= 0) sm->maxStart = maxStart;}#ifdef CONFIG_CTRL_IFACE/** * eapol_sm_get_status - Get EAPOL state machine status * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @buf: Buffer for status information * @buflen: Maximum buffer length * @verbose: Whether to include verbose status information * Returns: Number of bytes written to buf. * * Query EAPOL state machine for status information. This function fills in a * text area with current status information from the EAPOL state machine. If * the buffer (buf) is not large enough, status information will be truncated * to fit the buffer. */int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, int verbose){ int len, ret; if (sm == NULL) return 0; len = os_snprintf(buf, buflen, "Supplicant PAE state=%s\n" "suppPortStatus=%s\n", eapol_supp_pae_state(sm->SUPP_PAE_state), eapol_port_status(sm->suppPortStatus)); if (len < 0 || (size_t) len >= buflen) return 0; if (verbose) { ret = os_snprintf(buf + len, buflen - len, "heldPeriod=%u\n" "authPeriod=%u\n" "startPeriod=%u\n" "maxStart=%u\n" "portControl=%s\n" "Supplicant Backend state=%s\n", sm->heldPeriod, sm->authPeriod, sm->startPeriod, sm->maxStart, eapol_port_control(sm->portControl), eapol_supp_be_state(sm->SUPP_BE_state)); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; } len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose); return len;}/** * eapol_sm_get_mib - Get EAPOL state machine MIBs * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @buf: Buffer for MIB information * @buflen: Maximum buffer length * Returns: Number of bytes written to buf. * * Query EAPOL state machine for MIB information. This function fills in a * text area with current MIB information from the EAPOL state machine. If * the buffer (buf) is not large enough, MIB information will be truncated to * fit the buffer. */int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen){ size_t len; int ret; if (sm == NULL) return 0; ret = os_snprintf(buf, buflen, "dot1xSuppPaeState=%d\n" "dot1xSuppHeldPeriod=%u\n" "dot1xSuppAuthPeriod=%u\n" "dot1xSuppStartPeriod=%u\n" "dot1xSuppMaxStart=%u\n" "dot1xSuppSuppControlledPortStatus=%s\n" "dot1xSuppBackendPaeState=%d\n", sm->SUPP_PAE_state, sm->heldPeriod, sm->authPeriod, sm->startPeriod, sm->maxStart, sm->suppPortStatus == Authorized ? "Authorized" : "Unauthorized", sm->SUPP_BE_state); if (ret < 0 || (size_t) ret >= buflen) return 0; len = ret; ret = os_snprintf(buf + len, buflen - len, "dot1xSuppEapolFramesRx=%u\n" "dot1xSuppEapolFramesTx=%u\n" "dot1xSuppEapolStartFramesTx=%u\n" "dot1xSuppEapolLogoffFramesTx=%u\n" "dot1xSuppEapolRespFramesTx=%u\n" "dot1xSuppEapolReqIdFramesRx=%u\n" "dot1xSuppEapolReqFramesRx=%u\n" "dot1xSuppInvalidEapolFramesRx=%u\n" "dot1xSuppEapLengthErrorFramesRx=%u\n" "dot1xSuppLastEapolFrameVersion=%u\n" "dot1xSuppLastEapolFrameSource=" MACSTR "\n", sm->dot1xSuppEapolFramesRx, sm->dot1xSuppEapolFramesTx, sm->dot1xSuppEapolStartFramesTx, sm->dot1xSuppEapolLogoffFramesTx, sm->dot1xSuppEapolRespFramesTx, sm->dot1xSuppEapolReqIdFramesRx, sm->dot1xSuppEapolReqFramesRx, sm->dot1xSuppInvalidEapolFramesRx, sm->dot1xSuppEapLengthErrorFramesRx, sm->dot1xSuppLastEapolFrameVersion, MAC2STR(sm->dot1xSuppLastEapolFrameSource)); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; return len;}#endif /* CONFIG_CTRL_IFACE *//** * eapol_sm_rx_eapol - Process received EAPOL frames * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @src: Source MAC address of the EAPOL packet * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) * @len: Length of the EAPOL frame * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine, * -1 failure */int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, size_t len){ const struct ieee802_1x_hdr *hdr; const struct ieee802_1x_eapol_key *key; int data_len; int res = 1; size_t plen; if (sm == NULL) return 0; sm->dot1xSuppEapolFramesRx++; if (len < sizeof(*hdr)) { sm->dot1xSuppInvalidEapolFramesRx++; return 0; } hdr = (const struct ieee802_1x_hdr *) buf; sm->dot1xSuppLastEapolFrameVersion = hdr->version; os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN); if (hdr->version < EAPOL_VERSION) { /* TODO: backwards compatibility */ } plen = be_to_host16(hdr->length); if (plen > len - sizeof(*hdr)) { sm->dot1xSuppEapLengthErrorFramesRx++; return 0; } data_len = plen + sizeof(*hdr); switch (hdr->type) { case IEEE802_1X_TYPE_EAP_PACKET: if (sm->cached_pmk) { /* Trying to use PMKSA caching, but Authenticator did * not seem to have a matching entry. Need to restart * EAPOL state machines. */ eapol_sm_abort_cached(sm); } wpabuf_free(sm->eapReqData); sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen); if (sm->eapReqData) { wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " "frame"); sm->eapolEap = TRUE; eapol_sm_step(sm); } break; case IEEE802_1X_TYPE_EAPOL_KEY: if (plen < sizeof(*key)) { wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " "frame received"); break; } key = (const struct ieee802_1x_eapol_key *) (hdr + 1); if (key->type == EAPOL_KEY_TYPE_WPA || key->type == EAPOL_KEY_TYPE_RSN) { /* WPA Supplicant takes care of this frame. */ wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " "frame in EAPOL state machines"); res = 0; break; } if (key->type != EAPOL_KEY_TYPE_RC4) { wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " "EAPOL-Key type %d", key->type); break; } os_free(sm->last_rx_key); sm->last_rx_key = os_malloc(data_len); if (sm->last_rx_key) { wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " "frame"); os_memcpy(sm->last_rx_key, buf, data_len); sm->last_rx_key_len = data_len; sm->rxKey = TRUE; eapol_sm_step(sm); } break; default: wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", hdr->type); sm->dot1xSuppInvalidEapolFramesRx++; break; } return res;}/** * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * * Notify EAPOL state machine about transmitted EAPOL packet from an external * component, e.g., WPA. This will update the statistics. */void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm){ if (sm) sm->dot1xSuppEapolFramesTx++;}/** * eapol_sm_notify_portEnabled - Notification about portEnabled change * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @enabled: New portEnabled value * * Notify EAPOL state machine about new portEnabled value. */void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled){ if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: External notification - " "portEnabled=%d", enabled); sm->portEnabled = enabled; eapol_sm_step(sm);}/** * eapol_sm_notify_portValid - Notification about portValid change * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @valid: New portValid value * * Notify EAPOL state machine about new portValid value. */void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid){ if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: External notification - " "portValid=%d", valid); sm->portValid = valid; eapol_sm_step(sm);}/** * eapol_sm_notify_eap_success - Notification of external EAP success trigger * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @success: %TRUE = set success, %FALSE = clear success * * Notify the EAPOL state machine that external event has forced EAP state to * success (success = %TRUE). This can be cleared by setting success = %FALSE. * * This function is called to update EAP state when WPA-PSK key handshake has * been completed successfully since WPA-PSK does not use EAP state machine. */void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success){ if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: External notification - " "EAP success=%d", success); sm->eapSuccess = success; sm->altAccept = success; if (success) eap_notify_success(sm->eap); eapol_sm_step(sm);}/** * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @fail: %TRUE = set failure, %FALSE = clear failure * * Notify EAPOL state machine that external event has forced EAP state to * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE. */void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail){ if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: External notification - " "EAP fail=%d", fail); sm->eapFail = fail; sm->altReject = fail; eapol_sm_step(sm);}/** * eapol_sm_notify_config - Notification of EAPOL configuration change * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @config: Pointer to current network EAP configuration * @conf: Pointer to EAPOL configuration data * * Notify EAPOL state machine that configuration has changed. config will be * stored as a backpointer to network configuration. This can be %NULL to clear * the stored pointed. conf will be copied to local EAPOL/EAP configuration * data. If conf is %NULL, this part of the configuration change will be * skipped. */void eapol_sm_notify_config(struct eapol_sm *sm, struct eap_peer_config *config, const struct eapol_config *conf){ if (sm == NULL) return; sm->config = config; if (conf == NULL) return; sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys; sm->conf.required_keys = conf->required_keys; sm->conf.fast_reauth = conf->fast_reauth; if (sm->eap) { eap_set_fast_reauth(sm->eap, conf->fast_reauth); eap_set_workaround(sm->eap, conf->workaround); eap_set_force_disabled(sm->eap, conf->eap_disabled); }}/** * eapol_sm_get_key - Get master session key (MSK) from EAP * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @key: Pointer for key buffer * @len: Number of bytes to copy to key * Returns: 0 on success (len of key available), maximum available key len * (>0) if key is available but it is shorter than len, or -1 on failure. * * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key * is available only after a successful authentication. */int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len){ const u8 *eap_key; size_t eap_len; if (sm == NULL || !eap_key_available(sm->eap)) { wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); return -1; } eap_key = eap_get_eapKeyData(sm->eap, &eap_len); if (eap_key == NULL) { wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData"); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -