1189251Ssam/* 2189251Ssam * EAP peer method: EAP-GTC (RFC 3748) 3189251Ssam * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11189251Ssam#include "common.h" 12189251Ssam#include "eap_i.h" 13189251Ssam 14189251Ssam 15189251Ssamstruct eap_gtc_data { 16189251Ssam int prefix; 17189251Ssam}; 18189251Ssam 19189251Ssam 20189251Ssamstatic void * eap_gtc_init(struct eap_sm *sm) 21189251Ssam{ 22189251Ssam struct eap_gtc_data *data; 23189251Ssam data = os_zalloc(sizeof(*data)); 24189251Ssam if (data == NULL) 25189251Ssam return NULL; 26189251Ssam 27189251Ssam if (sm->m && sm->m->vendor == EAP_VENDOR_IETF && 28189251Ssam sm->m->method == EAP_TYPE_FAST) { 29189251Ssam wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " 30189251Ssam "with challenge/response"); 31189251Ssam data->prefix = 1; 32189251Ssam } 33189251Ssam return data; 34189251Ssam} 35189251Ssam 36189251Ssam 37189251Ssamstatic void eap_gtc_deinit(struct eap_sm *sm, void *priv) 38189251Ssam{ 39189251Ssam struct eap_gtc_data *data = priv; 40189251Ssam os_free(data); 41189251Ssam} 42189251Ssam 43189251Ssam 44189251Ssamstatic struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, 45189251Ssam struct eap_method_ret *ret, 46189251Ssam const struct wpabuf *reqData) 47189251Ssam{ 48189251Ssam struct eap_gtc_data *data = priv; 49189251Ssam struct wpabuf *resp; 50189251Ssam const u8 *pos, *password, *identity; 51189251Ssam size_t password_len, identity_len, len, plen; 52189251Ssam int otp; 53189251Ssam u8 id; 54189251Ssam 55189251Ssam pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); 56189251Ssam if (pos == NULL) { 57189251Ssam ret->ignore = TRUE; 58189251Ssam return NULL; 59189251Ssam } 60189251Ssam id = eap_get_id(reqData); 61189251Ssam 62189251Ssam wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len); 63189251Ssam if (data->prefix && 64189251Ssam (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) { 65189251Ssam wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with " 66189251Ssam "expected prefix"); 67189251Ssam 68189251Ssam /* Send an empty response in order to allow tunneled 69189251Ssam * acknowledgement of the failure. This will also cover the 70189251Ssam * error case which seems to use EAP-MSCHAPv2 like error 71189251Ssam * reporting with EAP-GTC inside EAP-FAST tunnel. */ 72189251Ssam resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, 73189251Ssam 0, EAP_CODE_RESPONSE, id); 74189251Ssam return resp; 75189251Ssam } 76189251Ssam 77189251Ssam password = eap_get_config_otp(sm, &password_len); 78189251Ssam if (password) 79189251Ssam otp = 1; 80189251Ssam else { 81189251Ssam password = eap_get_config_password(sm, &password_len); 82189251Ssam otp = 0; 83189251Ssam } 84189251Ssam 85189251Ssam if (password == NULL) { 86189251Ssam wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); 87189251Ssam eap_sm_request_otp(sm, (const char *) pos, len); 88189251Ssam ret->ignore = TRUE; 89189251Ssam return NULL; 90189251Ssam } 91189251Ssam 92189251Ssam ret->ignore = FALSE; 93189251Ssam 94189251Ssam ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; 95189251Ssam ret->decision = DECISION_COND_SUCC; 96189251Ssam ret->allowNotifications = FALSE; 97189251Ssam 98189251Ssam plen = password_len; 99189251Ssam identity = eap_get_config_identity(sm, &identity_len); 100189251Ssam if (identity == NULL) 101189251Ssam return NULL; 102189251Ssam if (data->prefix) 103189251Ssam plen += 9 + identity_len + 1; 104189251Ssam resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen, 105189251Ssam EAP_CODE_RESPONSE, id); 106189251Ssam if (resp == NULL) 107189251Ssam return NULL; 108189251Ssam if (data->prefix) { 109189251Ssam wpabuf_put_data(resp, "RESPONSE=", 9); 110189251Ssam wpabuf_put_data(resp, identity, identity_len); 111189251Ssam wpabuf_put_u8(resp, '\0'); 112189251Ssam } 113189251Ssam wpabuf_put_data(resp, password, password_len); 114189251Ssam wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", 115189251Ssam wpabuf_head_u8(resp) + sizeof(struct eap_hdr) + 116189251Ssam 1, plen); 117189251Ssam 118189251Ssam if (otp) { 119189251Ssam wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); 120189251Ssam eap_clear_config_otp(sm); 121189251Ssam } 122189251Ssam 123189251Ssam return resp; 124189251Ssam} 125189251Ssam 126189251Ssam 127189251Ssamint eap_peer_gtc_register(void) 128189251Ssam{ 129189251Ssam struct eap_method *eap; 130189251Ssam 131189251Ssam eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 132189251Ssam EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); 133189251Ssam if (eap == NULL) 134189251Ssam return -1; 135189251Ssam 136189251Ssam eap->init = eap_gtc_init; 137189251Ssam eap->deinit = eap_gtc_deinit; 138189251Ssam eap->process = eap_gtc_process; 139189251Ssam 140337817Scy return eap_peer_method_register(eap); 141189251Ssam} 142