From 3b2b194170c0b95991c8f8bf497ce1372173fee0 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Wed, 18 Apr 2018 07:03:24 +0200 Subject: [PATCH] eap-mschapv2: Implement .check_settings Move the settings validation from .load_settings plus allow the username/password to be supplied in the secrets l_queue instead of in the l_settings. --- src/eap-mschapv2.c | 97 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/src/eap-mschapv2.c b/src/eap-mschapv2.c index 63178f44..945187b3 100644 --- a/src/eap-mschapv2.c +++ b/src/eap-mschapv2.c @@ -641,6 +641,84 @@ static void set_user_name(struct eap_mschapv2_state *state, const char *user) state->user = l_strdup(user); } +static bool eap_mschapv2_check_settings(struct l_settings *settings, + struct l_queue *secrets, + const char *prefix, + struct l_queue **out_missing) +{ + const char *identity, *password = NULL, *password_hash; + const struct eap_secret_info *secret; + char setting[64], setting2[64]; + uint8_t hash[16]; + + snprintf(setting, sizeof(setting), "%sIdentity", prefix); + identity = l_settings_get_value(settings, "Security", setting); + + if (!identity) { + secret = l_queue_find(secrets, eap_secret_info_match, setting); + if (secret) { + identity = secret->value; + password = secret->value + strlen(secret->value); + + goto validate; + } + + eap_append_secret(out_missing, EAP_SECRET_REMOTE_USER_PASSWORD, + setting, NULL); + return true; + } + + snprintf(setting, sizeof(setting), "%sPassword-Hash", prefix); + password_hash = l_settings_get_value(settings, "Security", + setting); + + snprintf(setting2, sizeof(setting2), "%sPassword", prefix); + password = l_settings_get_value(settings, "Security", setting2); + + if (password && password_hash) { + l_error("Exactly one of (%s, %s) must be present", + setting, setting2); + return false; + } + + if (password_hash) { + unsigned char *tmp; + size_t len; + + tmp = l_util_from_hexstring(password, &len); + l_free(tmp); + + if (!tmp || len != 16) { + l_error("Property %s is not a 16-byte hexstring", + setting); + return false; + } + + return true; + } else if (password) + goto validate; + + secret = l_queue_find(secrets, eap_secret_info_match, setting2); + if (!secret) { + eap_append_secret(out_missing, EAP_SECRET_REMOTE_PASSWORD, + setting2, identity); + return true; + } + + password = secret->value; + +validate: + if (!l_utf8_validate(password, strlen(password), NULL)) { + l_error("Password is not valid UTF-8"); + return false; + } + + if (!mschapv2_nt_password_hash(password, hash)) + return false; + + return true; +} + static bool eap_mschapv2_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) @@ -655,9 +733,6 @@ static bool eap_mschapv2_load_settings(struct eap_state *eap, set_user_name(state, l_settings_get_value(settings, "Security", setting)); - if (!state->user) - goto err; - state->user_len = strlen(state->user); /* Either read the password-hash from hexdump or password and hash it */ @@ -668,31 +743,18 @@ static bool eap_mschapv2_load_settings(struct eap_state *eap, size_t len; tmp = l_util_from_hexstring(password, &len); - if (len != 16) { - l_error("Read an impossible password hash"); - l_free(tmp); - goto err; - } - memcpy(state->password_hash, tmp, 16); l_free(tmp); } else { snprintf(setting, sizeof(setting), "%sPassword", prefix); password = l_settings_get_value(settings, "Security", setting); - if (!password || !set_password_from_string(state, password)) - goto err; + set_password_from_string(state, password); } eap_set_data(eap, state); return true; - -err: - l_free(state->user); - l_free(state); - - return false; } static struct eap_method eap_mschapv2 = { @@ -702,6 +764,7 @@ static struct eap_method eap_mschapv2 = { .free = eap_mschapv2_free, .handle_request = eap_mschapv2_handle_request, + .check_settings = eap_mschapv2_check_settings, .load_settings = eap_mschapv2_load_settings, };