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