static struct gas_dialog_info * gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token) { struct sta_info *sta; struct gas_dialog_info *dia = NULL; int i, j; sta = ap_get_sta(hapd, addr); if (!sta) { /* * We need a STA entry to be able to maintain state for * the GAS query. */ wpa_printf(MSG_DEBUG, "ANQP: Add a temporary STA entry for " "GAS query"); sta = ap_sta_add(hapd, addr); if (!sta) { wpa_printf(MSG_DEBUG, "Failed to add STA " MACSTR " for GAS query", MAC2STR(addr)); return NULL; } sta->flags |= WLAN_STA_GAS; /* * The default inactivity is 300 seconds. We don't need * it to be that long. */ ap_sta_session_timeout(hapd, sta, 5); } else { ap_sta_replenish_timeout(hapd, sta, 5); } if (sta->gas_dialog == NULL) { sta->gas_dialog = os_zalloc(GAS_DIALOG_MAX * sizeof(struct gas_dialog_info)); if (sta->gas_dialog == NULL) return NULL; } for (i = sta->gas_dialog_next, j = 0; j < GAS_DIALOG_MAX; i++, j++) { if (i == GAS_DIALOG_MAX) i = 0; if (sta->gas_dialog[i].valid) continue; dia = &sta->gas_dialog[i]; dia->valid = 1; dia->index = i; dia->dialog_token = dialog_token; sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i; return dia; } wpa_msg(hapd->msg_ctx, MSG_ERROR, "ANQP: Could not create dialog for " MACSTR " dialog_token %u. Consider increasing " "GAS_DIALOG_MAX.", MAC2STR(addr), dialog_token); return NULL; }
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); }
/* Process the RADIUS frames from Authentication Server */ static RadiusRxResult ieee802_1x_receive_auth(struct wpa_supplicant *wpa_s, struct radius_msg *msg, struct radius_msg *req, u8 *shared_secret, size_t shared_secret_len, void *data) { #if 0 u32 session_timeout, termination_action; int session_timeout_set; int acct_interim_interval; #endif #if 0 sta = ap_get_sta_radius_identifier(hapd, msg->hdr->identifier); if (sta == NULL) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not " "find matching station for this RADIUS " "message\n"); return RADIUS_RX_UNKNOWN; } #endif /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be * present when packet contains an EAP-Message attribute */ if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT && radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 0) < 0 && radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { wpa_printf(MSG_DEBUG, "Allowing RADIUS " "Access-Reject without Message-Authenticator " "since it does not include EAP-Message\n"); } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, req)) { printf("Incoming RADIUS packet did not have correct " "Message-Authenticator - dropped\n"); return RADIUS_RX_UNKNOWN; } if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && msg->hdr->code != RADIUS_CODE_ACCESS_REJECT && msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { printf("Unknown RADIUS message code\n"); return RADIUS_RX_UNKNOWN; } wpa_s->radius_identifier = -1; wpa_printf(MSG_DEBUG, "RADIUS packet matching with station"); if (wpa_s->last_recv_radius) { radius_msg_free(wpa_s->last_recv_radius); free(wpa_s->last_recv_radius); } wpa_s->last_recv_radius = msg; #if 0 session_timeout_set = !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, &session_timeout); if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, &termination_action)) termination_action = RADIUS_TERMINATION_ACTION_DEFAULT; if (hapd->conf->radius_acct_interim_interval == 0 && msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT && radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, &acct_interim_interval) == 0) { if (acct_interim_interval < 60) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_INFO, "ignored too small " "Acct-Interim-Interval %d", acct_interim_interval); } else sta->acct_interim_interval = acct_interim_interval; } switch (msg->hdr->code) { case RADIUS_CODE_ACCESS_ACCEPT: /* draft-congdon-radius-8021x-22.txt, Ch. 3.17 */ if (session_timeout_set && termination_action == RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { sta->eapol_sm->reauth_timer.reAuthPeriod = session_timeout; } else if (session_timeout_set) ap_sta_session_timeout(hapd, sta, session_timeout); sta->eapol_sm->be_auth.aSuccess = TRUE; ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, shared_secret_len); if (sta->eapol_sm->keyAvailable) { pmksa_cache_add(hapd, sta, sta->eapol_key_crypt, session_timeout_set ? session_timeout : -1); } break; case RADIUS_CODE_ACCESS_REJECT: sta->eapol_sm->be_auth.aFail = TRUE; break; case RADIUS_CODE_ACCESS_CHALLENGE: if (session_timeout_set) { /* RFC 2869, Ch. 2.3.2 * draft-congdon-radius-8021x-22.txt, Ch. 3.17 */ sta->eapol_sm->be_auth.suppTimeout = session_timeout; } sta->eapol_sm->be_auth.aReq = TRUE; break; } #else switch (msg->hdr->code) { case RADIUS_CODE_ACCESS_ACCEPT: wpa_s->radius_access_accept_received = 1; ieee802_1x_get_keys(wpa_s, msg, req, shared_secret, shared_secret_len); break; case RADIUS_CODE_ACCESS_REJECT: wpa_s->radius_access_reject_received = 1; break; } #endif ieee802_1x_decapsulate_radius(wpa_s); /* eapol_sm_step(sta->eapol_sm); */ if (msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT || msg->hdr->code == RADIUS_CODE_ACCESS_REJECT) { eloop_terminate(); } return RADIUS_RX_QUEUED; }
/*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 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); }