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