1 /*
2  * Example application showing how EAP peer code from wpa_supplicant can be
3  * used as a library.
4  * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 
10 #include "includes.h"
11 
12 #include "common.h"
13 #include "eap_peer/eap.h"
14 #include "eap_peer/eap_config.h"
15 #include "wpabuf.h"
16 
17 void eap_example_server_rx(const u8 *data, size_t data_len);
18 
19 
20 struct eap_peer_ctx {
21 	bool eapSuccess;
22 	bool eapRestart;
23 	bool eapFail;
24 	bool eapResp;
25 	bool eapNoResp;
26 	bool eapReq;
27 	bool portEnabled;
28 	bool altAccept; /* for EAP */
29 	bool altReject; /* for EAP */
30 	bool eapTriggerStart;
31 
32 	struct wpabuf *eapReqData; /* for EAP */
33 
34 	unsigned int idleWhile; /* for EAP state machine */
35 
36 	struct eap_peer_config eap_config;
37 	struct eap_sm *eap;
38 };
39 
40 
41 static struct eap_peer_ctx eap_ctx;
42 
43 
peer_get_config(void * ctx)44 static struct eap_peer_config * peer_get_config(void *ctx)
45 {
46 	struct eap_peer_ctx *peer = ctx;
47 	return &peer->eap_config;
48 }
49 
50 
peer_get_bool(void * ctx,enum eapol_bool_var variable)51 static bool peer_get_bool(void *ctx, enum eapol_bool_var variable)
52 {
53 	struct eap_peer_ctx *peer = ctx;
54 	if (peer == NULL)
55 		return false;
56 	switch (variable) {
57 	case EAPOL_eapSuccess:
58 		return peer->eapSuccess;
59 	case EAPOL_eapRestart:
60 		return peer->eapRestart;
61 	case EAPOL_eapFail:
62 		return peer->eapFail;
63 	case EAPOL_eapResp:
64 		return peer->eapResp;
65 	case EAPOL_eapNoResp:
66 		return peer->eapNoResp;
67 	case EAPOL_eapReq:
68 		return peer->eapReq;
69 	case EAPOL_portEnabled:
70 		return peer->portEnabled;
71 	case EAPOL_altAccept:
72 		return peer->altAccept;
73 	case EAPOL_altReject:
74 		return peer->altReject;
75 	case EAPOL_eapTriggerStart:
76 		return peer->eapTriggerStart;
77 	}
78 	return false;
79 }
80 
81 
peer_set_bool(void * ctx,enum eapol_bool_var variable,bool value)82 static void peer_set_bool(void *ctx, enum eapol_bool_var variable, bool value)
83 {
84 	struct eap_peer_ctx *peer = ctx;
85 	if (peer == NULL)
86 		return;
87 	switch (variable) {
88 	case EAPOL_eapSuccess:
89 		peer->eapSuccess = value;
90 		break;
91 	case EAPOL_eapRestart:
92 		peer->eapRestart = value;
93 		break;
94 	case EAPOL_eapFail:
95 		peer->eapFail = value;
96 		break;
97 	case EAPOL_eapResp:
98 		peer->eapResp = value;
99 		break;
100 	case EAPOL_eapNoResp:
101 		peer->eapNoResp = value;
102 		break;
103 	case EAPOL_eapReq:
104 		peer->eapReq = value;
105 		break;
106 	case EAPOL_portEnabled:
107 		peer->portEnabled = value;
108 		break;
109 	case EAPOL_altAccept:
110 		peer->altAccept = value;
111 		break;
112 	case EAPOL_altReject:
113 		peer->altReject = value;
114 		break;
115 	case EAPOL_eapTriggerStart:
116 		peer->eapTriggerStart = value;
117 		break;
118 	}
119 }
120 
121 
peer_get_int(void * ctx,enum eapol_int_var variable)122 static unsigned int peer_get_int(void *ctx, enum eapol_int_var variable)
123 {
124 	struct eap_peer_ctx *peer = ctx;
125 	if (peer == NULL)
126 		return 0;
127 	switch (variable) {
128 	case EAPOL_idleWhile:
129 		return peer->idleWhile;
130 	}
131 	return 0;
132 }
133 
134 
peer_set_int(void * ctx,enum eapol_int_var variable,unsigned int value)135 static void peer_set_int(void *ctx, enum eapol_int_var variable,
136 			 unsigned int value)
137 {
138 	struct eap_peer_ctx *peer = ctx;
139 	if (peer == NULL)
140 		return;
141 	switch (variable) {
142 	case EAPOL_idleWhile:
143 		peer->idleWhile = value;
144 		break;
145 	}
146 }
147 
148 
peer_get_eapReqData(void * ctx)149 static struct wpabuf * peer_get_eapReqData(void *ctx)
150 {
151 	struct eap_peer_ctx *peer = ctx;
152 	if (peer == NULL || peer->eapReqData == NULL)
153 		return NULL;
154 
155 	return peer->eapReqData;
156 }
157 
158 
peer_set_config_blob(void * ctx,struct wpa_config_blob * blob)159 static void peer_set_config_blob(void *ctx, struct wpa_config_blob *blob)
160 {
161 	printf("TODO: %s\n", __func__);
162 }
163 
164 
165 static const struct wpa_config_blob *
peer_get_config_blob(void * ctx,const char * name)166 peer_get_config_blob(void *ctx, const char *name)
167 {
168 	printf("TODO: %s\n", __func__);
169 	return NULL;
170 }
171 
172 
peer_notify_pending(void * ctx)173 static void peer_notify_pending(void *ctx)
174 {
175 	printf("TODO: %s\n", __func__);
176 }
177 
178 
eap_peer_register_methods(void)179 static int eap_peer_register_methods(void)
180 {
181 	int ret = 0;
182 
183 #ifdef EAP_MD5
184 	if (ret == 0)
185 		ret = eap_peer_md5_register();
186 #endif /* EAP_MD5 */
187 
188 #ifdef EAP_TLS
189 	if (ret == 0)
190 		ret = eap_peer_tls_register();
191 #endif /* EAP_TLS */
192 
193 #ifdef EAP_MSCHAPv2
194 	if (ret == 0)
195 		ret = eap_peer_mschapv2_register();
196 #endif /* EAP_MSCHAPv2 */
197 
198 #ifdef EAP_PEAP
199 	if (ret == 0)
200 		ret = eap_peer_peap_register();
201 #endif /* EAP_PEAP */
202 
203 #ifdef EAP_TTLS
204 	if (ret == 0)
205 		ret = eap_peer_ttls_register();
206 #endif /* EAP_TTLS */
207 
208 #ifdef EAP_GTC
209 	if (ret == 0)
210 		ret = eap_peer_gtc_register();
211 #endif /* EAP_GTC */
212 
213 #ifdef EAP_OTP
214 	if (ret == 0)
215 		ret = eap_peer_otp_register();
216 #endif /* EAP_OTP */
217 
218 #ifdef EAP_SIM
219 	if (ret == 0)
220 		ret = eap_peer_sim_register();
221 #endif /* EAP_SIM */
222 
223 #ifdef EAP_LEAP
224 	if (ret == 0)
225 		ret = eap_peer_leap_register();
226 #endif /* EAP_LEAP */
227 
228 #ifdef EAP_PSK
229 	if (ret == 0)
230 		ret = eap_peer_psk_register();
231 #endif /* EAP_PSK */
232 
233 #ifdef EAP_AKA
234 	if (ret == 0)
235 		ret = eap_peer_aka_register();
236 #endif /* EAP_AKA */
237 
238 #ifdef EAP_AKA_PRIME
239 	if (ret == 0)
240 		ret = eap_peer_aka_prime_register();
241 #endif /* EAP_AKA_PRIME */
242 
243 #ifdef EAP_FAST
244 	if (ret == 0)
245 		ret = eap_peer_fast_register();
246 #endif /* EAP_FAST */
247 
248 #ifdef EAP_PAX
249 	if (ret == 0)
250 		ret = eap_peer_pax_register();
251 #endif /* EAP_PAX */
252 
253 #ifdef EAP_SAKE
254 	if (ret == 0)
255 		ret = eap_peer_sake_register();
256 #endif /* EAP_SAKE */
257 
258 #ifdef EAP_GPSK
259 	if (ret == 0)
260 		ret = eap_peer_gpsk_register();
261 #endif /* EAP_GPSK */
262 
263 #ifdef EAP_WSC
264 	if (ret == 0)
265 		ret = eap_peer_wsc_register();
266 #endif /* EAP_WSC */
267 
268 #ifdef EAP_IKEV2
269 	if (ret == 0)
270 		ret = eap_peer_ikev2_register();
271 #endif /* EAP_IKEV2 */
272 
273 #ifdef EAP_VENDOR_TEST
274 	if (ret == 0)
275 		ret = eap_peer_vendor_test_register();
276 #endif /* EAP_VENDOR_TEST */
277 
278 #ifdef EAP_TNC
279 	if (ret == 0)
280 		ret = eap_peer_tnc_register();
281 #endif /* EAP_TNC */
282 
283 	return ret;
284 }
285 
286 
287 static struct eapol_callbacks eap_cb;
288 static struct eap_config eap_conf;
289 
eap_example_peer_init(void)290 int eap_example_peer_init(void)
291 {
292 	if (eap_peer_register_methods() < 0)
293 		return -1;
294 
295 	os_memset(&eap_ctx, 0, sizeof(eap_ctx));
296 
297 	eap_ctx.eap_config.identity = (u8 *) os_strdup("user");
298 	eap_ctx.eap_config.identity_len = 4;
299 	eap_ctx.eap_config.password = (u8 *) os_strdup("password");
300 	eap_ctx.eap_config.password_len = 8;
301 	eap_ctx.eap_config.cert.ca_cert = os_strdup("ca.pem");
302 	eap_ctx.eap_config.fragment_size = 1398;
303 
304 	os_memset(&eap_cb, 0, sizeof(eap_cb));
305 	eap_cb.get_config = peer_get_config;
306 	eap_cb.get_bool = peer_get_bool;
307 	eap_cb.set_bool = peer_set_bool;
308 	eap_cb.get_int = peer_get_int;
309 	eap_cb.set_int = peer_set_int;
310 	eap_cb.get_eapReqData = peer_get_eapReqData;
311 	eap_cb.set_config_blob = peer_set_config_blob;
312 	eap_cb.get_config_blob = peer_get_config_blob;
313 	eap_cb.notify_pending = peer_notify_pending;
314 
315 	os_memset(&eap_conf, 0, sizeof(eap_conf));
316 	eap_ctx.eap = eap_peer_sm_init(&eap_ctx, &eap_cb, &eap_ctx, &eap_conf);
317 	if (eap_ctx.eap == NULL)
318 		return -1;
319 
320 	/* Enable "port" to allow authentication */
321 	eap_ctx.portEnabled = true;
322 
323 	return 0;
324 }
325 
326 
eap_example_peer_deinit(void)327 void eap_example_peer_deinit(void)
328 {
329 	eap_peer_sm_deinit(eap_ctx.eap);
330 	eap_peer_unregister_methods();
331 	wpabuf_free(eap_ctx.eapReqData);
332 	os_free(eap_ctx.eap_config.identity);
333 	os_free(eap_ctx.eap_config.password);
334 	os_free(eap_ctx.eap_config.cert.ca_cert);
335 }
336 
337 
eap_example_peer_step(void)338 int eap_example_peer_step(void)
339 {
340 	int res;
341 	res = eap_peer_sm_step(eap_ctx.eap);
342 
343 	if (eap_ctx.eapResp) {
344 		struct wpabuf *resp;
345 		printf("==> Response\n");
346 		eap_ctx.eapResp = false;
347 		resp = eap_get_eapRespData(eap_ctx.eap);
348 		if (resp) {
349 			/* Send EAP response to the server */
350 			eap_example_server_rx(wpabuf_head(resp),
351 					      wpabuf_len(resp));
352 			wpabuf_free(resp);
353 		}
354 	}
355 
356 	if (eap_ctx.eapSuccess) {
357 		res = 0;
358 		if (eap_key_available(eap_ctx.eap)) {
359 			const u8 *key;
360 			size_t key_len;
361 			key = eap_get_eapKeyData(eap_ctx.eap, &key_len);
362 			wpa_hexdump(MSG_DEBUG, "EAP keying material",
363 				    key, key_len);
364 		}
365 	}
366 
367 	return res;
368 }
369 
370 
eap_example_peer_rx(const u8 * data,size_t data_len)371 void eap_example_peer_rx(const u8 *data, size_t data_len)
372 {
373 	/* Make received EAP message available to the EAP library */
374 	eap_ctx.eapReq = true;
375 	wpabuf_free(eap_ctx.eapReqData);
376 	eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len);
377 }
378