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