diff --git a/lib/TTLS_UI/src/Module.cpp b/lib/TTLS_UI/src/Module.cpp index 6a66d74..4ae6ab4 100644 --- a/lib/TTLS_UI/src/Module.cpp +++ b/lib/TTLS_UI/src/Module.cpp @@ -117,21 +117,16 @@ void eap::peer_ttls_ui::invoke_config_ui( // This is a blank network profile. `cfg` is already set to defaults. } - int result; - { - // Initialize application. - wxInitializerPeer init(m_instance, hwndParent); + // Initialize application. + wxInitializerPeer init(m_instance, hwndParent); - // Create and launch configuration dialog. - wxEAPConfigDialog dlg(cfg, init.m_parent); - if (!init.m_parent) { - FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; - ::FlashWindowEx(&fwi); - } - result = dlg.ShowModal(); + // Create and launch configuration dialog. + wxEAPConfigDialog dlg(cfg, init.m_parent); + if (!init.m_parent) { + FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; + ::FlashWindowEx(&fwi); } - - if (result != wxID_OK) + if (dlg.ShowModal() != wxID_OK) throw win_runtime_error(ERROR_CANCELLED, __FUNCTION__ " Cancelled."); // Pack new configuration. @@ -150,9 +145,6 @@ void eap::peer_ttls_ui::invoke_identity_ui( _Out_ DWORD *pdwUserDataOutSize, _Out_ LPWSTR *ppwszIdentity) { -#ifdef _DEBUG - //::Sleep(10000); -#endif assert(ppwszIdentity); // Unpack configuration. @@ -173,14 +165,149 @@ void eap::peer_ttls_ui::invoke_identity_ui( config_provider *cfg_prov = NULL; config_method_ttls *cfg_method = NULL; - int result; - { - // Initialize application. - wxInitializerPeer init(m_instance, hwndParent); + // Initialize application. + wxInitializerPeer init(m_instance, hwndParent); - if (cfg.m_providers.size() > 1) { - // Multiple identity providers: User has to select one first. - wxEAPProviderSelectDialog dlg(cfg, init.m_parent); + if (cfg.m_providers.size() > 1) { + // Multiple identity providers: User has to select one first. + wxEAPProviderSelectDialog dlg(cfg, init.m_parent); + + // Centre and display dialog. + dlg.Centre(wxBOTH); + if (!init.m_parent) { + FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; + ::FlashWindowEx(&fwi); + } + if (dlg.ShowModal() != wxID_OK) + throw win_runtime_error(ERROR_CANCELLED, __FUNCTION__ " Cancelled."); + + cfg_prov = dlg.GetSelection(); + assert(cfg_prov); + } else if (!cfg.m_providers.empty()) { + // Single identity provider. No need to ask user to select one. + cfg_prov = &cfg.m_providers.front(); + } else { + // No identity provider. Bail out. + throw invalid_argument(__FUNCTION__ " Configuration has no identity providers."); + } + + // The identity provider is selected. + assert(cfg_prov); + cfg_method = dynamic_cast(cfg_prov->m_methods.front().get()); + assert(cfg_method); + + // Configure output credentials. + cred_out.m_namespace = cfg_prov->m_namespace; + cred_out.m_id = cfg_prov->m_id; + auto cred = dynamic_cast(cfg_method->make_credentials()); + cred_out.m_cred.reset(cred); +#if EAP_USE_NATIVE_CREDENTIAL_CACHE + bool has_cached = cred_in.m_cred && cred_in.match(*cfg_prov); +#endif + + if (dwFlags & EAP_FLAG_GUEST_ACCESS) { + // Disable credential saving for guests. + cfg_method-> m_allow_save = false; + cfg_method->m_inner->m_allow_save = false; + } + + // Combine outer credentials. + wstring target_name(std::move(cfg_prov->get_id())); + eap::credentials::source_t src_outer = cred->credentials_tls::combine( + dwFlags, + NULL, +#if EAP_USE_NATIVE_CREDENTIAL_CACHE + has_cached ? cred_in.m_cred.get() : NULL, +#else + NULL, +#endif + *cfg_method, + cfg_method->m_allow_save ? target_name.c_str() : NULL); + if (src_outer == eap::credentials::source_unknown || + src_outer != eap::credentials::source_config && eap::config_method::status_cred_begin <= cfg_method->m_last_status && cfg_method->m_last_status < eap::config_method::status_cred_end) + { + // Build dialog to prompt for outer credentials. + wxEAPCredentialsDialog dlg(*cfg_prov, init.m_parent); + if (eap::config_method::status_cred_begin <= cfg_method->m_last_status && cfg_method->m_last_status < eap::config_method::status_cred_end) + dlg.AddContent(new wxEAPCredentialWarningPanel(*cfg_prov, cfg_method->m_last_status, &dlg)); + auto panel = new wxTLSCredentialsPanel(*cfg_prov, *cfg_method, *cred, &dlg, false); + panel->SetRemember(src_outer == eap::credentials::source_storage); + dlg.AddContent(panel); + + // Update dialog layout. + dlg.Layout(); + dlg.GetSizer()->Fit(&dlg); + + // Centre and display dialog. + dlg.Centre(wxBOTH); + if (!init.m_parent) { + FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; + ::FlashWindowEx(&fwi); + } + if (dlg.ShowModal() != wxID_OK) + throw win_runtime_error(ERROR_CANCELLED, __FUNCTION__ " Cancelled."); + + if (panel->GetRemember()) { + // Write credentials to credential manager. + try { + cred->credentials_tls::store(target_name.c_str(), 0); + } catch (winstd::win_runtime_error &err) { + wxLogError(winstd::tstring_printf(_("Error writing credentials to Credential Manager: %hs (error %u)"), err.what(), err.number()).c_str()); + } catch (...) { + wxLogError(_("Writing credentials failed.")); + } + } + } + + // Combine inner credentials. + eap::credentials::source_t src_inner = cred->m_inner->combine( + dwFlags, + NULL, +#if EAP_USE_NATIVE_CREDENTIAL_CACHE + has_cached ? dynamic_cast(cred_in.m_cred.get())->m_inner.get() : NULL, +#else + NULL, +#endif + *cfg_method->m_inner, + cfg_method->m_inner->m_allow_save ? target_name.c_str() : NULL); + if (src_inner == eap::credentials::source_unknown || + src_inner != eap::credentials::source_config && eap::config_method::status_cred_begin <= cfg_method->m_inner->m_last_status && cfg_method->m_inner->m_last_status < eap::config_method::status_cred_end) + { + // Prompt for inner credentials. +#if EAP_INNER_EAPHOST + auto cfg_inner_eaphost = dynamic_cast(cfg_method->m_inner.get()); + if (!cfg_inner_eaphost) +#endif + { + // Native inner methods. Build dialog to prompt for inner credentials. + wxEAPCredentialsDialog dlg(*cfg_prov, init.m_parent); + if (eap::config_method::status_cred_begin <= cfg_method->m_inner->m_last_status && cfg_method->m_inner->m_last_status < eap::config_method::status_cred_end) + dlg.AddContent(new wxEAPCredentialWarningPanel(*cfg_prov, cfg_method->m_inner->m_last_status, &dlg)); + wxEAPCredentialsPanelBase *panel = NULL; + switch (cfg_method->m_inner->get_method_id()) { + case eap_type_legacy_pap : panel = new wxPAPCredentialsPanel (*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *dynamic_cast(cred->m_inner.get()), &dlg, false); break; + case eap_type_legacy_mschapv2: panel = new wxMSCHAPv2CredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *dynamic_cast(cred->m_inner.get()), &dlg, false); break; + case eap_type_mschapv2 : panel = new wxMSCHAPv2CredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *dynamic_cast(cred->m_inner.get()), &dlg, false); break; + case eap_type_gtc : { + // EAP-GTC credential prompt differes for "Challenge/Response" and "Password" authentication modes. + eap::credentials_identity *cred_resp; + eap::credentials_pass *cred_pass; + if ((cred_resp = dynamic_cast(cred->m_inner.get())) != NULL) + panel = new wxGTCResponseCredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *cred_resp, &dlg, false); + else if ((cred_pass = dynamic_cast(cred->m_inner.get())) != NULL) + panel = new wxGTCPasswordCredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *cred_pass, &dlg, false); + else + wxLogError("Unsupported authentication mode."); + break; + } + default : wxLogError("Unsupported inner authentication method."); + } + panel->SetRemember(src_inner == eap::credentials::source_storage); + dlg.AddContent(panel); + + // Update dialog layout. + dlg.Layout(); + dlg.GetSizer()->Fit(&dlg); // Centre and display dialog. dlg.Centre(wxBOTH); @@ -188,202 +315,61 @@ void eap::peer_ttls_ui::invoke_identity_ui( FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; ::FlashWindowEx(&fwi); } - if ((result = dlg.ShowModal()) == wxID_OK) { - cfg_prov = dlg.GetSelection(); - assert(cfg_prov); + if (dlg.ShowModal() != wxID_OK) + throw win_runtime_error(ERROR_CANCELLED, __FUNCTION__ " Cancelled."); + + // Write credentials to credential manager. + if (panel->GetRemember()) { + try { + cred->m_inner->store(target_name.c_str(), 1); + } catch (winstd::win_runtime_error &err) { + wxLogError(winstd::tstring_printf(_("Error writing credentials to Credential Manager: %hs (error %u)"), err.what(), err.number()).c_str()); + } catch (...) { + wxLogError(_("Writing credentials failed.")); + } } - } else if (!cfg.m_providers.empty()) { - // Single identity provider. No need to ask user to select one. - result = wxID_OK; - cfg_prov = &cfg.m_providers.front(); - } else { - // No identity provider. Bail out. - result = wxID_CANCEL; } - - if (cfg_prov) { - // The identity provider is selected. - cfg_method = dynamic_cast(cfg_prov->m_methods.front().get()); - assert(cfg_method); - - // Configure output credentials. - cred_out.m_namespace = cfg_prov->m_namespace; - cred_out.m_id = cfg_prov->m_id; - auto cred = dynamic_cast(cfg_method->make_credentials()); - cred_out.m_cred.reset(cred); -#if EAP_USE_NATIVE_CREDENTIAL_CACHE - bool has_cached = cred_in.m_cred && cred_in.match(*cfg_prov); -#endif - - if (dwFlags & EAP_FLAG_GUEST_ACCESS) { - // Disable credential saving for guests. - cfg_method-> m_allow_save = false; - cfg_method->m_inner->m_allow_save = false; - } - - // Combine outer credentials. - wstring target_name(std::move(cfg_prov->get_id())); - eap::credentials::source_t src_outer = cred->credentials_tls::combine( +#if EAP_INNER_EAPHOST + else { + // EapHost inner method + auto cred_inner = dynamic_cast(cred->m_inner.get()); + DWORD cred_data_size = 0; + winstd::eap_blob cred_data; + unique_ptr identity; + winstd::eap_error error; + DWORD dwResult = EapHostPeerInvokeIdentityUI( + 0, + cfg_inner_eaphost->get_type(), dwFlags, - NULL, -#if EAP_USE_NATIVE_CREDENTIAL_CACHE - has_cached ? cred_in.m_cred.get() : NULL, -#else - NULL, -#endif - *cfg_method, - cfg_method->m_allow_save ? target_name.c_str() : NULL); - if (src_outer == eap::credentials::source_unknown || - src_outer != eap::credentials::source_config && eap::config_method::status_cred_begin <= cfg_method->m_last_status && cfg_method->m_last_status < eap::config_method::status_cred_end) - { - // Build dialog to prompt for outer credentials. - wxEAPCredentialsDialog dlg(*cfg_prov, init.m_parent); - if (eap::config_method::status_cred_begin <= cfg_method->m_last_status && cfg_method->m_last_status < eap::config_method::status_cred_end) - dlg.AddContent(new wxEAPCredentialWarningPanel(*cfg_prov, cfg_method->m_last_status, &dlg)); - auto panel = new wxTLSCredentialsPanel(*cfg_prov, *cfg_method, *cred, &dlg, false); - panel->SetRemember(src_outer == eap::credentials::source_storage); - dlg.AddContent(panel); + hwndParent, + (DWORD)cfg_inner_eaphost->m_cfg_blob.size(), cfg_inner_eaphost->m_cfg_blob.data(), + (DWORD)cred_inner->m_cred_blob.size(), cred_inner->m_cred_blob.data(), + &cred_data_size, get_ptr(cred_data), + get_ptr(identity), + get_ptr(error), + NULL); + if (dwResult == ERROR_SUCCESS) { + // Inner EAP method provided credentials. + cred_inner->m_identity = identity.get(); + BYTE *_cred_data = cred_data.get(); + cred_inner->m_cred_blob.assign(_cred_data, _cred_data + cred_data_size); + SecureZeroMemory(_cred_data, cred_data_size); - // Update dialog layout. - dlg.Layout(); - dlg.GetSizer()->Fit(&dlg); - - // Centre and display dialog. - dlg.Centre(wxBOTH); - if (!init.m_parent) { - FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; - ::FlashWindowEx(&fwi); - } - if ((result = dlg.ShowModal()) == wxID_OK) { - if (panel->GetRemember()) { - // Write credentials to credential manager. - try { - cred->credentials_tls::store(target_name.c_str(), 0); - } catch (winstd::win_runtime_error &err) { - wxLogError(winstd::tstring_printf(_("Error writing credentials to Credential Manager: %hs (error %u)"), err.what(), err.number()).c_str()); - } catch (...) { - wxLogError(_("Writing credentials failed.")); - } - } - } - } else - result = wxID_OK; - - if (result == wxID_OK) { - // Combine inner credentials. - eap::credentials::source_t src_inner = cred->m_inner->combine( - dwFlags, - NULL, -#if EAP_USE_NATIVE_CREDENTIAL_CACHE - has_cached ? dynamic_cast(cred_in.m_cred.get())->m_inner.get() : NULL, -#else - NULL, -#endif - *cfg_method->m_inner, - cfg_method->m_inner->m_allow_save ? target_name.c_str() : NULL); - if (src_inner == eap::credentials::source_unknown || - src_inner != eap::credentials::source_config && eap::config_method::status_cred_begin <= cfg_method->m_inner->m_last_status && cfg_method->m_inner->m_last_status < eap::config_method::status_cred_end) - { - // Prompt for inner credentials. -#if EAP_INNER_EAPHOST - auto cfg_inner_eaphost = dynamic_cast(cfg_method->m_inner.get()); - if (!cfg_inner_eaphost) -#endif - { - // Native inner methods. Build dialog to prompt for inner credentials. - wxEAPCredentialsDialog dlg(*cfg_prov, init.m_parent); - if (eap::config_method::status_cred_begin <= cfg_method->m_inner->m_last_status && cfg_method->m_inner->m_last_status < eap::config_method::status_cred_end) - dlg.AddContent(new wxEAPCredentialWarningPanel(*cfg_prov, cfg_method->m_inner->m_last_status, &dlg)); - wxEAPCredentialsPanelBase *panel = NULL; - switch (cfg_method->m_inner->get_method_id()) { - case eap_type_legacy_pap : panel = new wxPAPCredentialsPanel (*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *dynamic_cast(cred->m_inner.get()), &dlg, false); break; - case eap_type_legacy_mschapv2: panel = new wxMSCHAPv2CredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *dynamic_cast(cred->m_inner.get()), &dlg, false); break; - case eap_type_mschapv2 : panel = new wxMSCHAPv2CredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *dynamic_cast(cred->m_inner.get()), &dlg, false); break; - case eap_type_gtc : { - // EAP-GTC credential prompt differes for "Challenge/Response" and "Password" authentication modes. - eap::credentials_identity *cred_resp; - eap::credentials_pass *cred_pass; - if ((cred_resp = dynamic_cast(cred->m_inner.get())) != NULL) - panel = new wxGTCResponseCredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *cred_resp, &dlg, false); - else if ((cred_pass = dynamic_cast(cred->m_inner.get())) != NULL) - panel = new wxGTCPasswordCredentialsPanel(*cfg_prov, *dynamic_cast(cfg_method->m_inner.get()), *cred_pass, &dlg, false); - else - wxLogError("Unsupported authentication mode."); - break; - } - default : wxLogError("Unsupported inner authentication method."); - } - panel->SetRemember(src_inner == eap::credentials::source_storage); - dlg.AddContent(panel); - - // Update dialog layout. - dlg.Layout(); - dlg.GetSizer()->Fit(&dlg); - - // Centre and display dialog. - dlg.Centre(wxBOTH); - if (!init.m_parent) { - FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; - ::FlashWindowEx(&fwi); - } - if ((result = dlg.ShowModal()) == wxID_OK) { - // Write credentials to credential manager. - if (panel->GetRemember()) { - try { - cred->m_inner->store(target_name.c_str(), 1); - } catch (winstd::win_runtime_error &err) { - wxLogError(winstd::tstring_printf(_("Error writing credentials to Credential Manager: %hs (error %u)"), err.what(), err.number()).c_str()); - } catch (...) { - wxLogError(_("Writing credentials failed.")); - } - } - } - } -#if EAP_INNER_EAPHOST - else { - // EapHost inner method - auto cred_inner = dynamic_cast(cred->m_inner.get()); - DWORD cred_data_size = 0; - winstd::eap_blob cred_data; - unique_ptr identity; - winstd::eap_error error; - DWORD dwResult = EapHostPeerInvokeIdentityUI( - 0, - cfg_inner_eaphost->get_type(), - dwFlags, - hwndParent, - (DWORD)cfg_inner_eaphost->m_cfg_blob.size(), cfg_inner_eaphost->m_cfg_blob.data(), - (DWORD)cred_inner->m_cred_blob.size(), cred_inner->m_cred_blob.data(), - &cred_data_size, get_ptr(cred_data), - get_ptr(identity), - get_ptr(error), - NULL); - result = dwResult == ERROR_SUCCESS ? wxID_OK : wxID_CANCEL; - if (dwResult == ERROR_SUCCESS) { - // Inner EAP method provided credentials. - cred_inner->m_identity = identity.get(); - BYTE *_cred_data = cred_data.get(); - cred_inner->m_cred_blob.assign(_cred_data, _cred_data + cred_data_size); - SecureZeroMemory(_cred_data, cred_data_size); - - // TODO: If we ever choose to store EapHost credentials to Windows Credential Manager, add a "Save credentials? Yes/No" prompt here and write them to Credential Manager. - } else if (dwResult == ERROR_CANCELLED) { - // Not really an error. - } else if (error) - wxLogError(_("Invoking EAP identity UI failed (error %u, %s, %s)."), error->dwWinError, error->pRootCauseString, error->pRepairString); - else - wxLogError(_("Invoking EAP identity UI failed (error %u)."), dwResult); - } -#endif - } else - result = wxID_OK; + // TODO: If we ever choose to store EapHost credentials to Windows Credential Manager, add a "Save credentials? Yes/No" prompt here and write them to Credential Manager. + } else if (dwResult == ERROR_CANCELLED) { + // Not really an error. + throw win_runtime_error(ERROR_CANCELLED, __FUNCTION__ " Cancelled."); + } else if (error) { + wxLogError(_("Invoking EAP identity UI failed (error %u, %s, %s)."), error->dwWinError, error->pRootCauseString, error->pRepairString); + throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerInvokeIdentityUI failed."); + } else { + wxLogError(_("Invoking EAP identity UI failed (error %u)."), dwResult); + throw win_runtime_error(dwResult, __FUNCTION__ " EapHostPeerInvokeIdentityUI failed."); } } +#endif } - if (result != wxID_OK) - throw win_runtime_error(ERROR_CANCELLED, __FUNCTION__ " Cancelled."); - // Build our identity. ;) wstring identity(std::move(cfg_method->get_public_identity(*dynamic_cast(cred_out.m_cred.get())))); log_event(&EAPMETHOD_TRACE_EVT_CRED_OUTER_ID1, event_data((unsigned int)eap_type_ttls), event_data(identity), event_data::blank); @@ -431,40 +417,35 @@ void eap::peer_ttls_ui::invoke_interactive_ui( if (!cfg_inner_eaphost) #endif { - int result; - { - // Initialize application. - wxInitializerPeer init(m_instance, hwndParent); + // Initialize application. + wxInitializerPeer init(m_instance, hwndParent); - sanitizing_wstring - challenge(reinterpret_cast(ctx.m_data.data()), ctx.m_data.size()/sizeof(sanitizing_wstring::value_type)), - response; + sanitizing_wstring + challenge(reinterpret_cast(ctx.m_data.data()), ctx.m_data.size()/sizeof(sanitizing_wstring::value_type)), + response; - // Build dialog to prompt for response. - wxGTCResponseDialog dlg(*cfg_prov, init.m_parent); - auto panel = new wxGTCResponsePanel(response, challenge.c_str(), &dlg); - dlg.AddContent(panel); + // Build dialog to prompt for response. + wxGTCResponseDialog dlg(*cfg_prov, init.m_parent); + auto panel = new wxGTCResponsePanel(response, challenge.c_str(), &dlg); + dlg.AddContent(panel); - // Update dialog layout. - dlg.Layout(); - dlg.GetSizer()->Fit(&dlg); + // Update dialog layout. + dlg.Layout(); + dlg.GetSizer()->Fit(&dlg); - // Centre and display dialog. - dlg.Centre(wxBOTH); - if (!init.m_parent) { - FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; - ::FlashWindowEx(&fwi); - } - if ((result = dlg.ShowModal()) == wxID_OK) { - // Save response. - ctx.m_data.assign( - reinterpret_cast(response.data() ), - reinterpret_cast(response.data() + response.length())); - } + // Centre and display dialog. + dlg.Centre(wxBOTH); + if (!init.m_parent) { + FLASHWINFO fwi = { sizeof(FLASHWINFO), dlg.GetHWND(), FLASHW_ALL | FLASHW_TIMERNOFG }; + ::FlashWindowEx(&fwi); } - - if (result != wxID_OK) + if (dlg.ShowModal() != wxID_OK) throw win_runtime_error(ERROR_CANCELLED, __FUNCTION__ " Cancelled."); + + // Save response. + ctx.m_data.assign( + reinterpret_cast(response.data() ), + reinterpret_cast(response.data() + response.length())); } #if EAP_INNER_EAPHOST else {