/*
 * hostapd / Station fingerprinting
 * Copyright (c) 2015 Google, Inc.
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

/*
 * Parse a series of IEs, as in Probe or Association packets,
 * and render them to a descriptive string. The tag number of
 * standard options is written to the string, while the vendor
 * ID and subtag are written for vendor options.
 *
 * Example strings:
 * tag:0,1,50,45,221(00904c,51)
 * tag:0,1,33,36,48,45,221(00904c,51),221(0050f2,2)
 */

#include "utils/includes.h"
#include "utils/common.h"
#include "sta_info.h"

/* Copy a string with no funny schtuff allowed; only alphanumerics. */
static void no_mischief_strncpy(char *dst, const char *src, size_t n)
{
	size_t i;
	for (i = 0; i < n; i++) {
		unsigned char s = src[i];
		int is_lower = (s >= 'a' && s <= 'z');
		int is_upper = (s >= 'A' && s <= 'Z');
		int is_digit = (s >= '0' && s <= '9');
		if (is_lower || is_upper || is_digit) {
			/* TODO: if any manufacturer uses Unicode within the
			 * WPS header, it will get mangled here. */
			dst[i] = s;
		} else {
			/* note that even spaces will be transformed to underscores,
			 * so 'Nexus 7' will turn into 'Nexus_7'. This is deliberate,
			 * to make the fingerprint easier to parse. */
			dst[i] = '_';
		}
	}
}

static int get_wps_name(char *name, size_t name_len,
		const u8 *data, size_t data_len)
{
	/* Inside the WPS IE are a series of sub-IEs, using two byte IDs
	 * and two byte lengths. We're looking for the model name, if
	 * present. */
	while (data_len >= 4) {
		u16 id, elen;
		id = (data[0] << 8) | data[1];
		elen = (data[2] << 8) | data[3];
		data += 4;
		data_len -= 4;

		if (elen > data_len) {
			return 0;
		}

		if (id == 0x1023) {
			/* Model name, like 'Nexus 7' */
			size_t n = (elen < name_len) ? elen : name_len;
			no_mischief_strncpy(name, data, n);
			return n;
		}

		data += elen;
		data_len -= elen;
	}

	return 0;
}

static void ie_to_string(char *fstr, size_t fstr_len,
                         const u8 *ie, size_t ie_len)
{
	size_t flen = fstr_len - 1;
	char htcap[7 + 4 + 1];  // ",htcap:" + %04hx + trailing NUL
	char vhtcap[8 + 8 + 1];  // ",vhtcap:" + %08x + trailing NUL
	#define WPS_NAME_LEN		32
	char wps[WPS_NAME_LEN + 5 + 1];  // room to prepend ",wps:" + trailing NUL
	int num = 0;

	memset(htcap, 0, sizeof(htcap));
	memset(vhtcap, 0, sizeof(vhtcap));
	memset(wps, 0, sizeof(wps));
	snprintf(fstr, flen, "tag:");
	flen = fstr_len - strlen(fstr) - 1;

	while (ie_len >= 2) {
		u8 id, elen;
		char tagbuf[32];
		char *sep = (num++ == 0) ? "" : ",";

		id = *ie++;
		elen = *ie++;
		ie_len -= 2;

		if (elen > ie_len) {
			break;
		}

		if ((id == 221) && (elen >= 4)) {
			/* Vendor specific */
			int is_MSFT = (ie[0] == 0x00 && ie[1] == 0x50 && ie[2] == 0xf2);
			if (is_MSFT && ie[3] == 0x04) {
				/* WPS */
				char model_name[WPS_NAME_LEN + 1];
				const u8 *data = &ie[4];
				size_t data_len = elen - 4;
				memset(model_name, 0, sizeof(model_name));
				if (get_wps_name(model_name, WPS_NAME_LEN, data, data_len)) {
					snprintf(wps, sizeof(wps), ",wps:%s", model_name);
				}
			}

			snprintf(tagbuf, sizeof(tagbuf), "%s%d(%02x%02x%02x,%d)",
			         sep, id, ie[0], ie[1], ie[2], ie[3]);
		} else {
			if ((id == 45) && (elen > 2)) {
				/* HT Capabilities (802.11n) */
				u16 cap;
				memcpy(&cap, ie, sizeof(cap));
				snprintf(htcap, sizeof(htcap), ",htcap:%04hx",
				         le_to_host16(cap));
			}
			if ((id == 191) && (elen > 4)) {
				/* VHT Capabilities (802.11ac) */
				u32 cap;
				memcpy(&cap, ie, sizeof(cap));
				snprintf(vhtcap, sizeof(vhtcap), ",vhtcap:%08x",
				         le_to_host32(cap));
			}
			snprintf(tagbuf, sizeof(tagbuf), "%s%d", sep, id);
		}

		strncat(fstr, tagbuf, flen);
		flen = fstr_len - strlen(fstr) - 1;

		ie += elen;
		ie_len -= elen;
	}

	if (strlen(htcap)) {
		strncat(fstr, htcap, flen);
		flen = fstr_len - strlen(fstr) - 1;
	}
	if (strlen(vhtcap)) {
		strncat(fstr, vhtcap, flen);
		flen = fstr_len - strlen(fstr) - 1;
	}
	if (strlen(wps)) {
		strncat(fstr, wps, flen);
		flen = fstr_len - strlen(fstr) - 1;
	}

	fstr[fstr_len - 1] = '\0';
}

void hostapd_fingerprint_probe_req(struct sta_info *sta,
	const u8 *ie, size_t ie_len, int is_bcast)
{
	char *fstr;
	size_t fstr_len;

	if (is_bcast) {
		fstr = sta->probe_bcast_ie_fingerprint;
		fstr_len = sizeof(sta->probe_bcast_ie_fingerprint);
	} else {
		fstr = sta->probe_ie_fingerprint;
		fstr_len = sizeof(sta->probe_ie_fingerprint);
	}

	ie_to_string(fstr, fstr_len, ie, ie_len);
}

void hostapd_fingerprint_assoc_req(struct sta_info *sta,
	const u8 *ie, size_t ie_len)
{
	ie_to_string(sta->assoc_ie_fingerprint,
	             sizeof(sta->assoc_ie_fingerprint),
	             ie, ie_len);
}

/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab : */
