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