ibss_rsn.c revision 281806
1214501Srpaulo/* 2214501Srpaulo * wpa_supplicant - IBSS RSN 3281806Srpaulo * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "includes.h" 10214501Srpaulo 11214501Srpaulo#include "common.h" 12281806Srpaulo#include "common/wpa_ctrl.h" 13281806Srpaulo#include "utils/eloop.h" 14214501Srpaulo#include "l2_packet/l2_packet.h" 15214501Srpaulo#include "rsn_supp/wpa.h" 16214501Srpaulo#include "rsn_supp/wpa_ie.h" 17214501Srpaulo#include "ap/wpa_auth.h" 18214501Srpaulo#include "wpa_supplicant_i.h" 19214501Srpaulo#include "driver_i.h" 20281806Srpaulo#include "common/ieee802_11_defs.h" 21214501Srpaulo#include "ibss_rsn.h" 22214501Srpaulo 23214501Srpaulo 24281806Srpaulostatic void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx); 25281806Srpaulo 26281806Srpaulo 27252726Srpaulostatic struct ibss_rsn_peer * ibss_rsn_get_peer(struct ibss_rsn *ibss_rsn, 28252726Srpaulo const u8 *addr) 29252726Srpaulo{ 30252726Srpaulo struct ibss_rsn_peer *peer; 31252726Srpaulo 32252726Srpaulo for (peer = ibss_rsn->peers; peer; peer = peer->next) 33252726Srpaulo if (os_memcmp(addr, peer->addr, ETH_ALEN) == 0) 34252726Srpaulo break; 35252726Srpaulo return peer; 36252726Srpaulo} 37252726Srpaulo 38252726Srpaulo 39214501Srpaulostatic void ibss_rsn_free(struct ibss_rsn_peer *peer) 40214501Srpaulo{ 41281806Srpaulo eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); 42214501Srpaulo wpa_auth_sta_deinit(peer->auth); 43214501Srpaulo wpa_sm_deinit(peer->supp); 44214501Srpaulo os_free(peer); 45214501Srpaulo} 46214501Srpaulo 47214501Srpaulo 48214501Srpaulostatic void supp_set_state(void *ctx, enum wpa_states state) 49214501Srpaulo{ 50214501Srpaulo struct ibss_rsn_peer *peer = ctx; 51214501Srpaulo peer->supp_state = state; 52214501Srpaulo} 53214501Srpaulo 54214501Srpaulo 55252726Srpaulostatic enum wpa_states supp_get_state(void *ctx) 56252726Srpaulo{ 57252726Srpaulo struct ibss_rsn_peer *peer = ctx; 58252726Srpaulo return peer->supp_state; 59252726Srpaulo} 60252726Srpaulo 61252726Srpaulo 62214501Srpaulostatic int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, 63214501Srpaulo size_t len) 64214501Srpaulo{ 65214501Srpaulo struct ibss_rsn_peer *peer = ctx; 66214501Srpaulo struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s; 67214501Srpaulo 68214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " 69214501Srpaulo "len=%lu)", 70214501Srpaulo __func__, MAC2STR(dest), proto, (unsigned long) len); 71214501Srpaulo 72214501Srpaulo if (wpa_s->l2) 73214501Srpaulo return l2_packet_send(wpa_s->l2, dest, proto, buf, len); 74214501Srpaulo 75281806Srpaulo return -1; 76214501Srpaulo} 77214501Srpaulo 78214501Srpaulo 79214501Srpaulostatic u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, 80214501Srpaulo u16 data_len, size_t *msg_len, void **data_pos) 81214501Srpaulo{ 82214501Srpaulo struct ieee802_1x_hdr *hdr; 83214501Srpaulo 84214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", 85214501Srpaulo __func__, type, data_len); 86214501Srpaulo 87214501Srpaulo *msg_len = sizeof(*hdr) + data_len; 88214501Srpaulo hdr = os_malloc(*msg_len); 89214501Srpaulo if (hdr == NULL) 90214501Srpaulo return NULL; 91214501Srpaulo 92214501Srpaulo hdr->version = 2; 93214501Srpaulo hdr->type = type; 94214501Srpaulo hdr->length = host_to_be16(data_len); 95214501Srpaulo 96214501Srpaulo if (data) 97214501Srpaulo os_memcpy(hdr + 1, data, data_len); 98214501Srpaulo else 99214501Srpaulo os_memset(hdr + 1, 0, data_len); 100214501Srpaulo 101214501Srpaulo if (data_pos) 102214501Srpaulo *data_pos = hdr + 1; 103214501Srpaulo 104214501Srpaulo return (u8 *) hdr; 105214501Srpaulo} 106214501Srpaulo 107214501Srpaulo 108214501Srpaulostatic int supp_get_beacon_ie(void *ctx) 109214501Srpaulo{ 110214501Srpaulo struct ibss_rsn_peer *peer = ctx; 111214501Srpaulo 112214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 113214501Srpaulo /* TODO: get correct RSN IE */ 114214501Srpaulo return wpa_sm_set_ap_rsn_ie(peer->supp, 115214501Srpaulo (u8 *) "\x30\x14\x01\x00" 116214501Srpaulo "\x00\x0f\xac\x04" 117214501Srpaulo "\x01\x00\x00\x0f\xac\x04" 118214501Srpaulo "\x01\x00\x00\x0f\xac\x02" 119214501Srpaulo "\x00\x00", 22); 120214501Srpaulo} 121214501Srpaulo 122214501Srpaulo 123281806Srpaulostatic void ibss_check_rsn_completed(struct ibss_rsn_peer *peer) 124281806Srpaulo{ 125281806Srpaulo struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s; 126281806Srpaulo 127281806Srpaulo if ((peer->authentication_status & 128281806Srpaulo (IBSS_RSN_SET_PTK_SUPP | IBSS_RSN_SET_PTK_AUTH)) != 129281806Srpaulo (IBSS_RSN_SET_PTK_SUPP | IBSS_RSN_SET_PTK_AUTH)) 130281806Srpaulo return; 131281806Srpaulo if (peer->authentication_status & IBSS_RSN_REPORTED_PTK) 132281806Srpaulo return; 133281806Srpaulo peer->authentication_status |= IBSS_RSN_REPORTED_PTK; 134281806Srpaulo wpa_msg(wpa_s, MSG_INFO, IBSS_RSN_COMPLETED MACSTR, 135281806Srpaulo MAC2STR(peer->addr)); 136281806Srpaulo} 137281806Srpaulo 138281806Srpaulo 139214501Srpaulostatic int supp_set_key(void *ctx, enum wpa_alg alg, 140214501Srpaulo const u8 *addr, int key_idx, int set_tx, 141214501Srpaulo const u8 *seq, size_t seq_len, 142214501Srpaulo const u8 *key, size_t key_len) 143214501Srpaulo{ 144214501Srpaulo struct ibss_rsn_peer *peer = ctx; 145214501Srpaulo 146214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " 147214501Srpaulo "set_tx=%d)", 148214501Srpaulo __func__, alg, MAC2STR(addr), key_idx, set_tx); 149214501Srpaulo wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); 150214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "SUPP: set_key - key", key, key_len); 151214501Srpaulo 152214501Srpaulo if (key_idx == 0) { 153281806Srpaulo peer->authentication_status |= IBSS_RSN_SET_PTK_SUPP; 154281806Srpaulo ibss_check_rsn_completed(peer); 155214501Srpaulo /* 156214501Srpaulo * In IBSS RSN, the pairwise key from the 4-way handshake 157214501Srpaulo * initiated by the peer with highest MAC address is used. 158214501Srpaulo */ 159214501Srpaulo if (os_memcmp(peer->ibss_rsn->wpa_s->own_addr, peer->addr, 160214501Srpaulo ETH_ALEN) > 0) { 161214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: Do not use this PTK"); 162214501Srpaulo return 0; 163214501Srpaulo } 164214501Srpaulo } 165214501Srpaulo 166252726Srpaulo if (is_broadcast_ether_addr(addr)) 167252726Srpaulo addr = peer->addr; 168214501Srpaulo return wpa_drv_set_key(peer->ibss_rsn->wpa_s, alg, addr, key_idx, 169214501Srpaulo set_tx, seq, seq_len, key, key_len); 170214501Srpaulo} 171214501Srpaulo 172214501Srpaulo 173214501Srpaulostatic void * supp_get_network_ctx(void *ctx) 174214501Srpaulo{ 175214501Srpaulo struct ibss_rsn_peer *peer = ctx; 176214501Srpaulo return wpa_supplicant_get_ssid(peer->ibss_rsn->wpa_s); 177214501Srpaulo} 178214501Srpaulo 179214501Srpaulo 180214501Srpaulostatic int supp_mlme_setprotection(void *ctx, const u8 *addr, 181214501Srpaulo int protection_type, int key_type) 182214501Srpaulo{ 183214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " 184214501Srpaulo "key_type=%d)", 185214501Srpaulo __func__, MAC2STR(addr), protection_type, key_type); 186214501Srpaulo return 0; 187214501Srpaulo} 188214501Srpaulo 189214501Srpaulo 190214501Srpaulostatic void supp_cancel_auth_timeout(void *ctx) 191214501Srpaulo{ 192214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 193214501Srpaulo} 194214501Srpaulo 195214501Srpaulo 196252726Srpaulostatic void supp_deauthenticate(void * ctx, int reason_code) 197214501Srpaulo{ 198252726Srpaulo wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__); 199252726Srpaulo} 200252726Srpaulo 201252726Srpaulo 202252726Srpaulostatic int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, 203252726Srpaulo const u8 *psk) 204252726Srpaulo{ 205214501Srpaulo struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); 206214501Srpaulo if (ctx == NULL) 207214501Srpaulo return -1; 208214501Srpaulo 209214501Srpaulo ctx->ctx = peer; 210214501Srpaulo ctx->msg_ctx = peer->ibss_rsn->wpa_s; 211214501Srpaulo ctx->set_state = supp_set_state; 212252726Srpaulo ctx->get_state = supp_get_state; 213214501Srpaulo ctx->ether_send = supp_ether_send; 214214501Srpaulo ctx->get_beacon_ie = supp_get_beacon_ie; 215214501Srpaulo ctx->alloc_eapol = supp_alloc_eapol; 216214501Srpaulo ctx->set_key = supp_set_key; 217214501Srpaulo ctx->get_network_ctx = supp_get_network_ctx; 218214501Srpaulo ctx->mlme_setprotection = supp_mlme_setprotection; 219214501Srpaulo ctx->cancel_auth_timeout = supp_cancel_auth_timeout; 220252726Srpaulo ctx->deauthenticate = supp_deauthenticate; 221214501Srpaulo peer->supp = wpa_sm_init(ctx); 222214501Srpaulo if (peer->supp == NULL) { 223214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); 224214501Srpaulo return -1; 225214501Srpaulo } 226214501Srpaulo 227214501Srpaulo wpa_sm_set_own_addr(peer->supp, own_addr); 228214501Srpaulo wpa_sm_set_param(peer->supp, WPA_PARAM_RSN_ENABLED, 1); 229214501Srpaulo wpa_sm_set_param(peer->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); 230214501Srpaulo wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); 231214501Srpaulo wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); 232214501Srpaulo wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); 233281806Srpaulo wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL); 234214501Srpaulo 235214501Srpaulo peer->supp_ie_len = sizeof(peer->supp_ie); 236214501Srpaulo if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie, 237214501Srpaulo &peer->supp_ie_len) < 0) { 238214501Srpaulo wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" 239214501Srpaulo " failed"); 240214501Srpaulo return -1; 241214501Srpaulo } 242214501Srpaulo 243214501Srpaulo wpa_sm_notify_assoc(peer->supp, peer->addr); 244214501Srpaulo 245214501Srpaulo return 0; 246214501Srpaulo} 247214501Srpaulo 248214501Srpaulo 249214501Srpaulostatic void auth_logger(void *ctx, const u8 *addr, logger_level level, 250214501Srpaulo const char *txt) 251214501Srpaulo{ 252214501Srpaulo if (addr) 253214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s", 254214501Srpaulo MAC2STR(addr), txt); 255214501Srpaulo else 256214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: %s", txt); 257214501Srpaulo} 258214501Srpaulo 259214501Srpaulo 260281806Srpaulostatic const u8 * auth_get_psk(void *ctx, const u8 *addr, 261281806Srpaulo const u8 *p2p_dev_addr, const u8 *prev_psk) 262214501Srpaulo{ 263214501Srpaulo struct ibss_rsn *ibss_rsn = ctx; 264214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", 265214501Srpaulo __func__, MAC2STR(addr), prev_psk); 266214501Srpaulo if (prev_psk) 267214501Srpaulo return NULL; 268214501Srpaulo return ibss_rsn->psk; 269214501Srpaulo} 270214501Srpaulo 271214501Srpaulo 272214501Srpaulostatic int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, 273214501Srpaulo size_t data_len, int encrypt) 274214501Srpaulo{ 275214501Srpaulo struct ibss_rsn *ibss_rsn = ctx; 276214501Srpaulo struct wpa_supplicant *wpa_s = ibss_rsn->wpa_s; 277214501Srpaulo 278214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu " 279214501Srpaulo "encrypt=%d)", 280214501Srpaulo __func__, MAC2STR(addr), (unsigned long) data_len, encrypt); 281214501Srpaulo 282214501Srpaulo if (wpa_s->l2) 283214501Srpaulo return l2_packet_send(wpa_s->l2, addr, ETH_P_EAPOL, data, 284214501Srpaulo data_len); 285214501Srpaulo 286281806Srpaulo return -1; 287214501Srpaulo} 288214501Srpaulo 289214501Srpaulo 290214501Srpaulostatic int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, 291214501Srpaulo const u8 *addr, int idx, u8 *key, size_t key_len) 292214501Srpaulo{ 293214501Srpaulo struct ibss_rsn *ibss_rsn = ctx; 294214501Srpaulo u8 seq[6]; 295214501Srpaulo 296214501Srpaulo os_memset(seq, 0, sizeof(seq)); 297214501Srpaulo 298214501Srpaulo if (addr) { 299214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d addr=" MACSTR 300214501Srpaulo " key_idx=%d)", 301214501Srpaulo __func__, alg, MAC2STR(addr), idx); 302214501Srpaulo } else { 303214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d key_idx=%d)", 304214501Srpaulo __func__, alg, idx); 305214501Srpaulo } 306214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len); 307214501Srpaulo 308214501Srpaulo if (idx == 0) { 309281806Srpaulo if (addr) { 310281806Srpaulo struct ibss_rsn_peer *peer; 311281806Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, addr); 312281806Srpaulo if (peer) { 313281806Srpaulo peer->authentication_status |= 314281806Srpaulo IBSS_RSN_SET_PTK_AUTH; 315281806Srpaulo ibss_check_rsn_completed(peer); 316281806Srpaulo } 317281806Srpaulo } 318214501Srpaulo /* 319214501Srpaulo * In IBSS RSN, the pairwise key from the 4-way handshake 320214501Srpaulo * initiated by the peer with highest MAC address is used. 321214501Srpaulo */ 322214501Srpaulo if (addr == NULL || 323214501Srpaulo os_memcmp(ibss_rsn->wpa_s->own_addr, addr, ETH_ALEN) < 0) { 324214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: Do not use this PTK"); 325214501Srpaulo return 0; 326214501Srpaulo } 327214501Srpaulo } 328214501Srpaulo 329214501Srpaulo return wpa_drv_set_key(ibss_rsn->wpa_s, alg, addr, idx, 330214501Srpaulo 1, seq, 6, key, key_len); 331214501Srpaulo} 332214501Srpaulo 333214501Srpaulo 334281806Srpaulostatic void ibss_rsn_disconnect(void *ctx, const u8 *addr, u16 reason) 335281806Srpaulo{ 336281806Srpaulo struct ibss_rsn *ibss_rsn = ctx; 337281806Srpaulo wpa_drv_sta_deauth(ibss_rsn->wpa_s, addr, reason); 338281806Srpaulo} 339281806Srpaulo 340281806Srpaulo 341252726Srpaulostatic int auth_for_each_sta(void *ctx, int (*cb)(struct wpa_state_machine *sm, 342252726Srpaulo void *ctx), 343252726Srpaulo void *cb_ctx) 344252726Srpaulo{ 345252726Srpaulo struct ibss_rsn *ibss_rsn = ctx; 346252726Srpaulo struct ibss_rsn_peer *peer; 347252726Srpaulo 348252726Srpaulo wpa_printf(MSG_DEBUG, "AUTH: for_each_sta"); 349252726Srpaulo 350252726Srpaulo for (peer = ibss_rsn->peers; peer; peer = peer->next) { 351252726Srpaulo if (peer->auth && cb(peer->auth, cb_ctx)) 352252726Srpaulo return 1; 353252726Srpaulo } 354252726Srpaulo 355252726Srpaulo return 0; 356252726Srpaulo} 357252726Srpaulo 358252726Srpaulo 359252726Srpaulostatic void ibss_set_sta_authorized(struct ibss_rsn *ibss_rsn, 360252726Srpaulo struct ibss_rsn_peer *peer, int authorized) 361252726Srpaulo{ 362252726Srpaulo int res; 363252726Srpaulo 364252726Srpaulo if (authorized) { 365252726Srpaulo res = wpa_drv_sta_set_flags(ibss_rsn->wpa_s, peer->addr, 366252726Srpaulo WPA_STA_AUTHORIZED, 367252726Srpaulo WPA_STA_AUTHORIZED, ~0); 368252726Srpaulo wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " authorizing port", 369252726Srpaulo MAC2STR(peer->addr)); 370252726Srpaulo } else { 371252726Srpaulo res = wpa_drv_sta_set_flags(ibss_rsn->wpa_s, peer->addr, 372252726Srpaulo 0, 0, ~WPA_STA_AUTHORIZED); 373252726Srpaulo wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " unauthorizing port", 374252726Srpaulo MAC2STR(peer->addr)); 375252726Srpaulo } 376252726Srpaulo 377252726Srpaulo if (res && errno != ENOENT) { 378252726Srpaulo wpa_printf(MSG_DEBUG, "Could not set station " MACSTR " flags " 379252726Srpaulo "for kernel driver (errno=%d)", 380252726Srpaulo MAC2STR(peer->addr), errno); 381252726Srpaulo } 382252726Srpaulo} 383252726Srpaulo 384252726Srpaulo 385252726Srpaulostatic void auth_set_eapol(void *ctx, const u8 *addr, 386252726Srpaulo wpa_eapol_variable var, int value) 387252726Srpaulo{ 388252726Srpaulo struct ibss_rsn *ibss_rsn = ctx; 389252726Srpaulo struct ibss_rsn_peer *peer = ibss_rsn_get_peer(ibss_rsn, addr); 390252726Srpaulo 391252726Srpaulo if (peer == NULL) 392252726Srpaulo return; 393252726Srpaulo 394252726Srpaulo switch (var) { 395252726Srpaulo case WPA_EAPOL_authorized: 396252726Srpaulo ibss_set_sta_authorized(ibss_rsn, peer, value); 397252726Srpaulo break; 398252726Srpaulo default: 399252726Srpaulo /* do not handle any other event */ 400252726Srpaulo wpa_printf(MSG_DEBUG, "AUTH: eapol event not handled %d", var); 401252726Srpaulo break; 402252726Srpaulo } 403252726Srpaulo} 404252726Srpaulo 405252726Srpaulo 406214501Srpaulostatic int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn, 407214501Srpaulo const u8 *own_addr) 408214501Srpaulo{ 409214501Srpaulo struct wpa_auth_config conf; 410214501Srpaulo struct wpa_auth_callbacks cb; 411214501Srpaulo 412214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine"); 413214501Srpaulo 414214501Srpaulo os_memset(&conf, 0, sizeof(conf)); 415214501Srpaulo conf.wpa = 2; 416214501Srpaulo conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; 417214501Srpaulo conf.wpa_pairwise = WPA_CIPHER_CCMP; 418214501Srpaulo conf.rsn_pairwise = WPA_CIPHER_CCMP; 419214501Srpaulo conf.wpa_group = WPA_CIPHER_CCMP; 420214501Srpaulo conf.eapol_version = 2; 421252726Srpaulo conf.wpa_group_rekey = 600; 422214501Srpaulo 423214501Srpaulo os_memset(&cb, 0, sizeof(cb)); 424214501Srpaulo cb.ctx = ibss_rsn; 425214501Srpaulo cb.logger = auth_logger; 426252726Srpaulo cb.set_eapol = auth_set_eapol; 427214501Srpaulo cb.send_eapol = auth_send_eapol; 428214501Srpaulo cb.get_psk = auth_get_psk; 429214501Srpaulo cb.set_key = auth_set_key; 430252726Srpaulo cb.for_each_sta = auth_for_each_sta; 431281806Srpaulo cb.disconnect = ibss_rsn_disconnect; 432214501Srpaulo 433214501Srpaulo ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb); 434214501Srpaulo if (ibss_rsn->auth_group == NULL) { 435214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); 436214501Srpaulo return -1; 437214501Srpaulo } 438214501Srpaulo 439252726Srpaulo wpa_init_keys(ibss_rsn->auth_group); 440252726Srpaulo 441214501Srpaulo return 0; 442214501Srpaulo} 443214501Srpaulo 444214501Srpaulo 445214501Srpaulostatic int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn, 446214501Srpaulo struct ibss_rsn_peer *peer) 447214501Srpaulo{ 448281806Srpaulo peer->auth = wpa_auth_sta_init(ibss_rsn->auth_group, peer->addr, NULL); 449214501Srpaulo if (peer->auth == NULL) { 450214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); 451214501Srpaulo return -1; 452214501Srpaulo } 453214501Srpaulo 454214501Srpaulo /* TODO: get peer RSN IE with Probe Request */ 455214501Srpaulo if (wpa_validate_wpa_ie(ibss_rsn->auth_group, peer->auth, 456214501Srpaulo (u8 *) "\x30\x14\x01\x00" 457214501Srpaulo "\x00\x0f\xac\x04" 458214501Srpaulo "\x01\x00\x00\x0f\xac\x04" 459214501Srpaulo "\x01\x00\x00\x0f\xac\x02" 460214501Srpaulo "\x00\x00", 22, NULL, 0) != 461214501Srpaulo WPA_IE_OK) { 462214501Srpaulo wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); 463214501Srpaulo return -1; 464214501Srpaulo } 465214501Srpaulo 466214501Srpaulo if (wpa_auth_sm_event(peer->auth, WPA_ASSOC)) 467214501Srpaulo return -1; 468214501Srpaulo 469214501Srpaulo if (wpa_auth_sta_associated(ibss_rsn->auth_group, peer->auth)) 470214501Srpaulo return -1; 471214501Srpaulo 472214501Srpaulo return 0; 473214501Srpaulo} 474214501Srpaulo 475214501Srpaulo 476281806Srpaulostatic int ibss_rsn_send_auth(struct ibss_rsn *ibss_rsn, const u8 *da, int seq) 477214501Srpaulo{ 478281806Srpaulo struct ieee80211_mgmt auth; 479281806Srpaulo const size_t auth_length = IEEE80211_HDRLEN + sizeof(auth.u.auth); 480281806Srpaulo struct wpa_supplicant *wpa_s = ibss_rsn->wpa_s; 481214501Srpaulo 482281806Srpaulo if (wpa_s->driver->send_frame == NULL) 483252726Srpaulo return -1; 484252726Srpaulo 485281806Srpaulo os_memset(&auth, 0, sizeof(auth)); 486281806Srpaulo 487281806Srpaulo auth.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 488281806Srpaulo WLAN_FC_STYPE_AUTH); 489281806Srpaulo os_memcpy(auth.da, da, ETH_ALEN); 490281806Srpaulo os_memcpy(auth.sa, wpa_s->own_addr, ETH_ALEN); 491281806Srpaulo os_memcpy(auth.bssid, wpa_s->bssid, ETH_ALEN); 492281806Srpaulo 493281806Srpaulo auth.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN); 494281806Srpaulo auth.u.auth.auth_transaction = host_to_le16(seq); 495281806Srpaulo auth.u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS); 496281806Srpaulo 497281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS TX Auth frame (SEQ %d) to " MACSTR, 498281806Srpaulo seq, MAC2STR(da)); 499281806Srpaulo 500281806Srpaulo return wpa_s->driver->send_frame(wpa_s->drv_priv, (u8 *) &auth, 501281806Srpaulo auth_length, 0); 502281806Srpaulo} 503281806Srpaulo 504281806Srpaulo 505281806Srpaulostatic int ibss_rsn_is_auth_started(struct ibss_rsn_peer * peer) 506281806Srpaulo{ 507281806Srpaulo return peer->authentication_status & 508281806Srpaulo (IBSS_RSN_AUTH_BY_US | IBSS_RSN_AUTH_EAPOL_BY_US); 509281806Srpaulo} 510281806Srpaulo 511281806Srpaulo 512281806Srpaulostatic struct ibss_rsn_peer * 513281806Srpauloibss_rsn_peer_init(struct ibss_rsn *ibss_rsn, const u8 *addr) 514281806Srpaulo{ 515281806Srpaulo struct ibss_rsn_peer *peer; 516281806Srpaulo if (ibss_rsn == NULL) 517281806Srpaulo return NULL; 518281806Srpaulo 519281806Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, addr); 520281806Srpaulo if (peer) { 521281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Supplicant for peer "MACSTR 522281806Srpaulo " already running", MAC2STR(addr)); 523281806Srpaulo return peer; 524252726Srpaulo } 525252726Srpaulo 526281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Supplicant for peer "MACSTR, 527281806Srpaulo MAC2STR(addr)); 528214501Srpaulo 529214501Srpaulo peer = os_zalloc(sizeof(*peer)); 530281806Srpaulo if (peer == NULL) { 531281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Could not allocate memory."); 532281806Srpaulo return NULL; 533281806Srpaulo } 534214501Srpaulo 535214501Srpaulo peer->ibss_rsn = ibss_rsn; 536214501Srpaulo os_memcpy(peer->addr, addr, ETH_ALEN); 537281806Srpaulo peer->authentication_status = IBSS_RSN_AUTH_NOT_AUTHENTICATED; 538214501Srpaulo 539281806Srpaulo if (ibss_rsn_supp_init(peer, ibss_rsn->wpa_s->own_addr, 540281806Srpaulo ibss_rsn->psk) < 0) { 541214501Srpaulo ibss_rsn_free(peer); 542281806Srpaulo return NULL; 543281806Srpaulo } 544281806Srpaulo 545281806Srpaulo peer->next = ibss_rsn->peers; 546281806Srpaulo ibss_rsn->peers = peer; 547281806Srpaulo 548281806Srpaulo return peer; 549281806Srpaulo} 550281806Srpaulo 551281806Srpaulo 552281806Srpaulostatic void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx) 553281806Srpaulo{ 554281806Srpaulo struct ibss_rsn_peer *peer = eloop_ctx; 555281806Srpaulo 556281806Srpaulo /* 557281806Srpaulo * Assume peer does not support Authentication exchange or the frame was 558281806Srpaulo * lost somewhere - start EAPOL Authenticator. 559281806Srpaulo */ 560281806Srpaulo wpa_printf(MSG_DEBUG, 561281806Srpaulo "RSN: Timeout on waiting Authentication frame response from " 562281806Srpaulo MACSTR " - start authenticator", MAC2STR(peer->addr)); 563281806Srpaulo 564281806Srpaulo peer->authentication_status |= IBSS_RSN_AUTH_BY_US; 565281806Srpaulo ibss_rsn_auth_init(peer->ibss_rsn, peer); 566281806Srpaulo} 567281806Srpaulo 568281806Srpaulo 569281806Srpauloint ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr) 570281806Srpaulo{ 571281806Srpaulo struct ibss_rsn_peer *peer; 572281806Srpaulo int res; 573281806Srpaulo 574281806Srpaulo /* if the peer already exists, exit immediately */ 575281806Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, addr); 576281806Srpaulo if (peer) 577281806Srpaulo return 0; 578281806Srpaulo 579281806Srpaulo peer = ibss_rsn_peer_init(ibss_rsn, addr); 580281806Srpaulo if (peer == NULL) 581214501Srpaulo return -1; 582281806Srpaulo 583281806Srpaulo /* Open Authentication: send first Authentication frame */ 584281806Srpaulo res = ibss_rsn_send_auth(ibss_rsn, addr, 1); 585281806Srpaulo if (res) { 586281806Srpaulo /* 587281806Srpaulo * The driver may not support Authentication frame exchange in 588281806Srpaulo * IBSS. Ignore authentication and go through EAPOL exchange. 589281806Srpaulo */ 590281806Srpaulo peer->authentication_status |= IBSS_RSN_AUTH_BY_US; 591281806Srpaulo return ibss_rsn_auth_init(ibss_rsn, peer); 592281806Srpaulo } else { 593281806Srpaulo os_get_reltime(&peer->own_auth_tx); 594281806Srpaulo eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL); 595214501Srpaulo } 596214501Srpaulo 597281806Srpaulo return 0; 598281806Srpaulo} 599281806Srpaulo 600281806Srpaulo 601281806Srpaulostatic int ibss_rsn_peer_authenticated(struct ibss_rsn *ibss_rsn, 602281806Srpaulo struct ibss_rsn_peer *peer, int reason) 603281806Srpaulo{ 604281806Srpaulo int already_started; 605281806Srpaulo 606281806Srpaulo if (ibss_rsn == NULL || peer == NULL) 607214501Srpaulo return -1; 608281806Srpaulo 609281806Srpaulo already_started = ibss_rsn_is_auth_started(peer); 610281806Srpaulo peer->authentication_status |= reason; 611281806Srpaulo 612281806Srpaulo if (already_started) { 613281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Authenticator already " 614281806Srpaulo "started for peer " MACSTR, MAC2STR(peer->addr)); 615281806Srpaulo return 0; 616214501Srpaulo } 617214501Srpaulo 618281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Authenticator " 619281806Srpaulo "for now-authenticated peer " MACSTR, MAC2STR(peer->addr)); 620214501Srpaulo 621281806Srpaulo return ibss_rsn_auth_init(ibss_rsn, peer); 622214501Srpaulo} 623214501Srpaulo 624214501Srpaulo 625252726Srpaulovoid ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac) 626252726Srpaulo{ 627252726Srpaulo struct ibss_rsn_peer *peer, *prev; 628252726Srpaulo 629252726Srpaulo if (ibss_rsn == NULL) 630252726Srpaulo return; 631252726Srpaulo 632252726Srpaulo if (peermac == NULL) { 633252726Srpaulo /* remove all peers */ 634252726Srpaulo wpa_printf(MSG_DEBUG, "%s: Remove all peers", __func__); 635252726Srpaulo peer = ibss_rsn->peers; 636252726Srpaulo while (peer) { 637252726Srpaulo prev = peer; 638252726Srpaulo peer = peer->next; 639252726Srpaulo ibss_rsn_free(prev); 640252726Srpaulo ibss_rsn->peers = peer; 641252726Srpaulo } 642252726Srpaulo } else { 643252726Srpaulo /* remove specific peer */ 644252726Srpaulo wpa_printf(MSG_DEBUG, "%s: Remove specific peer " MACSTR, 645252726Srpaulo __func__, MAC2STR(peermac)); 646252726Srpaulo 647252726Srpaulo for (prev = NULL, peer = ibss_rsn->peers; peer != NULL; 648252726Srpaulo prev = peer, peer = peer->next) { 649252726Srpaulo if (os_memcmp(peermac, peer->addr, ETH_ALEN) == 0) { 650252726Srpaulo if (prev == NULL) 651252726Srpaulo ibss_rsn->peers = peer->next; 652252726Srpaulo else 653252726Srpaulo prev->next = peer->next; 654252726Srpaulo ibss_rsn_free(peer); 655252726Srpaulo wpa_printf(MSG_DEBUG, "%s: Successfully " 656252726Srpaulo "removed a specific peer", 657252726Srpaulo __func__); 658252726Srpaulo break; 659252726Srpaulo } 660252726Srpaulo } 661252726Srpaulo } 662252726Srpaulo} 663252726Srpaulo 664252726Srpaulo 665214501Srpaulostruct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s) 666214501Srpaulo{ 667214501Srpaulo struct ibss_rsn *ibss_rsn; 668214501Srpaulo 669214501Srpaulo ibss_rsn = os_zalloc(sizeof(*ibss_rsn)); 670214501Srpaulo if (ibss_rsn == NULL) 671214501Srpaulo return NULL; 672214501Srpaulo ibss_rsn->wpa_s = wpa_s; 673214501Srpaulo 674214501Srpaulo if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr) < 0) { 675214501Srpaulo ibss_rsn_deinit(ibss_rsn); 676214501Srpaulo return NULL; 677214501Srpaulo } 678214501Srpaulo 679214501Srpaulo return ibss_rsn; 680214501Srpaulo} 681214501Srpaulo 682214501Srpaulo 683214501Srpaulovoid ibss_rsn_deinit(struct ibss_rsn *ibss_rsn) 684214501Srpaulo{ 685214501Srpaulo struct ibss_rsn_peer *peer, *prev; 686214501Srpaulo 687214501Srpaulo if (ibss_rsn == NULL) 688214501Srpaulo return; 689214501Srpaulo 690214501Srpaulo peer = ibss_rsn->peers; 691214501Srpaulo while (peer) { 692214501Srpaulo prev = peer; 693214501Srpaulo peer = peer->next; 694214501Srpaulo ibss_rsn_free(prev); 695214501Srpaulo } 696214501Srpaulo 697214501Srpaulo wpa_deinit(ibss_rsn->auth_group); 698214501Srpaulo os_free(ibss_rsn); 699214501Srpaulo 700214501Srpaulo} 701214501Srpaulo 702214501Srpaulo 703214501Srpaulostatic int ibss_rsn_eapol_dst_supp(const u8 *buf, size_t len) 704214501Srpaulo{ 705214501Srpaulo const struct ieee802_1x_hdr *hdr; 706214501Srpaulo const struct wpa_eapol_key *key; 707214501Srpaulo u16 key_info; 708214501Srpaulo size_t plen; 709214501Srpaulo 710214501Srpaulo /* TODO: Support other EAPOL packets than just EAPOL-Key */ 711214501Srpaulo 712214501Srpaulo if (len < sizeof(*hdr) + sizeof(*key)) 713214501Srpaulo return -1; 714214501Srpaulo 715214501Srpaulo hdr = (const struct ieee802_1x_hdr *) buf; 716214501Srpaulo key = (const struct wpa_eapol_key *) (hdr + 1); 717214501Srpaulo plen = be_to_host16(hdr->length); 718214501Srpaulo 719214501Srpaulo if (hdr->version < EAPOL_VERSION) { 720214501Srpaulo /* TODO: backwards compatibility */ 721214501Srpaulo } 722214501Srpaulo if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { 723214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: EAPOL frame (type %u) discarded, " 724214501Srpaulo "not a Key frame", hdr->type); 725214501Srpaulo return -1; 726214501Srpaulo } 727214501Srpaulo if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { 728214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: EAPOL frame payload size %lu " 729214501Srpaulo "invalid (frame size %lu)", 730214501Srpaulo (unsigned long) plen, (unsigned long) len); 731214501Srpaulo return -1; 732214501Srpaulo } 733214501Srpaulo 734214501Srpaulo if (key->type != EAPOL_KEY_TYPE_RSN) { 735214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: EAPOL-Key type (%d) unknown, " 736214501Srpaulo "discarded", key->type); 737214501Srpaulo return -1; 738214501Srpaulo } 739214501Srpaulo 740214501Srpaulo key_info = WPA_GET_BE16(key->key_info); 741214501Srpaulo 742214501Srpaulo return !!(key_info & WPA_KEY_INFO_ACK); 743214501Srpaulo} 744214501Srpaulo 745214501Srpaulo 746214501Srpaulostatic int ibss_rsn_process_rx_eapol(struct ibss_rsn *ibss_rsn, 747214501Srpaulo struct ibss_rsn_peer *peer, 748214501Srpaulo const u8 *buf, size_t len) 749214501Srpaulo{ 750214501Srpaulo int supp; 751214501Srpaulo u8 *tmp; 752214501Srpaulo 753214501Srpaulo supp = ibss_rsn_eapol_dst_supp(buf, len); 754214501Srpaulo if (supp < 0) 755214501Srpaulo return -1; 756214501Srpaulo 757214501Srpaulo tmp = os_malloc(len); 758214501Srpaulo if (tmp == NULL) 759214501Srpaulo return -1; 760214501Srpaulo os_memcpy(tmp, buf, len); 761214501Srpaulo if (supp) { 762281806Srpaulo peer->authentication_status |= IBSS_RSN_AUTH_EAPOL_BY_PEER; 763281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Supplicant from " 764281806Srpaulo MACSTR, MAC2STR(peer->addr)); 765214501Srpaulo wpa_sm_rx_eapol(peer->supp, peer->addr, tmp, len); 766214501Srpaulo } else { 767281806Srpaulo if (ibss_rsn_is_auth_started(peer) == 0) { 768281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS EAPOL for " 769281806Srpaulo "Authenticator dropped as " MACSTR " is not " 770281806Srpaulo "authenticated", MAC2STR(peer->addr)); 771281806Srpaulo os_free(tmp); 772281806Srpaulo return -1; 773281806Srpaulo } 774281806Srpaulo 775281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Authenticator " 776281806Srpaulo "from "MACSTR, MAC2STR(peer->addr)); 777214501Srpaulo wpa_receive(ibss_rsn->auth_group, peer->auth, tmp, len); 778214501Srpaulo } 779214501Srpaulo os_free(tmp); 780214501Srpaulo 781214501Srpaulo return 1; 782214501Srpaulo} 783214501Srpaulo 784214501Srpaulo 785214501Srpauloint ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, 786214501Srpaulo const u8 *buf, size_t len) 787214501Srpaulo{ 788214501Srpaulo struct ibss_rsn_peer *peer; 789214501Srpaulo 790252726Srpaulo if (ibss_rsn == NULL) 791252726Srpaulo return -1; 792214501Srpaulo 793252726Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, src_addr); 794252726Srpaulo if (peer) 795252726Srpaulo return ibss_rsn_process_rx_eapol(ibss_rsn, peer, buf, len); 796252726Srpaulo 797214501Srpaulo if (ibss_rsn_eapol_dst_supp(buf, len) > 0) { 798214501Srpaulo /* 799214501Srpaulo * Create new IBSS peer based on an EAPOL message from the peer 800214501Srpaulo * Authenticator. 801214501Srpaulo */ 802281806Srpaulo peer = ibss_rsn_peer_init(ibss_rsn, src_addr); 803281806Srpaulo if (peer == NULL) 804214501Srpaulo return -1; 805281806Srpaulo 806281806Srpaulo /* assume the peer is authenticated already */ 807281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Not using IBSS Auth for peer " 808281806Srpaulo MACSTR, MAC2STR(src_addr)); 809281806Srpaulo ibss_rsn_peer_authenticated(ibss_rsn, peer, 810281806Srpaulo IBSS_RSN_AUTH_EAPOL_BY_US); 811281806Srpaulo 812214501Srpaulo return ibss_rsn_process_rx_eapol(ibss_rsn, ibss_rsn->peers, 813214501Srpaulo buf, len); 814214501Srpaulo } 815214501Srpaulo 816214501Srpaulo return 0; 817214501Srpaulo} 818214501Srpaulo 819214501Srpaulovoid ibss_rsn_set_psk(struct ibss_rsn *ibss_rsn, const u8 *psk) 820214501Srpaulo{ 821252726Srpaulo if (ibss_rsn == NULL) 822252726Srpaulo return; 823214501Srpaulo os_memcpy(ibss_rsn->psk, psk, PMK_LEN); 824214501Srpaulo} 825281806Srpaulo 826281806Srpaulo 827281806Srpaulostatic void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn, 828281806Srpaulo struct ibss_rsn_peer *peer, 829281806Srpaulo const u8* addr) 830281806Srpaulo{ 831281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR, 832281806Srpaulo MAC2STR(addr)); 833281806Srpaulo 834281806Srpaulo if (peer && 835281806Srpaulo peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) { 836281806Srpaulo if (peer->own_auth_tx.sec) { 837281806Srpaulo struct os_reltime now, diff; 838281806Srpaulo os_get_reltime(&now); 839281806Srpaulo os_reltime_sub(&now, &peer->own_auth_tx, &diff); 840281806Srpaulo if (diff.sec == 0 && diff.usec < 500000) { 841281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX", 842281806Srpaulo (int) diff.usec); 843281806Srpaulo goto skip_reinit; 844281806Srpaulo } 845281806Srpaulo } 846281806Srpaulo /* 847281806Srpaulo * A peer sent us an Authentication frame even though it already 848281806Srpaulo * started an EAPOL session. We should reinit state machines 849281806Srpaulo * here, but it's much more complicated than just deleting and 850281806Srpaulo * recreating the state machine 851281806Srpaulo */ 852281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station " 853281806Srpaulo MACSTR, MAC2STR(addr)); 854281806Srpaulo 855281806Srpaulo ibss_rsn_stop(ibss_rsn, addr); 856281806Srpaulo peer = NULL; 857281806Srpaulo } 858281806Srpaulo 859281806Srpaulo if (!peer) { 860281806Srpaulo peer = ibss_rsn_peer_init(ibss_rsn, addr); 861281806Srpaulo if (!peer) 862281806Srpaulo return; 863281806Srpaulo 864281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Auth started by peer " MACSTR, 865281806Srpaulo MAC2STR(addr)); 866281806Srpaulo } 867281806Srpaulo 868281806Srpauloskip_reinit: 869281806Srpaulo /* reply with an Authentication frame now, before sending an EAPOL */ 870281806Srpaulo ibss_rsn_send_auth(ibss_rsn, addr, 2); 871281806Srpaulo /* no need to start another AUTH challenge in the other way.. */ 872281806Srpaulo ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US); 873281806Srpaulo} 874281806Srpaulo 875281806Srpaulo 876281806Srpaulovoid ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame, 877281806Srpaulo size_t len) 878281806Srpaulo{ 879281806Srpaulo const struct ieee80211_mgmt *header; 880281806Srpaulo struct ibss_rsn_peer *peer; 881281806Srpaulo size_t auth_length; 882281806Srpaulo 883281806Srpaulo header = (const struct ieee80211_mgmt *) auth_frame; 884281806Srpaulo auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth); 885281806Srpaulo 886281806Srpaulo if (ibss_rsn == NULL || len < auth_length) 887281806Srpaulo return; 888281806Srpaulo 889281806Srpaulo if (le_to_host16(header->u.auth.auth_alg) != WLAN_AUTH_OPEN || 890281806Srpaulo le_to_host16(header->u.auth.status_code) != WLAN_STATUS_SUCCESS) 891281806Srpaulo return; 892281806Srpaulo 893281806Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, header->sa); 894281806Srpaulo 895281806Srpaulo switch (le_to_host16(header->u.auth.auth_transaction)) { 896281806Srpaulo case 1: 897281806Srpaulo ibss_rsn_handle_auth_1_of_2(ibss_rsn, peer, header->sa); 898281806Srpaulo break; 899281806Srpaulo case 2: 900281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 2) from " 901281806Srpaulo MACSTR, MAC2STR(header->sa)); 902281806Srpaulo if (!peer) { 903281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Received Auth seq 2 from " 904281806Srpaulo "unknown STA " MACSTR, MAC2STR(header->sa)); 905281806Srpaulo break; 906281806Srpaulo } 907281806Srpaulo 908281806Srpaulo /* authentication has been completed */ 909281806Srpaulo eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); 910281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with " MACSTR, 911281806Srpaulo MAC2STR(header->sa)); 912281806Srpaulo ibss_rsn_peer_authenticated(ibss_rsn, peer, 913281806Srpaulo IBSS_RSN_AUTH_BY_US); 914281806Srpaulo break; 915281806Srpaulo } 916281806Srpaulo} 917