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