$search
00001 /* 00002 * EAP peer method: Test method for vendor specific (expanded) EAP type 00003 * Copyright (c) 2005-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 * This file implements a vendor specific test method using EAP expanded types. 00015 * This is only for test use and must not be used for authentication since no 00016 * security is provided. 00017 */ 00018 00019 #include "includes.h" 00020 00021 #include "common.h" 00022 #include "eap_i.h" 00023 #ifdef TEST_PENDING_REQUEST 00024 #include "eloop.h" 00025 #endif /* TEST_PENDING_REQUEST */ 00026 00027 00028 #define EAP_VENDOR_ID 0xfffefd 00029 #define EAP_VENDOR_TYPE 0xfcfbfaf9 00030 00031 00032 /* #define TEST_PENDING_REQUEST */ 00033 00034 struct eap_vendor_test_data { 00035 enum { INIT, CONFIRM, SUCCESS } state; 00036 int first_try; 00037 }; 00038 00039 00040 static void * eap_vendor_test_init(struct eap_sm *sm) 00041 { 00042 struct eap_vendor_test_data *data; 00043 data = os_zalloc(sizeof(*data)); 00044 if (data == NULL) 00045 return NULL; 00046 data->state = INIT; 00047 data->first_try = 1; 00048 return data; 00049 } 00050 00051 00052 static void eap_vendor_test_deinit(struct eap_sm *sm, void *priv) 00053 { 00054 struct eap_vendor_test_data *data = priv; 00055 os_free(data); 00056 } 00057 00058 00059 #ifdef TEST_PENDING_REQUEST 00060 static void eap_vendor_ready(void *eloop_ctx, void *timeout_ctx) 00061 { 00062 struct eap_sm *sm = eloop_ctx; 00063 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Ready to re-process pending " 00064 "request"); 00065 eap_notify_pending(sm); 00066 } 00067 #endif /* TEST_PENDING_REQUEST */ 00068 00069 00070 static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, 00071 struct eap_method_ret *ret, 00072 const struct wpabuf *reqData) 00073 { 00074 struct eap_vendor_test_data *data = priv; 00075 struct wpabuf *resp; 00076 const u8 *pos; 00077 size_t len; 00078 00079 pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len); 00080 if (pos == NULL || len < 1) { 00081 ret->ignore = TRUE; 00082 return NULL; 00083 } 00084 00085 if (data->state == INIT && *pos != 1) { 00086 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " 00087 "%d in INIT state", *pos); 00088 ret->ignore = TRUE; 00089 return NULL; 00090 } 00091 00092 if (data->state == CONFIRM && *pos != 3) { 00093 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " 00094 "%d in CONFIRM state", *pos); 00095 ret->ignore = TRUE; 00096 return NULL; 00097 } 00098 00099 if (data->state == SUCCESS) { 00100 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " 00101 "in SUCCESS state"); 00102 ret->ignore = TRUE; 00103 return NULL; 00104 } 00105 00106 if (data->state == CONFIRM) { 00107 #ifdef TEST_PENDING_REQUEST 00108 if (data->first_try) { 00109 data->first_try = 0; 00110 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing " 00111 "pending request"); 00112 ret->ignore = TRUE; 00113 eloop_register_timeout(1, 0, eap_vendor_ready, sm, 00114 NULL); 00115 return NULL; 00116 } 00117 #endif /* TEST_PENDING_REQUEST */ 00118 } 00119 00120 ret->ignore = FALSE; 00121 00122 wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); 00123 ret->allowNotifications = TRUE; 00124 00125 resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, 00126 EAP_CODE_RESPONSE, eap_get_id(reqData)); 00127 if (resp == NULL) 00128 return NULL; 00129 00130 if (data->state == INIT) { 00131 wpabuf_put_u8(resp, 2); 00132 data->state = CONFIRM; 00133 ret->methodState = METHOD_CONT; 00134 ret->decision = DECISION_FAIL; 00135 } else { 00136 wpabuf_put_u8(resp, 4); 00137 data->state = SUCCESS; 00138 ret->methodState = METHOD_DONE; 00139 ret->decision = DECISION_UNCOND_SUCC; 00140 } 00141 00142 return resp; 00143 } 00144 00145 00146 static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) 00147 { 00148 struct eap_vendor_test_data *data = priv; 00149 return data->state == SUCCESS; 00150 } 00151 00152 00153 static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) 00154 { 00155 struct eap_vendor_test_data *data = priv; 00156 u8 *key; 00157 const int key_len = 64; 00158 00159 if (data->state != SUCCESS) 00160 return NULL; 00161 00162 key = os_malloc(key_len); 00163 if (key == NULL) 00164 return NULL; 00165 00166 os_memset(key, 0x11, key_len / 2); 00167 os_memset(key + key_len / 2, 0x22, key_len / 2); 00168 *len = key_len; 00169 00170 return key; 00171 } 00172 00173 00174 int eap_peer_vendor_test_register(void) 00175 { 00176 struct eap_method *eap; 00177 int ret; 00178 00179 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 00180 EAP_VENDOR_ID, EAP_VENDOR_TYPE, 00181 "VENDOR-TEST"); 00182 if (eap == NULL) 00183 return -1; 00184 00185 eap->init = eap_vendor_test_init; 00186 eap->deinit = eap_vendor_test_deinit; 00187 eap->process = eap_vendor_test_process; 00188 eap->isKeyAvailable = eap_vendor_test_isKeyAvailable; 00189 eap->getKey = eap_vendor_test_getKey; 00190 00191 ret = eap_peer_method_register(eap); 00192 if (ret) 00193 eap_peer_method_free(eap); 00194 return ret; 00195 }