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