📄 ieee802_1x.c
字号:
}static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx, const u8 *data, size_t datalen){ struct hostapd_data *hapd = ctx; struct sta_info *sta = sta_ctx; ieee802_1x_encapsulate_radius(hapd, sta, data, datalen);}static void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success, int preauth){ struct hostapd_data *hapd = ctx; struct sta_info *sta = sta_ctx; if (preauth) rsn_preauth_finished(hapd, sta, success); else ieee802_1x_finished(hapd, sta, success);}static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, size_t identity_len, int phase2, struct eap_user *user){ struct hostapd_data *hapd = ctx; const struct hostapd_eap_user *eap_user; int i, count; eap_user = hostapd_get_eap_user(hapd->conf, identity, identity_len, phase2); if (eap_user == NULL) return -1; os_memset(user, 0, sizeof(*user)); user->phase2 = phase2; count = EAP_USER_MAX_METHODS; if (count > EAP_MAX_METHODS) count = EAP_MAX_METHODS; for (i = 0; i < count; i++) { user->methods[i].vendor = eap_user->methods[i].vendor; user->methods[i].method = eap_user->methods[i].method; } if (eap_user->password) { user->password = os_malloc(eap_user->password_len); if (user->password == NULL) return -1; os_memcpy(user->password, eap_user->password, eap_user->password_len); user->password_len = eap_user->password_len; } user->force_version = eap_user->force_version; user->ttls_auth = eap_user->ttls_auth; return 0;}static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr){ struct hostapd_data *hapd = ctx; struct sta_info *sta; sta = ap_get_sta(hapd, addr); if (sta == NULL || sta->eapol_sm == NULL) return 0; return 1;}static void ieee802_1x_logger(void *ctx, const u8 *addr, eapol_logger_level level, const char *txt){ struct hostapd_data *hapd = ctx; int hlevel; switch (level) { case EAPOL_LOGGER_WARNING: hlevel = HOSTAPD_LEVEL_WARNING; break; case EAPOL_LOGGER_INFO: hlevel = HOSTAPD_LEVEL_INFO; break; case EAPOL_LOGGER_DEBUG: default: hlevel = HOSTAPD_LEVEL_DEBUG; break; } hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s", txt);}static void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, int authorized){ struct hostapd_data *hapd = ctx; struct sta_info *sta = sta_ctx; ieee802_1x_set_sta_authorized(hapd, sta, authorized);}static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx){ struct hostapd_data *hapd = ctx; struct sta_info *sta = sta_ctx; ieee802_1x_abort_auth(hapd, sta);}static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx){ struct hostapd_data *hapd = ctx; struct sta_info *sta = sta_ctx; ieee802_1x_tx_key(hapd, sta);}int ieee802_1x_init(struct hostapd_data *hapd){ int i; struct eapol_auth_config conf; struct eapol_auth_cb cb; os_memset(&conf, 0, sizeof(conf)); conf.hapd = hapd; conf.eap_reauth_period = hapd->conf->eap_reauth_period; conf.wpa = hapd->conf->wpa; conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; conf.eap_server = hapd->conf->eap_server; conf.ssl_ctx = hapd->ssl_ctx; conf.eap_sim_db_priv = hapd->eap_sim_db_priv; conf.eap_req_id_text = hapd->conf->eap_req_id_text; conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key; conf.eap_fast_a_id = hapd->conf->eap_fast_a_id; conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len; conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info; conf.eap_fast_prov = hapd->conf->eap_fast_prov; conf.pac_key_lifetime = hapd->conf->pac_key_lifetime; conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time; conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; conf.tnc = hapd->conf->tnc; conf.wps = hapd->wps; os_memset(&cb, 0, sizeof(cb)); cb.eapol_send = ieee802_1x_eapol_send; cb.aaa_send = ieee802_1x_aaa_send; cb.finished = _ieee802_1x_finished; cb.get_eap_user = ieee802_1x_get_eap_user; cb.sta_entry_alive = ieee802_1x_sta_entry_alive; cb.logger = ieee802_1x_logger; cb.set_port_authorized = ieee802_1x_set_port_authorized; cb.abort_auth = _ieee802_1x_abort_auth; cb.tx_key = _ieee802_1x_tx_key; hapd->eapol_auth = eapol_auth_init(&conf, &cb); if (hapd->eapol_auth == NULL) return -1; 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) { hostapd_set_privacy(hapd, 1); 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){ eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); if (hapd->driver != NULL && (hapd->conf->ieee802_1x || hapd->conf->wpa)) hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0); eapol_auth_deinit(hapd->eapol_auth); hapd->eapol_auth = NULL;}int ieee802_1x_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, struct hostapd_bss_config *oldbss){ ieee802_1x_deinit(hapd); return ieee802_1x_init(hapd);}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; const unsigned char rfc1042_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; if (sta == NULL) return -1; if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr)) return 0; hdr = (struct ieee80211_hdr *) buf; pos = (u8 *) (hdr + 1); if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) return 0; pos += sizeof(rfc1042_hdr); if (WPA_GET_BE16(pos) != ETH_P_PAE) return 0; pos += 2; xhdr = (struct ieee802_1x_hdr *) pos; pos += sizeof(*xhdr); wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " "type=%d length=%d - ack=%d", MAC2STR(sta->addr), xhdr->version, xhdr->type, be_to_host16(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 >= (int) sm->radius_class.count) return NULL; *len = sm->radius_class.attr[idx].len; return sm->radius_class.attr[idx].data;}const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len){ if (sm == NULL) return NULL; *len = sm->eap_if->eapKeyDataLen; return sm->eap_if->eapKeyData;}void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, int enabled){ if (sm == NULL) return; sm->eap_if->portEnabled = enabled ? TRUE : FALSE; eapol_auth_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_auth_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, ret; struct eapol_state_machine *sm = sta->eapol_sm; if (sm == NULL) return 0; ret = os_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); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; /* dot1xAuthConfigTable */ ret = os_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)); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; /* dot1xAuthStatsTable */ ret = os_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)); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; /* dot1xAuthDiagTable */ ret = os_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); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; /* dot1xAuthSessionStatsTable */ ret = os_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_key_mgmt_wpa_ieee8021x( wpa_auth_sta_key_mgmt(sta->wpa_sm))) ? 1 : 2, (unsigned int) (time(NULL) - sta->acct_session_start), sm->identity); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; return len;}static void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, int success){ const u8 *key; size_t len; /* TODO: get PMKLifetime from WPA parameters */ static const int dot11RSNAConfigPMKLifetime = 43200; key = ieee802_1x_get_key(sta->eapol_sm, &len); if (success && key && len >= PMK_LEN && 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 + -