1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * hostapd / EAP-Identity 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_i.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_identity_data { 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt enum { CONTINUE, SUCCESS, FAILURE } state; 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pick_up; 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_identity_init(struct eap_sm *sm) 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_identity_data *data; 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = CONTINUE; 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_identity_initPickUp(struct eap_sm *sm) 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_identity_data *data; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = eap_identity_init(sm); 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data) { 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pick_up = 1; 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_identity_reset(struct eap_sm *sm, void *priv) 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_identity_data *data = priv; 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 id) 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_identity_data *data = priv; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *req; 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const char *req_data; 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t req_data_len; 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->eapol_cb->get_eap_req_id_text) { 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx, 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &req_data_len); 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req_data = NULL; 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req_data_len = 0; 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len, 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_REQUEST, id); 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req == NULL) { 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "memory for request"); 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = FAILURE; 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(req, req_data, req_data_len); 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return req; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_identity_check(struct eap_sm *sm, void *priv, 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt respData, &len); 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL) { 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return TRUE; 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return FALSE; 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_identity_process(struct eap_sm *sm, void *priv, 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *respData) 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_identity_data *data = priv; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->pick_up) { 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_identity_check(sm, data, respData)) { 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick " 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "up already started negotiation"); 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = FAILURE; 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->pick_up = 0; 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt respData, &len); 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL) 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return; /* Should not happen - frame already validated */ 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->identity) 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->update_user = TRUE; 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(sm->identity); 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->identity = os_malloc(len ? len : 1); 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->identity == NULL) { 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = FAILURE; 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(sm->identity, pos, len); 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt sm->identity_len = len; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->state = SUCCESS; 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_identity_data *data = priv; 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state != CONTINUE; 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_identity_data *data = priv; 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->state == SUCCESS; 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_server_identity_register(void) 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method *eap; 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "Identity"); 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->init = eap_identity_init; 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->initPickUp = eap_identity_initPickUp; 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->reset = eap_identity_reset; 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->buildReq = eap_identity_buildReq; 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->check = eap_identity_check; 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->process = eap_identity_process; 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isDone = eap_identity_isDone; 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isSuccess = eap_identity_isSuccess; 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = eap_server_method_register(eap); 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_server_method_free(eap); 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 181