/*
 * 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"


#ifdef IEEE8021X_EAPOL

#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 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, 0,
					sm->preauth_bssid, sm->own_addr,
					sm->network_ctx,
					WPA_KEY_MGMT_IEEE8021X);
		} 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 ||
	    (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
	     sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256 &&
	     sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B &&
	     sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)) {
		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);
		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, candidate->bssid, p->pmkid);
		}

		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);

	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);
	if (pmksa && (!pmksa->opportunistic ||
		      !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
		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 */
