static void handle_auth(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len) { u16 auth_alg, auth_transaction, status_code; u16 resp = WLAN_STATUS_SUCCESS; struct sta_info *sta = NULL; int res; u16 fc; u8 *challenge = NULL; u32 session_timeout, acct_interim_interval; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { printf("handle_auth - too short payload (len=%lu)\n", (unsigned long) len); return; } auth_alg = le_to_host16(mgmt->u.auth.auth_alg); auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); status_code = le_to_host16(mgmt->u.auth.status_code); fc = le_to_host16(mgmt->frame_control); if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2 + WLAN_AUTH_CHALLENGE_LEN && mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE && mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN) challenge = &mgmt->u.auth.variable[2]; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "authentication: STA=" MACSTR " auth_alg=%d " "auth_transaction=%d status_code=%d wep=%d%s\n", MAC2STR(mgmt->sa), auth_alg, auth_transaction, status_code, !!(fc & WLAN_FC_ISWEP), challenge ? " challenge" : ""); if (hapd->assoc_ap_state == AUTHENTICATE && auth_transaction == 2 && memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0 && memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { if (status_code != 0) { printf("Authentication (as station) with AP " MACSTR " failed (status_code=%d)\n", MAC2STR(hapd->conf->assoc_ap_addr), status_code); return; } printf("Authenticated (as station) with AP " MACSTR "\n", MAC2STR(hapd->conf->assoc_ap_addr)); ieee802_11_sta_associate(hapd, NULL); return; } if (hapd->tkip_countermeasures) { resp = WLAN_REASON_MICHAEL_MIC_FAILURE; goto fail; } if (!(((hapd->conf->auth_algs & HOSTAPD_AUTH_OPEN) && auth_alg == WLAN_AUTH_OPEN) || ((hapd->conf->auth_algs & HOSTAPD_AUTH_SHARED_KEY) && auth_alg == WLAN_AUTH_SHARED_KEY))) { printf("Unsupported authentication algorithm (%d)\n", auth_alg); resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; goto fail; } if (!(auth_transaction == 1 || (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { printf("Unknown authentication transaction number (%d)\n", auth_transaction); resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto fail; } if (memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) { printf("Station " MACSTR " not allowed to authenticate.\n", MAC2STR(mgmt->sa)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, &session_timeout, &acct_interim_interval); if (res == HOSTAPD_ACL_REJECT) { printf("Station " MACSTR " not allowed to authenticate.\n", MAC2STR(mgmt->sa)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } if (res == HOSTAPD_ACL_PENDING) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Authentication frame " "from " MACSTR " waiting for an external " "authentication\n", MAC2STR(mgmt->sa)); /* Authentication code will re-send the authentication frame * after it has received (and cached) information from the * external source. */ return; } sta = ap_sta_add(hapd, mgmt->sa); if (!sta) { resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } sta->flags &= ~WLAN_STA_PREAUTH; ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); if (hapd->conf->radius->acct_interim_interval == 0 && acct_interim_interval) sta->acct_interim_interval = acct_interim_interval; if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) ap_sta_session_timeout(hapd, sta, session_timeout); else ap_sta_no_session_timeout(hapd, sta); switch (auth_alg) { case WLAN_AUTH_OPEN: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "authentication OK (open system)"); #ifdef IEEE80211_REQUIRE_AUTH_ACK /* Station will be marked authenticated if it ACKs the * authentication reply. */ #else sta->flags |= WLAN_STA_AUTH; wpa_sm_event(hapd, sta, WPA_AUTH); #endif break; case WLAN_AUTH_SHARED_KEY: resp = auth_shared_key(hapd, sta, auth_transaction, challenge, fc & WLAN_FC_ISWEP); break; } fail: send_auth_reply(hapd, mgmt, auth_alg, auth_transaction + 1, resp, sta ? sta->challenge : NULL); }
/*AC代理终端发起MAC认证请求*/ static void mac_auth_req(struct hostapd_data * hapd, struct sta_info * sta) { AC_USER_DATA_QOS_T user_qos = {0} ; u32 session_timeout =0, acct_interim_interval = 0 ; int res ; if(hapd == NULL || hapd->iface == NULL || hapd->iface->pstWtp == NULL || sta == NULL){ ModuleLogMsg(APP_MODULE_HOSTAPD, APP_FATAL, "%s, point is NULL.\n", __func__) ; return ; } res = hostapd_allowed_address(hapd, sta->addr, NULL, 0, & session_timeout, & acct_interim_interval, NULL, & user_qos) ; switch(res){ case HOSTAPD_ACL_REJECT :{ ModuleLogMsg(APP_MODULE_HOSTAPD, APP_MSG, "%s, sta(%u/%u/%u/"MACSTR") is not allowed to authenticate.\n", __func__, hapd->iface->pstWtp->usWtpId, hapd->iface->interface_id, hapd->vap_id, MAC2STR(sta->addr)) ; mac_auth_disconnect(hapd, sta) ; return ; } case HOSTAPD_ACL_PENDING :{ if(sta->access_reason == WLAN_REASON_ACCESS_HANDOVER){ ModuleLogMsg(APP_MODULE_HOSTAPD, APP_MSG, "%s, sta(%u/%u/%u/"MACSTR") is allowed to authenticate, due to handover.\n", __func__, hapd->iface->pstWtp->usWtpId, hapd->iface->interface_id, hapd->vap_id, MAC2STR(sta->addr)) ; sta->flags |= WLAN_STA_AUTHORIZED_MAC ; if(! hapd->conf->ieee802_1x){ mac_auth_update_sta_identity(hapd, sta) ; /*QOS信息在切换时,从OLD STA拷贝,故此处无需获取QOS信息*/ } return ; } else{ ModuleLogMsg(APP_MODULE_HOSTAPD, APP_MSG, "%s, sta(%u/%u/%u/"MACSTR") waiting for external authentication.\n", __func__, hapd->iface->pstWtp->usWtpId, hapd->iface->interface_id, hapd->vap_id, MAC2STR(sta->addr)) ; mac_auth_set_sta_authorized(hapd, sta, 0) ; return ; } } case HOSTAPD_ACL_ACCEPT_TIMEOUT: { ap_sta_session_timeout(hapd, sta, session_timeout) ; /*follow on*/ } case HOSTAPD_ACL_ACCEPT :{ if (acct_interim_interval > 60){ sta->acct_interim_interval = acct_interim_interval; } ModuleLogMsg(APP_MODULE_HOSTAPD, APP_MSG, "%s, sta(%u/%u/%u/"MACSTR") is allowed to authenticate, due to it's in accept_mac_list or acl_cache (%s).\n", __func__, hapd->iface->pstWtp->usWtpId, hapd->iface->interface_id, hapd->vap_id, MAC2STR(sta->addr), res == HOSTAPD_ACL_ACCEPT_TIMEOUT ? "accept timeout" : "accept") ; sta->flags |= WLAN_STA_AUTHORIZED_MAC ; mac_auth_update_sta_identity(hapd, sta) ; mac_auth_update_sta_info(hapd, sta, & user_qos) ; return ; } default : ModuleLogMsg(APP_MODULE_HOSTAPD, APP_WARN, "%s, unknown res(%d).\n", __func__, res) ; return ; } return ; }
static void bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) { struct bsd_driver_data *drv = ctx; char buf[2048]; struct if_announcemsghdr *ifan; struct rt_msghdr *rtm; struct ieee80211_michael_event *mic; struct ieee80211_join_event *join; struct ieee80211_leave_event *leave; #ifdef CONFIG_DRIVER_RADIUS_ACL struct ieee80211_auth_event *auth; #endif int n; union wpa_event_data data; n = read(sock, buf, sizeof(buf)); if (n < 0) { if (errno != EINTR && errno != EAGAIN) perror("read(PF_ROUTE)"); return; } rtm = (struct rt_msghdr *) buf; if (rtm->rtm_version != RTM_VERSION) { wpa_printf(MSG_DEBUG, "Routing message version %d not " "understood\n", rtm->rtm_version); return; } ifan = (struct if_announcemsghdr *) rtm; if (ifan->ifan_index != drv->ifindex) { wpa_printf(MSG_DEBUG, "Discard routing message to if#%d " "(not for us %d)\n", ifan->ifan_index, drv->ifindex); return; } switch (rtm->rtm_type) { case RTM_IEEE80211: switch (ifan->ifan_what) { case RTM_IEEE80211_ASSOC: case RTM_IEEE80211_REASSOC: case RTM_IEEE80211_DISASSOC: case RTM_IEEE80211_SCAN: break; case RTM_IEEE80211_LEAVE: leave = (struct ieee80211_leave_event *) &ifan[1]; drv_event_disassoc(drv->hapd, leave->iev_addr); break; case RTM_IEEE80211_JOIN: #ifdef RTM_IEEE80211_REJOIN case RTM_IEEE80211_REJOIN: #endif join = (struct ieee80211_join_event *) &ifan[1]; bsd_new_sta(drv, drv->hapd, join->iev_addr); break; case RTM_IEEE80211_REPLAY: /* ignore */ break; case RTM_IEEE80211_MICHAEL: mic = (struct ieee80211_michael_event *) &ifan[1]; wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " "keyix=%u src_addr=" MACSTR, mic->iev_keyix, MAC2STR(mic->iev_src)); os_memset(&data, 0, sizeof(data)); data.michael_mic_failure.unicast = 1; data.michael_mic_failure.src = mic->iev_src; wpa_supplicant_event(drv->hapd, EVENT_MICHAEL_MIC_FAILURE, &data); break; #ifdef CONFIG_DRIVER_RADIUS_ACL_NOT_YET case RTM_IEEE80211_AUTH: auth = (struct ieee80211_auth_event *) &ifan[1]; wpa_printf(MSG_DEBUG, "802.11 AUTH, STA = " MACSTR, MAC2STR(auth->iev_addr)); n = hostapd_allowed_address(drv->hapd, auth->iev_addr, NULL, 0, NULL, NULL, NULL); switch (n) { case HOSTAPD_ACL_ACCEPT: case HOSTAPD_ACL_REJECT: hostapd_set_radius_acl_auth(drv->hapd, auth->iev_addr, n, 0); wpa_printf(MSG_DEBUG, "802.11 AUTH, STA = " MACSTR " hostapd says: %s", MAC2STR(auth->iev_addr), (n == HOSTAPD_ACL_ACCEPT ? "ACCEPT" : "REJECT" )); break; case HOSTAPD_ACL_PENDING: wpa_printf(MSG_DEBUG, "802.11 AUTH, STA = " MACSTR " pending", MAC2STR(auth->iev_addr)); break; } break; #endif /* CONFIG_DRIVER_RADIUS_ACL */ } break; } }
static int hostapd_config_reload_sta(struct hostapd_data *hapd, struct sta_info *sta, void *data) { struct hostapd_config_change *change = data; struct hostapd_bss_config *newbss, *oldbss; int deauth = 0; u8 reason = WLAN_REASON_PREV_AUTH_NOT_VALID; newbss = change->newbss; oldbss = change->oldbss; hapd = change->hapd; if (sta->ssid == &oldbss->ssid) { sta->ssid = &newbss->ssid; if (newbss->ssid.ssid_len != oldbss->ssid.ssid_len || memcmp(newbss->ssid.ssid, oldbss->ssid.ssid, newbss->ssid.ssid_len) != 0) { /* main SSID was changed - kick STA out */ deauth++; } } sta->ssid_probe = sta->ssid; /* * If MAC ACL configuration has changed, deauthenticate stations that * have been removed from accepted list or have been added to denied * list. If external RADIUS server is used for ACL, all stations are * deauthenticated and they will need to authenticate again. This * limits sudden load on the RADIUS server since the verification will * be done over the time needed for the STAs to reauthenticate * themselves. */ if (change->mac_acl_changed && (newbss->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH || !hostapd_allowed_address(hapd, sta->addr, NULL, 0, NULL, NULL, NULL))) deauth++; if (newbss->ieee802_1x != oldbss->ieee802_1x && sta->ssid == &hapd->conf->ssid) deauth++; if (newbss->wpa != oldbss->wpa) deauth++; if (!newbss->wme_enabled && (sta->flags & WLAN_STA_WME)) deauth++; if (newbss->auth_algs != oldbss->auth_algs && ((sta->auth_alg == WLAN_AUTH_OPEN && !(newbss->auth_algs & HOSTAPD_AUTH_OPEN)) || (sta->auth_alg == WLAN_AUTH_SHARED_KEY && !(newbss->auth_algs & HOSTAPD_AUTH_SHARED_KEY)))) deauth++; if (change->num_sta_remove > 0) { deauth++; reason = WLAN_REASON_DISASSOC_AP_BUSY; } if (deauth) { HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "STA " MACSTR " deauthenticated during config reloading " "(reason=%d)\n", MAC2STR(sta->addr), reason); ieee802_11_send_deauth(hapd, sta->addr, reason); ap_sta_deauthenticate(hapd, sta, reason); change->num_sta_remove--; } return 0; }
static void handle_auth(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { u16 auth_alg, auth_transaction, status_code; u16 resp = WLAN_STATUS_SUCCESS; struct sta_info *sta = NULL; int res; u16 fc; const u8 *challenge = NULL; u32 session_timeout, acct_interim_interval; int vlan_id = 0; u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; size_t resp_ies_len = 0; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { printf("handle_auth - too short payload (len=%lu)\n", (unsigned long) len); return; } auth_alg = le_to_host16(mgmt->u.auth.auth_alg); auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); status_code = le_to_host16(mgmt->u.auth.status_code); fc = le_to_host16(mgmt->frame_control); if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2 + WLAN_AUTH_CHALLENGE_LEN && mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE && mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN) challenge = &mgmt->u.auth.variable[2]; wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d " "auth_transaction=%d status_code=%d wep=%d%s", MAC2STR(mgmt->sa), auth_alg, auth_transaction, status_code, !!(fc & WLAN_FC_ISWEP), challenge ? " challenge" : ""); if (hapd->tkip_countermeasures) { resp = WLAN_REASON_MICHAEL_MIC_FAILURE; goto fail; } if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) && auth_alg == WLAN_AUTH_OPEN) || #ifdef CONFIG_IEEE80211R (hapd->conf->wpa && (hapd->conf->wpa_key_mgmt & (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) && auth_alg == WLAN_AUTH_FT) || #endif /* CONFIG_IEEE80211R */ ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) && auth_alg == WLAN_AUTH_SHARED_KEY))) { printf("Unsupported authentication algorithm (%d)\n", auth_alg); resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; goto fail; } if (!(auth_transaction == 1 || (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { printf("Unknown authentication transaction number (%d)\n", auth_transaction); resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto fail; } if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) { printf("Station " MACSTR " not allowed to authenticate.\n", MAC2STR(mgmt->sa)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, &session_timeout, &acct_interim_interval, &vlan_id); if (res == HOSTAPD_ACL_REJECT) { printf("Station " MACSTR " not allowed to authenticate.\n", MAC2STR(mgmt->sa)); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } if (res == HOSTAPD_ACL_PENDING) { wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR " waiting for an external authentication", MAC2STR(mgmt->sa)); /* Authentication code will re-send the authentication frame * after it has received (and cached) information from the * external source. */ return; } sta = ap_sta_add(hapd, mgmt->sa); if (!sta) { resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } if (vlan_id > 0) { if (hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id) == NULL) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "Invalid VLAN ID " "%d received from RADIUS server", vlan_id); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } sta->vlan_id = vlan_id; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); } sta->flags &= ~WLAN_STA_PREAUTH; ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval) sta->acct_interim_interval = acct_interim_interval; if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) ap_sta_session_timeout(hapd, sta, session_timeout); else ap_sta_no_session_timeout(hapd, sta); switch (auth_alg) { case WLAN_AUTH_OPEN: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "authentication OK (open system)"); #ifdef IEEE80211_REQUIRE_AUTH_ACK /* Station will be marked authenticated if it ACKs the * authentication reply. */ #else sta->flags |= WLAN_STA_AUTH; wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); sta->auth_alg = WLAN_AUTH_OPEN; mlme_authenticate_indication(hapd, sta); #endif break; case WLAN_AUTH_SHARED_KEY: resp = auth_shared_key(hapd, sta, auth_transaction, challenge, fc & WLAN_FC_ISWEP); sta->auth_alg = WLAN_AUTH_SHARED_KEY; mlme_authenticate_indication(hapd, sta); if (sta->challenge && auth_transaction == 1) { resp_ies[0] = WLAN_EID_CHALLENGE; resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN; os_memcpy(resp_ies + 2, sta->challenge, WLAN_AUTH_CHALLENGE_LEN); resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN; } break; #ifdef CONFIG_IEEE80211R case WLAN_AUTH_FT: sta->auth_alg = WLAN_AUTH_FT; if (sta->wpa_sm == NULL) sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); if (sta->wpa_sm == NULL) { wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA " "state machine"); resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid, auth_transaction, mgmt->u.auth.variable, len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth), handle_auth_ft_finish, hapd); /* handle_auth_ft_finish() callback will complete auth. */ return; #endif /* CONFIG_IEEE80211R */ } fail: send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg, auth_transaction + 1, resp, resp_ies, resp_ies_len); }