$search
00001 /* 00002 * EAP peer method: 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 int prefix; 00023 }; 00024 00025 00026 static void * eap_gtc_init(struct eap_sm *sm) 00027 { 00028 struct eap_gtc_data *data; 00029 data = os_zalloc(sizeof(*data)); 00030 if (data == NULL) 00031 return NULL; 00032 00033 if (sm->m && sm->m->vendor == EAP_VENDOR_IETF && 00034 sm->m->method == EAP_TYPE_FAST) { 00035 wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " 00036 "with challenge/response"); 00037 data->prefix = 1; 00038 } 00039 return data; 00040 } 00041 00042 00043 static void eap_gtc_deinit(struct eap_sm *sm, void *priv) 00044 { 00045 struct eap_gtc_data *data = priv; 00046 os_free(data); 00047 } 00048 00049 00050 static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, 00051 struct eap_method_ret *ret, 00052 const struct wpabuf *reqData) 00053 { 00054 struct eap_gtc_data *data = priv; 00055 struct wpabuf *resp; 00056 const u8 *pos, *password, *identity; 00057 size_t password_len, identity_len, len, plen; 00058 int otp; 00059 u8 id; 00060 00061 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); 00062 if (pos == NULL) { 00063 ret->ignore = TRUE; 00064 return NULL; 00065 } 00066 id = eap_get_id(reqData); 00067 00068 wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len); 00069 if (data->prefix && 00070 (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) { 00071 wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with " 00072 "expected prefix"); 00073 00074 /* Send an empty response in order to allow tunneled 00075 * acknowledgement of the failure. This will also cover the 00076 * error case which seems to use EAP-MSCHAPv2 like error 00077 * reporting with EAP-GTC inside EAP-FAST tunnel. */ 00078 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, 00079 0, EAP_CODE_RESPONSE, id); 00080 return resp; 00081 } 00082 00083 password = eap_get_config_otp(sm, &password_len); 00084 if (password) 00085 otp = 1; 00086 else { 00087 password = eap_get_config_password(sm, &password_len); 00088 otp = 0; 00089 } 00090 00091 if (password == NULL) { 00092 wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); 00093 eap_sm_request_otp(sm, (const char *) pos, len); 00094 ret->ignore = TRUE; 00095 return NULL; 00096 } 00097 00098 ret->ignore = FALSE; 00099 00100 ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; 00101 ret->decision = DECISION_COND_SUCC; 00102 ret->allowNotifications = FALSE; 00103 00104 plen = password_len; 00105 identity = eap_get_config_identity(sm, &identity_len); 00106 if (identity == NULL) 00107 return NULL; 00108 if (data->prefix) 00109 plen += 9 + identity_len + 1; 00110 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen, 00111 EAP_CODE_RESPONSE, id); 00112 if (resp == NULL) 00113 return NULL; 00114 if (data->prefix) { 00115 wpabuf_put_data(resp, "RESPONSE=", 9); 00116 wpabuf_put_data(resp, identity, identity_len); 00117 wpabuf_put_u8(resp, '\0'); 00118 } 00119 wpabuf_put_data(resp, password, password_len); 00120 wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", 00121 wpabuf_head_u8(resp) + sizeof(struct eap_hdr) + 00122 1, plen); 00123 00124 if (otp) { 00125 wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); 00126 eap_clear_config_otp(sm); 00127 } 00128 00129 return resp; 00130 } 00131 00132 00133 int eap_peer_gtc_register(void) 00134 { 00135 struct eap_method *eap; 00136 int ret; 00137 00138 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 00139 EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); 00140 if (eap == NULL) 00141 return -1; 00142 00143 eap->init = eap_gtc_init; 00144 eap->deinit = eap_gtc_deinit; 00145 eap->process = eap_gtc_process; 00146 00147 ret = eap_peer_method_register(eap); 00148 if (ret) 00149 eap_peer_method_free(eap); 00150 return ret; 00151 }