00001
00016 #include "includes.h"
00017
00018 #include "common.h"
00019 #include "eap_i.h"
00020
00021
00022 struct eap_gtc_data {
00023 enum { CONTINUE, SUCCESS, FAILURE } state;
00024 int prefix;
00025 };
00026
00027
00028 static void * eap_gtc_init(struct eap_sm *sm)
00029 {
00030 struct eap_gtc_data *data;
00031
00032 data = os_zalloc(sizeof(*data));
00033 if (data == NULL)
00034 return NULL;
00035 data->state = CONTINUE;
00036
00037 #ifdef EAP_SERVER_FAST
00038 if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
00039 sm->m->method == EAP_TYPE_FAST) {
00040 wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
00041 "with challenge/response");
00042 data->prefix = 1;
00043 }
00044 #endif
00045
00046 return data;
00047 }
00048
00049
00050 static void eap_gtc_reset(struct eap_sm *sm, void *priv)
00051 {
00052 struct eap_gtc_data *data = priv;
00053 os_free(data);
00054 }
00055
00056
00057 static struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id)
00058 {
00059 struct eap_gtc_data *data = priv;
00060 struct wpabuf *req;
00061 char *msg;
00062 size_t msg_len;
00063
00064 msg = data->prefix ? "CHALLENGE=Password" : "Password";
00065
00066 msg_len = os_strlen(msg);
00067 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, msg_len,
00068 EAP_CODE_REQUEST, id);
00069 if (req == NULL) {
00070 wpa_printf(MSG_ERROR, "EAP-GTC: Failed to allocate memory for "
00071 "request");
00072 data->state = FAILURE;
00073 return NULL;
00074 }
00075
00076 wpabuf_put_data(req, msg, msg_len);
00077
00078 data->state = CONTINUE;
00079
00080 return req;
00081 }
00082
00083
00084 static Boolean eap_gtc_check(struct eap_sm *sm, void *priv,
00085 struct wpabuf *respData)
00086 {
00087 const u8 *pos;
00088 size_t len;
00089
00090 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len);
00091 if (pos == NULL || len < 1) {
00092 wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame");
00093 return TRUE;
00094 }
00095
00096 return FALSE;
00097 }
00098
00099
00100 static void eap_gtc_process(struct eap_sm *sm, void *priv,
00101 struct wpabuf *respData)
00102 {
00103 struct eap_gtc_data *data = priv;
00104 const u8 *pos;
00105 size_t rlen;
00106
00107 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &rlen);
00108 if (pos == NULL || rlen < 1)
00109 return;
00110
00111 wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen);
00112
00113 #ifdef EAP_SERVER_FAST
00114 if (data->prefix) {
00115 const u8 *pos2, *end;
00116
00117 if (rlen < 10) {
00118 wpa_printf(MSG_DEBUG, "EAP-GTC: Too short response "
00119 "for EAP-FAST prefix");
00120 data->state = FAILURE;
00121 return;
00122 }
00123
00124 end = pos + rlen;
00125 pos += 9;
00126 pos2 = pos;
00127 while (pos2 < end && *pos2)
00128 pos2++;
00129 if (pos2 == end) {
00130 wpa_printf(MSG_DEBUG, "EAP-GTC: No password in "
00131 "response to EAP-FAST prefix");
00132 data->state = FAILURE;
00133 return;
00134 }
00135
00136 wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Response user",
00137 pos, pos2 - pos);
00138 if (sm->identity && sm->require_identity_match &&
00139 (pos2 - pos != (int) sm->identity_len ||
00140 os_memcmp(pos, sm->identity, sm->identity_len))) {
00141 wpa_printf(MSG_DEBUG, "EAP-GTC: Phase 2 Identity did "
00142 "not match with required Identity");
00143 wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Expected "
00144 "identity",
00145 sm->identity, sm->identity_len);
00146 data->state = FAILURE;
00147 return;
00148 } else {
00149 os_free(sm->identity);
00150 sm->identity_len = pos2 - pos;
00151 sm->identity = os_malloc(sm->identity_len);
00152 if (sm->identity == NULL) {
00153 data->state = FAILURE;
00154 return;
00155 }
00156 os_memcpy(sm->identity, pos, sm->identity_len);
00157 }
00158
00159 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
00160 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GTC: Phase2 "
00161 "Identity not found in the user "
00162 "database",
00163 sm->identity, sm->identity_len);
00164 data->state = FAILURE;
00165 return;
00166 }
00167
00168 pos = pos2 + 1;
00169 rlen = end - pos;
00170 wpa_hexdump_ascii_key(MSG_MSGDUMP,
00171 "EAP-GTC: Response password",
00172 pos, rlen);
00173 }
00174 #endif
00175
00176 if (sm->user == NULL || sm->user->password == NULL ||
00177 sm->user->password_hash) {
00178 wpa_printf(MSG_INFO, "EAP-GTC: Plaintext password not "
00179 "configured");
00180 data->state = FAILURE;
00181 return;
00182 }
00183
00184 if (rlen != sm->user->password_len ||
00185 os_memcmp(pos, sm->user->password, rlen) != 0) {
00186 wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Failure");
00187 data->state = FAILURE;
00188 } else {
00189 wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Success");
00190 data->state = SUCCESS;
00191 }
00192 }
00193
00194
00195 static Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv)
00196 {
00197 struct eap_gtc_data *data = priv;
00198 return data->state != CONTINUE;
00199 }
00200
00201
00202 static Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv)
00203 {
00204 struct eap_gtc_data *data = priv;
00205 return data->state == SUCCESS;
00206 }
00207
00208
00209 int eap_server_gtc_register(void)
00210 {
00211 struct eap_method *eap;
00212 int ret;
00213
00214 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
00215 EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
00216 if (eap == NULL)
00217 return -1;
00218
00219 eap->init = eap_gtc_init;
00220 eap->reset = eap_gtc_reset;
00221 eap->buildReq = eap_gtc_buildReq;
00222 eap->check = eap_gtc_check;
00223 eap->process = eap_gtc_process;
00224 eap->isDone = eap_gtc_isDone;
00225 eap->isSuccess = eap_gtc_isSuccess;
00226
00227 ret = eap_server_method_register(eap);
00228 if (ret)
00229 eap_server_method_free(eap);
00230 return ret;
00231 }
00232