From d27b0d5b1e98ae5bcb673cfb055530e09ac918b4 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Wed, 18 Apr 2018 07:03:26 +0200 Subject: [PATCH] eap-ttls: Implement .check_settings Confirm that the PEM file paths that we'll be passing to the l_tls object are loading Ok and request/validate the private key passphrase if needed. Then also call eap_check_settings to validate the inner method's settings. --- src/eap-ttls.c | 121 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 10 deletions(-) diff --git a/src/eap-ttls.c b/src/eap-ttls.c index 9c66487b..d9c9b5f6 100644 --- a/src/eap-ttls.c +++ b/src/eap-ttls.c @@ -630,6 +630,116 @@ err: eap_method_error(eap); } +static bool eap_ttls_check_settings(struct l_settings *settings, + struct l_queue *secrets, + const char *prefix, + struct l_queue **out_missing) +{ + char setting[64], client_cert_setting[64], passphrase_setting[64]; + const char *path, *client_cert, *passphrase; + uint8_t *cert; + size_t size; + + snprintf(setting, sizeof(setting), "%sTTLS-CACert", prefix); + path = l_settings_get_value(settings, "Security", setting); + if (path) { + cert = l_pem_load_certificate(path, &size); + if (!cert) { + l_error("Failed to load %s", path); + return false; + } + + l_free(cert); + } + + snprintf(client_cert_setting, sizeof(client_cert_setting), + "%sTTLS-ClientCert", prefix); + client_cert = l_settings_get_value(settings, "Security", + client_cert_setting); + if (client_cert) { + cert = l_pem_load_certificate(client_cert, &size); + if (!cert) { + l_error("Failed to load %s", client_cert); + return false; + } + + l_free(cert); + } + + snprintf(setting, sizeof(setting), "%sTTLS-ClientKey", prefix); + path = l_settings_get_value(settings, "Security", setting); + + if (path && !client_cert) { + l_error("%s present but no client certificate (%s)", + setting, client_cert_setting); + return false; + } + + snprintf(passphrase_setting, sizeof(passphrase_setting), + "%sTTLS-ClientKeyPassphrase", prefix); + passphrase = l_settings_get_value(settings, "Security", + passphrase_setting); + + if (!passphrase) { + const struct eap_secret_info *secret; + + secret = l_queue_find(secrets, eap_secret_info_match, + passphrase_setting); + if (secret) + passphrase = secret->value; + } + + if (path) { + bool encrypted; + uint8_t *priv_key; + size_t size; + + priv_key = l_pem_load_private_key(path, passphrase, + &encrypted, &size); + if (!priv_key) { + if (!encrypted) { + l_error("Error loading client private key %s", + path); + return false; + } + + if (passphrase) { + l_error("Error loading encrypted client " + "private key %s", path); + return false; + } + + /* + * We've got an encrypted key and passphrase was not + * saved in the network settings, need to request + * the passphrase. + */ + eap_append_secret(out_missing, + EAP_SECRET_LOCAL_PKEY_PASSPHRASE, + passphrase_setting, path); + } else { + memset(priv_key, 0, size); + l_free(priv_key); + + if (passphrase && !encrypted) { + l_error("%s present but client private " + "key %s is not encrypted", + passphrase_setting, path); + return false; + } + } + } else if (passphrase) { + l_error("%s present but no client private key path set (%s)", + passphrase_setting, setting); + return false; + } + + snprintf(setting, sizeof(setting), "%sTTLS-Phase2-", prefix); + + return eap_check_settings(settings, secrets, setting, false, + out_missing); +} + static bool eap_ttls_load_settings(struct eap_state *eap, struct l_settings *settings, const char *prefix) @@ -656,16 +766,6 @@ static bool eap_ttls_load_settings(struct eap_state *eap, ttls->passphrase = l_strdup(l_settings_get_value(settings, "Security", setting)); - if (!ttls->client_cert && ttls->client_key) { - l_error("Client key present but no client certificate"); - goto err; - } - - if (!ttls->client_key && ttls->passphrase) { - l_error("Passphrase present but no client private key"); - goto err; - } - ttls->eap = eap_new(eap_ttls_eap_tx_packet, eap_ttls_eap_complete, eap); if (!ttls->eap) { @@ -701,6 +801,7 @@ static struct eap_method eap_ttls = { .free = eap_ttls_free, .handle_request = eap_ttls_handle_request, + .check_settings = eap_ttls_check_settings, .load_settings = eap_ttls_load_settings, };