/*
 * hostapd / EAP user database
 * Copyright (c) 2012, 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"
#ifdef CONFIG_SQLITE
#include <sqlite3.h>
#endif /* CONFIG_SQLITE */

#include "common.h"
#include "eap_common/eap_wsc_common.h"
#include "eap_server/eap_methods.h"
#include "eap_server/eap.h"
#include "ap_config.h"
#include "hostapd.h"

#ifdef CONFIG_SQLITE

static void set_user_methods(struct hostapd_eap_user *user, const char *methods)
{
	char *buf, *start;
	int num_methods;

	buf = os_strdup(methods);
	if (buf == NULL)
		return;

	os_memset(&user->methods, 0, sizeof(user->methods));
	num_methods = 0;
	start = buf;
	while (*start) {
		char *pos3 = os_strchr(start, ',');
		if (pos3)
			*pos3++ = '\0';
		user->methods[num_methods].method =
			eap_server_get_type(start,
					    &user->methods[num_methods].vendor);
		if (user->methods[num_methods].vendor == EAP_VENDOR_IETF &&
		    user->methods[num_methods].method == EAP_TYPE_NONE) {
			if (os_strcmp(start, "TTLS-PAP") == 0) {
				user->ttls_auth |= EAP_TTLS_AUTH_PAP;
				goto skip_eap;
			}
			if (os_strcmp(start, "TTLS-CHAP") == 0) {
				user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
				goto skip_eap;
			}
			if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
				user->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
				goto skip_eap;
			}
			if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
				user->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
				goto skip_eap;
			}
			wpa_printf(MSG_INFO, "DB: Unsupported EAP type '%s'",
				   start);
			os_free(buf);
			return;
		}

		num_methods++;
		if (num_methods >= EAP_MAX_METHODS)
			break;
	skip_eap:
		if (pos3 == NULL)
			break;
		start = pos3;
	}

	os_free(buf);
}


static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
{
	struct hostapd_eap_user *user = ctx;
	int i;

	for (i = 0; i < argc; i++) {
		if (os_strcmp(col[i], "password") == 0 && argv[i]) {
			os_free(user->password);
			user->password_len = os_strlen(argv[i]);
			user->password = (u8 *) os_strdup(argv[i]);
			user->next = (void *) 1;
		} else if (os_strcmp(col[i], "methods") == 0 && argv[i]) {
			set_user_methods(user, argv[i]);
		}
	}

	return 0;
}


static int get_wildcard_cb(void *ctx, int argc, char *argv[], char *col[])
{
	struct hostapd_eap_user *user = ctx;
	int i, id = -1, methods = -1;
	size_t len;

	for (i = 0; i < argc; i++) {
		if (os_strcmp(col[i], "identity") == 0 && argv[i])
			id = i;
		else if (os_strcmp(col[i], "methods") == 0 && argv[i])
			methods = i;
	}

	if (id < 0 || methods < 0)
		return 0;

	len = os_strlen(argv[id]);
	if (len <= user->identity_len &&
	    os_memcmp(argv[id], user->identity, len) == 0 &&
	    (user->password == NULL || len > user->password_len)) {
		os_free(user->password);
		user->password_len = os_strlen(argv[id]);
		user->password = (u8 *) os_strdup(argv[id]);
		user->next = (void *) 1;
		set_user_methods(user, argv[methods]);
	}

	return 0;
}


static const struct hostapd_eap_user *
eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
		    size_t identity_len, int phase2)
{
	sqlite3 *db;
	struct hostapd_eap_user *user = NULL;
	char id_str[256], cmd[300];
	size_t i;

	if (identity_len >= sizeof(id_str))
		return NULL;
	os_memcpy(id_str, identity, identity_len);
	id_str[identity_len] = '\0';
	for (i = 0; i < identity_len; i++) {
		if (id_str[i] >= 'a' && id_str[i] <= 'z')
			continue;
		if (id_str[i] >= 'A' && id_str[i] <= 'Z')
			continue;
		if (id_str[i] >= '0' && id_str[i] <= '9')
			continue;
		if (id_str[i] == '-' || id_str[i] == '_' || id_str[i] == '.' ||
		    id_str[i] == ',' || id_str[i] == '@' || id_str[i] == '\\' ||
		    id_str[i] == '!' || id_str[i] == '#' || id_str[i] == '%' ||
		    id_str[i] == '=' || id_str[i] == ' ')
			continue;
		wpa_printf(MSG_INFO, "DB: Unsupported character in identity");
		return NULL;
	}

	os_free(hapd->tmp_eap_user.identity);
	os_free(hapd->tmp_eap_user.password);
	os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
	hapd->tmp_eap_user.phase2 = phase2;
	hapd->tmp_eap_user.identity = os_zalloc(identity_len + 1);
	if (hapd->tmp_eap_user.identity == NULL)
		return NULL;
	os_memcpy(hapd->tmp_eap_user.identity, identity, identity_len);

	if (sqlite3_open(hapd->conf->eap_user_sqlite, &db)) {
		wpa_printf(MSG_INFO, "DB: Failed to open database %s: %s",
			   hapd->conf->eap_user_sqlite, sqlite3_errmsg(db));
		sqlite3_close(db);
		return NULL;
	}

	os_snprintf(cmd, sizeof(cmd),
		    "SELECT password,methods FROM users WHERE "
		    "identity='%s' AND phase2=%d;", id_str, phase2);
	wpa_printf(MSG_DEBUG, "DB: %s", cmd);
	if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
	    SQLITE_OK) {
		wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL operation");
	} else if (hapd->tmp_eap_user.next)
		user = &hapd->tmp_eap_user;

	if (user == NULL && !phase2) {
		os_snprintf(cmd, sizeof(cmd),
			    "SELECT identity,methods FROM wildcards;");
		wpa_printf(MSG_DEBUG, "DB: %s", cmd);
		if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
				 NULL) != SQLITE_OK) {
			wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL "
				   "operation");
		} else if (hapd->tmp_eap_user.next) {
			user = &hapd->tmp_eap_user;
			os_free(user->identity);
			user->identity = user->password;
			user->identity_len = user->password_len;
			user->password = NULL;
			user->password_len = 0;
		}
	}

	sqlite3_close(db);

	return user;
}

#endif /* CONFIG_SQLITE */


const struct hostapd_eap_user *
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
		     size_t identity_len, int phase2)
{
	const struct hostapd_bss_config *conf = hapd->conf;
	struct hostapd_eap_user *user = conf->eap_user;

#ifdef CONFIG_WPS
	if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
		static struct hostapd_eap_user wsc_enrollee;
		os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
		wsc_enrollee.methods[0].method = eap_server_get_type(
			"WSC", &wsc_enrollee.methods[0].vendor);
		return &wsc_enrollee;
	}

	if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
		static struct hostapd_eap_user wsc_registrar;
		os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
		wsc_registrar.methods[0].method = eap_server_get_type(
			"WSC", &wsc_registrar.methods[0].vendor);
		wsc_registrar.password = (u8 *) conf->ap_pin;
		wsc_registrar.password_len = conf->ap_pin ?
			os_strlen(conf->ap_pin) : 0;
		return &wsc_registrar;
	}
#endif /* CONFIG_WPS */

	while (user) {
		if (!phase2 && user->identity == NULL) {
			/* Wildcard match */
			break;
		}

		if (user->phase2 == !!phase2 && user->wildcard_prefix &&
		    identity_len >= user->identity_len &&
		    os_memcmp(user->identity, identity, user->identity_len) ==
		    0) {
			/* Wildcard prefix match */
			break;
		}

		if (user->phase2 == !!phase2 &&
		    user->identity_len == identity_len &&
		    os_memcmp(user->identity, identity, identity_len) == 0)
			break;
		user = user->next;
	}

#ifdef CONFIG_SQLITE
	if (user == NULL && conf->eap_user_sqlite) {
		return eap_user_sqlite_get(hapd, identity, identity_len,
					   phase2);
	}
#endif /* CONFIG_SQLITE */

	return user;
}
