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