/*
 * RSN pre-authentication (supplicant)
 * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"

#include "common.h"
#include "wpa.h"
#include "eloop.h"
#include "l2_packet/l2_packet.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "preauth.h"
#include "pmksa_cache.h"
#include "wpa_i.h"


#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)

#define PMKID_CANDIDATE_PRIO_SCAN 1000


struct rsn_pmksa_candidate {
	struct dl_list list;
	u8 bssid[ETH_ALEN];
	int priority;
};


/**
 * pmksa_candidate_free - Free all entries in PMKSA candidate list
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 */
void pmksa_candidate_free(struct wpa_sm *sm)
{
	struct rsn_pmksa_candidate *entry, *n;

	if (sm == NULL)
		return;

	dl_list_for_each_safe(entry, n, &sm->pmksa_candidates,
			      struct rsn_pmksa_candidate, list) {
		dl_list_del(&entry->list);
		os_free(entry);
	}
}


static int rsn_preauth_key_mgmt(int akmp)
{
	return !!(akmp & (WPA_KEY_MGMT_IEEE8021X |
			  WPA_KEY_MGMT_IEEE8021X_SHA256 |
			  WPA_KEY_MGMT_IEEE8021X_SUITE_B |
			  WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
}


static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
				const u8 *buf, size_t len)
{
	struct wpa_sm *sm = ctx;

	wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr));
	wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len);

	if (sm->preauth_eapol == NULL ||
	    is_zero_ether_addr(sm->preauth_bssid) ||
	    os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) {
		wpa_printf(MSG_WARNING, "RSN pre-auth frame received from "
			   "unexpected source " MACSTR " - dropped",
			   MAC2STR(src_addr));
		return;
	}

	eapol_sm_rx_eapol(sm->preauth_eapol, src_addr, buf, len);
}


static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
				 enum eapol_supp_result result,
				 void *ctx)
{
	struct wpa_sm *sm = ctx;
	u8 pmk[PMK_LEN];

	if (result == EAPOL_SUPP_RESULT_SUCCESS) {
		int res, pmk_len;
		pmk_len = PMK_LEN;
		res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
		if (res) {
			/*
			 * EAP-LEAP is an exception from other EAP methods: it
			 * uses only 16-byte PMK.
			 */
			res = eapol_sm_get_key(eapol, pmk, 16);
			pmk_len = 16;
		}
		if (res == 0) {
			wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
					pmk, pmk_len);
			sm->pmk_len = pmk_len;
			pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL,
					NULL, 0,
					sm->preauth_bssid, sm->own_addr,
					sm->network_ctx,
					WPA_KEY_MGMT_IEEE8021X, NULL);
		} else {
			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
				"RSN: failed to get master session key from "
				"pre-auth EAPOL state machines");
			result = EAPOL_SUPP_RESULT_FAILURE;
		}
	}

	wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
		MACSTR " %s", MAC2STR(sm->preauth_bssid),
		result == EAPOL_SUPP_RESULT_SUCCESS ? "completed successfully" :
		"failed");

	rsn_preauth_deinit(sm);
	rsn_preauth_candidate_process(sm);
}


static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx)
{
	struct wpa_sm *sm = eloop_ctx;

	wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
		MACSTR " timed out", MAC2STR(sm->preauth_bssid));
	rsn_preauth_deinit(sm);
	rsn_preauth_candidate_process(sm);
}


static int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf,
				  size_t len)
{
	struct wpa_sm *sm = ctx;
	u8 *msg;
	size_t msglen;
	int res;

	/* TODO: could add l2_packet_sendmsg that allows fragments to avoid
	 * extra copy here */

	if (sm->l2_preauth == NULL)
		return -1;

	msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL);
	if (msg == NULL)
		return -1;

	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen);
	res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid,
			     ETH_P_RSN_PREAUTH, msg, msglen);
	os_free(msg);
	return res;
}


/**
 * rsn_preauth_init - Start new RSN pre-authentication
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @dst: Authenticator address (BSSID) with which to preauthenticate
 * @eap_conf: Current EAP configuration
 * Returns: 0 on success, -1 on another pre-authentication is in progress,
 * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine
 * initialization failure, -4 on memory allocation failure
 *
 * This function request an RSN pre-authentication with a given destination
 * address. This is usually called for PMKSA candidates found from scan results
 * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger
 * pre-authentication.
 */
int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
		     struct eap_peer_config *eap_conf)
{
	struct eapol_config eapol_conf;
	struct eapol_ctx *ctx;
	int ret;

	if (sm->preauth_eapol)
		return -1;

	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
		"RSN: starting pre-authentication with " MACSTR, MAC2STR(dst));

	sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr,
					ETH_P_RSN_PREAUTH,
					rsn_preauth_receive, sm, 0);
	if (sm->l2_preauth == NULL) {
		wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet "
			   "processing for pre-authentication");
		return -2;
	}

	if (sm->bridge_ifname) {
		sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname,
						   sm->own_addr,
						   ETH_P_RSN_PREAUTH,
						   rsn_preauth_receive, sm, 0);
		if (sm->l2_preauth_br == NULL) {
			wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 "
				   "packet processing (bridge) for "
				   "pre-authentication");
			ret = -2;
			goto fail;
		}
	}

	ctx = os_zalloc(sizeof(*ctx));
	if (ctx == NULL) {
		wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context.");
		ret = -4;
		goto fail;
	}
	ctx->ctx = sm->ctx->ctx;
	ctx->msg_ctx = sm->ctx->ctx;
	ctx->preauth = 1;
	ctx->cb = rsn_preauth_eapol_cb;
	ctx->cb_ctx = sm;
	ctx->scard_ctx = sm->scard_ctx;
	ctx->eapol_send = rsn_preauth_eapol_send;
	ctx->eapol_send_ctx = sm;
	ctx->set_config_blob = sm->ctx->set_config_blob;
	ctx->get_config_blob = sm->ctx->get_config_blob;

	sm->preauth_eapol = eapol_sm_init(ctx);
	if (sm->preauth_eapol == NULL) {
		os_free(ctx);
		wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL "
			   "state machines for pre-authentication");
		ret = -3;
		goto fail;
	}
	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
	eapol_conf.accept_802_1x_keys = 0;
	eapol_conf.required_keys = 0;
	eapol_conf.fast_reauth = sm->fast_reauth;
	eapol_conf.workaround = sm->eap_workaround;
	eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf);
	/*
	 * Use a shorter startPeriod with preauthentication since the first
	 * preauth EAPOL-Start frame may end up being dropped due to race
	 * condition in the AP between the data receive and key configuration
	 * after the 4-Way Handshake.
	 */
	eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6);
	os_memcpy(sm->preauth_bssid, dst, ETH_ALEN);

	eapol_sm_notify_portValid(sm->preauth_eapol, true);
	/* 802.1X::portControl = Auto */
	eapol_sm_notify_portEnabled(sm->preauth_eapol, true);

	eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0,
			       rsn_preauth_timeout, sm, NULL);

	return 0;

fail:
	if (sm->l2_preauth_br) {
		l2_packet_deinit(sm->l2_preauth_br);
		sm->l2_preauth_br = NULL;
	}
	l2_packet_deinit(sm->l2_preauth);
	sm->l2_preauth = NULL;
	return ret;
}


/**
 * rsn_preauth_deinit - Abort RSN pre-authentication
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 *
 * This function aborts the current RSN pre-authentication (if one is started)
 * and frees resources allocated for it.
 */
void rsn_preauth_deinit(struct wpa_sm *sm)
{
	if (sm == NULL || !sm->preauth_eapol)
		return;

	eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL);
	eapol_sm_deinit(sm->preauth_eapol);
	sm->preauth_eapol = NULL;
	os_memset(sm->preauth_bssid, 0, ETH_ALEN);

	l2_packet_deinit(sm->l2_preauth);
	sm->l2_preauth = NULL;
	if (sm->l2_preauth_br) {
		l2_packet_deinit(sm->l2_preauth_br);
		sm->l2_preauth_br = NULL;
	}
}


/**
 * rsn_preauth_candidate_process - Process PMKSA candidates
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 *
 * Go through the PMKSA candidates and start pre-authentication if a candidate
 * without an existing PMKSA cache entry is found. Processed candidates will be
 * removed from the list.
 */
void rsn_preauth_candidate_process(struct wpa_sm *sm)
{
	struct rsn_pmksa_candidate *candidate, *n;

	if (dl_list_empty(&sm->pmksa_candidates))
		return;

	/* TODO: drop priority for old candidate entries */

	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate "
		"list");
	if (sm->preauth_eapol ||
	    sm->proto != WPA_PROTO_RSN ||
	    wpa_sm_get_state(sm) != WPA_COMPLETED ||
	    !rsn_preauth_key_mgmt(sm->key_mgmt)) {
		wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable "
			"state for new pre-authentication");
		return; /* invalid state for new pre-auth */
	}

	dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
			      struct rsn_pmksa_candidate, list) {
		struct rsn_pmksa_cache_entry *p = NULL;
		p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL, 0);
		if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
		    (p == NULL || p->opportunistic)) {
			wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
				"candidate " MACSTR
				" selected for pre-authentication",
				MAC2STR(candidate->bssid));
			dl_list_del(&candidate->list);
			rsn_preauth_init(sm, candidate->bssid,
					 sm->eap_conf_ctx);
			os_free(candidate);
			return;
		}
		wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate "
			MACSTR " does not need pre-authentication anymore",
			MAC2STR(candidate->bssid));
		/* Some drivers (e.g., NDIS) expect to get notified about the
		 * PMKIDs again, so report the existing data now. */
		if (p) {
			wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid,
					 NULL, p->pmk, p->pmk_len, 0, 0);
		}

		dl_list_del(&candidate->list);
		os_free(candidate);
	}
	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
		"candidates");
}


/**
 * pmksa_candidate_add - Add a new PMKSA candidate
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @bssid: BSSID (authenticator address) of the candidate
 * @prio: Priority (the smaller number, the higher priority)
 * @preauth: Whether the candidate AP advertises support for pre-authentication
 *
 * This function is used to add PMKSA candidates for RSN pre-authentication. It
 * is called from scan result processing and from driver events for PMKSA
 * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event().
 */
void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
			 int prio, int preauth)
{
	struct rsn_pmksa_candidate *cand, *pos;

	if (sm->network_ctx && sm->proactive_key_caching)
		pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
					      bssid, 0);

	if (!preauth) {
		wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
			   "preauth flag");
		return;
	}

	/* If BSSID already on candidate list, update the priority of the old
	 * entry. Do not override priority based on normal scan results. */
	cand = NULL;
	dl_list_for_each(pos, &sm->pmksa_candidates,
			 struct rsn_pmksa_candidate, list) {
		if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) {
			cand = pos;
			break;
		}
	}

	if (cand) {
		dl_list_del(&cand->list);
		if (prio < PMKID_CANDIDATE_PRIO_SCAN)
			cand->priority = prio;
	} else {
		cand = os_zalloc(sizeof(*cand));
		if (cand == NULL)
			return;
		os_memcpy(cand->bssid, bssid, ETH_ALEN);
		cand->priority = prio;
	}

	/* Add candidate to the list; order by increasing priority value. i.e.,
	 * highest priority (smallest value) first. */
	dl_list_for_each(pos, &sm->pmksa_candidates,
			 struct rsn_pmksa_candidate, list) {
		if (cand->priority <= pos->priority) {
			if (!pos->list.prev) {
				/*
				 * This cannot really happen in pracrice since
				 * pos was fetched from the list and the prev
				 * pointer must be set. It looks like clang
				 * static analyzer gets confused with the
				 * dl_list_del(&cand->list) call above and ends
				 * up assuming pos->list.prev could be NULL.
				 */
				os_free(cand);
				return;
			}
			dl_list_add(pos->list.prev, &cand->list);
			cand = NULL;
			break;
		}
	}
	if (cand)
		dl_list_add_tail(&sm->pmksa_candidates, &cand->list);

	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache "
		"candidate " MACSTR " prio %d", MAC2STR(bssid), prio);
	rsn_preauth_candidate_process(sm);
}


/* TODO: schedule periodic scans if current AP supports preauth */

/**
 * rsn_preauth_scan_results - Start processing scan results for canditates
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * Returns: 0 if ready to process results or -1 to skip processing
 *
 * This functions is used to notify RSN code about start of new scan results
 * processing. The actual scan results will be provided by calling
 * rsn_preauth_scan_result() for each BSS if this function returned 0.
 */
int rsn_preauth_scan_results(struct wpa_sm *sm)
{
	if (sm->ssid_len == 0)
		return -1;

	/*
	 * TODO: is it ok to free all candidates? What about the entries
	 * received from EVENT_PMKID_CANDIDATE?
	 */
	pmksa_candidate_free(sm);

	return 0;
}


/**
 * rsn_preauth_scan_result - Processing scan result for PMKSA canditates
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 *
 * Add all suitable APs (Authenticators) from scan results into PMKSA
 * candidate list.
 */
void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
			     const u8 *ssid, const u8 *rsn)
{
	struct wpa_ie_data ie;
	struct rsn_pmksa_cache_entry *pmksa;

	if (ssid[1] != sm->ssid_len ||
	    os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0)
		return; /* Not for the current SSID */

	if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0)
		return; /* Ignore current AP */

	if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
		return;

	pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL, 0);
	if (pmksa && (!pmksa->opportunistic ||
		      !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
		return;

	if (!rsn_preauth_key_mgmt(ie.key_mgmt))
		return;

	/* Give less priority to candidates found from normal scan results. */
	pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN,
			    ie.capabilities & WPA_CAPABILITY_PREAUTH);
}


#ifdef CONFIG_CTRL_IFACE
/**
 * rsn_preauth_get_status - Get pre-authentication status
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @buf: Buffer for status information
 * @buflen: Maximum buffer length
 * @verbose: Whether to include verbose status information
 * Returns: Number of bytes written to buf.
 *
 * Query WPA2 pre-authentication for status information. This function fills in
 * a text area with current status information. If the buffer (buf) is not
 * large enough, status information will be truncated to fit the buffer.
 */
int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
			   int verbose)
{
	char *pos = buf, *end = buf + buflen;
	int res, ret;

	if (sm->preauth_eapol) {
		ret = os_snprintf(pos, end - pos, "Pre-authentication "
				  "EAPOL state machines:\n");
		if (os_snprintf_error(end - pos, ret))
			return pos - buf;
		pos += ret;
		res = eapol_sm_get_status(sm->preauth_eapol,
					  pos, end - pos, verbose);
		if (res >= 0)
			pos += res;
	}

	return pos - buf;
}
#endif /* CONFIG_CTRL_IFACE */


/**
 * rsn_preauth_in_progress - Verify whether pre-authentication is in progress
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 */
int rsn_preauth_in_progress(struct wpa_sm *sm)
{
	return sm->preauth_eapol != NULL;
}

#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
