16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer * EAP peer method: EAP-GTC (RFC 3748)
36d49e1aeSJan Lentfer * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
76d49e1aeSJan Lentfer */
86d49e1aeSJan Lentfer
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer
116d49e1aeSJan Lentfer #include "common.h"
126d49e1aeSJan Lentfer #include "eap_i.h"
136d49e1aeSJan Lentfer
146d49e1aeSJan Lentfer
156d49e1aeSJan Lentfer struct eap_gtc_data {
166d49e1aeSJan Lentfer int prefix;
176d49e1aeSJan Lentfer };
186d49e1aeSJan Lentfer
196d49e1aeSJan Lentfer
eap_gtc_init(struct eap_sm * sm)206d49e1aeSJan Lentfer static void * eap_gtc_init(struct eap_sm *sm)
216d49e1aeSJan Lentfer {
226d49e1aeSJan Lentfer struct eap_gtc_data *data;
236d49e1aeSJan Lentfer data = os_zalloc(sizeof(*data));
246d49e1aeSJan Lentfer if (data == NULL)
256d49e1aeSJan Lentfer return NULL;
266d49e1aeSJan Lentfer
276d49e1aeSJan Lentfer if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
286d49e1aeSJan Lentfer sm->m->method == EAP_TYPE_FAST) {
296d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
306d49e1aeSJan Lentfer "with challenge/response");
316d49e1aeSJan Lentfer data->prefix = 1;
326d49e1aeSJan Lentfer }
336d49e1aeSJan Lentfer return data;
346d49e1aeSJan Lentfer }
356d49e1aeSJan Lentfer
366d49e1aeSJan Lentfer
eap_gtc_deinit(struct eap_sm * sm,void * priv)376d49e1aeSJan Lentfer static void eap_gtc_deinit(struct eap_sm *sm, void *priv)
386d49e1aeSJan Lentfer {
396d49e1aeSJan Lentfer struct eap_gtc_data *data = priv;
406d49e1aeSJan Lentfer os_free(data);
416d49e1aeSJan Lentfer }
426d49e1aeSJan Lentfer
436d49e1aeSJan Lentfer
eap_gtc_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)446d49e1aeSJan Lentfer static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv,
456d49e1aeSJan Lentfer struct eap_method_ret *ret,
466d49e1aeSJan Lentfer const struct wpabuf *reqData)
476d49e1aeSJan Lentfer {
486d49e1aeSJan Lentfer struct eap_gtc_data *data = priv;
496d49e1aeSJan Lentfer struct wpabuf *resp;
506d49e1aeSJan Lentfer const u8 *pos, *password, *identity;
516d49e1aeSJan Lentfer size_t password_len, identity_len, len, plen;
526d49e1aeSJan Lentfer int otp;
536d49e1aeSJan Lentfer u8 id;
546d49e1aeSJan Lentfer
556d49e1aeSJan Lentfer pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len);
566d49e1aeSJan Lentfer if (pos == NULL) {
576d49e1aeSJan Lentfer ret->ignore = TRUE;
586d49e1aeSJan Lentfer return NULL;
596d49e1aeSJan Lentfer }
606d49e1aeSJan Lentfer id = eap_get_id(reqData);
616d49e1aeSJan Lentfer
626d49e1aeSJan Lentfer wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
636d49e1aeSJan Lentfer if (data->prefix &&
646d49e1aeSJan Lentfer (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) {
656d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
666d49e1aeSJan Lentfer "expected prefix");
676d49e1aeSJan Lentfer
686d49e1aeSJan Lentfer /* Send an empty response in order to allow tunneled
696d49e1aeSJan Lentfer * acknowledgement of the failure. This will also cover the
706d49e1aeSJan Lentfer * error case which seems to use EAP-MSCHAPv2 like error
716d49e1aeSJan Lentfer * reporting with EAP-GTC inside EAP-FAST tunnel. */
726d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC,
736d49e1aeSJan Lentfer 0, EAP_CODE_RESPONSE, id);
746d49e1aeSJan Lentfer return resp;
756d49e1aeSJan Lentfer }
766d49e1aeSJan Lentfer
776d49e1aeSJan Lentfer password = eap_get_config_otp(sm, &password_len);
786d49e1aeSJan Lentfer if (password)
796d49e1aeSJan Lentfer otp = 1;
806d49e1aeSJan Lentfer else {
816d49e1aeSJan Lentfer password = eap_get_config_password(sm, &password_len);
826d49e1aeSJan Lentfer otp = 0;
836d49e1aeSJan Lentfer }
846d49e1aeSJan Lentfer
856d49e1aeSJan Lentfer if (password == NULL) {
866d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
876d49e1aeSJan Lentfer eap_sm_request_otp(sm, (const char *) pos, len);
886d49e1aeSJan Lentfer ret->ignore = TRUE;
896d49e1aeSJan Lentfer return NULL;
906d49e1aeSJan Lentfer }
916d49e1aeSJan Lentfer
926d49e1aeSJan Lentfer ret->ignore = FALSE;
936d49e1aeSJan Lentfer
946d49e1aeSJan Lentfer ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE;
956d49e1aeSJan Lentfer ret->decision = DECISION_COND_SUCC;
966d49e1aeSJan Lentfer ret->allowNotifications = FALSE;
976d49e1aeSJan Lentfer
986d49e1aeSJan Lentfer plen = password_len;
996d49e1aeSJan Lentfer identity = eap_get_config_identity(sm, &identity_len);
1006d49e1aeSJan Lentfer if (identity == NULL)
1016d49e1aeSJan Lentfer return NULL;
1026d49e1aeSJan Lentfer if (data->prefix)
1036d49e1aeSJan Lentfer plen += 9 + identity_len + 1;
1046d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen,
1056d49e1aeSJan Lentfer EAP_CODE_RESPONSE, id);
1066d49e1aeSJan Lentfer if (resp == NULL)
1076d49e1aeSJan Lentfer return NULL;
1086d49e1aeSJan Lentfer if (data->prefix) {
1096d49e1aeSJan Lentfer wpabuf_put_data(resp, "RESPONSE=", 9);
1106d49e1aeSJan Lentfer wpabuf_put_data(resp, identity, identity_len);
1116d49e1aeSJan Lentfer wpabuf_put_u8(resp, '\0');
1126d49e1aeSJan Lentfer }
1136d49e1aeSJan Lentfer wpabuf_put_data(resp, password, password_len);
1146d49e1aeSJan Lentfer wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
1156d49e1aeSJan Lentfer wpabuf_head_u8(resp) + sizeof(struct eap_hdr) +
1166d49e1aeSJan Lentfer 1, plen);
1176d49e1aeSJan Lentfer
1186d49e1aeSJan Lentfer if (otp) {
1196d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password");
1206d49e1aeSJan Lentfer eap_clear_config_otp(sm);
1216d49e1aeSJan Lentfer }
1226d49e1aeSJan Lentfer
1236d49e1aeSJan Lentfer return resp;
1246d49e1aeSJan Lentfer }
1256d49e1aeSJan Lentfer
1266d49e1aeSJan Lentfer
eap_peer_gtc_register(void)1276d49e1aeSJan Lentfer int eap_peer_gtc_register(void)
1286d49e1aeSJan Lentfer {
1296d49e1aeSJan Lentfer struct eap_method *eap;
1306d49e1aeSJan Lentfer
1316d49e1aeSJan Lentfer eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1326d49e1aeSJan Lentfer EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
1336d49e1aeSJan Lentfer if (eap == NULL)
1346d49e1aeSJan Lentfer return -1;
1356d49e1aeSJan Lentfer
1366d49e1aeSJan Lentfer eap->init = eap_gtc_init;
1376d49e1aeSJan Lentfer eap->deinit = eap_gtc_deinit;
1386d49e1aeSJan Lentfer eap->process = eap_gtc_process;
1396d49e1aeSJan Lentfer
140*a1157835SDaniel Fojt return eap_peer_method_register(eap);
1416d49e1aeSJan Lentfer }
142