18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant - IBSS RSN 3b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 12b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt#include "common/wpa_ctrl.h" 1392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt#include "utils/eloop.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa_ie.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/wpa_auth.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h" 20c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#include "common/ieee802_11_defs.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ibss_rsn.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidtstatic void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx); 2592c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt 2692c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt 27c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic struct ibss_rsn_peer * ibss_rsn_get_peer(struct ibss_rsn *ibss_rsn, 28c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *addr) 29c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 30c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct ibss_rsn_peer *peer; 31c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 32c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (peer = ibss_rsn->peers; peer; peer = peer->next) 33c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (os_memcmp(addr, peer->addr, ETH_ALEN) == 0) 34c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt break; 35c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return peer; 36c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 37c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 38c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ibss_rsn_free(struct ibss_rsn_peer *peer) 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4192c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_sta_deinit(peer->auth); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_deinit(peer->supp); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer); 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void supp_set_state(void *ctx, enum wpa_states state) 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer = ctx; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->supp_state = state; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum wpa_states supp_get_state(void *ctx) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer = ctx; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return peer->supp_state; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer = ctx; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "len=%lu)", 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, MAC2STR(dest), proto, (unsigned long) len); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->l2) 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return l2_packet_send(wpa_s->l2, dest, proto, buf, len); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 data_len, size_t *msg_len, void **data_pos) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_1x_hdr *hdr; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, type, data_len); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *msg_len = sizeof(*hdr) + data_len; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = os_malloc(*msg_len); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = 2; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->type = type; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(data_len); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr + 1, data, data_len); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(hdr + 1, 0, data_len); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data_pos) 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *data_pos = hdr + 1; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (u8 *) hdr; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int supp_get_beacon_ie(void *ctx) 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer = ctx; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: get correct RSN IE */ 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_set_ap_rsn_ie(peer->supp, 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) "\x30\x14\x01\x00" 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x00\x0f\xac\x04" 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x01\x00\x00\x0f\xac\x04" 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x01\x00\x00\x0f\xac\x02" 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x00\x00", 22); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 123b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic void ibss_check_rsn_completed(struct ibss_rsn_peer *peer) 124b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 125b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s; 126b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 127b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if ((peer->authentication_status & 128b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt (IBSS_RSN_SET_PTK_SUPP | IBSS_RSN_SET_PTK_AUTH)) != 129b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt (IBSS_RSN_SET_PTK_SUPP | IBSS_RSN_SET_PTK_AUTH)) 130b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 131b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (peer->authentication_status & IBSS_RSN_REPORTED_PTK) 132b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 133b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt peer->authentication_status |= IBSS_RSN_REPORTED_PTK; 134b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, IBSS_RSN_COMPLETED MACSTR, 135b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt MAC2STR(peer->addr)); 136b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 137b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 138b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int supp_set_key(void *ctx, enum wpa_alg alg, 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int key_idx, int set_tx, 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *seq, size_t seq_len, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key, size_t key_len) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer = ctx; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "set_tx=%d)", 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, alg, MAC2STR(addr), key_idx, set_tx); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "SUPP: set_key - key", key, key_len); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_idx == 0) { 153b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt peer->authentication_status |= IBSS_RSN_SET_PTK_SUPP; 154b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt ibss_check_rsn_completed(peer); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * In IBSS RSN, the pairwise key from the 4-way handshake 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * initiated by the peer with highest MAC address is used. 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->ibss_rsn->wpa_s->own_addr, peer->addr, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_ALEN) > 0) { 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: Do not use this PTK"); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (is_broadcast_ether_addr(addr)) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = peer->addr; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_drv_set_key(peer->ibss_rsn->wpa_s, alg, addr, key_idx, 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_tx, seq, seq_len, key, key_len); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * supp_get_network_ctx(void *ctx) 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer = ctx; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_supplicant_get_ssid(peer->ibss_rsn->wpa_s); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int supp_mlme_setprotection(void *ctx, const u8 *addr, 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int protection_type, int key_type) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key_type=%d)", 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, MAC2STR(addr), protection_type, key_type); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void supp_cancel_auth_timeout(void *ctx) 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void supp_deauthenticate(void * ctx, int reason_code) 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, 2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *psk) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ctx == NULL) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->ctx = peer; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->msg_ctx = peer->ibss_rsn->wpa_s; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->set_state = supp_set_state; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->get_state = supp_get_state; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->ether_send = supp_ether_send; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->get_beacon_ie = supp_get_beacon_ie; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->alloc_eapol = supp_alloc_eapol; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->set_key = supp_set_key; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->get_network_ctx = supp_get_network_ctx; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->mlme_setprotection = supp_mlme_setprotection; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->cancel_auth_timeout = supp_cancel_auth_timeout; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ctx->deauthenticate = supp_deauthenticate; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->supp = wpa_sm_init(ctx); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->supp == NULL) { 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_own_addr(peer->supp, own_addr); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_param(peer->supp, WPA_PARAM_RSN_ENABLED, 1); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_param(peer->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_pmk(peer->supp, psk, PMK_LEN); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->supp_ie_len = sizeof(peer->supp_ie); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie, 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &peer->supp_ie_len) < 0) { 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " failed"); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_notify_assoc(peer->supp, peer->addr); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void auth_logger(void *ctx, const u8 *addr, logger_level level, 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *txt) 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s", 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr), txt); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: %s", txt); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 260391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic const u8 * auth_get_psk(void *ctx, const u8 *addr, 261391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt const u8 *p2p_dev_addr, const u8 *prev_psk) 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn *ibss_rsn = ctx; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, MAC2STR(addr), prev_psk); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev_psk) 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ibss_rsn->psk; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len, int encrypt) 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn *ibss_rsn = ctx; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = ibss_rsn->wpa_s; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu " 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encrypt=%d)", 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, MAC2STR(addr), (unsigned long) data_len, encrypt); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->l2) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return l2_packet_send(wpa_s->l2, addr, ETH_P_EAPOL, data, 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_drv_send_eapol(wpa_s, addr, ETH_P_EAPOL, data, data_len); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int idx, u8 *key, size_t key_len) 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn *ibss_rsn = ctx; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 seq[6]; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(seq, 0, sizeof(seq)); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) { 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d addr=" MACSTR 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " key_idx=%d)", 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, alg, MAC2STR(addr), idx); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d key_idx=%d)", 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, alg, idx); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (idx == 0) { 309b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (addr) { 310b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt struct ibss_rsn_peer *peer; 311b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt peer = ibss_rsn_get_peer(ibss_rsn, addr); 312b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (peer) { 313b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt peer->authentication_status |= 314b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt IBSS_RSN_SET_PTK_AUTH; 315b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt ibss_check_rsn_completed(peer); 316b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 317b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * In IBSS RSN, the pairwise key from the 4-way handshake 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * initiated by the peer with highest MAC address is used. 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr == NULL || 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(ibss_rsn->wpa_s->own_addr, addr, ETH_ALEN) < 0) { 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: Do not use this PTK"); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_drv_set_key(ibss_rsn->wpa_s, alg, addr, idx, 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1, seq, 6, key, key_len); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic void ibss_rsn_disconnect(void *ctx, const u8 *addr, u16 reason) 33534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 33634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct ibss_rsn *ibss_rsn = ctx; 33734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_drv_sta_deauth(ibss_rsn->wpa_s, addr, reason); 33834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 33934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 34034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int auth_for_each_sta(void *ctx, int (*cb)(struct wpa_state_machine *sm, 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx), 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *cb_ctx) 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn *ibss_rsn = ctx; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: for_each_sta"); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = ibss_rsn->peers; peer; peer = peer->next) { 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->auth && cb(peer->auth, cb_ctx)) 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 359c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void ibss_set_sta_authorized(struct ibss_rsn *ibss_rsn, 360c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct ibss_rsn_peer *peer, int authorized) 361c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 362c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int res; 363c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 364c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (authorized) { 365c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt res = wpa_drv_sta_set_flags(ibss_rsn->wpa_s, peer->addr, 366c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt WPA_STA_AUTHORIZED, 367c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt WPA_STA_AUTHORIZED, ~0); 368c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " authorizing port", 369c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt MAC2STR(peer->addr)); 370c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } else { 371c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt res = wpa_drv_sta_set_flags(ibss_rsn->wpa_s, peer->addr, 372c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 0, 0, ~WPA_STA_AUTHORIZED); 373c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " unauthorizing port", 374c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt MAC2STR(peer->addr)); 375c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 376c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 377c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (res && errno != ENOENT) { 378c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not set station " MACSTR " flags " 379c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "for kernel driver (errno=%d)", 380c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt MAC2STR(peer->addr), errno); 381c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 382c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 383c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 384c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 385c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void auth_set_eapol(void *ctx, const u8 *addr, 386c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_eapol_variable var, int value) 387c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 388c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct ibss_rsn *ibss_rsn = ctx; 389c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct ibss_rsn_peer *peer = ibss_rsn_get_peer(ibss_rsn, addr); 390c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 391c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (peer == NULL) 392c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 393c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 394c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt switch (var) { 395c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt case WPA_EAPOL_authorized: 396c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt ibss_set_sta_authorized(ibss_rsn, peer, value); 397c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt break; 398c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt default: 399c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* do not handle any other event */ 400c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: eapol event not handled %d", var); 401c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt break; 402c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 403c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 404c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 405c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn, 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *own_addr) 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_config conf; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_callbacks cb; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine"); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&conf, 0, sizeof(conf)); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wpa = 2; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wpa_pairwise = WPA_CIPHER_CCMP; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.rsn_pairwise = WPA_CIPHER_CCMP; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wpa_group = WPA_CIPHER_CCMP; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.eapol_version = 2; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf.wpa_group_rekey = 600; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&cb, 0, sizeof(cb)); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.ctx = ibss_rsn; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.logger = auth_logger; 426c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt cb.set_eapol = auth_set_eapol; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.send_eapol = auth_send_eapol; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.get_psk = auth_get_psk; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.set_key = auth_set_key; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb.for_each_sta = auth_for_each_sta; 43134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt cb.disconnect = ibss_rsn_disconnect; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn->auth_group == NULL) { 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_init_keys(ibss_rsn->auth_group); 4401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn, 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 448391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt peer->auth = wpa_auth_sta_init(ibss_rsn->auth_group, peer->addr, NULL); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->auth == NULL) { 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: get peer RSN IE with Probe Request */ 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_validate_wpa_ie(ibss_rsn->auth_group, peer->auth, 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) "\x30\x14\x01\x00" 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x00\x0f\xac\x04" 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x01\x00\x00\x0f\xac\x04" 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x01\x00\x00\x0f\xac\x02" 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x00\x00", 22, NULL, 0) != 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_IE_OK) { 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_sm_event(peer->auth, WPA_ASSOC)) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth_sta_associated(ibss_rsn->auth_group, peer->auth)) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 476c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic int ibss_rsn_send_auth(struct ibss_rsn *ibss_rsn, const u8 *da, int seq) 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 478c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct ieee80211_mgmt auth; 479c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt const size_t auth_length = IEEE80211_HDRLEN + sizeof(auth.u.auth); 480c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct wpa_supplicant *wpa_s = ibss_rsn->wpa_s; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 482c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (wpa_s->driver->send_frame == NULL) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 485c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_memset(&auth, 0, sizeof(auth)); 486c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 487c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt auth.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 488c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt WLAN_FC_STYPE_AUTH); 489c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_memcpy(auth.da, da, ETH_ALEN); 490c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_memcpy(auth.sa, wpa_s->own_addr, ETH_ALEN); 491c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_memcpy(auth.bssid, wpa_s->bssid, ETH_ALEN); 492c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 493c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt auth.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN); 494c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt auth.u.auth.auth_transaction = host_to_le16(seq); 495c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt auth.u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS); 496c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 497c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS TX Auth frame (SEQ %d) to " MACSTR, 498c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt seq, MAC2STR(da)); 499c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 500c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return wpa_s->driver->send_frame(wpa_s->drv_priv, (u8 *) &auth, 501c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt auth_length, 0); 502c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt} 503c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 504c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 505c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic int ibss_rsn_is_auth_started(struct ibss_rsn_peer * peer) 506c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{ 507c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return peer->authentication_status & 508c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt (IBSS_RSN_AUTH_BY_US | IBSS_RSN_AUTH_EAPOL_BY_US); 509c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt} 510c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 511c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 512c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic struct ibss_rsn_peer * 513c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtibss_rsn_peer_init(struct ibss_rsn *ibss_rsn, const u8 *addr) 514c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{ 515c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct ibss_rsn_peer *peer; 516c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (ibss_rsn == NULL) 517c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return NULL; 518c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 519c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer = ibss_rsn_get_peer(ibss_rsn, addr); 520c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (peer) { 521c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS Supplicant for peer "MACSTR 522c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt " already running", MAC2STR(addr)); 523c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return peer; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 526c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Supplicant for peer "MACSTR, 527c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MAC2STR(addr)); 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = os_zalloc(sizeof(*peer)); 530c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (peer == NULL) { 531c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Could not allocate memory."); 532c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return NULL; 533c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->ibss_rsn = ibss_rsn; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->addr, addr, ETH_ALEN); 537c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer->authentication_status = IBSS_RSN_AUTH_NOT_AUTHENTICATED; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 539c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (ibss_rsn_supp_init(peer, ibss_rsn->wpa_s->own_addr, 540c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn->psk) < 0) { 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn_free(peer); 542c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return NULL; 543c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 544c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 545c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer->next = ibss_rsn->peers; 546c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn->peers = peer; 547c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 548c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return peer; 549c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt} 550c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 551c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 55292c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidtstatic void ibss_rsn_auth_timeout(void *eloop_ctx, void *timeout_ctx) 55392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt{ 55492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt struct ibss_rsn_peer *peer = eloop_ctx; 55592c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt 55692c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt /* 55792c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt * Assume peer does not support Authentication exchange or the frame was 55892c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt * lost somewhere - start EAPOL Authenticator. 55992c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt */ 56092c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt wpa_printf(MSG_DEBUG, 56192c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt "RSN: Timeout on waiting Authentication frame response from " 56292c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt MACSTR " - start authenticator", MAC2STR(peer->addr)); 56392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt 56492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt peer->authentication_status |= IBSS_RSN_AUTH_BY_US; 56592c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt ibss_rsn_auth_init(peer->ibss_rsn, peer); 56692c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt} 56792c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt 56892c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt 569c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtint ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr) 570c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{ 571c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct ibss_rsn_peer *peer; 572c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt int res; 573c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 574c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* if the peer already exists, exit immediately */ 575c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer = ibss_rsn_get_peer(ibss_rsn, addr); 576c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (peer) 577c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return 0; 578c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 579c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer = ibss_rsn_peer_init(ibss_rsn, addr); 580c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (peer == NULL) 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 582c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 583c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* Open Authentication: send first Authentication frame */ 584c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt res = ibss_rsn_send_auth(ibss_rsn, addr, 1); 585c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (res) { 586c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* 587c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * The driver may not support Authentication frame exchange in 588c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * IBSS. Ignore authentication and go through EAPOL exchange. 589c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt */ 590c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer->authentication_status |= IBSS_RSN_AUTH_BY_US; 591c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return ibss_rsn_auth_init(ibss_rsn, peer); 59292c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt } else { 59392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt os_get_time(&peer->own_auth_tx); 59492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 597c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return 0; 598c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt} 599c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 600c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 601c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic int ibss_rsn_peer_authenticated(struct ibss_rsn *ibss_rsn, 602c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct ibss_rsn_peer *peer, int reason) 603c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{ 604c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt int already_started; 605c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 606c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (ibss_rsn == NULL || peer == NULL) 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 608c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 609c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt already_started = ibss_rsn_is_auth_started(peer); 610c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer->authentication_status |= reason; 611c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 612c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (already_started) { 613c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS Authenticator already " 614c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "started for peer " MACSTR, MAC2STR(peer->addr)); 615c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return 0; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Authenticator " 619c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "for now-authenticated peer " MACSTR, MAC2STR(peer->addr)); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 621c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return ibss_rsn_auth_init(ibss_rsn, peer); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac) 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer, *prev; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn == NULL) 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peermac == NULL) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* remove all peers */ 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Remove all peers", __func__); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = ibss_rsn->peers; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peer) { 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = peer; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = peer->next; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn_free(prev); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn->peers = peer; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* remove specific peer */ 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Remove specific peer " MACSTR, 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, MAC2STR(peermac)); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (prev = NULL, peer = ibss_rsn->peers; peer != NULL; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = peer, peer = peer->next) { 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peermac, peer->addr, ETH_ALEN) == 0) { 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn->peers = peer->next; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = peer->next; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn_free(peer); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Successfully " 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "removed a specific peer", 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s) 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn *ibss_rsn; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn = os_zalloc(sizeof(*ibss_rsn)); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn == NULL) 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn->wpa_s = wpa_s; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr) < 0) { 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn_deinit(ibss_rsn); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ibss_rsn; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ibss_rsn_deinit(struct ibss_rsn *ibss_rsn) 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer, *prev; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn == NULL) 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = ibss_rsn->peers; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peer) { 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = peer; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = peer->next; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ibss_rsn_free(prev); 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_deinit(ibss_rsn->auth_group); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(ibss_rsn); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ibss_rsn_eapol_dst_supp(const u8 *buf, size_t len) 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee802_1x_hdr *hdr; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_eapol_key *key; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 key_info; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: Support other EAPOL packets than just EAPOL-Key */ 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*hdr) + sizeof(*key)) 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (const struct ieee802_1x_hdr *) buf; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = (const struct wpa_eapol_key *) (hdr + 1); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = be_to_host16(hdr->length); 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->version < EAPOL_VERSION) { 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: backwards compatibility */ 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: EAPOL frame (type %u) discarded, " 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not a Key frame", hdr->type); 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: EAPOL frame payload size %lu " 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "invalid (frame size %lu)", 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) plen, (unsigned long) len); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key->type != EAPOL_KEY_TYPE_RSN) { 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: EAPOL-Key type (%d) unknown, " 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "discarded", key->type); 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_info = WPA_GET_BE16(key->key_info); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return !!(key_info & WPA_KEY_INFO_ACK); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ibss_rsn_process_rx_eapol(struct ibss_rsn *ibss_rsn, 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer, 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int supp; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *tmp; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt supp = ibss_rsn_eapol_dst_supp(buf, len); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (supp < 0) 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_malloc(len); 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(tmp, buf, len); 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (supp) { 762c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer->authentication_status |= IBSS_RSN_AUTH_EAPOL_BY_PEER; 763c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Supplicant from " 764c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MACSTR, MAC2STR(peer->addr)); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_rx_eapol(peer->supp, peer->addr, tmp, len); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 767c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (ibss_rsn_is_auth_started(peer) == 0) { 768c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS EAPOL for " 769c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "Authenticator dropped as " MACSTR " is not " 770c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "authenticated", MAC2STR(peer->addr)); 771c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_free(tmp); 772c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return -1; 773c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 774c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 775c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS RX EAPOL for Authenticator " 776c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "from "MACSTR, MAC2STR(peer->addr)); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_receive(ibss_rsn->auth_group, peer->auth, tmp, len); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(tmp); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ibss_rsn_peer *peer; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn == NULL) 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 793c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt peer = ibss_rsn_get_peer(ibss_rsn, src_addr); 794c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (peer) 795c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return ibss_rsn_process_rx_eapol(ibss_rsn, peer, buf, len); 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn_eapol_dst_supp(buf, len) > 0) { 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Create new IBSS peer based on an EAPOL message from the peer 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Authenticator. 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 802c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer = ibss_rsn_peer_init(ibss_rsn, src_addr); 803c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (peer == NULL) 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 805c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 806c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* assume the peer is authenticated already */ 807c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS Not using IBSS Auth for peer " 808c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MACSTR, MAC2STR(src_addr)); 809c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn_peer_authenticated(ibss_rsn, peer, 810c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt IBSS_RSN_AUTH_EAPOL_BY_US); 811c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ibss_rsn_process_rx_eapol(ibss_rsn, ibss_rsn->peers, 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, len); 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ibss_rsn_set_psk(struct ibss_rsn *ibss_rsn, const u8 *psk) 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ibss_rsn == NULL) 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ibss_rsn->psk, psk, PMK_LEN); 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 825c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 826c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 827c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn, 828c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct ibss_rsn_peer *peer, 829c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt const u8* addr) 830c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{ 831c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR, 832c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MAC2STR(addr)); 833c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 834c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (peer && 835c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) { 83692c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt if (peer->own_auth_tx.sec) { 83792c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt struct os_time now, diff; 83892c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt os_get_time(&now); 83992c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt os_time_sub(&now, &peer->own_auth_tx, &diff); 84092c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt if (diff.sec == 0 && diff.usec < 500000) { 84192c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX", 84292c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt (int) diff.usec); 84392c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt goto skip_reinit; 84492c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt } 84592c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt } 846c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* 847c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * A peer sent us an Authentication frame even though it already 848c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * started an EAPOL session. We should reinit state machines 849c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * here, but it's much more complicated than just deleting and 850c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt * recreating the state machine 851c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt */ 852c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station " 853c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MACSTR, MAC2STR(addr)); 854c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 855c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn_stop(ibss_rsn, addr); 856c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer = NULL; 857c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 858c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 859c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (!peer) { 860c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer = ibss_rsn_peer_init(ibss_rsn, addr); 861c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (!peer) 862c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return; 863c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 864c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS Auth started by peer " MACSTR, 865c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MAC2STR(addr)); 866c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 867c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 86892c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidtskip_reinit: 869c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* reply with an Authentication frame now, before sending an EAPOL */ 870c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn_send_auth(ibss_rsn, addr, 2); 871c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* no need to start another AUTH challenge in the other way.. */ 872c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US); 873c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt} 874c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 875c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 876c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtvoid ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame, 877c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt size_t len) 878c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{ 879c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt const struct ieee80211_mgmt *header; 880c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct ibss_rsn_peer *peer; 881c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt size_t auth_length; 882c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 883c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt header = (const struct ieee80211_mgmt *) auth_frame; 884c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth); 885c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 886c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (ibss_rsn == NULL || len < auth_length) 887c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return; 888c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 889c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (le_to_host16(header->u.auth.auth_alg) != WLAN_AUTH_OPEN || 890c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt le_to_host16(header->u.auth.status_code) != WLAN_STATUS_SUCCESS) 891c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt return; 892c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 893c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt peer = ibss_rsn_get_peer(ibss_rsn, header->sa); 894c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 895c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt switch (le_to_host16(header->u.auth.auth_transaction)) { 896c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt case 1: 897c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn_handle_auth_1_of_2(ibss_rsn, peer, header->sa); 898c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt break; 899c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt case 2: 900c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 2) from " 901c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MACSTR, MAC2STR(header->sa)); 902c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (!peer) { 903c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Received Auth seq 2 from " 904c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt "unknown STA " MACSTR, MAC2STR(header->sa)); 905c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt break; 906c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 907c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 908c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt /* authentication has been completed */ 90992c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); 91092c368d56f46a4e648b441085707c1381b5e5f63Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with " MACSTR, 911c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt MAC2STR(header->sa)); 912c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt ibss_rsn_peer_authenticated(ibss_rsn, peer, 913c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt IBSS_RSN_AUTH_BY_US); 914c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt break; 915c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt } 916c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt} 917