Line data Source code
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 EAP_VENDOR_HOSTAP
23 : #define EAP_VENDOR_TYPE 0xfcfbfaf9
24 :
25 :
26 : /* #define TEST_PENDING_REQUEST */
27 :
28 : struct eap_vendor_test_data {
29 : enum { INIT, CONFIRM, SUCCESS } state;
30 : int first_try;
31 : };
32 :
33 :
34 2 : static void * eap_vendor_test_init(struct eap_sm *sm)
35 : {
36 : struct eap_vendor_test_data *data;
37 2 : data = os_zalloc(sizeof(*data));
38 2 : if (data == NULL)
39 0 : return NULL;
40 2 : data->state = INIT;
41 2 : data->first_try = 1;
42 2 : return data;
43 : }
44 :
45 :
46 2 : static void eap_vendor_test_deinit(struct eap_sm *sm, void *priv)
47 : {
48 2 : struct eap_vendor_test_data *data = priv;
49 2 : os_free(data);
50 2 : }
51 :
52 :
53 : #ifdef TEST_PENDING_REQUEST
54 : static 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 :
64 4 : static 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 4 : struct eap_vendor_test_data *data = priv;
69 : struct wpabuf *resp;
70 : const u8 *pos;
71 : size_t len;
72 :
73 4 : pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len);
74 4 : if (pos == NULL || len < 1) {
75 0 : ret->ignore = TRUE;
76 0 : return NULL;
77 : }
78 :
79 4 : if (data->state == INIT && *pos != 1) {
80 0 : wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
81 0 : "%d in INIT state", *pos);
82 0 : ret->ignore = TRUE;
83 0 : return NULL;
84 : }
85 :
86 4 : if (data->state == CONFIRM && *pos != 3) {
87 0 : wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
88 0 : "%d in CONFIRM state", *pos);
89 0 : ret->ignore = TRUE;
90 0 : return NULL;
91 : }
92 :
93 4 : if (data->state == SUCCESS) {
94 0 : wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message "
95 : "in SUCCESS state");
96 0 : ret->ignore = TRUE;
97 0 : return NULL;
98 : }
99 :
100 4 : 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 4 : ret->ignore = FALSE;
115 :
116 4 : wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response");
117 4 : ret->allowNotifications = TRUE;
118 :
119 4 : resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1,
120 4 : EAP_CODE_RESPONSE, eap_get_id(reqData));
121 4 : if (resp == NULL)
122 0 : return NULL;
123 :
124 4 : if (data->state == INIT) {
125 2 : wpabuf_put_u8(resp, 2);
126 2 : data->state = CONFIRM;
127 2 : ret->methodState = METHOD_CONT;
128 2 : ret->decision = DECISION_FAIL;
129 : } else {
130 2 : wpabuf_put_u8(resp, 4);
131 2 : data->state = SUCCESS;
132 2 : ret->methodState = METHOD_DONE;
133 2 : ret->decision = DECISION_UNCOND_SUCC;
134 : }
135 :
136 4 : return resp;
137 : }
138 :
139 :
140 4 : static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv)
141 : {
142 4 : struct eap_vendor_test_data *data = priv;
143 4 : return data->state == SUCCESS;
144 : }
145 :
146 :
147 2 : static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len)
148 : {
149 2 : struct eap_vendor_test_data *data = priv;
150 : u8 *key;
151 2 : const int key_len = 64;
152 :
153 2 : if (data->state != SUCCESS)
154 0 : return NULL;
155 :
156 2 : key = os_malloc(key_len);
157 2 : if (key == NULL)
158 0 : return NULL;
159 :
160 2 : os_memset(key, 0x11, key_len / 2);
161 2 : os_memset(key + key_len / 2, 0x22, key_len / 2);
162 2 : *len = key_len;
163 :
164 2 : return key;
165 : }
166 :
167 :
168 4 : int eap_peer_vendor_test_register(void)
169 : {
170 : struct eap_method *eap;
171 : int ret;
172 :
173 4 : eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
174 : EAP_VENDOR_ID, EAP_VENDOR_TYPE,
175 : "VENDOR-TEST");
176 4 : if (eap == NULL)
177 0 : return -1;
178 :
179 4 : eap->init = eap_vendor_test_init;
180 4 : eap->deinit = eap_vendor_test_deinit;
181 4 : eap->process = eap_vendor_test_process;
182 4 : eap->isKeyAvailable = eap_vendor_test_isKeyAvailable;
183 4 : eap->getKey = eap_vendor_test_getKey;
184 :
185 4 : ret = eap_peer_method_register(eap);
186 4 : if (ret)
187 0 : eap_peer_method_free(eap);
188 4 : return ret;
189 : }
|