xref: /dflybsd-src/contrib/wpa_supplicant/src/eap_peer/eap_gtc.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
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