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