int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, const u8 *buf, size_t len) { struct ibss_rsn_peer *peer; if (ibss_rsn == NULL) return -1; peer = ibss_rsn_get_peer(ibss_rsn, src_addr); if (peer) return ibss_rsn_process_rx_eapol(ibss_rsn, peer, buf, len); if (ibss_rsn_eapol_dst_supp(buf, len) > 0) { /* * Create new IBSS peer based on an EAPOL message from the peer * Authenticator. */ if (ibss_rsn_start(ibss_rsn, src_addr) < 0) return -1; return ibss_rsn_process_rx_eapol(ibss_rsn, ibss_rsn->peers, buf, len); } return 0; }
int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, const u8 *buf, size_t len) { struct ibss_rsn_peer *peer; if (ibss_rsn == NULL) return -1; peer = ibss_rsn_get_peer(ibss_rsn, src_addr); if (peer) return ibss_rsn_process_rx_eapol(ibss_rsn, peer, buf, len); if (ibss_rsn_eapol_dst_supp(buf, len) > 0) { /* * Create new IBSS peer based on an EAPOL message from the peer * Authenticator. */ peer = ibss_rsn_peer_init(ibss_rsn, src_addr); if (peer == NULL) return -1; /* assume the peer is authenticated already */ wpa_printf(MSG_DEBUG, "RSN: IBSS Not using IBSS Auth for peer " MACSTR, MAC2STR(src_addr)); ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US); return ibss_rsn_process_rx_eapol(ibss_rsn, ibss_rsn->peers, buf, len); } return 0; }
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr) { struct ibss_rsn_peer *peer; int res; if (!ibss_rsn) return -1; /* if the peer already exists, exit immediately */ peer = ibss_rsn_get_peer(ibss_rsn, addr); if (peer) return 0; peer = ibss_rsn_peer_init(ibss_rsn, addr); if (peer == NULL) return -1; /* Open Authentication: send first Authentication frame */ res = ibss_rsn_send_auth(ibss_rsn, addr, 1); if (res) { /* * The driver may not support Authentication frame exchange in * IBSS. Ignore authentication and go through EAPOL exchange. */ peer->authentication_status |= IBSS_RSN_AUTH_BY_US; return ibss_rsn_auth_init(ibss_rsn, peer); } else { os_get_reltime(&peer->own_auth_tx); eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL); } return 0; }
static void auth_set_eapol(void *ctx, const u8 *addr, wpa_eapol_variable var, int value) { struct ibss_rsn *ibss_rsn = ctx; struct ibss_rsn_peer *peer = ibss_rsn_get_peer(ibss_rsn, addr); if (peer == NULL) return; switch (var) { case WPA_EAPOL_authorized: ibss_set_sta_authorized(ibss_rsn, peer, value); break; default: /* do not handle any other event */ wpa_printf(MSG_DEBUG, "AUTH: eapol event not handled %d", var); break; } }
static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, const u8 *addr, int idx, u8 *key, size_t key_len) { struct ibss_rsn *ibss_rsn = ctx; u8 seq[6]; os_memset(seq, 0, sizeof(seq)); if (addr) { wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d addr=" MACSTR " key_idx=%d)", __func__, alg, MAC2STR(addr), idx); } else { wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d key_idx=%d)", __func__, alg, idx); } wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len); if (idx == 0) { if (addr) { struct ibss_rsn_peer *peer; peer = ibss_rsn_get_peer(ibss_rsn, addr); if (peer) { peer->authentication_status |= IBSS_RSN_SET_PTK_AUTH; ibss_check_rsn_completed(peer); } } /* * In IBSS RSN, the pairwise key from the 4-way handshake * initiated by the peer with highest MAC address is used. */ if (addr == NULL || os_memcmp(ibss_rsn->wpa_s->own_addr, addr, ETH_ALEN) < 0) { wpa_printf(MSG_DEBUG, "AUTH: Do not use this PTK"); return 0; } } return wpa_drv_set_key(ibss_rsn->wpa_s, alg, addr, idx, 1, seq, 6, key, key_len); }
void ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame, size_t len) { const struct ieee80211_mgmt *header; struct ibss_rsn_peer *peer; size_t auth_length; header = (const struct ieee80211_mgmt *) auth_frame; auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth); if (ibss_rsn == NULL || len < auth_length) return; if (le_to_host16(header->u.auth.auth_alg) != WLAN_AUTH_OPEN || le_to_host16(header->u.auth.status_code) != WLAN_STATUS_SUCCESS) return; peer = ibss_rsn_get_peer(ibss_rsn, header->sa); switch (le_to_host16(header->u.auth.auth_transaction)) { case 1: ibss_rsn_handle_auth_1_of_2(ibss_rsn, peer, header->sa); break; case 2: wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 2) from " MACSTR, MAC2STR(header->sa)); if (!peer) { wpa_printf(MSG_DEBUG, "RSN: Received Auth seq 2 from " "unknown STA " MACSTR, MAC2STR(header->sa)); break; } /* authentication has been completed */ eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL); wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with " MACSTR, MAC2STR(header->sa)); ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_BY_US); break; } }
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr) { struct ibss_rsn_peer *peer; if (ibss_rsn == NULL) return -1; if (ibss_rsn_get_peer(ibss_rsn, addr)) { wpa_printf(MSG_DEBUG, "RSN: IBSS Authenticator and Supplicant " "for peer " MACSTR " already running", MAC2STR(addr)); return 0; } wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Authenticator and " "Supplicant for peer " MACSTR, MAC2STR(addr)); peer = os_zalloc(sizeof(*peer)); if (peer == NULL) return -1; peer->ibss_rsn = ibss_rsn; os_memcpy(peer->addr, addr, ETH_ALEN); if (ibss_rsn_supp_init(peer, ibss_rsn->wpa_s->own_addr, ibss_rsn->psk) < 0) { ibss_rsn_free(peer); return -1; } if (ibss_rsn_auth_init(ibss_rsn, peer) < 0) { ibss_rsn_free(peer); return -1; } peer->next = ibss_rsn->peers; ibss_rsn->peers = peer; return 0; }
static struct ibss_rsn_peer * ibss_rsn_peer_init(struct ibss_rsn *ibss_rsn, const u8 *addr) { struct ibss_rsn_peer *peer; if (ibss_rsn == NULL) return NULL; peer = ibss_rsn_get_peer(ibss_rsn, addr); if (peer) { wpa_printf(MSG_DEBUG, "RSN: IBSS Supplicant for peer "MACSTR " already running", MAC2STR(addr)); return peer; } wpa_printf(MSG_DEBUG, "RSN: Starting IBSS Supplicant for peer "MACSTR, MAC2STR(addr)); peer = os_zalloc(sizeof(*peer)); if (peer == NULL) { wpa_printf(MSG_DEBUG, "RSN: Could not allocate memory."); return NULL; } peer->ibss_rsn = ibss_rsn; os_memcpy(peer->addr, addr, ETH_ALEN); peer->authentication_status = IBSS_RSN_AUTH_NOT_AUTHENTICATED; if (ibss_rsn_supp_init(peer, ibss_rsn->wpa_s->own_addr, ibss_rsn->psk) < 0) { ibss_rsn_free(peer); return NULL; } peer->next = ibss_rsn->peers; ibss_rsn->peers = peer; return peer; }