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