18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-GTC (RFC 3748)
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_gtc_data {
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum { CONTINUE, SUCCESS, FAILURE } state;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int prefix;
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_gtc_init(struct eap_sm *sm)
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_gtc_data *data;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data = os_zalloc(sizeof(*data));
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->state = CONTINUE;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_FAST
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->m->method == EAP_TYPE_FAST) {
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "with challenge/response");
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->prefix = 1;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_FAST */
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gtc_reset(struct eap_sm *sm, void *priv)
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_gtc_data *data = priv;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(data);
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id)
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_gtc_data *data = priv;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *msg;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t msg_len;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg = data->prefix ? "CHALLENGE=Password" : "Password";
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	msg_len = os_strlen(msg);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, msg_len,
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    EAP_CODE_REQUEST, id);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL) {
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "EAP-GTC: Failed to allocate memory for "
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "request");
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = FAILURE;
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(req, msg, msg_len);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	data->state = CONTINUE;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return req;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_gtc_check(struct eap_sm *sm, void *priv,
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wpabuf *respData)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len);
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL || len < 1) {
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame");
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return TRUE;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return FALSE;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_gtc_process(struct eap_sm *sm, void *priv,
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    struct wpabuf *respData)
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_gtc_data *data = priv;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t rlen;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &rlen);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == NULL || rlen < 1)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Should not happen - frame already validated */
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_FAST
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->prefix) {
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *pos2, *end;
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* "RESPONSE=<user>\0<password>" */
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rlen < 10) {
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-GTC: Too short response "
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for EAP-FAST prefix");
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->state = FAILURE;
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		end = pos + rlen;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += 9;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos2 = pos;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (pos2 < end && *pos2)
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos2++;
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos2 == end) {
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-GTC: No password in "
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "response to EAP-FAST prefix");
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->state = FAILURE;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Response user",
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  pos, pos2 - pos);
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sm->identity && sm->require_identity_match &&
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (pos2 - pos != (int) sm->identity_len ||
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     os_memcmp(pos, sm->identity, sm->identity_len))) {
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "EAP-GTC: Phase 2 Identity did "
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "not match with required Identity");
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Expected "
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "identity",
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  sm->identity, sm->identity_len);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->state = FAILURE;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(sm->identity);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->identity_len = pos2 - pos;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sm->identity = os_malloc(sm->identity_len);
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sm->identity == NULL) {
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->state = FAILURE;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(sm->identity, pos, sm->identity_len);
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump_ascii(MSG_DEBUG, "EAP-GTC: Phase2 "
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "Identity not found in the user "
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  "database",
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  sm->identity, sm->identity_len);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->state = FAILURE;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = pos2 + 1;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		rlen = end - pos;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_ascii_key(MSG_MSGDUMP,
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      "EAP-GTC: Response password",
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      pos, rlen);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_FAST */
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sm->user == NULL || sm->user->password == NULL ||
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    sm->user->password_hash) {
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "EAP-GTC: Plaintext password not "
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "configured");
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = FAILURE;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rlen != sm->user->password_len ||
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(pos, sm->user->password, rlen) != 0) {
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Failure");
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = FAILURE;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Success");
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->state = SUCCESS;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_gtc_data *data = priv;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->state != CONTINUE;
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv)
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_gtc_data *data = priv;
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return data->state == SUCCESS;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_gtc_register(void)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eap_method *eap;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap == NULL)
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->init = eap_gtc_init;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->reset = eap_gtc_reset;
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->buildReq = eap_gtc_buildReq;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->check = eap_gtc_check;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->process = eap_gtc_process;
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->isDone = eap_gtc_isDone;
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eap->isSuccess = eap_gtc_isSuccess;
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = eap_server_method_register(eap);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret)
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eap_server_method_free(eap);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
231