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;
}
static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
					struct ibss_rsn_peer *peer,
					const u8* addr)
{
	wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR,
		   MAC2STR(addr));

	if (peer &&
	    peer->authentication_status & (IBSS_RSN_SET_PTK_SUPP |
					   IBSS_RSN_SET_PTK_AUTH)) {
		/* Clear the TK for this pair to allow recovery from the case
		 * where the peer STA has restarted and lost its key while we
		 * still have a pairwise key configured. */
		wpa_printf(MSG_DEBUG, "RSN: Clear pairwise key for peer "
			   MACSTR, MAC2STR(addr));
		wpa_drv_set_key(ibss_rsn->wpa_s, WPA_ALG_NONE, addr, 0, 0,
				NULL, 0, NULL, 0);
	}

	if (peer &&
	    peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) {
		if (peer->own_auth_tx.sec) {
			struct os_reltime now, diff;
			os_get_reltime(&now);
			os_reltime_sub(&now, &peer->own_auth_tx, &diff);
			if (diff.sec == 0 && diff.usec < 500000) {
				wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX",
					   (int) diff.usec);
				goto skip_reinit;
			}
		}
		/*
		 * A peer sent us an Authentication frame even though it already
		 * started an EAPOL session. We should reinit state machines
		 * here, but it's much more complicated than just deleting and
		 * recreating the state machine
		 */
		wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station "
			   MACSTR, MAC2STR(addr));

		ibss_rsn_stop(ibss_rsn, addr);
		peer = NULL;
	}

	if (!peer) {
		peer = ibss_rsn_peer_init(ibss_rsn, addr);
		if (!peer)
			return;

		wpa_printf(MSG_DEBUG, "RSN: IBSS Auth started by peer " MACSTR,
			   MAC2STR(addr));
	}

skip_reinit:
	/* reply with an Authentication frame now, before sending an EAPOL */
	ibss_rsn_send_auth(ibss_rsn, addr, 2);
	/* no need to start another AUTH challenge in the other way.. */
	ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US);
}
Exemple #3
0
static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
					struct ibss_rsn_peer *peer,
					const u8* addr)
{
	wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR,
		   MAC2STR(addr));

	if (peer &&
	    peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) {
		if (peer->own_auth_tx.sec) {
			struct os_reltime now, diff;
			os_get_reltime(&now);
			os_reltime_sub(&now, &peer->own_auth_tx, &diff);
			if (diff.sec == 0 && diff.usec < 500000) {
				wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX",
					   (int) diff.usec);
				goto skip_reinit;
			}
		}
		/*
		 * A peer sent us an Authentication frame even though it already
		 * started an EAPOL session. We should reinit state machines
		 * here, but it's much more complicated than just deleting and
		 * recreating the state machine
		 */
		wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station "
			   MACSTR, MAC2STR(addr));

		ibss_rsn_stop(ibss_rsn, addr);
		peer = NULL;
	}

	if (!peer) {
		peer = ibss_rsn_peer_init(ibss_rsn, addr);
		if (!peer)
			return;

		wpa_printf(MSG_DEBUG, "RSN: IBSS Auth started by peer " MACSTR,
			   MAC2STR(addr));
	}

skip_reinit:
	/* reply with an Authentication frame now, before sending an EAPOL */
	ibss_rsn_send_auth(ibss_rsn, addr, 2);
	/* no need to start another AUTH challenge in the other way.. */
	ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US);
}
void ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame,
			  size_t len)
{
	const struct ieee80211_mgmt *header;
	struct ibss_rsn_peer *peer;
	size_t auth_length;

	header = (const struct ieee80211_mgmt *) auth_frame;
	auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);

	if (ibss_rsn == NULL || len < auth_length)
		return;

	if (le_to_host16(header->u.auth.auth_alg) != WLAN_AUTH_OPEN ||
	    le_to_host16(header->u.auth.status_code) != WLAN_STATUS_SUCCESS)
		return;

	peer = ibss_rsn_get_peer(ibss_rsn, header->sa);

	switch (le_to_host16(header->u.auth.auth_transaction)) {
	case 1:
		ibss_rsn_handle_auth_1_of_2(ibss_rsn, peer, header->sa);
		break;
	case 2:
		wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 2) from "
			   MACSTR, MAC2STR(header->sa));
		if (!peer) {
			wpa_printf(MSG_DEBUG, "RSN: Received Auth seq 2 from "
				   "unknown STA " MACSTR, MAC2STR(header->sa));
			break;
		}

		/* authentication has been completed */
		eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL);
		wpa_printf(MSG_DEBUG, "RSN: IBSS Auth completed with " MACSTR,
			   MAC2STR(header->sa));
		ibss_rsn_peer_authenticated(ibss_rsn, peer,
					    IBSS_RSN_AUTH_BY_US);
		break;
	}
}