📄 ieee802_1x.c
字号:
if (c >= 32 && c < 127) fprintf(f, "%c", c); else fprintf(f, "<%02x>", c);}void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta){ struct eapol_state_machine *sm = sta->eapol_sm; if (sm == NULL) return; fprintf(f, "%sIEEE 802.1X:\n", prefix); if (sm->identity) { size_t i; fprintf(f, "%sidentity=", prefix); for (i = 0; i < sm->identity_len; i++) fprint_char(f, sm->identity[i]); fprintf(f, "\n"); } fprintf(f, "%scached_packets=%s%s%s\n", prefix, sm->last_recv_radius ? "[RX RADIUS]" : "", sm->last_eap_radius ? "[EAP RADIUS]" : "", sm->last_eap_supp ? "[EAP SUPPLICANT]" : ""); eapol_sm_dump_state(f, prefix, sm);}#endif /* HOSTAPD_DUMP_STATE */static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd){ if (hapd->conf->default_wep_key_len < 1) return 0; free(hapd->default_wep_key); hapd->default_wep_key = malloc(hapd->conf->default_wep_key_len); if (hapd->default_wep_key == NULL || hostapd_get_rand(hapd->default_wep_key, hapd->conf->default_wep_key_len)) { printf("Could not generate random WEP key.\n"); free(hapd->default_wep_key); hapd->default_wep_key = NULL; return -1; } wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", hapd->default_wep_key, hapd->conf->default_wep_key_len); return 0;}static int ieee802_1x_sta_key_available(struct hostapd_data *hapd, struct sta_info *sta, void *ctx){ if (sta->eapol_sm) { sta->eapol_sm->keyAvailable = TRUE; eapol_sm_step(sta->eapol_sm); } return 0;}static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx){ struct hostapd_data *hapd = eloop_ctx; if (hapd->default_wep_key_idx >= 3) hapd->default_wep_key_idx = hapd->conf->individual_wep_key_len > 0 ? 1 : 0; else hapd->default_wep_key_idx++; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: New default WEP " "key index %d\n", hapd->default_wep_key_idx); if (ieee802_1x_rekey_broadcast(hapd)) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_WARNING, "failed to generate a " "new broadcast key"); free(hapd->default_wep_key); hapd->default_wep_key = NULL; return; } /* TODO: Could setup key for RX here, but change default TX keyid only * after new broadcast key has been sent to all stations. */ if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP", NULL, hapd->default_wep_key_idx, hapd->default_wep_key, hapd->conf->default_wep_key_len, 1)) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_WARNING, "failed to configure a " "new broadcast key"); free(hapd->default_wep_key); hapd->default_wep_key = NULL; return; } ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL); if (hapd->conf->wep_rekeying_period > 0) { eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, ieee802_1x_rekey, hapd, NULL); }}int ieee802_1x_init(struct hostapd_data *hapd){ int i; if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1)) return -1; if (radius_client_register(hapd->radius, RADIUS_AUTH, ieee802_1x_receive_auth, hapd)) return -1; if (hapd->conf->default_wep_key_len) { for (i = 0; i < 4; i++) hostapd_set_encryption(hapd->conf->iface, hapd, "none", NULL, i, NULL, 0, 0); ieee802_1x_rekey(hapd, NULL); if (hapd->default_wep_key == NULL) return -1; } return 0;}void ieee802_1x_deinit(struct hostapd_data *hapd){ if (hapd->driver != NULL && (hapd->conf->ieee802_1x || hapd->conf->wpa)) hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0);}static void ieee802_1x_new_auth_session(struct hostapd_data *hapd, struct sta_info *sta){ struct eapol_state_machine *sm = sta->eapol_sm; if (sm == NULL) return; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: station " MACSTR " - new auth session, " "clearing State\n", MAC2STR(sta->addr)); if (sm->last_recv_radius) { radius_msg_free(sm->last_recv_radius); free(sm->last_recv_radius); sm->last_recv_radius = NULL; } sm->eapSuccess = FALSE; sm->eapFail = FALSE;}int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, u8 *buf, size_t len, int ack){ struct ieee80211_hdr *hdr; struct ieee802_1x_hdr *xhdr; struct ieee802_1x_eapol_key *key; u8 *pos; if (sta == NULL) return -1; if (len < sizeof(*hdr) + sizeof(rfc1042_header) + 2 + sizeof(*xhdr)) return 0; hdr = (struct ieee80211_hdr *) buf; pos = (u8 *) (hdr + 1); if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) return 0; pos += sizeof(rfc1042_header); if (((pos[0] << 8) | pos[1]) != ETH_P_PAE) return 0; pos += 2; xhdr = (struct ieee802_1x_hdr *) pos; pos += sizeof(*xhdr); HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: " MACSTR " TX status - version=%d type=%d length=%d - ack=%d\n", MAC2STR(sta->addr), xhdr->version, xhdr->type, ntohs(xhdr->length), ack); /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant * or Authenticator state machines, but EAPOL-Key packets are not * retransmitted in case of failure. Try to re-sent failed EAPOL-Key * packets couple of times because otherwise STA keys become * unsynchronized with AP. */ if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack && pos + sizeof(*key) <= buf + len) { key = (struct ieee802_1x_eapol_key *) pos; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " "frame (%scast index=%d)", key->key_index & BIT(7) ? "uni" : "broad", key->key_index & ~BIT(7)); /* TODO: re-send EAPOL-Key couple of times (with short delay * between them?). If all attempt fail, report error and * deauthenticate STA so that it will get new keys when * authenticating again (e.g., after returning in range). * Separate limit/transmit state needed both for unicast and * broadcast keys(?) */ } /* TODO: could move unicast key configuration from ieee802_1x_tx_key() * to here and change the key only if the EAPOL-Key packet was Acked. */ return 1;}u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len){ if (sm == NULL || sm->identity == NULL) return NULL; *len = sm->identity_len; return sm->identity;}u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, int idx){ if (sm == NULL || sm->radius_class.attr == NULL || idx >= sm->radius_class.count) return NULL; *len = sm->radius_class.attr[idx].len; return sm->radius_class.attr[idx].data;}u8 * ieee802_1x_get_key_crypt(struct eapol_state_machine *sm, size_t *len){ if (sm == NULL) return NULL; *len = sm->eapol_key_crypt_len; return sm->eapol_key_crypt;}void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, int enabled){ if (sm == NULL) return; sm->portEnabled = enabled ? TRUE : FALSE; eapol_sm_step(sm);}void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, int valid){ if (sm == NULL) return; sm->portValid = valid ? TRUE : FALSE; eapol_sm_step(sm);}void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth){ if (sm == NULL) return; if (pre_auth) sm->flags |= EAPOL_SM_PREAUTH; else sm->flags &= ~EAPOL_SM_PREAUTH;}static const char * bool_txt(Boolean bool){ return bool ? "TRUE" : "FALSE";}int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen){ /* TODO */ return 0;}int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, char *buf, size_t buflen){ int len = 0; struct eapol_state_machine *sm = sta->eapol_sm; if (sm == NULL) return 0; len += snprintf(buf + len, buflen - len, "dot1xPaePortNumber=%d\n" "dot1xPaePortProtocolVersion=%d\n" "dot1xPaePortCapabilities=1\n" "dot1xPaePortInitialize=%d\n" "dot1xPaePortReauthenticate=FALSE\n", sta->aid, EAPOL_VERSION, sm->initialize); /* dot1xAuthConfigTable */ len += snprintf(buf + len, buflen - len, "dot1xAuthPaeState=%d\n" "dot1xAuthBackendAuthState=%d\n" "dot1xAuthAdminControlledDirections=%d\n" "dot1xAuthOperControlledDirections=%d\n" "dot1xAuthAuthControlledPortStatus=%d\n" "dot1xAuthAuthControlledPortControl=%d\n" "dot1xAuthQuietPeriod=%u\n" "dot1xAuthServerTimeout=%u\n" "dot1xAuthReAuthPeriod=%u\n" "dot1xAuthReAuthEnabled=%s\n" "dot1xAuthKeyTxEnabled=%s\n", sm->auth_pae_state + 1, sm->be_auth_state + 1, sm->adminControlledDirections, sm->operControlledDirections, sm->authPortStatus, sm->portControl, sm->quietPeriod, sm->serverTimeout, sm->reAuthPeriod, bool_txt(sm->reAuthEnabled), bool_txt(sm->keyTxEnabled)); /* dot1xAuthStatsTable */ len += snprintf(buf + len, buflen - len, "dot1xAuthEapolFramesRx=%u\n" "dot1xAuthEapolFramesTx=%u\n" "dot1xAuthEapolStartFramesRx=%u\n" "dot1xAuthEapolLogoffFramesRx=%u\n" "dot1xAuthEapolRespIdFramesRx=%u\n" "dot1xAuthEapolRespFramesRx=%u\n" "dot1xAuthEapolReqIdFramesTx=%u\n" "dot1xAuthEapolReqFramesTx=%u\n" "dot1xAuthInvalidEapolFramesRx=%u\n" "dot1xAuthEapLengthErrorFramesRx=%u\n" "dot1xAuthLastEapolFrameVersion=%u\n" "dot1xAuthLastEapolFrameSource=" MACSTR "\n", sm->dot1xAuthEapolFramesRx, sm->dot1xAuthEapolFramesTx, sm->dot1xAuthEapolStartFramesRx, sm->dot1xAuthEapolLogoffFramesRx, sm->dot1xAuthEapolRespIdFramesRx, sm->dot1xAuthEapolRespFramesRx, sm->dot1xAuthEapolReqIdFramesTx, sm->dot1xAuthEapolReqFramesTx, sm->dot1xAuthInvalidEapolFramesRx, sm->dot1xAuthEapLengthErrorFramesRx, sm->dot1xAuthLastEapolFrameVersion, MAC2STR(sm->addr)); /* dot1xAuthDiagTable */ len += snprintf(buf + len, buflen - len, "dot1xAuthEntersConnecting=%u\n" "dot1xAuthEapLogoffsWhileConnecting=%u\n" "dot1xAuthEntersAuthenticating=%u\n" "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n" "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n" "dot1xAuthAuthFailWhileAuthenticating=%u\n" "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n" "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n" "dot1xAuthAuthReauthsWhileAuthenticated=%u\n" "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n" "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n" "dot1xAuthBackendResponses=%u\n" "dot1xAuthBackendAccessChallenges=%u\n" "dot1xAuthBackendOtherRequestsToSupplicant=%u\n" "dot1xAuthBackendAuthSuccesses=%u\n" "dot1xAuthBackendAuthFails=%u\n", sm->authEntersConnecting, sm->authEapLogoffsWhileConnecting, sm->authEntersAuthenticating, sm->authAuthSuccessesWhileAuthenticating, sm->authAuthTimeoutsWhileAuthenticating, sm->authAuthFailWhileAuthenticating, sm->authAuthEapStartsWhileAuthenticating, sm->authAuthEapLogoffWhileAuthenticating, sm->authAuthReauthsWhileAuthenticated, sm->authAuthEapStartsWhileAuthenticated, sm->authAuthEapLogoffWhileAuthenticated, sm->backendResponses, sm->backendAccessChallenges, sm->backendOtherRequestsToSupplicant, sm->backendAuthSuccesses, sm->backendAuthFails); /* dot1xAuthSessionStatsTable */ len += snprintf(buf + len, buflen - len, /* TODO: dot1xAuthSessionOctetsRx */ /* TODO: dot1xAuthSessionOctetsTx */ /* TODO: dot1xAuthSessionFramesRx */ /* TODO: dot1xAuthSessionFramesTx */ "dot1xAuthSessionId=%08X-%08X\n" "dot1xAuthSessionAuthenticMethod=%d\n" "dot1xAuthSessionTime=%u\n" "dot1xAuthSessionTerminateCause=999\n" "dot1xAuthSessionUserName=%s\n", sta->acct_session_id_hi, sta->acct_session_id_lo, wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_IEEE8021X ? 1 : 2, (unsigned int) (time(NULL) - sta->acct_session_start), sm->identity); return len;}void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, int success){ u8 *key; size_t len; /* TODO: get PMKLifetime from WPA parameters */ static const int dot11RSNAConfigPMKLifetime = 43200; key = ieee802_1x_get_key_crypt(sta->eapol_sm, &len); if (success && key && wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime, sta->eapol_sm) == 0) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, HOSTAPD_LEVEL_DEBUG, "Added PMKSA cache entry (IEEE 802.1X)"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -