$search
00001 /* 00002 * hostapd / EAP-Identity 00003 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "eap_i.h" 00019 00020 00021 struct eap_identity_data { 00022 enum { CONTINUE, SUCCESS, FAILURE } state; 00023 int pick_up; 00024 }; 00025 00026 00027 static void * eap_identity_init(struct eap_sm *sm) 00028 { 00029 struct eap_identity_data *data; 00030 00031 data = os_zalloc(sizeof(*data)); 00032 if (data == NULL) 00033 return NULL; 00034 data->state = CONTINUE; 00035 00036 return data; 00037 } 00038 00039 00040 static void * eap_identity_initPickUp(struct eap_sm *sm) 00041 { 00042 struct eap_identity_data *data; 00043 data = eap_identity_init(sm); 00044 if (data) { 00045 data->pick_up = 1; 00046 } 00047 return data; 00048 } 00049 00050 00051 static void eap_identity_reset(struct eap_sm *sm, void *priv) 00052 { 00053 struct eap_identity_data *data = priv; 00054 os_free(data); 00055 } 00056 00057 00058 static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, 00059 u8 id) 00060 { 00061 struct eap_identity_data *data = priv; 00062 struct wpabuf *req; 00063 const char *req_data; 00064 size_t req_data_len; 00065 00066 if (sm->eapol_cb->get_eap_req_id_text) { 00067 req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx, 00068 &req_data_len); 00069 } else { 00070 req_data = NULL; 00071 req_data_len = 0; 00072 } 00073 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len, 00074 EAP_CODE_REQUEST, id); 00075 if (req == NULL) { 00076 wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " 00077 "memory for request"); 00078 data->state = FAILURE; 00079 return NULL; 00080 } 00081 00082 wpabuf_put_data(req, req_data, req_data_len); 00083 00084 return req; 00085 } 00086 00087 00088 static Boolean eap_identity_check(struct eap_sm *sm, void *priv, 00089 struct wpabuf *respData) 00090 { 00091 const u8 *pos; 00092 size_t len; 00093 00094 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 00095 respData, &len); 00096 if (pos == NULL) { 00097 wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); 00098 return TRUE; 00099 } 00100 00101 return FALSE; 00102 } 00103 00104 00105 static void eap_identity_process(struct eap_sm *sm, void *priv, 00106 struct wpabuf *respData) 00107 { 00108 struct eap_identity_data *data = priv; 00109 const u8 *pos; 00110 size_t len; 00111 00112 if (data->pick_up) { 00113 if (eap_identity_check(sm, data, respData)) { 00114 wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick " 00115 "up already started negotiation"); 00116 data->state = FAILURE; 00117 return; 00118 } 00119 data->pick_up = 0; 00120 } 00121 00122 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 00123 respData, &len); 00124 if (pos == NULL) 00125 return; /* Should not happen - frame already validated */ 00126 00127 wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); 00128 if (sm->identity) 00129 sm->update_user = TRUE; 00130 os_free(sm->identity); 00131 sm->identity = os_malloc(len ? len : 1); 00132 if (sm->identity == NULL) { 00133 data->state = FAILURE; 00134 } else { 00135 os_memcpy(sm->identity, pos, len); 00136 sm->identity_len = len; 00137 data->state = SUCCESS; 00138 } 00139 } 00140 00141 00142 static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) 00143 { 00144 struct eap_identity_data *data = priv; 00145 return data->state != CONTINUE; 00146 } 00147 00148 00149 static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) 00150 { 00151 struct eap_identity_data *data = priv; 00152 return data->state == SUCCESS; 00153 } 00154 00155 00156 int eap_server_identity_register(void) 00157 { 00158 struct eap_method *eap; 00159 int ret; 00160 00161 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 00162 EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 00163 "Identity"); 00164 if (eap == NULL) 00165 return -1; 00166 00167 eap->init = eap_identity_init; 00168 eap->initPickUp = eap_identity_initPickUp; 00169 eap->reset = eap_identity_reset; 00170 eap->buildReq = eap_identity_buildReq; 00171 eap->check = eap_identity_check; 00172 eap->process = eap_identity_process; 00173 eap->isDone = eap_identity_isDone; 00174 eap->isSuccess = eap_identity_isSuccess; 00175 00176 ret = eap_server_method_register(eap); 00177 if (ret) 00178 eap_server_method_free(eap); 00179 return ret; 00180 }