mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-12-04 15:39:34 +01:00
Passkeys improvements (#10318)
Refactors the Passkey implementation to include more checks and a structure that is more aligned with the official specification. Notable changes: - _BrowserService_ no longer does the checks by itself. A new class _BrowserPasskeysClient_ constructs the relevant objects, acting as a client. _BrowserService_ only acts as a bridge between the client and _BrowserPasskeys_ (authenticator) and calls the relevant popups for user interaction. - A new helper class _PasskeyUtils_ includes the actual checks and parses the objects. - _BrowserPasskeys_ is pretty much intact, but some functions have been moved to PasskeyUtils. - Fixes Ed25519 encoding in _BrowserCBOR_. - Adds new error messages. - User confirmation for Passkey retrieval is also asked even if `discouraged` is used. This goes against the specification, but currently there's no other way to verify the user. - `cross-platform` is also accepted for compatibility. This could be removed if there's a potential issue with it. - Extension data is now handled correctly during Authentication. - Allowed and excluded credentials are now handled correctly. - `KPEX_PASSKEY_GENERATED_USER_ID` is renamed to `KPEX_PASSKEY_CREDENTIAL_ID` - Adds a new option "Allow localhost with Passkeys" to Browser Integration -> Advanced tab. By default it's not allowed to access HTTP sites, but `http://localhost` can be allowed for debugging and testing purposes for local servers. - Add tag `Passkey` to a Passkey entry, or an entry with an imported Passkey. Fixes #10287.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
|
||||
* Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
|
||||
* Copyright (C) 2011 Felix Geyer <debfx@fobos.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -167,6 +167,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
|
||||
{Config::Browser_UseCustomBrowser, {QS("Browser/UseCustomBrowser"), Local, false}},
|
||||
{Config::Browser_CustomBrowserType, {QS("Browser/CustomBrowserType"), Local, -1}},
|
||||
{Config::Browser_CustomBrowserLocation, {QS("Browser/CustomBrowserLocation"), Local, {}}},
|
||||
{Config::Browser_AllowLocalhostWithPasskeys, {QS("Browser/Browser_AllowLocalhostWithPasskeys"), Roaming, false}},
|
||||
#ifdef QT_DEBUG
|
||||
{Config::Browser_CustomExtensionId, {QS("Browser/CustomExtensionId"), Local, {}}},
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
|
||||
* Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
|
||||
* Copyright (C) 2011 Felix Geyer <debfx@fobos.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -147,6 +147,7 @@ public:
|
||||
Browser_UseCustomBrowser,
|
||||
Browser_CustomBrowserType,
|
||||
Browser_CustomBrowserLocation,
|
||||
Browser_AllowLocalhostWithPasskeys,
|
||||
#ifdef QT_DEBUG
|
||||
Browser_CustomExtensionId,
|
||||
#endif
|
||||
|
||||
@@ -230,6 +230,13 @@ namespace Tools
|
||||
return regexp.exactMatch(base64);
|
||||
}
|
||||
|
||||
bool isAsciiString(const QString& str)
|
||||
{
|
||||
constexpr auto pattern = R"(^[\x00-\x7F]+$)";
|
||||
QRegularExpression regexp(pattern, QRegularExpression::CaseInsensitiveOption);
|
||||
return regexp.match(str).hasMatch();
|
||||
}
|
||||
|
||||
void sleep(int ms)
|
||||
{
|
||||
Q_ASSERT(ms >= 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
|
||||
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
|
||||
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -37,6 +37,7 @@ namespace Tools
|
||||
bool readAllFromDevice(QIODevice* device, QByteArray& data);
|
||||
bool isHex(const QByteArray& ba);
|
||||
bool isBase64(const QByteArray& ba);
|
||||
bool isAsciiString(const QString& str);
|
||||
void sleep(int ms);
|
||||
void wait(int ms);
|
||||
QString uuidToHex(const QUuid& uuid);
|
||||
|
||||
@@ -102,7 +102,7 @@ QString UrlTools::getTopLevelDomainFromUrl(const QString& url) const
|
||||
cookie.setDomain(host);
|
||||
|
||||
// Check if dummy cookie's domain/TLD matches with public suffix list
|
||||
if (!QNetworkCookieJar{}.setCookiesFromUrl(QList{cookie}, url)) {
|
||||
if (!QNetworkCookieJar{}.setCookiesFromUrl(QList{cookie}, QUrl::fromUserInput(url))) {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,9 @@ QString UrlTools::getTopLevelDomainFromUrl(const QString& url) const
|
||||
|
||||
bool UrlTools::isIpAddress(const QString& host) const
|
||||
{
|
||||
QHostAddress address(host);
|
||||
// Handle IPv6 host with brackets, e.g [::1]
|
||||
const auto hostAddress = host.startsWith('[') && host.endsWith(']') ? host.mid(1, host.length() - 2) : host;
|
||||
QHostAddress address(hostAddress);
|
||||
return address.protocol() == QAbstractSocket::IPv4Protocol || address.protocol() == QAbstractSocket::IPv6Protocol;
|
||||
}
|
||||
#endif
|
||||
@@ -171,3 +173,9 @@ bool UrlTools::isUrlValid(const QString& urlField) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UrlTools::domainHasIllegalCharacters(const QString& domain) const
|
||||
{
|
||||
QRegularExpression re(R"([\s\^#|/:<>\?@\[\]\\])");
|
||||
return re.match(domain).hasMatch();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org>
|
||||
* Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
#endif
|
||||
bool isUrlIdentical(const QString& first, const QString& second) const;
|
||||
bool isUrlValid(const QString& urlField) const;
|
||||
bool domainHasIllegalCharacters(const QString& domain) const;
|
||||
|
||||
private:
|
||||
QUrl convertVariantToUrl(const QVariant& var) const;
|
||||
|
||||
Reference in New Issue
Block a user