| /* |
| * EAP peer method: Test method for vendor specific (expanded) EAP type |
| * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> |
| * |
| * This software may be distributed under the terms of the BSD license. |
| * See README for more details. |
| * |
| * This file implements a vendor specific test method using EAP expanded types. |
| * This is only for test use and must not be used for authentication since no |
| * security is provided. |
| */ |
| |
| #include "includes.h" |
| |
| #include "common.h" |
| #include "eap_i.h" |
| #ifdef TEST_PENDING_REQUEST |
| #include "eloop.h" |
| #endif /* TEST_PENDING_REQUEST */ |
| |
| |
| #define EAP_VENDOR_ID EAP_VENDOR_HOSTAP |
| #define EAP_VENDOR_TYPE 0xfcfbfaf9 |
| |
| |
| /* #define TEST_PENDING_REQUEST */ |
| |
| struct eap_vendor_test_data { |
| enum { INIT, CONFIRM, SUCCESS } state; |
| int first_try; |
| }; |
| |
| |
| static void * eap_vendor_test_init(struct eap_sm *sm) |
| { |
| struct eap_vendor_test_data *data; |
| data = os_zalloc(sizeof(*data)); |
| if (data == NULL) |
| return NULL; |
| data->state = INIT; |
| data->first_try = 1; |
| return data; |
| } |
| |
| |
| static void eap_vendor_test_deinit(struct eap_sm *sm, void *priv) |
| { |
| struct eap_vendor_test_data *data = priv; |
| os_free(data); |
| } |
| |
| |
| #ifdef TEST_PENDING_REQUEST |
| static void eap_vendor_ready(void *eloop_ctx, void *timeout_ctx) |
| { |
| struct eap_sm *sm = eloop_ctx; |
| wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Ready to re-process pending " |
| "request"); |
| eap_notify_pending(sm); |
| } |
| #endif /* TEST_PENDING_REQUEST */ |
| |
| |
| static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, |
| struct eap_method_ret *ret, |
| const struct wpabuf *reqData) |
| { |
| struct eap_vendor_test_data *data = priv; |
| struct wpabuf *resp; |
| const u8 *pos; |
| size_t len; |
| |
| pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len); |
| if (pos == NULL || len < 1) { |
| ret->ignore = TRUE; |
| return NULL; |
| } |
| |
| if (data->state == INIT && *pos != 1) { |
| wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " |
| "%d in INIT state", *pos); |
| ret->ignore = TRUE; |
| return NULL; |
| } |
| |
| if (data->state == CONFIRM && *pos != 3) { |
| wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " |
| "%d in CONFIRM state", *pos); |
| ret->ignore = TRUE; |
| return NULL; |
| } |
| |
| if (data->state == SUCCESS) { |
| wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " |
| "in SUCCESS state"); |
| ret->ignore = TRUE; |
| return NULL; |
| } |
| |
| if (data->state == CONFIRM) { |
| #ifdef TEST_PENDING_REQUEST |
| if (data->first_try) { |
| data->first_try = 0; |
| wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing " |
| "pending request"); |
| ret->ignore = TRUE; |
| eloop_register_timeout(1, 0, eap_vendor_ready, sm, |
| NULL); |
| return NULL; |
| } |
| #endif /* TEST_PENDING_REQUEST */ |
| } |
| |
| ret->ignore = FALSE; |
| |
| wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); |
| ret->allowNotifications = TRUE; |
| |
| resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, |
| EAP_CODE_RESPONSE, eap_get_id(reqData)); |
| if (resp == NULL) |
| return NULL; |
| |
| if (data->state == INIT) { |
| wpabuf_put_u8(resp, 2); |
| data->state = CONFIRM; |
| ret->methodState = METHOD_CONT; |
| ret->decision = DECISION_FAIL; |
| } else { |
| wpabuf_put_u8(resp, 4); |
| data->state = SUCCESS; |
| ret->methodState = METHOD_DONE; |
| ret->decision = DECISION_UNCOND_SUCC; |
| } |
| |
| return resp; |
| } |
| |
| |
| static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) |
| { |
| struct eap_vendor_test_data *data = priv; |
| return data->state == SUCCESS; |
| } |
| |
| |
| static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) |
| { |
| struct eap_vendor_test_data *data = priv; |
| u8 *key; |
| const int key_len = 64; |
| |
| if (data->state != SUCCESS) |
| return NULL; |
| |
| key = os_malloc(key_len); |
| if (key == NULL) |
| return NULL; |
| |
| os_memset(key, 0x11, key_len / 2); |
| os_memset(key + key_len / 2, 0x22, key_len / 2); |
| *len = key_len; |
| |
| return key; |
| } |
| |
| |
| int eap_peer_vendor_test_register(void) |
| { |
| struct eap_method *eap; |
| int ret; |
| |
| eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, |
| EAP_VENDOR_ID, EAP_VENDOR_TYPE, |
| "VENDOR-TEST"); |
| if (eap == NULL) |
| return -1; |
| |
| eap->init = eap_vendor_test_init; |
| eap->deinit = eap_vendor_test_deinit; |
| eap->process = eap_vendor_test_process; |
| eap->isKeyAvailable = eap_vendor_test_isKeyAvailable; |
| eap->getKey = eap_vendor_test_getKey; |
| |
| ret = eap_peer_method_register(eap); |
| if (ret) |
| eap_peer_method_free(eap); |
| return ret; |
| } |