From 60f1b4ccfb9158473e378678af627c20e80ec521 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 31 Aug 2016 16:33:19 +0200 Subject: [PATCH] Pre&post-processing of XML configuration introduced to allow draft-winter-opsawg-eap-metadata-02 compliant XML profiles on the outside, while maintaining internal simplicity --- lib/EAPBase/src/Config.cpp | 8 ++--- lib/TTLS/src/Config.cpp | 70 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/lib/EAPBase/src/Config.cpp b/lib/EAPBase/src/Config.cpp index 66e7309..28e7993 100644 --- a/lib/EAPBase/src/Config.cpp +++ b/lib/EAPBase/src/Config.cpp @@ -159,11 +159,11 @@ eap::config_method_with_cred::config_method_with_cred(_In_ const config_method_w eap::config_method_with_cred::config_method_with_cred(_Inout_ config_method_with_cred &&other) : - m_allow_save(std::move(other.m_allow_save)), + m_allow_save (std::move(other.m_allow_save )), m_use_preshared(std::move(other.m_use_preshared)), - m_preshared(std::move(other.m_preshared)), - m_auth_failed(std::move(other.m_auth_failed)), - config_method(std::move(other)) + m_preshared (std::move(other.m_preshared )), + m_auth_failed (std::move(other.m_auth_failed )), + config_method (std::move(other )) { } diff --git a/lib/TTLS/src/Config.cpp b/lib/TTLS/src/Config.cpp index 40690c1..8d6c0da 100644 --- a/lib/TTLS/src/Config.cpp +++ b/lib/TTLS/src/Config.cpp @@ -120,6 +120,39 @@ void eap::config_method_ttls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode // /... m_inner->save(pDoc, pXmlElInnerAuthenticationMethod); + + { + com_obj pXmlElClientSideCredential; + if (SUCCEEDED(hr = eapxml::select_node(pConfigRoot, bstr(L"eap-metadata:ClientSideCredential"), &pXmlElClientSideCredential))) { + // Fix 1: Pre-shared outer credentials in draft-winter-opsawg-eap-metadata has some bizarre presence/absence/blank logic for EAP-TTLS methods only. + // To keep our code clean, we do some post-processing, to make draft compliant XML on output, while keeping things simple on the inside. + if (m_use_preshared && m_preshared->empty()) { + // For empty pre-shared client certificate must not be present. + com_obj pXmlElClientCertificate; + if (SUCCEEDED(hr = eapxml::select_node(pXmlElClientSideCredential, bstr(L"eap-metadata:ClientCertificate"), &pXmlElClientCertificate))) { + com_obj pXmlElClientCertificateOld; + hr = pXmlElClientSideCredential->removeChild(pXmlElClientCertificate, &pXmlElClientCertificateOld); + } + } else if (!m_use_preshared) { + // When not using pre-shared (user must supply one), add empty . + com_obj pXmlElClientCertificate; + hr = eapxml::create_element(pDoc, pXmlElClientSideCredential, bstr(L"eap-metadata:ClientCertificate"), bstr(L"ClientCertificate"), namespace_eapmetadata, &pXmlElClientCertificate); + } + + // Fix 2: draft-winter-opsawg-eap-metadata is using name for when referring to outer identity of EAP-TTLS. + // GÉANTLink is using for identities and usernames uniformly. Create and remove . + com_obj pXmlElUserName; + if (SUCCEEDED(hr = eapxml::select_element(pXmlElClientSideCredential, bstr(L"eap-metadata:UserName"), &pXmlElUserName))) { + bstr identity; + if (SUCCEEDED(hr = pXmlElUserName->get_text(&identity))) { + if (SUCCEEDED(hr = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, bstr(L"OuterIdentity"), namespace_eapmetadata, identity))) { + com_obj pXmlElClientCertificateOld; + hr = pXmlElClientSideCredential->removeChild(pXmlElUserName, &pXmlElClientCertificateOld); + } + } + } + } + } } @@ -128,6 +161,43 @@ void eap::config_method_ttls::load(_In_ IXMLDOMNode *pConfigRoot) assert(pConfigRoot); HRESULT hr; + { + com_obj pXmlElClientSideCredential; + if (SUCCEEDED(hr = eapxml::select_node(pConfigRoot, bstr(L"eap-metadata:ClientSideCredential"), &pXmlElClientSideCredential))) { + com_obj pDoc; + if (SUCCEEDED(hr = pXmlElClientSideCredential->get_ownerDocument(&pDoc))) { + // Fix 1: Pre-shared outer credentials in draft-winter-opsawg-eap-metadata has some bizarre presence/absence/blank logic for EAP-TTLS methods only. + // To keep our code clean, we do some pre-processing, to accept draft compliant XML on input, while keeping things simple on the inside. + com_obj pXmlElClientCertificate; + if (SUCCEEDED(hr = eapxml::select_node(pXmlElClientSideCredential, bstr(L"eap-metadata:ClientCertificate"), &pXmlElClientCertificate))) { + VARIANT_BOOL has_children; + if (SUCCEEDED(hr = pXmlElClientCertificate->hasChildNodes(&has_children)) && !has_children) { + // Empty means: do not use pre-shared credentials. + com_obj pXmlElClientCertificateOld; + hr = pXmlElClientSideCredential->removeChild(pXmlElClientCertificate, &pXmlElClientCertificateOld); + } + } else { + // Nonexisting means: use blank pre-shared credentials. + com_obj pXmlElClientCertificate; + hr = eapxml::create_element(pDoc, pXmlElClientSideCredential, bstr(L"eap-metadata:ClientCertificate"), bstr(L"ClientCertificate"), namespace_eapmetadata, &pXmlElClientCertificate); + } + + // Fix 2: draft-winter-opsawg-eap-metadata is using name for when referring to outer identity of EAP-TTLS. + // GÉANTLink is using for identities and usernames uniformly. Create and remove . + com_obj pXmlElOuterIdentity; + if (SUCCEEDED(hr = eapxml::select_element(pXmlElClientSideCredential, bstr(L"eap-metadata:OuterIdentity"), &pXmlElOuterIdentity))) { + bstr identity; + if (SUCCEEDED(hr = pXmlElOuterIdentity->get_text(&identity))) { + if (SUCCEEDED(hr = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, bstr(L"UserName"), namespace_eapmetadata, identity))) { + com_obj pXmlElClientCertificateOld; + hr = pXmlElClientSideCredential->removeChild(pXmlElOuterIdentity, &pXmlElClientCertificateOld); + } + } + } + } + } + } + config_method_tls::load(pConfigRoot); std::wstring xpath(eapxml::get_xpath(pConfigRoot));