From 70518fad5f76d5ea23447c404e20dffac1da9ca1 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Wed, 6 Sep 2017 04:12:17 +0200 Subject: [PATCH] eap: Drop method's .probe, rename .remove The EAP-method's .probe methods only checked the method name so do that in eap.c instead and allocate method state in .load_settings. Rename method's .remove method to .free to improve the naming. --- src/eap-aka.c | 71 ++++++++++++++++++++-------------------------- src/eap-md5.c | 31 +++++++------------- src/eap-mschapv2.c | 41 ++++++++++++-------------- src/eap-sim.c | 24 ++++------------ src/eap-tls.c | 38 ++++++++++++------------- src/eap-ttls.c | 47 ++++++++++++++++-------------- src/eap-wsc.c | 56 ++++++++++++++++++------------------ src/eap.c | 10 +++---- src/eap.h | 4 +-- 9 files changed, 142 insertions(+), 180 deletions(-) diff --git a/src/eap-aka.c b/src/eap-aka.c index 05620b0a..85a42a34 100644 --- a/src/eap-aka.c +++ b/src/eap-aka.c @@ -119,37 +119,7 @@ struct eap_aka_handle { uint8_t k_re[EAP_AKA_K_RE_LEN]; }; -static int eap_aka_probe(struct eap_state *eap, const char *name) -{ - struct eap_aka_handle *aka; - - if (strcasecmp(name, "AKA")) - return -ENOTSUP; - - aka = l_new(struct eap_aka_handle, 1); - aka->type = EAP_TYPE_AKA; - - eap_set_data(eap, aka); - - return 0; -} - -static int eap_aka_prime_probe(struct eap_state *eap, const char *name) -{ - struct eap_aka_handle *aka; - - if (strcasecmp(name, "AKA'")) - return -ENOTSUP; - - aka = l_new(struct eap_aka_handle, 1); - aka->type = EAP_TYPE_AKA_PRIME; - - eap_set_data(eap, aka); - - return 0; -} - -static void eap_aka_remove(struct eap_state *eap) +static void eap_aka_free(struct eap_state *eap) { struct eap_aka_handle *aka = eap_get_data(eap); @@ -573,11 +543,10 @@ req_error: eap_sim_client_error(eap, aka->type, EAP_SIM_ERROR_PROCESS); } -static bool eap_aka_load_settings(struct eap_state *eap, - struct l_settings *settings, - const char *prefix) +static bool eap_aka_common_load_settings(struct eap_aka_handle *aka, + struct l_settings *settings, + const char *prefix) { - struct eap_aka_handle *aka = eap_get_data(eap); char setting[64]; const char *imsi; const char *ki; @@ -630,12 +599,35 @@ static bool eap_aka_load_settings(struct eap_state *eap, return true; } +static bool eap_aka_load_settings(struct eap_state *eap, + struct l_settings *settings, + const char *prefix) +{ + struct eap_aka_handle *aka = l_new(struct eap_aka_handle, 1); + + aka->type = EAP_TYPE_AKA; + eap_set_data(eap, aka); + + return eap_aka_common_load_settings(aka, settings, prefix); +} + +static bool eap_aka_prime_load_settings(struct eap_state *eap, + struct l_settings *settings, + const char *prefix) +{ + struct eap_aka_handle *aka = l_new(struct eap_aka_handle, 1); + + aka->type = EAP_TYPE_AKA_PRIME; + eap_set_data(eap, aka); + + return eap_aka_common_load_settings(aka, settings, prefix); +} + static struct eap_method eap_aka = { .request_type = EAP_TYPE_AKA, .exports_msk = true, .name = "AKA", - .probe = eap_aka_probe, - .remove = eap_aka_remove, + .free = eap_aka_free, .handle_request = eap_aka_handle_request, .load_settings = eap_aka_load_settings, }; @@ -644,10 +636,9 @@ static struct eap_method eap_aka_prime = { .request_type = EAP_TYPE_AKA_PRIME, .exports_msk = true, .name = "AKA'", - .probe = eap_aka_prime_probe, - .remove = eap_aka_remove, + .free = eap_aka_free, .handle_request = eap_aka_handle_request, - .load_settings = eap_aka_load_settings, + .load_settings = eap_aka_prime_load_settings, }; static int eap_aka_init(void) diff --git a/src/eap-md5.c b/src/eap-md5.c index 264fa6fd..e44ae51f 100644 --- a/src/eap-md5.c +++ b/src/eap-md5.c @@ -34,21 +34,7 @@ struct eap_md5_state { char *secret; }; -static int eap_md5_probe(struct eap_state *eap, const char *name) -{ - struct eap_md5_state *md5; - - if (strcasecmp(name, "MD5")) - return -ENOTSUP; - - md5 = l_new(struct eap_md5_state, 1); - - eap_set_data(eap, md5); - - return 0; -} - -static void eap_md5_remove(struct eap_state *eap) +static void eap_md5_free(struct eap_state *eap) { struct eap_md5_state *md5 = eap_get_data(eap); @@ -104,18 +90,22 @@ static bool eap_md5_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) { - struct eap_md5_state *md5 = eap_get_data(eap); + struct eap_md5_state *md5; char setting[64]; + char *secret; snprintf(setting, sizeof(setting), "%sMD5-Secret", prefix); - md5->secret = l_strdup(l_settings_get_value(settings, - "Security", setting)); + secret = l_strdup(l_settings_get_value(settings, "Security", setting)); - if (!md5->secret) { + if (!secret) { l_error("EAP-MD5 secret is missing"); return false; } + md5 = l_new(struct eap_md5_state, 1); + md5->secret = secret; + eap_set_data(eap, md5); + return true; } @@ -124,8 +114,7 @@ static struct eap_method eap_md5 = { .exports_msk = false, .name = "MD5", - .probe = eap_md5_probe, - .remove = eap_md5_remove, + .free = eap_md5_free, .handle_request = eap_md5_handle_request, .load_settings = eap_md5_load_settings, }; diff --git a/src/eap-mschapv2.c b/src/eap-mschapv2.c index 77fbc1bc..63178f44 100644 --- a/src/eap-mschapv2.c +++ b/src/eap-mschapv2.c @@ -404,35 +404,21 @@ bool mschapv2_generate_authenticator_response( return true; } -static int eap_mschapv2_probe(struct eap_state *eap, const char *name) -{ - struct eap_mschapv2_state *state; - - if (strcasecmp(name, "MSCHAPV2")) - return -ENOTSUP; - - state = l_new(struct eap_mschapv2_state, 1); - - eap_set_data(eap, state); - - return 0; -} - -static void eap_mschapv2_free(struct eap_mschapv2_state *state) +static void eap_mschapv2_state_free(struct eap_mschapv2_state *state) { l_free(state->user); l_free(state); } -static void eap_mschapv2_remove(struct eap_state *eap) +static void eap_mschapv2_free(struct eap_state *eap) { struct eap_mschapv2_state *state; state = eap_get_data(eap); eap_set_data(eap, NULL); - eap_mschapv2_free(state); + eap_mschapv2_state_free(state); } static bool eap_mschapv2_send_response(struct eap_state *eap) @@ -659,16 +645,18 @@ static bool eap_mschapv2_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) { - struct eap_mschapv2_state *state = eap_get_data(eap); + struct eap_mschapv2_state *state; const char *password; char setting[64]; + state = l_new(struct eap_mschapv2_state, 1); + snprintf(setting, sizeof(setting), "%sIdentity", prefix); set_user_name(state, l_settings_get_value(settings, "Security", setting)); if (!state->user) - return false; + goto err; state->user_len = strlen(state->user); @@ -683,7 +671,7 @@ static bool eap_mschapv2_load_settings(struct eap_state *eap, if (len != 16) { l_error("Read an impossible password hash"); l_free(tmp); - return false; + goto err; } memcpy(state->password_hash, tmp, 16); @@ -693,10 +681,18 @@ static bool eap_mschapv2_load_settings(struct eap_state *eap, password = l_settings_get_value(settings, "Security", setting); if (!password || !set_password_from_string(state, password)) - return false; + goto err; } + eap_set_data(eap, state); + return true; + +err: + l_free(state->user); + l_free(state); + + return false; } static struct eap_method eap_mschapv2 = { @@ -704,8 +700,7 @@ static struct eap_method eap_mschapv2 = { .exports_msk = true, .name = "MSCHAPV2", - .probe = eap_mschapv2_probe, - .remove = eap_mschapv2_remove, + .free = eap_mschapv2_free, .handle_request = eap_mschapv2_handle_request, .load_settings = eap_mschapv2_load_settings, }; diff --git a/src/eap-sim.c b/src/eap-sim.c index c86a742c..21f60cb7 100644 --- a/src/eap-sim.c +++ b/src/eap-sim.c @@ -125,21 +125,7 @@ struct eap_sim_handle { bool protected : 1; }; -static int eap_sim_probe(struct eap_state *eap, const char *name) -{ - struct eap_sim_handle *sim; - - if (strcasecmp(name, "SIM")) - return -ENOTSUP; - - sim = l_new(struct eap_sim_handle, 1); - - eap_set_data(eap, sim); - - return 0; -} - -static void eap_sim_remove(struct eap_state *eap) +static void eap_sim_free(struct eap_state *eap) { struct eap_sim_handle *sim = eap_get_data(eap); @@ -577,13 +563,16 @@ static bool eap_sim_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) { - struct eap_sim_handle *sim = eap_get_data(eap); + struct eap_sim_handle *sim; char setting[64]; const char *kcs; const char *imsi; const char *sres; size_t len; + sim = l_new(struct eap_sim_handle, 1); + eap_set_data(eap, sim); + /* * TODO: These values will be loaded from a SIM card. Kc and SRES * values should be kept secret and crucial to the security of EAP-SIM. @@ -620,8 +609,7 @@ static struct eap_method eap_sim = { .request_type = EAP_TYPE_SIM, .exports_msk = true, .name = "SIM", - .probe = eap_sim_probe, - .remove = eap_sim_remove, + .free = eap_sim_free, .handle_request = eap_sim_handle_request, .load_settings = eap_sim_load_settings, }; diff --git a/src/eap-tls.c b/src/eap-tls.c index ab137fcd..fa02836d 100644 --- a/src/eap-tls.c +++ b/src/eap-tls.c @@ -46,21 +46,7 @@ struct eap_tls_state { bool completed; }; -static int eap_tls_probe(struct eap_state *eap, const char *name) -{ - struct eap_tls_state *tls; - - if (strcasecmp(name, "TLS")) - return -ENOTSUP; - - tls = l_new(struct eap_tls_state, 1); - - eap_set_data(eap, tls); - - return 0; -} - -static void eap_tls_remove(struct eap_state *eap) +static void eap_tls_free(struct eap_state *eap) { struct eap_tls_state *tls = eap_get_data(eap); @@ -387,9 +373,11 @@ static bool eap_tls_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) { - struct eap_tls_state *tls = eap_get_data(eap); + struct eap_tls_state *tls; char setting[64]; + tls = l_new(struct eap_tls_state, 1); + snprintf(setting, sizeof(setting), "%sTLS-CACert", prefix); tls->ca_cert = l_strdup(l_settings_get_value(settings, "Security", setting)); @@ -408,15 +396,26 @@ static bool eap_tls_load_settings(struct eap_state *eap, if (!tls->client_cert && tls->client_key) { l_error("Client key present but no client certificate"); - return false; + goto err; } if (!tls->client_key && tls->passphrase) { l_error("Passphrase present but no client private key"); - return false; + goto err; } + eap_set_data(eap, tls); + return true; + +err: + l_free(tls->ca_cert); + l_free(tls->client_cert); + l_free(tls->client_key); + l_free(tls->passphrase); + l_free(tls); + + return false; } static struct eap_method eap_tls = { @@ -424,8 +423,7 @@ static struct eap_method eap_tls = { .exports_msk = true, .name = "TLS", - .probe = eap_tls_probe, - .remove = eap_tls_remove, + .free = eap_tls_free, .handle_request = eap_tls_handle_request, .load_settings = eap_tls_load_settings, }; diff --git a/src/eap-ttls.c b/src/eap-ttls.c index 900b67fa..9c66487b 100644 --- a/src/eap-ttls.c +++ b/src/eap-ttls.c @@ -51,21 +51,7 @@ struct eap_ttls_state { uint8_t negotiated_version; }; -static int eap_ttls_probe(struct eap_state *eap, const char *name) -{ - struct eap_ttls_state *ttls; - - if (strcasecmp(name, "TTLS")) - return -ENOTSUP; - - ttls = l_new(struct eap_ttls_state, 1); - - eap_set_data(eap, ttls); - - return 0; -} - -static void eap_ttls_remove(struct eap_state *eap) +static void eap_ttls_free(struct eap_state *eap) { struct eap_ttls_state *ttls = eap_get_data(eap); @@ -648,9 +634,11 @@ static bool eap_ttls_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) { - struct eap_ttls_state *ttls = eap_get_data(eap); + struct eap_ttls_state *ttls; char setting[64]; + ttls = l_new(struct eap_ttls_state, 1); + snprintf(setting, sizeof(setting), "%sTTLS-CACert", prefix); ttls->ca_cert = l_strdup(l_settings_get_value(settings, "Security", setting)); @@ -670,24 +658,40 @@ static bool eap_ttls_load_settings(struct eap_state *eap, if (!ttls->client_cert && ttls->client_key) { l_error("Client key present but no client certificate"); - return false; + goto err; } if (!ttls->client_key && ttls->passphrase) { l_error("Passphrase present but no client private key"); - return false; + goto err; } ttls->eap = eap_new(eap_ttls_eap_tx_packet, eap_ttls_eap_complete, eap); if (!ttls->eap) { l_error("Could not create the TTLS inner EAP instance"); - return false; + goto err; } snprintf(setting, sizeof(setting), "%sTTLS-Phase2-", prefix); - return eap_load_settings(ttls->eap, settings, setting); + if (!eap_load_settings(ttls->eap, settings, setting)) { + eap_free(ttls->eap); + goto err; + } + + eap_set_data(eap, ttls); + + return true; + +err: + l_free(ttls->ca_cert); + l_free(ttls->client_cert); + l_free(ttls->client_key); + l_free(ttls->passphrase); + l_free(ttls); + + return false; } static struct eap_method eap_ttls = { @@ -695,8 +699,7 @@ static struct eap_method eap_ttls = { .exports_msk = true, .name = "TTLS", - .probe = eap_ttls_probe, - .remove = eap_ttls_remove, + .free = eap_ttls_free, .handle_request = eap_ttls_handle_request, .load_settings = eap_ttls_load_settings, }; diff --git a/src/eap-wsc.c b/src/eap-wsc.c index a51b0ba4..d8854037 100644 --- a/src/eap-wsc.c +++ b/src/eap-wsc.c @@ -269,21 +269,7 @@ static bool encrypted_settings_encrypt(struct eap_wsc_state *wsc, return true; } -static int eap_wsc_probe(struct eap_state *eap, const char *name) -{ - struct eap_wsc_state *wsc; - - if (strcasecmp(name, "WSC")) - return -ENOTSUP; - - wsc = l_new(struct eap_wsc_state, 1); - - eap_set_data(eap, wsc); - - return 0; -} - -static void eap_wsc_remove(struct eap_state *eap) +static void eap_wsc_free(struct eap_state *eap) { struct eap_wsc_state *wsc = eap_get_data(eap); @@ -1167,25 +1153,27 @@ static bool eap_wsc_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) { - struct eap_wsc_state *wsc = eap_get_data(eap); + struct eap_wsc_state *wsc; const char *v; uint8_t private_key[192]; size_t len; unsigned int u32; const char *device_password; + wsc = l_new(struct eap_wsc_state, 1); + wsc->m1 = l_new(struct wsc_m1, 1); wsc->m1->version2 = true; v = l_settings_get_value(settings, "WSC", "EnrolleeMAC"); if (!v) - return false; + goto err; if (!util_string_to_address(v, wsc->m1->addr)) - return false; + goto err; if (!wsc_uuid_from_addr(wsc->m1->addr, wsc->m1->uuid_e)) - return false; + goto err; if (!load_hexencoded(settings, "EnrolleeNonce", wsc->m1->enrollee_nonce, 16)) @@ -1198,15 +1186,15 @@ static bool eap_wsc_load_settings(struct eap_state *eap, memset(private_key, 0, 192); if (!wsc->private) - return false; + goto err; len = sizeof(wsc->m1->public_key); if (!l_key_compute_dh_public(dh5_generator, wsc->private, dh5_prime, wsc->m1->public_key, &len)) - return false; + goto err; if (len != sizeof(wsc->m1->public_key)) - return false; + goto err; wsc->m1->auth_type_flags = WSC_AUTHENTICATION_TYPE_WPA2_PERSONAL | WSC_AUTHENTICATION_TYPE_WPA_PERSONAL | @@ -1252,7 +1240,7 @@ static bool eap_wsc_load_settings(struct eap_state *eap, strcpy(wsc->m1->device_name, " "); if (!l_settings_get_uint(settings, "WSC", "RFBand", &u32)) - return false; + goto err; switch (u32) { case WSC_RF_BAND_2_4_GHZ: @@ -1261,7 +1249,7 @@ static bool eap_wsc_load_settings(struct eap_state *eap, wsc->m1->rf_bands = u32; break; default: - return false; + goto err; } wsc->m1->association_state = WSC_ASSOCIATION_STATE_NOT_ASSOCIATED; @@ -1285,11 +1273,11 @@ static bool eap_wsc_load_settings(struct eap_state *eap, for (i = 0; device_password[i]; i++) { if (!l_ascii_isxdigit(device_password[i])) - return false; + goto err; } if (i < 8) - return false; + goto err; wsc->device_password = strdup(device_password); /* @@ -1320,7 +1308,20 @@ static bool eap_wsc_load_settings(struct eap_state *eap, if (!load_hexencoded(settings, "IV2", wsc->iv2, 16)) l_getrandom(wsc->iv2, 16); + eap_set_data(eap, wsc); + return true; + +err: + l_free(wsc->device_password); + + if (wsc->private) + l_key_free(wsc->private); + + l_free(wsc->m1); + l_free(wsc); + + return false; } static struct eap_method eap_wsc = { @@ -1329,8 +1330,7 @@ static struct eap_method eap_wsc = { .request_type = EAP_TYPE_EXPANDED, .exports_msk = true, .name = "WSC", - .probe = eap_wsc_probe, - .remove = eap_wsc_remove, + .free = eap_wsc_free, .handle_request = eap_wsc_handle_request, .handle_retransmit = eap_wsc_handle_retransmit, .load_settings = eap_wsc_load_settings, diff --git a/src/eap.c b/src/eap.c index d68ff451..5c05c615 100644 --- a/src/eap.c +++ b/src/eap.c @@ -87,7 +87,7 @@ void eap_set_event_func(struct eap_state *eap, eap_event_func_t func) void eap_free(struct eap_state *eap) { if (eap->method_state) - eap->method->remove(eap); + eap->method->free(eap); if (eap->identity) l_free(eap->identity); @@ -319,7 +319,7 @@ void eap_rx_packet(struct eap_state *eap, const uint8_t *pkt, size_t len) return; if (eap->method_state) - eap->method->remove(eap); + eap->method->free(eap); eap->method = NULL; @@ -351,7 +351,7 @@ bool eap_load_settings(struct eap_state *eap, struct l_settings *settings, entry = entry->next) { method = entry->data; - if (method->probe(eap, method_name) == 0) { + if (!strcasecmp(method_name, method->name)) { eap->method = method; break; @@ -387,8 +387,8 @@ bool eap_load_settings(struct eap_state *eap, struct l_settings *settings, return true; err: - if (eap->method->remove) - eap->method->remove(eap); + if (eap->method_state) + eap->method->free(eap); eap->method = NULL; diff --git a/src/eap.h b/src/eap.h index f64e0f7b..4f0b6a1e 100644 --- a/src/eap.h +++ b/src/eap.h @@ -93,12 +93,10 @@ struct eap_method { bool exports_msk; const char *name; - int (*probe)(struct eap_state *eap, const char *method_string); - void (*remove)(struct eap_state *eap); - bool (*load_settings)(struct eap_state *eap, struct l_settings *settings, const char *prefix); + void (*free)(struct eap_state *eap); void (*handle_request)(struct eap_state *eap, const uint8_t *pkt, size_t len);