| /* |
| * Example application showing how EAP server code from hostapd can be used as |
| * a library. |
| * Copyright (c) 2007, Jouni Malinen <j@w1.fi> |
| * |
| * This software may be distributed under the terms of the BSD license. |
| * See README for more details. |
| */ |
| |
| #include "includes.h" |
| |
| #include "common.h" |
| #include "crypto/tls.h" |
| #include "eap_server/eap.h" |
| #include "wpabuf.h" |
| |
| void eap_example_peer_rx(const u8 *data, size_t data_len); |
| |
| |
| struct eap_server_ctx { |
| struct eap_eapol_interface *eap_if; |
| struct eap_sm *eap; |
| void *tls_ctx; |
| }; |
| |
| static struct eap_server_ctx eap_ctx; |
| |
| |
| static int server_get_eap_user(void *ctx, const u8 *identity, |
| size_t identity_len, int phase2, |
| struct eap_user *user) |
| { |
| os_memset(user, 0, sizeof(*user)); |
| |
| if (!phase2) { |
| /* Only allow EAP-PEAP as the Phase 1 method */ |
| user->methods[0].vendor = EAP_VENDOR_IETF; |
| user->methods[0].method = EAP_TYPE_PEAP; |
| return 0; |
| } |
| |
| if (identity_len != 4 || identity == NULL || |
| os_memcmp(identity, "user", 4) != 0) { |
| printf("Unknown user\n"); |
| return -1; |
| } |
| |
| /* Only allow EAP-MSCHAPv2 as the Phase 2 method */ |
| user->methods[0].vendor = EAP_VENDOR_IETF; |
| user->methods[0].method = EAP_TYPE_MSCHAPV2; |
| user->password = (u8 *) os_strdup("password"); |
| user->password_len = 8; |
| |
| return 0; |
| } |
| |
| |
| static const char * server_get_eap_req_id_text(void *ctx, size_t *len) |
| { |
| *len = 0; |
| return NULL; |
| } |
| |
| |
| static struct eapol_callbacks eap_cb; |
| static struct eap_config eap_conf; |
| |
| static int eap_example_server_init_tls(void) |
| { |
| struct tls_config tconf; |
| struct tls_connection_params tparams; |
| |
| os_memset(&tconf, 0, sizeof(tconf)); |
| eap_ctx.tls_ctx = tls_init(&tconf); |
| if (eap_ctx.tls_ctx == NULL) |
| return -1; |
| |
| os_memset(&tparams, 0, sizeof(tparams)); |
| tparams.ca_cert = "ca.pem"; |
| tparams.client_cert = "server.pem"; |
| /* tparams.private_key = "server.key"; */ |
| tparams.private_key = "server-key.pem"; |
| /* tparams.private_key_passwd = "whatever"; */ |
| tparams.dh_file = "dh.conf"; |
| |
| if (tls_global_set_params(eap_ctx.tls_ctx, &tparams)) { |
| printf("Failed to set TLS parameters\n"); |
| return -1; |
| } |
| |
| if (tls_global_set_verify(eap_ctx.tls_ctx, 0)) { |
| printf("Failed to set check_crl\n"); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| |
| static int eap_server_register_methods(void) |
| { |
| int ret = 0; |
| |
| #ifdef EAP_SERVER_IDENTITY |
| if (ret == 0) |
| ret = eap_server_identity_register(); |
| #endif /* EAP_SERVER_IDENTITY */ |
| |
| #ifdef EAP_SERVER_MD5 |
| if (ret == 0) |
| ret = eap_server_md5_register(); |
| #endif /* EAP_SERVER_MD5 */ |
| |
| #ifdef EAP_SERVER_TLS |
| if (ret == 0) |
| ret = eap_server_tls_register(); |
| #endif /* EAP_SERVER_TLS */ |
| |
| #ifdef EAP_SERVER_MSCHAPV2 |
| if (ret == 0) |
| ret = eap_server_mschapv2_register(); |
| #endif /* EAP_SERVER_MSCHAPV2 */ |
| |
| #ifdef EAP_SERVER_PEAP |
| if (ret == 0) |
| ret = eap_server_peap_register(); |
| #endif /* EAP_SERVER_PEAP */ |
| |
| #ifdef EAP_SERVER_TLV |
| if (ret == 0) |
| ret = eap_server_tlv_register(); |
| #endif /* EAP_SERVER_TLV */ |
| |
| #ifdef EAP_SERVER_GTC |
| if (ret == 0) |
| ret = eap_server_gtc_register(); |
| #endif /* EAP_SERVER_GTC */ |
| |
| #ifdef EAP_SERVER_TTLS |
| if (ret == 0) |
| ret = eap_server_ttls_register(); |
| #endif /* EAP_SERVER_TTLS */ |
| |
| #ifdef EAP_SERVER_SIM |
| if (ret == 0) |
| ret = eap_server_sim_register(); |
| #endif /* EAP_SERVER_SIM */ |
| |
| #ifdef EAP_SERVER_AKA |
| if (ret == 0) |
| ret = eap_server_aka_register(); |
| #endif /* EAP_SERVER_AKA */ |
| |
| #ifdef EAP_SERVER_AKA_PRIME |
| if (ret == 0) |
| ret = eap_server_aka_prime_register(); |
| #endif /* EAP_SERVER_AKA_PRIME */ |
| |
| #ifdef EAP_SERVER_PAX |
| if (ret == 0) |
| ret = eap_server_pax_register(); |
| #endif /* EAP_SERVER_PAX */ |
| |
| #ifdef EAP_SERVER_PSK |
| if (ret == 0) |
| ret = eap_server_psk_register(); |
| #endif /* EAP_SERVER_PSK */ |
| |
| #ifdef EAP_SERVER_SAKE |
| if (ret == 0) |
| ret = eap_server_sake_register(); |
| #endif /* EAP_SERVER_SAKE */ |
| |
| #ifdef EAP_SERVER_GPSK |
| if (ret == 0) |
| ret = eap_server_gpsk_register(); |
| #endif /* EAP_SERVER_GPSK */ |
| |
| #ifdef EAP_SERVER_VENDOR_TEST |
| if (ret == 0) |
| ret = eap_server_vendor_test_register(); |
| #endif /* EAP_SERVER_VENDOR_TEST */ |
| |
| #ifdef EAP_SERVER_FAST |
| if (ret == 0) |
| ret = eap_server_fast_register(); |
| #endif /* EAP_SERVER_FAST */ |
| |
| #ifdef EAP_SERVER_WSC |
| if (ret == 0) |
| ret = eap_server_wsc_register(); |
| #endif /* EAP_SERVER_WSC */ |
| |
| #ifdef EAP_SERVER_IKEV2 |
| if (ret == 0) |
| ret = eap_server_ikev2_register(); |
| #endif /* EAP_SERVER_IKEV2 */ |
| |
| #ifdef EAP_SERVER_TNC |
| if (ret == 0) |
| ret = eap_server_tnc_register(); |
| #endif /* EAP_SERVER_TNC */ |
| |
| return ret; |
| } |
| |
| |
| int eap_example_server_init(void) |
| { |
| if (eap_server_register_methods() < 0) |
| return -1; |
| |
| os_memset(&eap_ctx, 0, sizeof(eap_ctx)); |
| |
| if (eap_example_server_init_tls() < 0) |
| return -1; |
| |
| os_memset(&eap_cb, 0, sizeof(eap_cb)); |
| eap_cb.get_eap_user = server_get_eap_user; |
| eap_cb.get_eap_req_id_text = server_get_eap_req_id_text; |
| |
| os_memset(&eap_conf, 0, sizeof(eap_conf)); |
| eap_conf.eap_server = 1; |
| eap_conf.ssl_ctx = eap_ctx.tls_ctx; |
| |
| eap_ctx.eap = eap_server_sm_init(&eap_ctx, &eap_cb, &eap_conf); |
| if (eap_ctx.eap == NULL) |
| return -1; |
| |
| eap_ctx.eap_if = eap_get_interface(eap_ctx.eap); |
| |
| /* Enable "port" and request EAP to start authentication. */ |
| eap_ctx.eap_if->portEnabled = TRUE; |
| eap_ctx.eap_if->eapRestart = TRUE; |
| |
| return 0; |
| } |
| |
| |
| void eap_example_server_deinit(void) |
| { |
| eap_server_sm_deinit(eap_ctx.eap); |
| eap_server_unregister_methods(); |
| tls_deinit(eap_ctx.tls_ctx); |
| } |
| |
| |
| int eap_example_server_step(void) |
| { |
| int res, process = 0; |
| |
| res = eap_server_sm_step(eap_ctx.eap); |
| |
| if (eap_ctx.eap_if->eapReq) { |
| printf("==> Request\n"); |
| process = 1; |
| eap_ctx.eap_if->eapReq = 0; |
| } |
| |
| if (eap_ctx.eap_if->eapSuccess) { |
| printf("==> Success\n"); |
| process = 1; |
| res = 0; |
| eap_ctx.eap_if->eapSuccess = 0; |
| |
| if (eap_ctx.eap_if->eapKeyAvailable) { |
| wpa_hexdump(MSG_DEBUG, "EAP keying material", |
| eap_ctx.eap_if->eapKeyData, |
| eap_ctx.eap_if->eapKeyDataLen); |
| } |
| } |
| |
| if (eap_ctx.eap_if->eapFail) { |
| printf("==> Fail\n"); |
| process = 1; |
| eap_ctx.eap_if->eapFail = 0; |
| } |
| |
| if (process && eap_ctx.eap_if->eapReqData) { |
| /* Send EAP response to the server */ |
| eap_example_peer_rx(wpabuf_head(eap_ctx.eap_if->eapReqData), |
| wpabuf_len(eap_ctx.eap_if->eapReqData)); |
| } |
| |
| return res; |
| } |
| |
| |
| void eap_example_server_rx(const u8 *data, size_t data_len) |
| { |
| /* Make received EAP message available to the EAP library */ |
| wpabuf_free(eap_ctx.eap_if->eapRespData); |
| eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len); |
| if (eap_ctx.eap_if->eapRespData) |
| eap_ctx.eap_if->eapResp = TRUE; |
| } |