462 lines
17 KiB
C++
462 lines
17 KiB
C++
#include "pch.h"
|
|
#include "MainPage.xaml.h"
|
|
#if __has_include("MainPage.g.cpp")
|
|
#include "MainPage.g.cpp"
|
|
#include "App.xaml.h"
|
|
#include <ncrypt.h>
|
|
#include "Credential.h"
|
|
#endif
|
|
#include "PluginManagement/PluginRegistrationManager.h"
|
|
#include "PluginManagement/PluginCredentialManager.h"
|
|
#include <future>
|
|
#include <coroutine>
|
|
#include <DispatcherQueue.h>
|
|
|
|
namespace winrt {
|
|
using namespace winrt::Microsoft::UI::Xaml;
|
|
}
|
|
|
|
// To learn more about WinUI, the WinUI project structure,
|
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
|
|
|
namespace winrt::PasskeyManager::implementation
|
|
{
|
|
winrt::fire_and_forget MainPage::UpdatePluginEnableState()
|
|
{
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
auto hr = PluginRegistrationManager::getInstance().RefreshPluginState();
|
|
auto pluginState = PluginRegistrationManager::getInstance().GetPluginState();
|
|
bool vaultLocked = PluginCredentialManager::getInstance().GetVaultLock();
|
|
bool silentOperation = PluginCredentialManager::getInstance().GetSilentOperation();
|
|
co_await ui_thread;
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pluginStateRun().Text(L"Not Registered");
|
|
auto resources = Application::Current().Resources();
|
|
auto neutralBrush = resources.Lookup(winrt::box_value(L"SystemFillColorNeutralBrush")).as<winrt::Microsoft::UI::Xaml::Media::SolidColorBrush>();
|
|
pluginStateRun().Foreground(neutralBrush);
|
|
registerPluginButton().IsEnabled(true);
|
|
unregisterPluginButton().IsEnabled(false);
|
|
}
|
|
else
|
|
{
|
|
registerPluginButton().IsEnabled(false);
|
|
unregisterPluginButton().IsEnabled(true);
|
|
UpdatePluginStateTextBlock(pluginState);
|
|
vaultLockSwitch().IsOn(vaultLocked);
|
|
silentOperationSwitch().IsOn(silentOperation);
|
|
}
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::vaultLockSwitch_Toggled(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
auto toggleSwitch = sender.as<Microsoft::UI::Xaml::Controls::ToggleSwitch>();
|
|
bool toggleSwitchState = toggleSwitch.IsOn();
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
auto hr = PluginCredentialManager::getInstance().SetVaultLock(toggleSwitchState);
|
|
if (FAILED(hr))
|
|
{
|
|
co_await ui_thread;
|
|
LogFailure(L"Failed to change 'Simulate Vault Unlock'", hr);
|
|
}
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::silentOperationSwitch_Toggled(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
winrt::apartment_context ui_thread;
|
|
auto toggleSwitch = sender.as<Microsoft::UI::Xaml::Controls::ToggleSwitch>();
|
|
auto toggleSwitchState = toggleSwitch.IsOn();
|
|
co_await winrt::resume_background();
|
|
auto hr = PluginCredentialManager::getInstance().SetSilentOperation(toggleSwitchState);
|
|
if (FAILED(hr))
|
|
{
|
|
co_await ui_thread;
|
|
LogFailure(L"Failed to change 'Minimize UI'", hr);
|
|
}
|
|
co_return;
|
|
}
|
|
|
|
MainPage::MainPage()
|
|
{
|
|
m_credentialListViewModel = winrt::make<PasskeyManager::implementation::CredentialListViewModel>();
|
|
DataContext(m_credentialListViewModel);
|
|
auto weakThis = get_weak();
|
|
m_registryWatcher = wil::make_registry_watcher(
|
|
HKEY_CURRENT_USER,
|
|
c_pluginRegistryPath,
|
|
true,
|
|
[context = winrt::apartment_context{}, weakThis](wil::RegistryChangeKind changeKind) -> winrt::fire_and_forget {
|
|
auto weakThisCopy = weakThis;
|
|
auto contextCopy = context;
|
|
co_await contextCopy;
|
|
if (changeKind == wil::RegistryChangeKind::Modify)
|
|
{
|
|
PluginCredentialManager::getInstance().ReloadRegistryValues();
|
|
}
|
|
if (auto self{ weakThisCopy.get() })
|
|
{
|
|
self->UpdatePluginEnableState();
|
|
}
|
|
});
|
|
std::wstring mockDBfilePath;
|
|
PluginCredentialManager::getInstance().GetCredentialStorageFolderPath(mockDBfilePath);
|
|
THROW_IF_FAILED(m_mockCredentialsDBWatcher.create(mockDBfilePath.c_str(),
|
|
true,
|
|
wil::FolderChangeEvents::All,
|
|
[context = winrt::apartment_context{}, weakThis](wil::FolderChangeEvent, PCWSTR) -> winrt::fire_and_forget {
|
|
auto weakThisCopy = weakThis;
|
|
auto contextCopy = context;
|
|
co_await contextCopy;
|
|
PluginCredentialManager::getInstance().ReloadRegistryValues();
|
|
if (auto self{ weakThisCopy.get() })
|
|
{
|
|
self->UpdatePluginEnableState();
|
|
self->UpdateCredentialList();
|
|
}
|
|
}));
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::refreshButton_Click(IInspectable const&, RoutedEventArgs const&)
|
|
{
|
|
UpdatePluginEnableState();
|
|
UpdateCredentialList();
|
|
co_return;
|
|
}
|
|
|
|
winrt::fire_and_forget MainPage::UpdateCredentialList()
|
|
{
|
|
m_credentialListViewModel.credentials().Clear();
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
|
|
PluginCredentialManager& pluginCredentialManager = PluginCredentialManager::getInstance();
|
|
pluginCredentialManager.ReloadCredentialManager();
|
|
|
|
co_await ui_thread;
|
|
auto credentialViewList = pluginCredentialManager.GetCredentialListViewModel();
|
|
|
|
if (pluginCredentialManager.IsLocalCredentialMetadataLoaded())
|
|
{
|
|
std::wstring countOfLocalCreds = std::to_wstring(pluginCredentialManager.GetLocalCredentialCount()) + L" passkeys in Local DB";
|
|
credsStatsRun1().Text(countOfLocalCreds);
|
|
}
|
|
else
|
|
{
|
|
credsStatsRun1().Text(L"Local DB not loaded");
|
|
}
|
|
|
|
if (pluginCredentialManager.IsCachedCredentialsMetadataLoaded())
|
|
{
|
|
std::wstring countOfPluginCreds = std::to_wstring(pluginCredentialManager.GetCachedCredentialCount()) + L" passkeys in system Cache";
|
|
credsStatsRun2().Text(countOfPluginCreds);
|
|
}
|
|
else
|
|
{
|
|
credsStatsRun2().Text(L"Windows Cache Data not loaded");
|
|
}
|
|
|
|
m_credentialListViewModel.credentials().Clear();
|
|
for (auto credListItem : credentialViewList)
|
|
{
|
|
m_credentialListViewModel.credentials().Append(*credListItem.detach());
|
|
}
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::OnNavigatedTo(Navigation::NavigationEventArgs e)
|
|
{
|
|
UpdatePluginEnableState();
|
|
UpdateCredentialList();
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::unregisterPluginButton_Click(IInspectable const&, RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Unregistering plugin...");
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
HRESULT hr = PluginRegistrationManager::getInstance().UnregisterPlugin();
|
|
|
|
co_await ui_thread;
|
|
|
|
UpdatePluginEnableState();
|
|
if (FAILED(hr))
|
|
{
|
|
LogFailure(L"Failed to Unregister plugin: ", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"Plugin unregistered");
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::registerPluginButton_Click(IInspectable const&, RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Registering plugin...");
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
HRESULT hr = PluginRegistrationManager::getInstance().RegisterPlugin();
|
|
|
|
co_await ui_thread;
|
|
|
|
UpdatePluginEnableState();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LogFailure(L"WebAuthNPluginAddAuthenticator", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"Plugin registered");
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::addAllPluginCredentials_Click(IInspectable const&, RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Adding All credentials to windows...");
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
HRESULT hr = PluginCredentialManager::getInstance().AddAllPluginCredentials();
|
|
|
|
co_await ui_thread;
|
|
|
|
UpdateCredentialList();
|
|
if (FAILED(hr))
|
|
{
|
|
LogFailure(L"Failed to add credential to system cache: ", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"Credentials synced");
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::addSelectedCredentials_Click(IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Adding selected passkey metadata to system cache...");
|
|
|
|
std::vector<std::vector<UINT8>> credentialIdList;
|
|
auto selectedItems = credentialListView().SelectedItems();
|
|
if (selectedItems.Size() == 0)
|
|
{
|
|
LogWarning(L"No credentials selected", E_NOT_SET);
|
|
co_return;
|
|
}
|
|
|
|
for (auto item : selectedItems)
|
|
{
|
|
auto credential = item.as<PasskeyManager::implementation::Credential>();
|
|
auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(credential->CredentialId());
|
|
std::vector<UINT8> credentialIdToAdd(reader.UnconsumedBufferLength());
|
|
reader.ReadBytes(credentialIdToAdd);
|
|
credentialIdList.push_back(credentialIdToAdd);
|
|
}
|
|
|
|
hstring statusText = L"Adding " + winrt::to_hstring(credentialIdList.size()) + L" selected credentials...";
|
|
UpdatePasskeyOperationStatusText(statusText);
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
HRESULT hr = PluginCredentialManager::getInstance().AddPluginCredentialById(credentialIdList);
|
|
|
|
co_await ui_thread;
|
|
|
|
UpdateCredentialList();
|
|
if (FAILED(hr))
|
|
{
|
|
LogFailure(L"Failed to add credentials to system cache", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"Selected credentials are added to system cache");
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::deleteAllPluginCredentials_Click(IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Deleting all credentials stored on this device...");
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
HRESULT hr = PluginCredentialManager::getInstance().DeleteAllPluginCredentials();
|
|
|
|
co_await ui_thread;
|
|
|
|
UpdateCredentialList();
|
|
if (FAILED(hr))
|
|
{
|
|
LogFailure(L"Failed to delete credential from system cache", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"All credentials deleted from system cache");
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::deleteSelectedPluginCredentials_Click(IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Deleting selected credentials...");
|
|
|
|
// find the list of creds with checkbox checked
|
|
std::vector<std::vector<UINT8>> credentialIdList;
|
|
auto selectedItems = credentialListView().SelectedItems();
|
|
if (selectedItems.Size() == 0)
|
|
{
|
|
LogWarning(L"No credentials selected", E_NOT_SET);
|
|
co_return;
|
|
}
|
|
|
|
for (auto item : selectedItems)
|
|
{
|
|
auto credential = item.as<PasskeyManager::implementation::Credential>();
|
|
auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(credential->CredentialId());
|
|
std::vector<UINT8> credentialIdToDelete(reader.UnconsumedBufferLength());
|
|
reader.ReadBytes(credentialIdToDelete);
|
|
credentialIdList.push_back(credentialIdToDelete);
|
|
}
|
|
|
|
// update the status block with count of selected creds
|
|
hstring statusText = L"Deleting " + winrt::to_hstring(credentialIdList.size()) + L" selected credentials...";
|
|
UpdatePasskeyOperationStatusText(statusText);
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
HRESULT hr = PluginCredentialManager::getInstance().DeletePluginCredentialById(credentialIdList, false);
|
|
|
|
co_await ui_thread;
|
|
|
|
UpdateCredentialList();
|
|
if (FAILED(hr))
|
|
{
|
|
LogFailure(L"Failed to delete credentials from system cache", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"Selected credentials deleted from system cache");
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::deleteSelectedPluginCredentialsEverywhere_Click(IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Deleting selected credentials everywhere...");
|
|
|
|
// find the list of creds with checkbox checked
|
|
std::vector<std::vector<UINT8>> credentialIdList;
|
|
auto selectedItems = credentialListView().SelectedItems();
|
|
if (selectedItems.Size() == 0)
|
|
{
|
|
LogWarning(L"No credentials selected", E_NOT_SET);
|
|
co_return;
|
|
}
|
|
|
|
for (auto item : selectedItems)
|
|
{
|
|
auto credential = item.as<PasskeyManager::implementation::Credential>();
|
|
auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(credential->CredentialId());
|
|
std::vector<UINT8> credentialIdToDelete(reader.UnconsumedBufferLength());
|
|
reader.ReadBytes(credentialIdToDelete);
|
|
credentialIdList.push_back(credentialIdToDelete);
|
|
}
|
|
|
|
// update the status block with count of selected creds
|
|
hstring statusText = winrt::to_hstring(credentialIdList.size()) + L" credentials selected...";
|
|
UpdatePasskeyOperationStatusText(statusText);
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
HRESULT hr = PluginCredentialManager::getInstance().DeletePluginCredentialById(credentialIdList, true);
|
|
|
|
co_await ui_thread;
|
|
|
|
UpdateCredentialList();
|
|
if (FAILED(hr))
|
|
{
|
|
LogFailure(L"Failed to delete credentials", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"Selected credentials deleted everywhere");
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::clearLogsButton_Click(IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
textContent().Inlines().Clear();
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::deleteAllLocalCredentials_Click(IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Deleting all local credentials...");
|
|
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
|
|
bool resetResult = PluginCredentialManager::getInstance().ResetLocalCredentialsStore();
|
|
|
|
co_await ui_thread;
|
|
UpdateCredentialList();
|
|
if (resetResult)
|
|
{
|
|
LogFailure(L"Failed to delete all local credentials", E_FAIL);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"All local credentials deleted");
|
|
co_return;
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::deleteAllCredentials_Click(IInspectable const&, Microsoft::UI::Xaml::RoutedEventArgs const&)
|
|
{
|
|
LogInProgress(L"Deleting all credentials stored on this device and cache...");
|
|
winrt::apartment_context ui_thread;
|
|
co_await winrt::resume_background();
|
|
auto& credManager = PluginCredentialManager::getInstance();
|
|
HRESULT hr = credManager.DeleteAllPluginCredentials();
|
|
bool resetResult = credManager.ResetLocalCredentialsStore();
|
|
co_await ui_thread;
|
|
|
|
UpdateCredentialList();
|
|
if (FAILED(hr) || !resetResult)
|
|
{
|
|
LogFailure(L"Failed to delete all credentials", hr);
|
|
co_return;
|
|
}
|
|
LogSuccess(L"All credentials deleted");
|
|
}
|
|
|
|
void MainPage::UpdatePluginStateTextBlock(EXPERIMENTAL_PLUGIN_AUTHENTICATOR_STATE state)
|
|
{
|
|
auto resources = Application::Current().Resources();
|
|
auto successBrush = resources.Lookup(winrt::box_value(L"SystemFillColorSuccessBrush")).as<winrt::Microsoft::UI::Xaml::Media::SolidColorBrush>();
|
|
auto criticalBrush = resources.Lookup(winrt::box_value(L"SystemFillColorCriticalBrush")).as<winrt::Microsoft::UI::Xaml::Media::SolidColorBrush>();
|
|
auto cautionBrush = resources.Lookup(winrt::box_value(L"SystemFillColorCautionBrush")).as<winrt::Microsoft::UI::Xaml::Media::SolidColorBrush>();
|
|
|
|
switch (state)
|
|
{
|
|
case PluginAuthenticatorState_Enabled:
|
|
pluginStateRun().Text(L"Enabled");
|
|
pluginStateRun().Foreground(successBrush);
|
|
break;
|
|
case PluginAuthenticatorState_Disabled:
|
|
pluginStateRun().Text(L"Disabled");
|
|
pluginStateRun().Foreground(criticalBrush);
|
|
break;
|
|
case PluginAuthenticatorState_Unknown:
|
|
[[fallthrough]];
|
|
default:
|
|
pluginStateRun().Text(L"Unknown");
|
|
pluginStateRun().Foreground(cautionBrush);
|
|
break;
|
|
}
|
|
}
|
|
|
|
winrt::IAsyncAction MainPage::SelectionChanged(IInspectable const& sender, Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
|
|
{
|
|
Microsoft::UI::Xaml::Controls::ListView listView = sender.as<Microsoft::UI::Xaml::Controls::ListView>();
|
|
auto selected = listView.SelectedItems().Size() > 0;
|
|
selectedAddButton().IsEnabled(selected);
|
|
deleteSelectedCacheButton().IsEnabled(selected);
|
|
deleteSelectedLocalButton().IsEnabled(selected);
|
|
co_return;
|
|
}
|
|
}
|