1189251Ssam/* 2189251Ssam * EAP peer method: Test method for vendor specific (expanded) EAP type 3189251Ssam * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam * 8189251Ssam * This file implements a vendor specific test method using EAP expanded types. 9189251Ssam * This is only for test use and must not be used for authentication since no 10189251Ssam * security is provided. 11189251Ssam */ 12189251Ssam 13189251Ssam#include "includes.h" 14189251Ssam 15189251Ssam#include "common.h" 16189251Ssam#include "eap_i.h" 17189251Ssam#ifdef TEST_PENDING_REQUEST 18189251Ssam#include "eloop.h" 19189251Ssam#endif /* TEST_PENDING_REQUEST */ 20189251Ssam 21189251Ssam 22252726Srpaulo#define EAP_VENDOR_ID EAP_VENDOR_HOSTAP 23189251Ssam#define EAP_VENDOR_TYPE 0xfcfbfaf9 24189251Ssam 25189251Ssam 26189251Ssam/* #define TEST_PENDING_REQUEST */ 27189251Ssam 28189251Ssamstruct eap_vendor_test_data { 29189251Ssam enum { INIT, CONFIRM, SUCCESS } state; 30189251Ssam int first_try; 31189251Ssam}; 32189251Ssam 33189251Ssam 34189251Ssamstatic void * eap_vendor_test_init(struct eap_sm *sm) 35189251Ssam{ 36189251Ssam struct eap_vendor_test_data *data; 37189251Ssam data = os_zalloc(sizeof(*data)); 38189251Ssam if (data == NULL) 39189251Ssam return NULL; 40189251Ssam data->state = INIT; 41189251Ssam data->first_try = 1; 42189251Ssam return data; 43189251Ssam} 44189251Ssam 45189251Ssam 46189251Ssamstatic void eap_vendor_test_deinit(struct eap_sm *sm, void *priv) 47189251Ssam{ 48189251Ssam struct eap_vendor_test_data *data = priv; 49189251Ssam os_free(data); 50189251Ssam} 51189251Ssam 52189251Ssam 53189251Ssam#ifdef TEST_PENDING_REQUEST 54189251Ssamstatic void eap_vendor_ready(void *eloop_ctx, void *timeout_ctx) 55189251Ssam{ 56189251Ssam struct eap_sm *sm = eloop_ctx; 57189251Ssam wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Ready to re-process pending " 58189251Ssam "request"); 59189251Ssam eap_notify_pending(sm); 60189251Ssam} 61189251Ssam#endif /* TEST_PENDING_REQUEST */ 62189251Ssam 63189251Ssam 64189251Ssamstatic struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, 65189251Ssam struct eap_method_ret *ret, 66189251Ssam const struct wpabuf *reqData) 67189251Ssam{ 68189251Ssam struct eap_vendor_test_data *data = priv; 69189251Ssam struct wpabuf *resp; 70189251Ssam const u8 *pos; 71189251Ssam size_t len; 72189251Ssam 73189251Ssam pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len); 74189251Ssam if (pos == NULL || len < 1) { 75189251Ssam ret->ignore = TRUE; 76189251Ssam return NULL; 77189251Ssam } 78189251Ssam 79189251Ssam if (data->state == INIT && *pos != 1) { 80189251Ssam wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " 81189251Ssam "%d in INIT state", *pos); 82189251Ssam ret->ignore = TRUE; 83189251Ssam return NULL; 84189251Ssam } 85189251Ssam 86189251Ssam if (data->state == CONFIRM && *pos != 3) { 87189251Ssam wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " 88189251Ssam "%d in CONFIRM state", *pos); 89189251Ssam ret->ignore = TRUE; 90189251Ssam return NULL; 91189251Ssam } 92189251Ssam 93189251Ssam if (data->state == SUCCESS) { 94189251Ssam wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " 95189251Ssam "in SUCCESS state"); 96189251Ssam ret->ignore = TRUE; 97189251Ssam return NULL; 98189251Ssam } 99189251Ssam 100189251Ssam if (data->state == CONFIRM) { 101189251Ssam#ifdef TEST_PENDING_REQUEST 102189251Ssam if (data->first_try) { 103189251Ssam data->first_try = 0; 104189251Ssam wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing " 105189251Ssam "pending request"); 106189251Ssam ret->ignore = TRUE; 107189251Ssam eloop_register_timeout(1, 0, eap_vendor_ready, sm, 108189251Ssam NULL); 109189251Ssam return NULL; 110189251Ssam } 111189251Ssam#endif /* TEST_PENDING_REQUEST */ 112189251Ssam } 113189251Ssam 114189251Ssam ret->ignore = FALSE; 115189251Ssam 116189251Ssam wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); 117189251Ssam ret->allowNotifications = TRUE; 118189251Ssam 119189251Ssam resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, 120189251Ssam EAP_CODE_RESPONSE, eap_get_id(reqData)); 121189251Ssam if (resp == NULL) 122189251Ssam return NULL; 123189251Ssam 124189251Ssam if (data->state == INIT) { 125189251Ssam wpabuf_put_u8(resp, 2); 126189251Ssam data->state = CONFIRM; 127189251Ssam ret->methodState = METHOD_CONT; 128189251Ssam ret->decision = DECISION_FAIL; 129189251Ssam } else { 130189251Ssam wpabuf_put_u8(resp, 4); 131189251Ssam data->state = SUCCESS; 132189251Ssam ret->methodState = METHOD_DONE; 133189251Ssam ret->decision = DECISION_UNCOND_SUCC; 134189251Ssam } 135189251Ssam 136189251Ssam return resp; 137189251Ssam} 138189251Ssam 139189251Ssam 140189251Ssamstatic Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) 141189251Ssam{ 142189251Ssam struct eap_vendor_test_data *data = priv; 143189251Ssam return data->state == SUCCESS; 144189251Ssam} 145189251Ssam 146189251Ssam 147189251Ssamstatic u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) 148189251Ssam{ 149189251Ssam struct eap_vendor_test_data *data = priv; 150189251Ssam u8 *key; 151189251Ssam const int key_len = 64; 152189251Ssam 153189251Ssam if (data->state != SUCCESS) 154189251Ssam return NULL; 155189251Ssam 156189251Ssam key = os_malloc(key_len); 157189251Ssam if (key == NULL) 158189251Ssam return NULL; 159189251Ssam 160189251Ssam os_memset(key, 0x11, key_len / 2); 161189251Ssam os_memset(key + key_len / 2, 0x22, key_len / 2); 162189251Ssam *len = key_len; 163189251Ssam 164189251Ssam return key; 165189251Ssam} 166189251Ssam 167189251Ssam 168189251Ssamint eap_peer_vendor_test_register(void) 169189251Ssam{ 170189251Ssam struct eap_method *eap; 171189251Ssam int ret; 172189251Ssam 173189251Ssam eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 174189251Ssam EAP_VENDOR_ID, EAP_VENDOR_TYPE, 175189251Ssam "VENDOR-TEST"); 176189251Ssam if (eap == NULL) 177189251Ssam return -1; 178189251Ssam 179189251Ssam eap->init = eap_vendor_test_init; 180189251Ssam eap->deinit = eap_vendor_test_deinit; 181189251Ssam eap->process = eap_vendor_test_process; 182189251Ssam eap->isKeyAvailable = eap_vendor_test_isKeyAvailable; 183189251Ssam eap->getKey = eap_vendor_test_getKey; 184189251Ssam 185189251Ssam ret = eap_peer_method_register(eap); 186189251Ssam if (ret) 187189251Ssam eap_peer_method_free(eap); 188189251Ssam return ret; 189189251Ssam} 190