X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mech_eap.git;a=blobdiff_plain;f=libeap%2Fwpa_supplicant%2Fibss_rsn.c;h=d9d0ae7f10dd63c25a04175d32d3682bac5c3410;hp=0e332534e491efe5b3f5920562c32c71492414e8;hb=4f319dde67a76fe0aaf33f6d2788968012584ada;hpb=ed09b5e64dd485851310307979d5eed14678087b diff --git a/libeap/wpa_supplicant/ibss_rsn.c b/libeap/wpa_supplicant/ibss_rsn.c index 0e33253..d9d0ae7 100644 --- a/libeap/wpa_supplicant/ibss_rsn.c +++ b/libeap/wpa_supplicant/ibss_rsn.c @@ -1,31 +1,44 @@ /* * wpa_supplicant - IBSS RSN - * Copyright (c) 2009, Jouni Malinen + * Copyright (c) 2009-2013, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" #include "common.h" +#include "common/wpa_ctrl.h" +#include "utils/eloop.h" #include "l2_packet/l2_packet.h" #include "rsn_supp/wpa.h" #include "rsn_supp/wpa_ie.h" #include "ap/wpa_auth.h" #include "wpa_supplicant_i.h" #include "driver_i.h" +#include "common/ieee802_11_defs.h" #include "ibss_rsn.h" +static void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx); + + +static struct ibss_rsn_peer * ibss_rsn_get_peer(struct ibss_rsn *ibss_rsn, + const u8 *addr) +{ + struct ibss_rsn_peer *peer; + + for (peer = ibss_rsn->peers; peer; peer = peer->next) + if (os_memcmp(addr, peer->addr, ETH_ALEN) == 0) + break; + return peer; +} + + static void ibss_rsn_free(struct ibss_rsn_peer *peer) { + eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); wpa_auth_sta_deinit(peer->auth); wpa_sm_deinit(peer->supp); os_free(peer); @@ -39,6 +52,13 @@ static void supp_set_state(void *ctx, enum wpa_states state) } +static enum wpa_states supp_get_state(void *ctx) +{ + struct ibss_rsn_peer *peer = ctx; + return peer->supp_state; +} + + static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, size_t len) { @@ -52,7 +72,7 @@ static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, if (wpa_s->l2) return l2_packet_send(wpa_s->l2, dest, proto, buf, len); - return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len); + return -1; } @@ -100,6 +120,22 @@ static int supp_get_beacon_ie(void *ctx) } +static void ibss_check_rsn_completed(struct ibss_rsn_peer *peer) +{ + struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s; + + if ((peer->authentication_status & + (IBSS_RSN_SET_PTK_SUPP | IBSS_RSN_SET_PTK_AUTH)) != + (IBSS_RSN_SET_PTK_SUPP | IBSS_RSN_SET_PTK_AUTH)) + return; + if (peer->authentication_status & IBSS_RSN_REPORTED_PTK) + return; + peer->authentication_status |= IBSS_RSN_REPORTED_PTK; + wpa_msg(wpa_s, MSG_INFO, IBSS_RSN_COMPLETED MACSTR, + MAC2STR(peer->addr)); +} + + static int supp_set_key(void *ctx, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, @@ -114,6 +150,8 @@ static int supp_set_key(void *ctx, enum wpa_alg alg, wpa_hexdump_key(MSG_DEBUG, "SUPP: set_key - key", key, key_len); if (key_idx == 0) { + peer->authentication_status |= IBSS_RSN_SET_PTK_SUPP; + ibss_check_rsn_completed(peer); /* * In IBSS RSN, the pairwise key from the 4-way handshake * initiated by the peer with highest MAC address is used. @@ -125,6 +163,8 @@ static int supp_set_key(void *ctx, enum wpa_alg alg, } } + if (is_broadcast_ether_addr(addr)) + addr = peer->addr; return wpa_drv_set_key(peer->ibss_rsn->wpa_s, alg, addr, key_idx, set_tx, seq, seq_len, key, key_len); } @@ -153,8 +193,14 @@ static void supp_cancel_auth_timeout(void *ctx) } -int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, - const u8 *psk) +static void supp_deauthenticate(void * ctx, int reason_code) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__); +} + + +static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, + const u8 *psk) { struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) @@ -163,6 +209,7 @@ int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, ctx->ctx = peer; ctx->msg_ctx = peer->ibss_rsn->wpa_s; ctx->set_state = supp_set_state; + ctx->get_state = supp_get_state; ctx->ether_send = supp_ether_send; ctx->get_beacon_ie = supp_get_beacon_ie; ctx->alloc_eapol = supp_alloc_eapol; @@ -170,6 +217,7 @@ int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, ctx->get_network_ctx = supp_get_network_ctx; ctx->mlme_setprotection = supp_mlme_setprotection; ctx->cancel_auth_timeout = supp_cancel_auth_timeout; + ctx->deauthenticate = supp_deauthenticate; peer->supp = wpa_sm_init(ctx); if (peer->supp == NULL) { wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); @@ -182,7 +230,7 @@ int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); - wpa_sm_set_pmk(peer->supp, psk, PMK_LEN); + wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL); peer->supp_ie_len = sizeof(peer->supp_ie); if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie, @@ -209,7 +257,8 @@ static void auth_logger(void *ctx, const u8 *addr, logger_level level, } -static const u8 * auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk) +static const u8 * auth_get_psk(void *ctx, const u8 *addr, + const u8 *p2p_dev_addr, const u8 *prev_psk) { struct ibss_rsn *ibss_rsn = ctx; wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", @@ -234,7 +283,7 @@ static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, return l2_packet_send(wpa_s->l2, addr, ETH_P_EAPOL, data, data_len); - return wpa_drv_send_eapol(wpa_s, addr, ETH_P_EAPOL, data, data_len); + return -1; } @@ -257,6 +306,15 @@ static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len); if (idx == 0) { + if (addr) { + struct ibss_rsn_peer *peer; + peer = ibss_rsn_get_peer(ibss_rsn, addr); + if (peer) { + peer->authentication_status |= + IBSS_RSN_SET_PTK_AUTH; + ibss_check_rsn_completed(peer); + } + } /* * In IBSS RSN, the pairwise key from the 4-way handshake * initiated by the peer with highest MAC address is used. @@ -273,6 +331,78 @@ static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, } +static void ibss_rsn_disconnect(void *ctx, const u8 *addr, u16 reason) +{ + struct ibss_rsn *ibss_rsn = ctx; + wpa_drv_sta_deauth(ibss_rsn->wpa_s, addr, reason); +} + + +static int auth_for_each_sta(void *ctx, int (*cb)(struct wpa_state_machine *sm, + void *ctx), + void *cb_ctx) +{ + struct ibss_rsn *ibss_rsn = ctx; + struct ibss_rsn_peer *peer; + + wpa_printf(MSG_DEBUG, "AUTH: for_each_sta"); + + for (peer = ibss_rsn->peers; peer; peer = peer->next) { + if (peer->auth && cb(peer->auth, cb_ctx)) + return 1; + } + + return 0; +} + + +static void ibss_set_sta_authorized(struct ibss_rsn *ibss_rsn, + struct ibss_rsn_peer *peer, int authorized) +{ + int res; + + if (authorized) { + res = wpa_drv_sta_set_flags(ibss_rsn->wpa_s, peer->addr, + WPA_STA_AUTHORIZED, + WPA_STA_AUTHORIZED, ~0); + wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " authorizing port", + MAC2STR(peer->addr)); + } else { + res = wpa_drv_sta_set_flags(ibss_rsn->wpa_s, peer->addr, + 0, 0, ~WPA_STA_AUTHORIZED); + wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " unauthorizing port", + MAC2STR(peer->addr)); + } + + if (res && errno != ENOENT) { + wpa_printf(MSG_DEBUG, "Could not set station " MACSTR " flags " + "for kernel driver (errno=%d)", + MAC2STR(peer->addr), errno); + } +} + + +static void auth_set_eapol(void *ctx, const u8 *addr, + wpa_eapol_variable var, int value) +{ + struct ibss_rsn *ibss_rsn = ctx; + struct ibss_rsn_peer *peer = ibss_rsn_get_peer(ibss_rsn, addr); + + if (peer == NULL) + return; + + switch (var) { + case WPA_EAPOL_authorized: + ibss_set_sta_authorized(ibss_rsn, peer, value); + break; + default: + /* do not handle any other event */ + wpa_printf(MSG_DEBUG, "AUTH: eapol event not handled %d", var); + break; + } +} + + static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn, const u8 *own_addr) { @@ -288,13 +418,17 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn, conf.rsn_pairwise = WPA_CIPHER_CCMP; conf.wpa_group = WPA_CIPHER_CCMP; conf.eapol_version = 2; + conf.wpa_group_rekey = 600; os_memset(&cb, 0, sizeof(cb)); cb.ctx = ibss_rsn; cb.logger = auth_logger; + cb.set_eapol = auth_set_eapol; cb.send_eapol = auth_send_eapol; cb.get_psk = auth_get_psk; cb.set_key = auth_set_key; + cb.for_each_sta = auth_for_each_sta; + cb.disconnect = ibss_rsn_disconnect; ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb); if (ibss_rsn->auth_group == NULL) { @@ -302,6 +436,8 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn, return -1; } + wpa_init_keys(ibss_rsn->auth_group); + return 0; } @@ -309,7 +445,7 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn, static int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn, struct ibss_rsn_peer *peer) { - peer->auth = wpa_auth_sta_init(ibss_rsn->auth_group, peer->addr); + peer->auth = wpa_auth_sta_init(ibss_rsn->auth_group, peer->addr, NULL); if (peer->auth == NULL) { wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); return -1; @@ -337,35 +473,195 @@ static int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn, } -int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr) +static int ibss_rsn_send_auth(struct ibss_rsn *ibss_rsn, const u8 *da, int seq) +{ + struct ieee80211_mgmt auth; + const size_t auth_length = IEEE80211_HDRLEN + sizeof(auth.u.auth); + struct wpa_supplicant *wpa_s = ibss_rsn->wpa_s; + + if (wpa_s->driver->send_frame == NULL) + return -1; + + os_memset(&auth, 0, sizeof(auth)); + + auth.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_AUTH); + os_memcpy(auth.da, da, ETH_ALEN); + os_memcpy(auth.sa, wpa_s->own_addr, ETH_ALEN); + os_memcpy(auth.bssid, wpa_s->bssid, ETH_ALEN); + + auth.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN); + auth.u.auth.auth_transaction = host_to_le16(seq); + auth.u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS); + + wpa_printf(MSG_DEBUG, "RSN: IBSS TX Auth frame (SEQ %d) to " MACSTR, + seq, MAC2STR(da)); + + return wpa_s->driver->send_frame(wpa_s->drv_priv, (u8 *) &auth, + auth_length, 0); +} + + +static int ibss_rsn_is_auth_started(struct ibss_rsn_peer * peer) +{ + return peer->authentication_status & + (IBSS_RSN_AUTH_BY_US | IBSS_RSN_AUTH_EAPOL_BY_US); +} + + +static struct ibss_rsn_peer * +ibss_rsn_peer_init(struct ibss_rsn *ibss_rsn, const u8 *addr) { struct ibss_rsn_peer *peer; + if (ibss_rsn == NULL) + return NULL; + + peer = ibss_rsn_get_peer(ibss_rsn, addr); + if (peer) { + wpa_printf(MSG_DEBUG, "RSN: IBSS Supplicant for peer "MACSTR + " already running", MAC2STR(addr)); + return peer; + } - wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Authenticator and " - "Supplicant for peer " MACSTR, MAC2STR(addr)); + wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Supplicant for peer "MACSTR, + MAC2STR(addr)); peer = os_zalloc(sizeof(*peer)); - if (peer == NULL) - return -1; + if (peer == NULL) { + wpa_printf(MSG_DEBUG, "RSN: Could not allocate memory."); + return NULL; + } peer->ibss_rsn = ibss_rsn; os_memcpy(peer->addr, addr, ETH_ALEN); + peer->authentication_status = IBSS_RSN_AUTH_NOT_AUTHENTICATED; - if (ibss_rsn_supp_init(peer, ibss_rsn->wpa_s->own_addr, ibss_rsn->psk) - < 0) { + if (ibss_rsn_supp_init(peer, ibss_rsn->wpa_s->own_addr, + ibss_rsn->psk) < 0) { ibss_rsn_free(peer); + return NULL; + } + + peer->next = ibss_rsn->peers; + ibss_rsn->peers = peer; + + return peer; +} + + +static void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct ibss_rsn_peer *peer = eloop_ctx; + + /* + * Assume peer does not support Authentication exchange or the frame was + * lost somewhere - start EAPOL Authenticator. + */ + wpa_printf(MSG_DEBUG, + "RSN: Timeout on waiting Authentication frame response from " + MACSTR " - start authenticator", MAC2STR(peer->addr)); + + peer->authentication_status |= IBSS_RSN_AUTH_BY_US; + ibss_rsn_auth_init(peer->ibss_rsn, peer); +} + + +int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr) +{ + struct ibss_rsn_peer *peer; + int res; + + if (!ibss_rsn) return -1; + + /* if the peer already exists, exit immediately */ + peer = ibss_rsn_get_peer(ibss_rsn, addr); + if (peer) + return 0; + + peer = ibss_rsn_peer_init(ibss_rsn, addr); + if (peer == NULL) + return -1; + + /* Open Authentication: send first Authentication frame */ + res = ibss_rsn_send_auth(ibss_rsn, addr, 1); + if (res) { + /* + * The driver may not support Authentication frame exchange in + * IBSS. Ignore authentication and go through EAPOL exchange. + */ + peer->authentication_status |= IBSS_RSN_AUTH_BY_US; + return ibss_rsn_auth_init(ibss_rsn, peer); + } else { + os_get_reltime(&peer->own_auth_tx); + eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL); } - if (ibss_rsn_auth_init(ibss_rsn, peer) < 0) { - ibss_rsn_free(peer); + return 0; +} + + +static int ibss_rsn_peer_authenticated(struct ibss_rsn *ibss_rsn, + struct ibss_rsn_peer *peer, int reason) +{ + int already_started; + + if (ibss_rsn == NULL || peer == NULL) return -1; + + already_started = ibss_rsn_is_auth_started(peer); + peer->authentication_status |= reason; + + if (already_started) { + wpa_printf(MSG_DEBUG, "RSN: IBSS Authenticator already " + "started for peer " MACSTR, MAC2STR(peer->addr)); + return 0; } - peer->next = ibss_rsn->peers; - ibss_rsn->peers = peer; + wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Authenticator " + "for now-authenticated peer " MACSTR, MAC2STR(peer->addr)); - return 0; + return ibss_rsn_auth_init(ibss_rsn, peer); +} + + +void ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac) +{ + struct ibss_rsn_peer *peer, *prev; + + if (ibss_rsn == NULL) + return; + + if (peermac == NULL) { + /* remove all peers */ + wpa_printf(MSG_DEBUG, "%s: Remove all peers", __func__); + peer = ibss_rsn->peers; + while (peer) { + prev = peer; + peer = peer->next; + ibss_rsn_free(prev); + ibss_rsn->peers = peer; + } + } else { + /* remove specific peer */ + wpa_printf(MSG_DEBUG, "%s: Remove specific peer " MACSTR, + __func__, MAC2STR(peermac)); + + for (prev = NULL, peer = ibss_rsn->peers; peer != NULL; + prev = peer, peer = peer->next) { + if (os_memcmp(peermac, peer->addr, ETH_ALEN) == 0) { + if (prev == NULL) + ibss_rsn->peers = peer->next; + else + prev->next = peer->next; + ibss_rsn_free(peer); + wpa_printf(MSG_DEBUG, "%s: Successfully " + "removed a specific peer", + __func__); + break; + } + } + } } @@ -401,7 +697,8 @@ void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn) ibss_rsn_free(prev); } - wpa_deinit(ibss_rsn->auth_group); + if (ibss_rsn->auth_group) + wpa_deinit(ibss_rsn->auth_group); os_free(ibss_rsn); } @@ -466,10 +763,21 @@ static int ibss_rsn_process_rx_eapol(struct ibss_rsn *ibss_rsn, return -1; os_memcpy(tmp, buf, len); if (supp) { - wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Supplicant"); + peer->authentication_status |= IBSS_RSN_AUTH_EAPOL_BY_PEER; + wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Supplicant from " + MACSTR, MAC2STR(peer->addr)); wpa_sm_rx_eapol(peer->supp, peer->addr, tmp, len); } else { - wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Authenticator"); + if (ibss_rsn_is_auth_started(peer) == 0) { + wpa_printf(MSG_DEBUG, "RSN: IBSS EAPOL for " + "Authenticator dropped as " MACSTR " is not " + "authenticated", MAC2STR(peer->addr)); + os_free(tmp); + return -1; + } + + wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Authenticator " + "from "MACSTR, MAC2STR(peer->addr)); wpa_receive(ibss_rsn->auth_group, peer->auth, tmp, len); } os_free(tmp); @@ -483,19 +791,28 @@ int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, { struct ibss_rsn_peer *peer; - for (peer = ibss_rsn->peers; peer; peer = peer->next) { - if (os_memcmp(src_addr, peer->addr, ETH_ALEN) == 0) - return ibss_rsn_process_rx_eapol(ibss_rsn, peer, - buf, len); - } + if (ibss_rsn == NULL) + return -1; + + peer = ibss_rsn_get_peer(ibss_rsn, src_addr); + if (peer) + return ibss_rsn_process_rx_eapol(ibss_rsn, peer, buf, len); if (ibss_rsn_eapol_dst_supp(buf, len) > 0) { /* * Create new IBSS peer based on an EAPOL message from the peer * Authenticator. */ - if (ibss_rsn_start(ibss_rsn, src_addr) < 0) + peer = ibss_rsn_peer_init(ibss_rsn, src_addr); + if (peer == NULL) return -1; + + /* assume the peer is authenticated already */ + wpa_printf(MSG_DEBUG, "RSN: IBSS Not using IBSS Auth for peer " + MACSTR, MAC2STR(src_addr)); + ibss_rsn_peer_authenticated(ibss_rsn, peer, + IBSS_RSN_AUTH_EAPOL_BY_US); + return ibss_rsn_process_rx_eapol(ibss_rsn, ibss_rsn->peers, buf, len); } @@ -503,8 +820,101 @@ int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, return 0; } - void ibss_rsn_set_psk(struct ibss_rsn *ibss_rsn, const u8 *psk) { + if (ibss_rsn == NULL) + return; os_memcpy(ibss_rsn->psk, psk, PMK_LEN); } + + +static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn, + struct ibss_rsn_peer *peer, + const u8* addr) +{ + wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR, + MAC2STR(addr)); + + if (peer && + peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) { + if (peer->own_auth_tx.sec) { + struct os_reltime now, diff; + os_get_reltime(&now); + os_reltime_sub(&now, &peer->own_auth_tx, &diff); + if (diff.sec == 0 && diff.usec < 500000) { + wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX", + (int) diff.usec); + goto skip_reinit; + } + } + /* + * A peer sent us an Authentication frame even though it already + * started an EAPOL session. We should reinit state machines + * here, but it's much more complicated than just deleting and + * recreating the state machine + */ + wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station " + MACSTR, MAC2STR(addr)); + + ibss_rsn_stop(ibss_rsn, addr); + peer = NULL; + } + + if (!peer) { + peer = ibss_rsn_peer_init(ibss_rsn, addr); + if (!peer) + return; + + wpa_printf(MSG_DEBUG, "RSN: IBSS Auth started by peer " MACSTR, + MAC2STR(addr)); + } + +skip_reinit: + /* reply with an Authentication frame now, before sending an EAPOL */ + ibss_rsn_send_auth(ibss_rsn, addr, 2); + /* no need to start another AUTH challenge in the other way.. */ + ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US); +} + + +void ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame, + size_t len) +{ + const struct ieee80211_mgmt *header; + struct ibss_rsn_peer *peer; + size_t auth_length; + + header = (const struct ieee80211_mgmt *) auth_frame; + auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth); + + if (ibss_rsn == NULL || len < auth_length) + return; + + if (le_to_host16(header->u.auth.auth_alg) != WLAN_AUTH_OPEN || + le_to_host16(header->u.auth.status_code) != WLAN_STATUS_SUCCESS) + return; + + peer = ibss_rsn_get_peer(ibss_rsn, header->sa); + + switch (le_to_host16(header->u.auth.auth_transaction)) { + case 1: + ibss_rsn_handle_auth_1_of_2(ibss_rsn, peer, header->sa); + break; + case 2: + wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 2) from " + MACSTR, MAC2STR(header->sa)); + if (!peer) { + wpa_printf(MSG_DEBUG, "RSN: Received Auth seq 2 from " + "unknown STA " MACSTR, MAC2STR(header->sa)); + break; + } + + /* authentication has been completed */ + eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); + wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with " MACSTR, + MAC2STR(header->sa)); + ibss_rsn_peer_authenticated(ibss_rsn, peer, + IBSS_RSN_AUTH_BY_US); + break; + } +}