eap_vendor_test.c revision c5ec7f57ead87efa365800228aa0b09a12d9e6c4
1/*
2 * EAP peer method: Test method for vendor specific (expanded) EAP type
3 * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 *
8 * This file implements a vendor specific test method using EAP expanded types.
9 * This is only for test use and must not be used for authentication since no
10 * security is provided.
11 */
12
13#include "includes.h"
14
15#include "common.h"
16#include "eap_i.h"
17#ifdef TEST_PENDING_REQUEST
18#include "eloop.h"
19#endif /* TEST_PENDING_REQUEST */
20
21
22#define EAP_VENDOR_ID 0xfffefd
23#define EAP_VENDOR_TYPE 0xfcfbfaf9
24
25
26/* #define TEST_PENDING_REQUEST */
27
28struct eap_vendor_test_data {
29	enum { INIT, CONFIRM, SUCCESS } state;
30	int first_try;
31};
32
33
34static void * eap_vendor_test_init(struct eap_sm *sm)
35{
36	struct eap_vendor_test_data *data;
37	data = os_zalloc(sizeof(*data));
38	if (data == NULL)
39		return NULL;
40	data->state = INIT;
41	data->first_try = 1;
42	return data;
43}
44
45
46static void eap_vendor_test_deinit(struct eap_sm *sm, void *priv)
47{
48	struct eap_vendor_test_data *data = priv;
49	os_free(data);
50}
51
52
53#ifdef TEST_PENDING_REQUEST
54static void eap_vendor_ready(void *eloop_ctx, void *timeout_ctx)
55{
56	struct eap_sm *sm = eloop_ctx;
57	wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Ready to re-process pending "
58		   "request");
59	eap_notify_pending(sm);
60}
61#endif /* TEST_PENDING_REQUEST */
62
63
64static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv,
65					       struct eap_method_ret *ret,
66					       const struct wpabuf *reqData)
67{
68	struct eap_vendor_test_data *data = priv;
69	struct wpabuf *resp;
70	const u8 *pos;
71	size_t len;
72
73	pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len);
74	if (pos == NULL || len < 1) {
75		ret->ignore = TRUE;
76		return NULL;
77	}
78
79	if (data->state == INIT && *pos != 1) {
80		wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
81			   "%d in INIT state", *pos);
82		ret->ignore = TRUE;
83		return NULL;
84	}
85
86	if (data->state == CONFIRM && *pos != 3) {
87		wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
88			   "%d in CONFIRM state", *pos);
89		ret->ignore = TRUE;
90		return NULL;
91	}
92
93	if (data->state == SUCCESS) {
94		wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
95			   "in SUCCESS state");
96		ret->ignore = TRUE;
97		return NULL;
98	}
99
100	if (data->state == CONFIRM) {
101#ifdef TEST_PENDING_REQUEST
102		if (data->first_try) {
103			data->first_try = 0;
104			wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing "
105				   "pending request");
106			ret->ignore = TRUE;
107			eloop_register_timeout(1, 0, eap_vendor_ready, sm,
108					       NULL);
109			return NULL;
110		}
111#endif /* TEST_PENDING_REQUEST */
112	}
113
114	ret->ignore = FALSE;
115
116	wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response");
117	ret->allowNotifications = TRUE;
118
119	resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1,
120			     EAP_CODE_RESPONSE, eap_get_id(reqData));
121	if (resp == NULL)
122		return NULL;
123
124	if (data->state == INIT) {
125		wpabuf_put_u8(resp, 2);
126		data->state = CONFIRM;
127		ret->methodState = METHOD_CONT;
128		ret->decision = DECISION_FAIL;
129	} else {
130		wpabuf_put_u8(resp, 4);
131		data->state = SUCCESS;
132		ret->methodState = METHOD_DONE;
133		ret->decision = DECISION_UNCOND_SUCC;
134	}
135
136	return resp;
137}
138
139
140static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv)
141{
142	struct eap_vendor_test_data *data = priv;
143	return data->state == SUCCESS;
144}
145
146
147static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len)
148{
149	struct eap_vendor_test_data *data = priv;
150	u8 *key;
151	const int key_len = 64;
152
153	if (data->state != SUCCESS)
154		return NULL;
155
156	key = os_malloc(key_len);
157	if (key == NULL)
158		return NULL;
159
160	os_memset(key, 0x11, key_len / 2);
161	os_memset(key + key_len / 2, 0x22, key_len / 2);
162	*len = key_len;
163
164	return key;
165}
166
167
168int eap_peer_vendor_test_register(void)
169{
170	struct eap_method *eap;
171	int ret;
172
173	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
174				    EAP_VENDOR_ID, EAP_VENDOR_TYPE,
175				    "VENDOR-TEST");
176	if (eap == NULL)
177		return -1;
178
179	eap->init = eap_vendor_test_init;
180	eap->deinit = eap_vendor_test_deinit;
181	eap->process = eap_vendor_test_process;
182	eap->isKeyAvailable = eap_vendor_test_isKeyAvailable;
183	eap->getKey = eap_vendor_test_getKey;
184
185	ret = eap_peer_method_register(eap);
186	if (ret)
187		eap_peer_method_free(eap);
188	return ret;
189}
190