1 /* 2 * hostapd / EAP-Identity 3 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "eap_i.h" 13 14 15 struct eap_identity_data { 16 enum { CONTINUE, SUCCESS, FAILURE } state; 17 int pick_up; 18 }; 19 20 21 static void * eap_identity_init(struct eap_sm *sm) 22 { 23 struct eap_identity_data *data; 24 25 data = os_zalloc(sizeof(*data)); 26 if (data == NULL) 27 return NULL; 28 data->state = CONTINUE; 29 30 return data; 31 } 32 33 34 static void * eap_identity_initPickUp(struct eap_sm *sm) 35 { 36 struct eap_identity_data *data; 37 data = eap_identity_init(sm); 38 if (data) { 39 data->pick_up = 1; 40 } 41 return data; 42 } 43 44 45 static void eap_identity_reset(struct eap_sm *sm, void *priv) 46 { 47 struct eap_identity_data *data = priv; 48 os_free(data); 49 } 50 51 52 static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, 53 u8 id) 54 { 55 struct eap_identity_data *data = priv; 56 struct wpabuf *req; 57 const char *req_data; 58 size_t req_data_len; 59 60 if (sm->eapol_cb->get_eap_req_id_text) { 61 req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx, 62 &req_data_len); 63 } else { 64 req_data = NULL; 65 req_data_len = 0; 66 } 67 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len, 68 EAP_CODE_REQUEST, id); 69 if (req == NULL) { 70 wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " 71 "memory for request"); 72 data->state = FAILURE; 73 return NULL; 74 } 75 76 wpabuf_put_data(req, req_data, req_data_len); 77 78 return req; 79 } 80 81 82 static Boolean eap_identity_check(struct eap_sm *sm, void *priv, 83 struct wpabuf *respData) 84 { 85 const u8 *pos; 86 size_t len; 87 88 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 89 respData, &len); 90 if (pos == NULL) { 91 wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); 92 return TRUE; 93 } 94 95 return FALSE; 96 } 97 98 99 static void eap_identity_process(struct eap_sm *sm, void *priv, 100 struct wpabuf *respData) 101 { 102 struct eap_identity_data *data = priv; 103 const u8 *pos; 104 size_t len; 105 char *buf; 106 107 if (data->pick_up) { 108 if (eap_identity_check(sm, data, respData)) { 109 wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick " 110 "up already started negotiation"); 111 data->state = FAILURE; 112 return; 113 } 114 data->pick_up = 0; 115 } 116 117 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 118 respData, &len); 119 if (pos == NULL) 120 return; /* Should not happen - frame already validated */ 121 122 wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); 123 buf = os_malloc(len * 4 + 1); 124 if (buf) { 125 printf_encode(buf, len * 4 + 1, pos, len); 126 eap_log_msg(sm, "EAP-Response/Identity '%s'", buf); 127 os_free(buf); 128 } 129 if (sm->identity) 130 sm->update_user = TRUE; 131 os_free(sm->identity); 132 sm->identity = os_malloc(len ? len : 1); 133 if (sm->identity == NULL) { 134 data->state = FAILURE; 135 } else { 136 os_memcpy(sm->identity, pos, len); 137 sm->identity_len = len; 138 data->state = SUCCESS; 139 } 140 } 141 142 143 static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) 144 { 145 struct eap_identity_data *data = priv; 146 return data->state != CONTINUE; 147 } 148 149 150 static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) 151 { 152 struct eap_identity_data *data = priv; 153 return data->state == SUCCESS; 154 } 155 156 157 int eap_server_identity_register(void) 158 { 159 struct eap_method *eap; 160 int ret; 161 162 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 163 EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 164 "Identity"); 165 if (eap == NULL) 166 return -1; 167 168 eap->init = eap_identity_init; 169 eap->initPickUp = eap_identity_initPickUp; 170 eap->reset = eap_identity_reset; 171 eap->buildReq = eap_identity_buildReq; 172 eap->check = eap_identity_check; 173 eap->process = eap_identity_process; 174 eap->isDone = eap_identity_isDone; 175 eap->isSuccess = eap_identity_isSuccess; 176 177 ret = eap_server_method_register(eap); 178 if (ret) 179 eap_server_method_free(eap); 180 return ret; 181 } 182