/* This function will be called whenever a station associates with the AP */
void hostapd_new_assoc_sta(hostapd *hapd, struct sta_info *sta, int reassoc)
{
	if (hapd->tkip_countermeasures) {
		hostapd_sta_deauth(hapd, sta->addr,
				   WLAN_REASON_MICHAEL_MIC_FAILURE);
		return;
	}

	/* IEEE 802.11F (IAPP) */
	if (hapd->conf->ieee802_11f)
		iapp_new_station(hapd->iapp, sta);

	/* Start accounting here, if IEEE 802.1X and WPA are not used.
	 * IEEE 802.1X/WPA code will start accounting after the station has
	 * been authorized. */
	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
		accounting_sta_start(hapd, sta);

	/* Start IEEE 802.1X authentication process for new stations */
	ieee802_1x_new_station(hapd, sta);
	if (reassoc)
		wpa_sm_event(hapd, sta, WPA_REAUTH);
	else
		wpa_new_station(hapd, sta);
}
예제 #2
0
static u16 auth_shared_key(hostapd *hapd, struct sta_info *sta,
                           u16 auth_transaction, u8 *challenge, int iswep)
{
    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_DEBUG,
                   "authentication (shared key, transaction %d)",
                   auth_transaction);

    if (auth_transaction == 1) {
        if (!sta->challenge) {
            /* Generate a pseudo-random challenge */
            u8 key[8];
            time_t now;
            int r;
            sta->challenge = malloc(WLAN_AUTH_CHALLENGE_LEN);
            if (!sta->challenge)
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
            memset(sta->challenge, 0, WLAN_AUTH_CHALLENGE_LEN);

            now = time(NULL);
            r = random();
            memcpy(key, &now, 4);
            memcpy(key + 4, &r, 4);
            rc4(sta->challenge, WLAN_AUTH_CHALLENGE_LEN,
                key, sizeof(key));
        }
        return 0;
    }

    if (auth_transaction != 3)
        return WLAN_STATUS_UNSPECIFIED_FAILURE;

    /* Transaction 3 */
    if (!iswep || !sta->challenge || !challenge ||
            memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) {
        hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                       HOSTAPD_LEVEL_INFO,
                       "shared key authentication - invalid "
                       "challenge-response");
        return WLAN_STATUS_CHALLENGE_FAIL;
    }

    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_DEBUG,
                   "authentication OK (shared key)");
#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
    free(sta->challenge);
    sta->challenge = NULL;

    return 0;
}
예제 #3
0
static void handle_disassoc(hostapd *hapd, struct ieee80211_mgmt *mgmt,
                            size_t len)
{
    struct sta_info *sta;

    if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
        printf("handle_disassoc - too short payload (len=%lu)\n",
               (unsigned long) len);
        return;
    }

    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                  "disassocation: STA=" MACSTR " reason_code=%d\n",
                  MAC2STR(mgmt->sa),
                  le_to_host16(mgmt->u.disassoc.reason_code));

    if (hapd->assoc_ap_state != DO_NOT_ASSOC &&
            memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
        printf("Assoc AP " MACSTR " sent disassociation "
               "(reason_code=%d) - try to authenticate\n",
               MAC2STR(hapd->conf->assoc_ap_addr),
               le_to_host16(mgmt->u.disassoc.reason_code));
        hapd->assoc_ap_state = AUTHENTICATE;
        ieee802_11_sta_authenticate(hapd, NULL);
        eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate,
                               hapd, NULL);
        return;
    }

    sta = ap_get_sta(hapd, mgmt->sa);
    if (sta == NULL) {
        printf("Station " MACSTR " trying to disassociate, but it "
               "is not associated.\n", MAC2STR(mgmt->sa));
        return;
    }

    sta->flags &= ~WLAN_STA_ASSOC;
    wpa_sm_event(hapd, sta, WPA_DISASSOC);
    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_INFO, "disassociated");
    sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
    ieee802_1x_set_port_enabled(hapd, sta, 0);
    /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
     * authenticated. */
    accounting_sta_stop(hapd, sta);
    ieee802_1x_free_station(sta);
    hostapd_sta_remove(hapd, sta->addr);

    if (sta->timeout_next == STA_NULLFUNC ||
            sta->timeout_next == STA_DISASSOC) {
        sta->timeout_next = STA_DEAUTH;
        eloop_cancel_timeout(ap_handle_timer, hapd, sta);
        eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
                               hapd, sta);
    }
}
예제 #4
0
static void handle_deauth(hostapd *hapd, struct ieee80211_mgmt *mgmt,
                          size_t len)
{
    struct sta_info *sta;

    if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
        printf("handle_deauth - too short payload (len=%lu)\n",
               (unsigned long) len);
        return;
    }

    HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,
                  "deauthentication: STA=" MACSTR " reason_code=%d\n",
                  MAC2STR(mgmt->sa),
                  le_to_host16(mgmt->u.deauth.reason_code));

    if (hapd->assoc_ap_state != DO_NOT_ASSOC &&
            memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) {
        printf("Assoc AP " MACSTR " sent deauthentication "
               "(reason_code=%d) - try to authenticate\n",
               MAC2STR(hapd->conf->assoc_ap_addr),
               le_to_host16(mgmt->u.deauth.reason_code));
        hapd->assoc_ap_state = AUTHENTICATE;
        eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate,
                               hapd, NULL);
        return;
    }

    sta = ap_get_sta(hapd, mgmt->sa);
    if (sta == NULL) {
        printf("Station " MACSTR " trying to deauthenticate, but it "
               "is not authenticated.\n", MAC2STR(mgmt->sa));
        return;
    }

    sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
    wpa_sm_event(hapd, sta, WPA_DEAUTH);
    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_DEBUG, "deauthenticated");
    sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
    ieee802_1x_set_port_enabled(hapd, sta, 0);
    ap_free_sta(hapd, sta);
}
예제 #5
0
static int
bsd_del_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
	struct hostapd_data *hapd = drv->hapd;
	struct hostapd_config *conf = hapd->conf;
	struct sta_info *sta;

	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
		HOSTAPD_LEVEL_INFO, "deassociated");

	sta = ap_get_sta(hapd, addr);
	if (sta != NULL) {
		sta->flags &= ~WLAN_STA_ASSOC;
		if (conf->wpa)
			wpa_sm_event(hapd, sta, WPA_DISASSOC);
		sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
		ieee802_1x_set_port_enabled(hapd, sta, 0);
		ap_free_sta(hapd, sta);
	}
	return 0;
}
예제 #6
0
static int
bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
{
	struct hostapd_data *hapd = drv->hapd;
	struct hostapd_config *conf = hapd->conf;
	struct sta_info *sta;
	struct ieee80211req_wpaie ie;
	int new_assoc, ielen, res;

	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
		HOSTAPD_LEVEL_INFO, "associated");

	sta = ap_sta_add(hapd, addr);
	if (sta == NULL)
		return -1;
	/*
	 * Fetch and validate any negotiated WPA/RSN parameters.
	 */
	if (conf->wpa) {
		memset(&ie, 0, sizeof(ie));
		memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
		if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
			printf("Failed to get WPA/RSN information element.\n");
			return -1;		/* XXX not right */
		}
		ielen = ie.wpa_ie[1];
		if (ielen == 0) {
			printf("No WPA/RSN information element for station!\n");
			return -1;		/* XXX not right */
		}
		ielen += 2;
		res = wpa_validate_wpa_ie(hapd, sta, ie.wpa_ie, ielen,
				ie.wpa_ie[0] == WLAN_EID_RSN ?
				    HOSTAPD_WPA_VERSION_WPA2 :
				    HOSTAPD_WPA_VERSION_WPA);
		if (res != WPA_IE_OK) {
			printf("WPA/RSN information element rejected? "
				"(res %u)\n", res);
			return -1;
		}
		if (sta->wpa_ie != NULL)
			free(sta->wpa_ie);
		sta->wpa_ie = malloc(ielen);
		if (sta->wpa_ie == NULL) {
			printf("No memory for WPA/RSN information element!\n");
			return -1;
		}
		memcpy(sta->wpa_ie, ie.wpa_ie, ielen);
		sta->wpa_ie_len = ielen;
	} else {
		if (sta->wpa_ie != NULL)
			free(sta->wpa_ie);
		sta->wpa_ie = NULL;
		sta->wpa_ie_len = 0;
	}

	/*
	 * Now that the internal station state is setup
	 * kick the authenticator into action.
	 */
	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
	sta->flags |= WLAN_STA_ASSOC;
	if (conf->wpa)
		wpa_sm_event(hapd, sta, WPA_ASSOC);
	if (new_assoc)
		hostapd_new_assoc_sta(hapd, sta);
	else if (conf->wpa)
		wpa_sm_event(hapd, sta, WPA_REAUTH);
	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
	return 0;
}
예제 #7
0
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);
}
예제 #8
0
static void handle_assoc_cb(hostapd *hapd, struct ieee80211_mgmt *mgmt,
                            size_t len, int reassoc, int ok)
{
    u16 status;
    struct sta_info *sta;
    int new_assoc = 1;

    if (!ok) {
        hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
                       HOSTAPD_LEVEL_DEBUG,
                       "did not acknowledge association response");
        return;
    }

    if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
                                  sizeof(mgmt->u.assoc_req))) {
        printf("handle_assoc_cb(reassoc=%d) - too short payload "
               "(len=%lu)\n", reassoc, (unsigned long) len);
        return;
    }

    if (reassoc)
        status = le_to_host16(mgmt->u.reassoc_resp.status_code);
    else
        status = le_to_host16(mgmt->u.assoc_resp.status_code);

    sta = ap_get_sta(hapd, mgmt->da);
    if (!sta) {
        printf("handle_assoc_cb: STA " MACSTR " not found\n",
               MAC2STR(mgmt->da));
        return;
    }

    if (status != WLAN_STATUS_SUCCESS)
        goto fail;

    /* Stop previous accounting session, if one is started, and allocate
     * new session id for the new session. */
    accounting_sta_stop(hapd, sta);
    accounting_sta_get_id(hapd, sta);

    hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                   HOSTAPD_LEVEL_INFO,
                   "associated (aid %d, accounting session %08X-%08X)",
                   sta->aid, sta->acct_session_id_hi,
                   sta->acct_session_id_lo);

    if (sta->flags & WLAN_STA_ASSOC)
        new_assoc = 0;
    sta->flags |= WLAN_STA_ASSOC;

    if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
                        sta->tx_supp_rates)) {
        printf("Could not add station to kernel driver.\n");
    }

    wpa_sm_event(hapd, sta, WPA_ASSOC);
    hostapd_new_assoc_sta(hapd, sta, !new_assoc);

    ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);

fail:
    /* Copy of the association request is not needed anymore */
    if (sta->last_assoc_req) {
        free(sta->last_assoc_req);
        sta->last_assoc_req = NULL;
    }
}
예제 #9
0
파일: ieee802_11.c 프로젝트: OPSF/uClinux
static void handle_assoc_cb(hostapd *hapd, struct ieee80211_mgmt *mgmt,
			    size_t len, int reassoc, int ok)
{
	u16 status;
	struct prism2_hostapd_param param;
	struct sta_info *sta;
	int new_assoc = 1;

	if (!ok) {
		hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
			       HOSTAPD_LEVEL_DEBUG,
			       "did not acknowledge association response");
		return;
	}

	if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
				      sizeof(mgmt->u.assoc_req))) {
		printf("handle_assoc_cb(reassoc=%d) - too short payload "
		       "(len=%d)\n", reassoc, len);
		return;
	}

	if (reassoc)
		status = le_to_host16(mgmt->u.reassoc_resp.status_code);
	else
		status = le_to_host16(mgmt->u.assoc_resp.status_code);

	sta = ap_get_sta(hapd, mgmt->da);
	if (!sta) {
		printf("handle_assoc_cb: STA " MACSTR " not found\n",
		       MAC2STR(mgmt->da));
		return;
	}

	if (status != WLAN_STATUS_SUCCESS)
		goto fail;

	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
		       HOSTAPD_LEVEL_INFO, "associated (aid %d)", sta->aid);
	if (sta->flags & WLAN_STA_ASSOC)
		new_assoc = 0;
	sta->flags |= WLAN_STA_ASSOC;

	memset(&param, 0, sizeof(param));
	param.cmd = PRISM2_HOSTAPD_ADD_STA;
	memcpy(param.sta_addr, sta->addr, ETH_ALEN);
	param.u.add_sta.aid = sta->aid;
	param.u.add_sta.capability = sta->capability;
	param.u.add_sta.tx_supp_rates = sta->tx_supp_rates;
	if (hostapd_ioctl(hapd->driver.data, &param, sizeof(param))) {
		printf("Could not add station to kernel driver.\n");
	}

	wpa_sm_event(hapd, sta, WPA_ASSOC);
	if (new_assoc)
		hostapd_new_assoc_sta(hapd, sta);
	else
		wpa_sm_event(hapd, sta, WPA_REAUTH);

	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);

 fail:
	/* Copy of the association request is not needed anymore */
	if (sta->last_assoc_req) {
		free(sta->last_assoc_req);
		sta->last_assoc_req = NULL;
	}
}