1214501Srpaulo/* 2214501Srpaulo * hostapd / EAP-Identity 3214501Srpaulo * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5214501Srpaulo * This program is free software; you can redistribute it and/or modify 6214501Srpaulo * it under the terms of the GNU General Public License version 2 as 7214501Srpaulo * published by the Free Software Foundation. 8214501Srpaulo * 9214501Srpaulo * Alternatively, this software may be distributed under the terms of BSD 10214501Srpaulo * license. 11214501Srpaulo * 12214501Srpaulo * See README and COPYING for more details. 13214501Srpaulo */ 14214501Srpaulo 15214501Srpaulo#include "includes.h" 16214501Srpaulo 17214501Srpaulo#include "common.h" 18214501Srpaulo#include "eap_i.h" 19214501Srpaulo 20214501Srpaulo 21214501Srpaulostruct eap_identity_data { 22214501Srpaulo enum { CONTINUE, SUCCESS, FAILURE } state; 23214501Srpaulo int pick_up; 24214501Srpaulo}; 25214501Srpaulo 26214501Srpaulo 27214501Srpaulostatic void * eap_identity_init(struct eap_sm *sm) 28214501Srpaulo{ 29214501Srpaulo struct eap_identity_data *data; 30214501Srpaulo 31214501Srpaulo data = os_zalloc(sizeof(*data)); 32214501Srpaulo if (data == NULL) 33214501Srpaulo return NULL; 34214501Srpaulo data->state = CONTINUE; 35214501Srpaulo 36214501Srpaulo return data; 37214501Srpaulo} 38214501Srpaulo 39214501Srpaulo 40214501Srpaulostatic void * eap_identity_initPickUp(struct eap_sm *sm) 41214501Srpaulo{ 42214501Srpaulo struct eap_identity_data *data; 43214501Srpaulo data = eap_identity_init(sm); 44214501Srpaulo if (data) { 45214501Srpaulo data->pick_up = 1; 46214501Srpaulo } 47214501Srpaulo return data; 48214501Srpaulo} 49214501Srpaulo 50214501Srpaulo 51214501Srpaulostatic void eap_identity_reset(struct eap_sm *sm, void *priv) 52214501Srpaulo{ 53214501Srpaulo struct eap_identity_data *data = priv; 54214501Srpaulo os_free(data); 55214501Srpaulo} 56214501Srpaulo 57214501Srpaulo 58214501Srpaulostatic struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, 59214501Srpaulo u8 id) 60214501Srpaulo{ 61214501Srpaulo struct eap_identity_data *data = priv; 62214501Srpaulo struct wpabuf *req; 63214501Srpaulo const char *req_data; 64214501Srpaulo size_t req_data_len; 65214501Srpaulo 66214501Srpaulo if (sm->eapol_cb->get_eap_req_id_text) { 67214501Srpaulo req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx, 68214501Srpaulo &req_data_len); 69214501Srpaulo } else { 70214501Srpaulo req_data = NULL; 71214501Srpaulo req_data_len = 0; 72214501Srpaulo } 73214501Srpaulo req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len, 74214501Srpaulo EAP_CODE_REQUEST, id); 75214501Srpaulo if (req == NULL) { 76214501Srpaulo wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " 77214501Srpaulo "memory for request"); 78214501Srpaulo data->state = FAILURE; 79214501Srpaulo return NULL; 80214501Srpaulo } 81214501Srpaulo 82214501Srpaulo wpabuf_put_data(req, req_data, req_data_len); 83214501Srpaulo 84214501Srpaulo return req; 85214501Srpaulo} 86214501Srpaulo 87214501Srpaulo 88214501Srpaulostatic Boolean eap_identity_check(struct eap_sm *sm, void *priv, 89214501Srpaulo struct wpabuf *respData) 90214501Srpaulo{ 91214501Srpaulo const u8 *pos; 92214501Srpaulo size_t len; 93214501Srpaulo 94214501Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 95214501Srpaulo respData, &len); 96214501Srpaulo if (pos == NULL) { 97214501Srpaulo wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); 98214501Srpaulo return TRUE; 99214501Srpaulo } 100214501Srpaulo 101214501Srpaulo return FALSE; 102214501Srpaulo} 103214501Srpaulo 104214501Srpaulo 105214501Srpaulostatic void eap_identity_process(struct eap_sm *sm, void *priv, 106214501Srpaulo struct wpabuf *respData) 107214501Srpaulo{ 108214501Srpaulo struct eap_identity_data *data = priv; 109214501Srpaulo const u8 *pos; 110214501Srpaulo size_t len; 111214501Srpaulo 112214501Srpaulo if (data->pick_up) { 113214501Srpaulo if (eap_identity_check(sm, data, respData)) { 114214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick " 115214501Srpaulo "up already started negotiation"); 116214501Srpaulo data->state = FAILURE; 117214501Srpaulo return; 118214501Srpaulo } 119214501Srpaulo data->pick_up = 0; 120214501Srpaulo } 121214501Srpaulo 122214501Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 123214501Srpaulo respData, &len); 124214501Srpaulo if (pos == NULL) 125214501Srpaulo return; /* Should not happen - frame already validated */ 126214501Srpaulo 127214501Srpaulo wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); 128214501Srpaulo if (sm->identity) 129214501Srpaulo sm->update_user = TRUE; 130214501Srpaulo os_free(sm->identity); 131214501Srpaulo sm->identity = os_malloc(len ? len : 1); 132214501Srpaulo if (sm->identity == NULL) { 133214501Srpaulo data->state = FAILURE; 134214501Srpaulo } else { 135214501Srpaulo os_memcpy(sm->identity, pos, len); 136214501Srpaulo sm->identity_len = len; 137214501Srpaulo data->state = SUCCESS; 138214501Srpaulo } 139214501Srpaulo} 140214501Srpaulo 141214501Srpaulo 142214501Srpaulostatic Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) 143214501Srpaulo{ 144214501Srpaulo struct eap_identity_data *data = priv; 145214501Srpaulo return data->state != CONTINUE; 146214501Srpaulo} 147214501Srpaulo 148214501Srpaulo 149214501Srpaulostatic Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) 150214501Srpaulo{ 151214501Srpaulo struct eap_identity_data *data = priv; 152214501Srpaulo return data->state == SUCCESS; 153214501Srpaulo} 154214501Srpaulo 155214501Srpaulo 156214501Srpauloint eap_server_identity_register(void) 157214501Srpaulo{ 158214501Srpaulo struct eap_method *eap; 159214501Srpaulo int ret; 160214501Srpaulo 161214501Srpaulo eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 162214501Srpaulo EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 163214501Srpaulo "Identity"); 164214501Srpaulo if (eap == NULL) 165214501Srpaulo return -1; 166214501Srpaulo 167214501Srpaulo eap->init = eap_identity_init; 168214501Srpaulo eap->initPickUp = eap_identity_initPickUp; 169214501Srpaulo eap->reset = eap_identity_reset; 170214501Srpaulo eap->buildReq = eap_identity_buildReq; 171214501Srpaulo eap->check = eap_identity_check; 172214501Srpaulo eap->process = eap_identity_process; 173214501Srpaulo eap->isDone = eap_identity_isDone; 174214501Srpaulo eap->isSuccess = eap_identity_isSuccess; 175214501Srpaulo 176214501Srpaulo ret = eap_server_method_register(eap); 177214501Srpaulo if (ret) 178214501Srpaulo eap_server_method_free(eap); 179214501Srpaulo return ret; 180214501Srpaulo} 181