2 * hostapd / EAP-GTC (RFC 3748)
3 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
22 enum { CONTINUE
, SUCCESS
, FAILURE
} state
;
27 static void * eap_gtc_init(struct eap_sm
*sm
)
29 struct eap_gtc_data
*data
;
31 data
= os_zalloc(sizeof(*data
));
34 data
->state
= CONTINUE
;
37 if (sm
->m
&& sm
->m
->vendor
== EAP_VENDOR_IETF
&&
38 sm
->m
->method
== EAP_TYPE_FAST
) {
39 wpa_printf(MSG_DEBUG
, "EAP-GTC: EAP-FAST tunnel - use prefix "
40 "with challenge/response");
49 static void eap_gtc_reset(struct eap_sm
*sm
, void *priv
)
51 struct eap_gtc_data
*data
= priv
;
56 static struct wpabuf
* eap_gtc_buildReq(struct eap_sm
*sm
, void *priv
, u8 id
)
58 struct eap_gtc_data
*data
= priv
;
63 msg
= data
->prefix
? "CHALLENGE=Password" : "Password";
65 msg_len
= os_strlen(msg
);
66 req
= eap_msg_alloc(EAP_VENDOR_IETF
, EAP_TYPE_GTC
, msg_len
,
67 EAP_CODE_REQUEST
, id
);
69 wpa_printf(MSG_ERROR
, "EAP-GTC: Failed to allocate memory for "
71 data
->state
= FAILURE
;
75 wpabuf_put_data(req
, msg
, msg_len
);
77 data
->state
= CONTINUE
;
83 static Boolean
eap_gtc_check(struct eap_sm
*sm
, void *priv
,
84 struct wpabuf
*respData
)
89 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_GTC
, respData
, &len
);
90 if (pos
== NULL
|| len
< 1) {
91 wpa_printf(MSG_INFO
, "EAP-GTC: Invalid frame");
99 static void eap_gtc_process(struct eap_sm
*sm
, void *priv
,
100 struct wpabuf
*respData
)
102 struct eap_gtc_data
*data
= priv
;
106 pos
= eap_hdr_validate(EAP_VENDOR_IETF
, EAP_TYPE_GTC
, respData
, &rlen
);
107 if (pos
== NULL
|| rlen
< 1)
108 return; /* Should not happen - frame already validated */
110 wpa_hexdump_ascii_key(MSG_MSGDUMP
, "EAP-GTC: Response", pos
, rlen
);
114 const u8
*pos2
, *end
;
115 /* "RESPONSE=<user>\0<password>" */
117 wpa_printf(MSG_DEBUG
, "EAP-GTC: Too short response "
118 "for EAP-FAST prefix");
119 data
->state
= FAILURE
;
126 while (pos2
< end
&& *pos2
)
129 wpa_printf(MSG_DEBUG
, "EAP-GTC: No password in "
130 "response to EAP-FAST prefix");
131 data
->state
= FAILURE
;
135 wpa_hexdump_ascii(MSG_MSGDUMP
, "EAP-GTC: Response user",
137 if (sm
->identity
&& sm
->require_identity_match
&&
138 (pos2
- pos
!= (int) sm
->identity_len
||
139 os_memcmp(pos
, sm
->identity
, sm
->identity_len
))) {
140 wpa_printf(MSG_DEBUG
, "EAP-GTC: Phase 2 Identity did "
141 "not match with required Identity");
142 wpa_hexdump_ascii(MSG_MSGDUMP
, "EAP-GTC: Expected "
144 sm
->identity
, sm
->identity_len
);
145 data
->state
= FAILURE
;
148 os_free(sm
->identity
);
149 sm
->identity_len
= pos2
- pos
;
150 sm
->identity
= os_malloc(sm
->identity_len
);
151 if (sm
->identity
== NULL
) {
152 data
->state
= FAILURE
;
155 os_memcpy(sm
->identity
, pos
, sm
->identity_len
);
158 if (eap_user_get(sm
, sm
->identity
, sm
->identity_len
, 1) != 0) {
159 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-GTC: Phase2 "
160 "Identity not found in the user "
162 sm
->identity
, sm
->identity_len
);
163 data
->state
= FAILURE
;
169 wpa_hexdump_ascii_key(MSG_MSGDUMP
,
170 "EAP-GTC: Response password",
173 #endif /* EAP_FAST */
175 if (sm
->user
== NULL
|| sm
->user
->password
== NULL
||
176 sm
->user
->password_hash
) {
177 wpa_printf(MSG_INFO
, "EAP-GTC: Plaintext password not "
179 data
->state
= FAILURE
;
183 if (rlen
!= sm
->user
->password_len
||
184 os_memcmp(pos
, sm
->user
->password
, rlen
) != 0) {
185 wpa_printf(MSG_DEBUG
, "EAP-GTC: Done - Failure");
186 data
->state
= FAILURE
;
188 wpa_printf(MSG_DEBUG
, "EAP-GTC: Done - Success");
189 data
->state
= SUCCESS
;
194 static Boolean
eap_gtc_isDone(struct eap_sm
*sm
, void *priv
)
196 struct eap_gtc_data
*data
= priv
;
197 return data
->state
!= CONTINUE
;
201 static Boolean
eap_gtc_isSuccess(struct eap_sm
*sm
, void *priv
)
203 struct eap_gtc_data
*data
= priv
;
204 return data
->state
== SUCCESS
;
208 int eap_server_gtc_register(void)
210 struct eap_method
*eap
;
213 eap
= eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION
,
214 EAP_VENDOR_IETF
, EAP_TYPE_GTC
, "GTC");
218 eap
->init
= eap_gtc_init
;
219 eap
->reset
= eap_gtc_reset
;
220 eap
->buildReq
= eap_gtc_buildReq
;
221 eap
->check
= eap_gtc_check
;
222 eap
->process
= eap_gtc_process
;
223 eap
->isDone
= eap_gtc_isDone
;
224 eap
->isSuccess
= eap_gtc_isSuccess
;
226 ret
= eap_server_method_register(eap
);
228 eap_server_method_free(eap
);