ibss_rsn.c revision 289549
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 574289549Srpaulo if (!ibss_rsn) 575289549Srpaulo return -1; 576289549Srpaulo 577281806Srpaulo /* if the peer already exists, exit immediately */ 578281806Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, addr); 579281806Srpaulo if (peer) 580281806Srpaulo return 0; 581281806Srpaulo 582281806Srpaulo peer = ibss_rsn_peer_init(ibss_rsn, addr); 583281806Srpaulo if (peer == NULL) 584214501Srpaulo return -1; 585281806Srpaulo 586281806Srpaulo /* Open Authentication: send first Authentication frame */ 587281806Srpaulo res = ibss_rsn_send_auth(ibss_rsn, addr, 1); 588281806Srpaulo if (res) { 589281806Srpaulo /* 590281806Srpaulo * The driver may not support Authentication frame exchange in 591281806Srpaulo * IBSS. Ignore authentication and go through EAPOL exchange. 592281806Srpaulo */ 593281806Srpaulo peer->authentication_status |= IBSS_RSN_AUTH_BY_US; 594281806Srpaulo return ibss_rsn_auth_init(ibss_rsn, peer); 595281806Srpaulo } else { 596281806Srpaulo os_get_reltime(&peer->own_auth_tx); 597281806Srpaulo eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL); 598214501Srpaulo } 599214501Srpaulo 600281806Srpaulo return 0; 601281806Srpaulo} 602281806Srpaulo 603281806Srpaulo 604281806Srpaulostatic int ibss_rsn_peer_authenticated(struct ibss_rsn *ibss_rsn, 605281806Srpaulo struct ibss_rsn_peer *peer, int reason) 606281806Srpaulo{ 607281806Srpaulo int already_started; 608281806Srpaulo 609281806Srpaulo if (ibss_rsn == NULL || peer == NULL) 610214501Srpaulo return -1; 611281806Srpaulo 612281806Srpaulo already_started = ibss_rsn_is_auth_started(peer); 613281806Srpaulo peer->authentication_status |= reason; 614281806Srpaulo 615281806Srpaulo if (already_started) { 616281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Authenticator already " 617281806Srpaulo "started for peer " MACSTR, MAC2STR(peer->addr)); 618281806Srpaulo return 0; 619214501Srpaulo } 620214501Srpaulo 621281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Authenticator " 622281806Srpaulo "for now-authenticated peer " MACSTR, MAC2STR(peer->addr)); 623214501Srpaulo 624281806Srpaulo return ibss_rsn_auth_init(ibss_rsn, peer); 625214501Srpaulo} 626214501Srpaulo 627214501Srpaulo 628252726Srpaulovoid ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac) 629252726Srpaulo{ 630252726Srpaulo struct ibss_rsn_peer *peer, *prev; 631252726Srpaulo 632252726Srpaulo if (ibss_rsn == NULL) 633252726Srpaulo return; 634252726Srpaulo 635252726Srpaulo if (peermac == NULL) { 636252726Srpaulo /* remove all peers */ 637252726Srpaulo wpa_printf(MSG_DEBUG, "%s: Remove all peers", __func__); 638252726Srpaulo peer = ibss_rsn->peers; 639252726Srpaulo while (peer) { 640252726Srpaulo prev = peer; 641252726Srpaulo peer = peer->next; 642252726Srpaulo ibss_rsn_free(prev); 643252726Srpaulo ibss_rsn->peers = peer; 644252726Srpaulo } 645252726Srpaulo } else { 646252726Srpaulo /* remove specific peer */ 647252726Srpaulo wpa_printf(MSG_DEBUG, "%s: Remove specific peer " MACSTR, 648252726Srpaulo __func__, MAC2STR(peermac)); 649252726Srpaulo 650252726Srpaulo for (prev = NULL, peer = ibss_rsn->peers; peer != NULL; 651252726Srpaulo prev = peer, peer = peer->next) { 652252726Srpaulo if (os_memcmp(peermac, peer->addr, ETH_ALEN) == 0) { 653252726Srpaulo if (prev == NULL) 654252726Srpaulo ibss_rsn->peers = peer->next; 655252726Srpaulo else 656252726Srpaulo prev->next = peer->next; 657252726Srpaulo ibss_rsn_free(peer); 658252726Srpaulo wpa_printf(MSG_DEBUG, "%s: Successfully " 659252726Srpaulo "removed a specific peer", 660252726Srpaulo __func__); 661252726Srpaulo break; 662252726Srpaulo } 663252726Srpaulo } 664252726Srpaulo } 665252726Srpaulo} 666252726Srpaulo 667252726Srpaulo 668214501Srpaulostruct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s) 669214501Srpaulo{ 670214501Srpaulo struct ibss_rsn *ibss_rsn; 671214501Srpaulo 672214501Srpaulo ibss_rsn = os_zalloc(sizeof(*ibss_rsn)); 673214501Srpaulo if (ibss_rsn == NULL) 674214501Srpaulo return NULL; 675214501Srpaulo ibss_rsn->wpa_s = wpa_s; 676214501Srpaulo 677214501Srpaulo if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr) < 0) { 678214501Srpaulo ibss_rsn_deinit(ibss_rsn); 679214501Srpaulo return NULL; 680214501Srpaulo } 681214501Srpaulo 682214501Srpaulo return ibss_rsn; 683214501Srpaulo} 684214501Srpaulo 685214501Srpaulo 686214501Srpaulovoid ibss_rsn_deinit(struct ibss_rsn *ibss_rsn) 687214501Srpaulo{ 688214501Srpaulo struct ibss_rsn_peer *peer, *prev; 689214501Srpaulo 690214501Srpaulo if (ibss_rsn == NULL) 691214501Srpaulo return; 692214501Srpaulo 693214501Srpaulo peer = ibss_rsn->peers; 694214501Srpaulo while (peer) { 695214501Srpaulo prev = peer; 696214501Srpaulo peer = peer->next; 697214501Srpaulo ibss_rsn_free(prev); 698214501Srpaulo } 699214501Srpaulo 700289549Srpaulo if (ibss_rsn->auth_group) 701289549Srpaulo wpa_deinit(ibss_rsn->auth_group); 702214501Srpaulo os_free(ibss_rsn); 703214501Srpaulo 704214501Srpaulo} 705214501Srpaulo 706214501Srpaulo 707214501Srpaulostatic int ibss_rsn_eapol_dst_supp(const u8 *buf, size_t len) 708214501Srpaulo{ 709214501Srpaulo const struct ieee802_1x_hdr *hdr; 710214501Srpaulo const struct wpa_eapol_key *key; 711214501Srpaulo u16 key_info; 712214501Srpaulo size_t plen; 713214501Srpaulo 714214501Srpaulo /* TODO: Support other EAPOL packets than just EAPOL-Key */ 715214501Srpaulo 716214501Srpaulo if (len < sizeof(*hdr) + sizeof(*key)) 717214501Srpaulo return -1; 718214501Srpaulo 719214501Srpaulo hdr = (const struct ieee802_1x_hdr *) buf; 720214501Srpaulo key = (const struct wpa_eapol_key *) (hdr + 1); 721214501Srpaulo plen = be_to_host16(hdr->length); 722214501Srpaulo 723214501Srpaulo if (hdr->version < EAPOL_VERSION) { 724214501Srpaulo /* TODO: backwards compatibility */ 725214501Srpaulo } 726214501Srpaulo if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { 727214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: EAPOL frame (type %u) discarded, " 728214501Srpaulo "not a Key frame", hdr->type); 729214501Srpaulo return -1; 730214501Srpaulo } 731214501Srpaulo if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { 732214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: EAPOL frame payload size %lu " 733214501Srpaulo "invalid (frame size %lu)", 734214501Srpaulo (unsigned long) plen, (unsigned long) len); 735214501Srpaulo return -1; 736214501Srpaulo } 737214501Srpaulo 738214501Srpaulo if (key->type != EAPOL_KEY_TYPE_RSN) { 739214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: EAPOL-Key type (%d) unknown, " 740214501Srpaulo "discarded", key->type); 741214501Srpaulo return -1; 742214501Srpaulo } 743214501Srpaulo 744214501Srpaulo key_info = WPA_GET_BE16(key->key_info); 745214501Srpaulo 746214501Srpaulo return !!(key_info & WPA_KEY_INFO_ACK); 747214501Srpaulo} 748214501Srpaulo 749214501Srpaulo 750214501Srpaulostatic int ibss_rsn_process_rx_eapol(struct ibss_rsn *ibss_rsn, 751214501Srpaulo struct ibss_rsn_peer *peer, 752214501Srpaulo const u8 *buf, size_t len) 753214501Srpaulo{ 754214501Srpaulo int supp; 755214501Srpaulo u8 *tmp; 756214501Srpaulo 757214501Srpaulo supp = ibss_rsn_eapol_dst_supp(buf, len); 758214501Srpaulo if (supp < 0) 759214501Srpaulo return -1; 760214501Srpaulo 761214501Srpaulo tmp = os_malloc(len); 762214501Srpaulo if (tmp == NULL) 763214501Srpaulo return -1; 764214501Srpaulo os_memcpy(tmp, buf, len); 765214501Srpaulo if (supp) { 766281806Srpaulo peer->authentication_status |= IBSS_RSN_AUTH_EAPOL_BY_PEER; 767281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Supplicant from " 768281806Srpaulo MACSTR, MAC2STR(peer->addr)); 769214501Srpaulo wpa_sm_rx_eapol(peer->supp, peer->addr, tmp, len); 770214501Srpaulo } else { 771281806Srpaulo if (ibss_rsn_is_auth_started(peer) == 0) { 772281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS EAPOL for " 773281806Srpaulo "Authenticator dropped as " MACSTR " is not " 774281806Srpaulo "authenticated", MAC2STR(peer->addr)); 775281806Srpaulo os_free(tmp); 776281806Srpaulo return -1; 777281806Srpaulo } 778281806Srpaulo 779281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Authenticator " 780281806Srpaulo "from "MACSTR, MAC2STR(peer->addr)); 781214501Srpaulo wpa_receive(ibss_rsn->auth_group, peer->auth, tmp, len); 782214501Srpaulo } 783214501Srpaulo os_free(tmp); 784214501Srpaulo 785214501Srpaulo return 1; 786214501Srpaulo} 787214501Srpaulo 788214501Srpaulo 789214501Srpauloint ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, 790214501Srpaulo const u8 *buf, size_t len) 791214501Srpaulo{ 792214501Srpaulo struct ibss_rsn_peer *peer; 793214501Srpaulo 794252726Srpaulo if (ibss_rsn == NULL) 795252726Srpaulo return -1; 796214501Srpaulo 797252726Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, src_addr); 798252726Srpaulo if (peer) 799252726Srpaulo return ibss_rsn_process_rx_eapol(ibss_rsn, peer, buf, len); 800252726Srpaulo 801214501Srpaulo if (ibss_rsn_eapol_dst_supp(buf, len) > 0) { 802214501Srpaulo /* 803214501Srpaulo * Create new IBSS peer based on an EAPOL message from the peer 804214501Srpaulo * Authenticator. 805214501Srpaulo */ 806281806Srpaulo peer = ibss_rsn_peer_init(ibss_rsn, src_addr); 807281806Srpaulo if (peer == NULL) 808214501Srpaulo return -1; 809281806Srpaulo 810281806Srpaulo /* assume the peer is authenticated already */ 811281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Not using IBSS Auth for peer " 812281806Srpaulo MACSTR, MAC2STR(src_addr)); 813281806Srpaulo ibss_rsn_peer_authenticated(ibss_rsn, peer, 814281806Srpaulo IBSS_RSN_AUTH_EAPOL_BY_US); 815281806Srpaulo 816214501Srpaulo return ibss_rsn_process_rx_eapol(ibss_rsn, ibss_rsn->peers, 817214501Srpaulo buf, len); 818214501Srpaulo } 819214501Srpaulo 820214501Srpaulo return 0; 821214501Srpaulo} 822214501Srpaulo 823214501Srpaulovoid ibss_rsn_set_psk(struct ibss_rsn *ibss_rsn, const u8 *psk) 824214501Srpaulo{ 825252726Srpaulo if (ibss_rsn == NULL) 826252726Srpaulo return; 827214501Srpaulo os_memcpy(ibss_rsn->psk, psk, PMK_LEN); 828214501Srpaulo} 829281806Srpaulo 830281806Srpaulo 831281806Srpaulostatic void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn, 832281806Srpaulo struct ibss_rsn_peer *peer, 833281806Srpaulo const u8* addr) 834281806Srpaulo{ 835281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR, 836281806Srpaulo MAC2STR(addr)); 837281806Srpaulo 838281806Srpaulo if (peer && 839281806Srpaulo peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) { 840281806Srpaulo if (peer->own_auth_tx.sec) { 841281806Srpaulo struct os_reltime now, diff; 842281806Srpaulo os_get_reltime(&now); 843281806Srpaulo os_reltime_sub(&now, &peer->own_auth_tx, &diff); 844281806Srpaulo if (diff.sec == 0 && diff.usec < 500000) { 845281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX", 846281806Srpaulo (int) diff.usec); 847281806Srpaulo goto skip_reinit; 848281806Srpaulo } 849281806Srpaulo } 850281806Srpaulo /* 851281806Srpaulo * A peer sent us an Authentication frame even though it already 852281806Srpaulo * started an EAPOL session. We should reinit state machines 853281806Srpaulo * here, but it's much more complicated than just deleting and 854281806Srpaulo * recreating the state machine 855281806Srpaulo */ 856281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station " 857281806Srpaulo MACSTR, MAC2STR(addr)); 858281806Srpaulo 859281806Srpaulo ibss_rsn_stop(ibss_rsn, addr); 860281806Srpaulo peer = NULL; 861281806Srpaulo } 862281806Srpaulo 863281806Srpaulo if (!peer) { 864281806Srpaulo peer = ibss_rsn_peer_init(ibss_rsn, addr); 865281806Srpaulo if (!peer) 866281806Srpaulo return; 867281806Srpaulo 868281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Auth started by peer " MACSTR, 869281806Srpaulo MAC2STR(addr)); 870281806Srpaulo } 871281806Srpaulo 872281806Srpauloskip_reinit: 873281806Srpaulo /* reply with an Authentication frame now, before sending an EAPOL */ 874281806Srpaulo ibss_rsn_send_auth(ibss_rsn, addr, 2); 875281806Srpaulo /* no need to start another AUTH challenge in the other way.. */ 876281806Srpaulo ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US); 877281806Srpaulo} 878281806Srpaulo 879281806Srpaulo 880281806Srpaulovoid ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame, 881281806Srpaulo size_t len) 882281806Srpaulo{ 883281806Srpaulo const struct ieee80211_mgmt *header; 884281806Srpaulo struct ibss_rsn_peer *peer; 885281806Srpaulo size_t auth_length; 886281806Srpaulo 887281806Srpaulo header = (const struct ieee80211_mgmt *) auth_frame; 888281806Srpaulo auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth); 889281806Srpaulo 890281806Srpaulo if (ibss_rsn == NULL || len < auth_length) 891281806Srpaulo return; 892281806Srpaulo 893281806Srpaulo if (le_to_host16(header->u.auth.auth_alg) != WLAN_AUTH_OPEN || 894281806Srpaulo le_to_host16(header->u.auth.status_code) != WLAN_STATUS_SUCCESS) 895281806Srpaulo return; 896281806Srpaulo 897281806Srpaulo peer = ibss_rsn_get_peer(ibss_rsn, header->sa); 898281806Srpaulo 899281806Srpaulo switch (le_to_host16(header->u.auth.auth_transaction)) { 900281806Srpaulo case 1: 901281806Srpaulo ibss_rsn_handle_auth_1_of_2(ibss_rsn, peer, header->sa); 902281806Srpaulo break; 903281806Srpaulo case 2: 904281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 2) from " 905281806Srpaulo MACSTR, MAC2STR(header->sa)); 906281806Srpaulo if (!peer) { 907281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: Received Auth seq 2 from " 908281806Srpaulo "unknown STA " MACSTR, MAC2STR(header->sa)); 909281806Srpaulo break; 910281806Srpaulo } 911281806Srpaulo 912281806Srpaulo /* authentication has been completed */ 913281806Srpaulo eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); 914281806Srpaulo wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with " MACSTR, 915281806Srpaulo MAC2STR(header->sa)); 916281806Srpaulo ibss_rsn_peer_authenticated(ibss_rsn, peer, 917281806Srpaulo IBSS_RSN_AUTH_BY_US); 918281806Srpaulo break; 919281806Srpaulo } 920281806Srpaulo} 921