mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
parent
c07a57d141
commit
860fcfd78d
@ -120,6 +120,14 @@
|
||||
<source>Use OpenSSH</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SSH_SK_PROVIDER value</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SSH_SK_PROVIDER override</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>ApplicationSettingsWidget</name>
|
||||
@ -5472,6 +5480,14 @@ We recommend you use the AppImage available on our downloads page.</source>
|
||||
<source>Decryption failed: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unexpected EOF while reading key</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unsupported key part</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PasswordEdit</name>
|
||||
@ -7624,6 +7640,10 @@ Please consider generating a new key file.</source>
|
||||
<source>No agent running, cannot list identities.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Security keys are not supported by the agent or the security key provider is unavailable.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SearchHelpWidget</name>
|
||||
|
@ -170,6 +170,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
|
||||
{Config::SSHAgent_UseOpenSSH, {QS("SSHAgent/UseOpenSSH"), Roaming, false}},
|
||||
{Config::SSHAgent_UsePageant, {QS("SSHAgent/UsePageant"), Roaming, false} },
|
||||
{Config::SSHAgent_AuthSockOverride, {QS("SSHAgent/AuthSockOverride"), Local, {}}},
|
||||
{Config::SSHAgent_SecurityKeyProviderOverride, {QS("SSHAgent/SecurityKeyProviderOverride"), Local, {}}},
|
||||
|
||||
// FdoSecrets
|
||||
{Config::FdoSecrets_Enabled, {QS("FdoSecrets/Enabled"), Roaming, false}},
|
||||
|
@ -148,6 +148,7 @@ public:
|
||||
SSHAgent_UseOpenSSH,
|
||||
SSHAgent_UsePageant,
|
||||
SSHAgent_AuthSockOverride,
|
||||
SSHAgent_SecurityKeyProviderOverride,
|
||||
|
||||
FdoSecrets_Enabled,
|
||||
FdoSecrets_ShowNotification,
|
||||
|
@ -55,6 +55,11 @@ void AgentSettingsWidget::loadSettings()
|
||||
auto sshAuthSockOverride = sshAgent()->authSockOverride();
|
||||
m_ui->sshAuthSockLabel->setText(sshAuthSock.isEmpty() ? tr("(empty)") : sshAuthSock);
|
||||
m_ui->sshAuthSockOverrideEdit->setText(sshAuthSockOverride);
|
||||
auto sshSecurityKeyProvider = sshAgent()->securityKeyProvider(false);
|
||||
auto sshSecurityKeyProviderOverride = sshAgent()->securityKeyProviderOverride();
|
||||
m_ui->sshSecurityKeyProviderLabel->setText(sshSecurityKeyProvider.isEmpty() ? tr("(empty)")
|
||||
: sshSecurityKeyProvider);
|
||||
m_ui->sshSecurityKeyProviderOverrideEdit->setText(sshSecurityKeyProviderOverride);
|
||||
#endif
|
||||
|
||||
m_ui->sshAuthSockMessageWidget->setVisible(sshAgentEnabled);
|
||||
@ -85,6 +90,8 @@ void AgentSettingsWidget::saveSettings()
|
||||
{
|
||||
auto sshAuthSockOverride = m_ui->sshAuthSockOverrideEdit->text();
|
||||
sshAgent()->setAuthSockOverride(sshAuthSockOverride);
|
||||
auto sshSecurityKeyProviderOverride = m_ui->sshSecurityKeyProviderOverrideEdit->text();
|
||||
sshAgent()->setSecurityKeyProviderOverride(sshSecurityKeyProviderOverride);
|
||||
#ifdef Q_OS_WIN
|
||||
sshAgent()->setUsePageant(m_ui->usePageantCheckBox->isChecked());
|
||||
sshAgent()->setUseOpenSSH(m_ui->useOpenSSHCheckBox->isChecked());
|
||||
|
@ -100,6 +100,16 @@
|
||||
<property name="verticalSpacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="sshAuthSockOverrideLabel">
|
||||
<property name="text">
|
||||
<string>SSH_AUTH_SOCK override</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="sshAuthSockValueLabel">
|
||||
<property name="text">
|
||||
@ -110,15 +120,18 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="sshAuthSockOverrideLabel">
|
||||
<property name="text">
|
||||
<string>SSH_AUTH_SOCK override</string>
|
||||
<item row="4" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="sshAuthSockOverrideEdit"/>
|
||||
@ -139,17 +152,42 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="QLabel" name="sshSecurityKeyProviderValueLabel">
|
||||
<property name="text">
|
||||
<string>SSH_SK_PROVIDER value</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</spacer>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="sshSecurityKeyProviderLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>(empty)</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="sshSecurityKeyProviderOverrideLabel">
|
||||
<property name="text">
|
||||
<string>SSH_SK_PROVIDER override</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="sshSecurityKeyProviderOverrideEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
@ -473,6 +473,8 @@ bool OpenSSHKey::readPublic(BinaryStream& stream)
|
||||
{ "ecdsa-sha2-nistp384", {STR_PART, STR_PART} },
|
||||
{ "ecdsa-sha2-nistp521", {STR_PART, STR_PART} },
|
||||
{ "ssh-ed25519", {STR_PART} },
|
||||
{ "sk-ecdsa-sha2-nistp256@openssh.com", {STR_PART, STR_PART, STR_PART} },
|
||||
{ "sk-ssh-ed25519@openssh.com", {STR_PART, STR_PART} },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@ -502,6 +504,8 @@ bool OpenSSHKey::readPrivate(BinaryStream& stream)
|
||||
{ "ecdsa-sha2-nistp384", {STR_PART, STR_PART, STR_PART} },
|
||||
{ "ecdsa-sha2-nistp521", {STR_PART, STR_PART, STR_PART} },
|
||||
{ "ssh-ed25519", {STR_PART, STR_PART} },
|
||||
{ "sk-ecdsa-sha2-nistp256@openssh.com", {STR_PART, STR_PART, STR_PART, UINT8_PART, STR_PART, STR_PART} },
|
||||
{ "sk-ssh-ed25519@openssh.com", {STR_PART, STR_PART, UINT8_PART, STR_PART, STR_PART} },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -61,11 +61,21 @@ QString SSHAgent::authSockOverride() const
|
||||
return config()->get(Config::SSHAgent_AuthSockOverride).toString();
|
||||
}
|
||||
|
||||
QString SSHAgent::securityKeyProviderOverride() const
|
||||
{
|
||||
return config()->get(Config::SSHAgent_SecurityKeyProviderOverride).toString();
|
||||
}
|
||||
|
||||
void SSHAgent::setAuthSockOverride(QString& authSockOverride)
|
||||
{
|
||||
config()->set(Config::SSHAgent_AuthSockOverride, authSockOverride);
|
||||
}
|
||||
|
||||
void SSHAgent::setSecurityKeyProviderOverride(QString& securityKeyProviderOverride)
|
||||
{
|
||||
config()->set(Config::SSHAgent_SecurityKeyProviderOverride, securityKeyProviderOverride);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
bool SSHAgent::useOpenSSH() const
|
||||
{
|
||||
@ -109,6 +119,21 @@ QString SSHAgent::socketPath(bool allowOverride) const
|
||||
return socketPath;
|
||||
}
|
||||
|
||||
QString SSHAgent::securityKeyProvider(bool allowOverride) const
|
||||
{
|
||||
QString skProvider;
|
||||
|
||||
if (allowOverride) {
|
||||
skProvider = securityKeyProviderOverride();
|
||||
}
|
||||
|
||||
if (skProvider.isEmpty()) {
|
||||
skProvider = QProcessEnvironment::systemEnvironment().value("SSH_SK_PROVIDER", "internal");
|
||||
}
|
||||
|
||||
return skProvider;
|
||||
}
|
||||
|
||||
const QString SSHAgent::errorString() const
|
||||
{
|
||||
return m_error;
|
||||
@ -257,10 +282,12 @@ bool SSHAgent::addIdentity(OpenSSHKey& key, const KeeAgentSettings& settings, co
|
||||
|
||||
QByteArray requestData;
|
||||
BinaryStream request(&requestData);
|
||||
bool isSecurityKey = key.type().startsWith("sk-");
|
||||
|
||||
request.write((settings.useLifetimeConstraintWhenAdding() || settings.useConfirmConstraintWhenAdding())
|
||||
? SSH_AGENTC_ADD_ID_CONSTRAINED
|
||||
: SSH_AGENTC_ADD_IDENTITY);
|
||||
request.write(
|
||||
(settings.useLifetimeConstraintWhenAdding() || settings.useConfirmConstraintWhenAdding() || isSecurityKey)
|
||||
? SSH_AGENTC_ADD_ID_CONSTRAINED
|
||||
: SSH_AGENTC_ADD_IDENTITY);
|
||||
key.writePrivate(request);
|
||||
|
||||
if (settings.useLifetimeConstraintWhenAdding()) {
|
||||
@ -272,6 +299,12 @@ bool SSHAgent::addIdentity(OpenSSHKey& key, const KeeAgentSettings& settings, co
|
||||
request.write(SSH_AGENT_CONSTRAIN_CONFIRM);
|
||||
}
|
||||
|
||||
if (isSecurityKey) {
|
||||
request.write(SSH_AGENT_CONSTRAIN_EXTENSION);
|
||||
request.writeString(QString("sk-provider@openssh.com"));
|
||||
request.writeString(securityKeyProvider());
|
||||
}
|
||||
|
||||
QByteArray responseData;
|
||||
if (!sendMessage(requestData, responseData)) {
|
||||
return false;
|
||||
@ -289,6 +322,11 @@ bool SSHAgent::addIdentity(OpenSSHKey& key, const KeeAgentSettings& settings, co
|
||||
m_error += "\n" + tr("A confirmation request is not supported by the agent (check options).");
|
||||
}
|
||||
|
||||
if (isSecurityKey) {
|
||||
m_error +=
|
||||
"\n" + tr("Security keys are not supported by the agent or the security key provider is unavailable.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,11 @@ public:
|
||||
bool isEnabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
QString socketPath(bool allowOverride = true) const;
|
||||
QString securityKeyProvider(bool allowOverride = true) const;
|
||||
QString authSockOverride() const;
|
||||
QString securityKeyProviderOverride() const;
|
||||
void setAuthSockOverride(QString& authSockOverride);
|
||||
void setSecurityKeyProviderOverride(QString& securityKeyProviderOverride);
|
||||
#ifdef Q_OS_WIN
|
||||
bool useOpenSSH() const;
|
||||
bool usePageant() const;
|
||||
@ -74,6 +77,7 @@ private:
|
||||
|
||||
const quint8 SSH_AGENT_CONSTRAIN_LIFETIME = 1;
|
||||
const quint8 SSH_AGENT_CONSTRAIN_CONFIRM = 2;
|
||||
const quint8 SSH_AGENT_CONSTRAIN_EXTENSION = 255;
|
||||
|
||||
bool sendMessage(const QByteArray& in, QByteArray& out);
|
||||
bool sendMessageOpenSSH(const QByteArray& in, QByteArray& out);
|
||||
|
@ -509,3 +509,52 @@ void TestOpenSSHKey::testDecryptUTF8()
|
||||
QCOMPARE(key.type(), QString("ssh-ed25519"));
|
||||
QCOMPARE(key.comment(), QString("opensshkey-test-utf8@keepassxc"));
|
||||
}
|
||||
|
||||
void TestOpenSSHKey::testParseECDSASecurityKey()
|
||||
{
|
||||
const QString keyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2\n"
|
||||
"RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQQ2Pr1d6zUa\n"
|
||||
"qcmYgjTGQUF9QPkFEo2Q7aQbvyL/0KL9FObuOfzqxs8mDqswXEsXR4g5L6P7vEe6nPqzSW\n"
|
||||
"X9/jJfAAAABHNzaDoAAAD4kyJ795Mie/cAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv\n"
|
||||
"cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEENj69Xes1GqnJmII0xkFBfUD5BRKNkO2kG7\n"
|
||||
"8i/9Ci/RTm7jn86sbPJg6rMFxLF0eIOS+j+7xHupz6s0ll/f4yXwAAAARzc2g6AQAAAEA4\n"
|
||||
"Dbqd2ub7R1QQRm8nBZWDGJSiNIh58vvJ4EuAh0FnJsRvvASsSDiGuuXqh56wT5xmlnYvbb\n"
|
||||
"nLWO4/1+Mp5PaDAAAAAAAAACJvcGVuc3Noa2V5LXRlc3QtZWNkc2Etc2tAa2VlcGFzc3hj\n"
|
||||
"AQI=\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n");
|
||||
|
||||
const QByteArray keyData = keyString.toLatin1();
|
||||
|
||||
OpenSSHKey key;
|
||||
QVERIFY(key.parsePKCS1PEM(keyData));
|
||||
QVERIFY(!key.encrypted());
|
||||
QCOMPARE(key.cipherName(), QString("none"));
|
||||
QCOMPARE(key.type(), QString("sk-ecdsa-sha2-nistp256@openssh.com"));
|
||||
QCOMPARE(key.comment(), QString("opensshkey-test-ecdsa-sk@keepassxc"));
|
||||
QCOMPARE(key.fingerprint(), QString("SHA256:ctOtAsPMqbtumGI41o2oeWfGDah4m1ACILRj+x0gx0E"));
|
||||
}
|
||||
|
||||
void TestOpenSSHKey::testParseED25519SecurityKey()
|
||||
{
|
||||
const QString keyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
||||
"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2\n"
|
||||
"gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCSIfzsjUBlhsVBfHHlQCUpj1Yt+404RetvfTnd\n"
|
||||
"DJIIqgAAAARzc2g6AAABCN1MUOzdTFDsAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2\n"
|
||||
"9tAAAAIJIh/OyNQGWGxUF8ceVAJSmPVi37jThF6299Od0MkgiqAAAABHNzaDoBAAAAgF+0\n"
|
||||
"UB3uNf48T/u9eSHmhfTfqgZZZxQ81UQmlw9Xw1eNZ2F+y+JwbQYK3gLMxro2cv2PHgYqIW\n"
|
||||
"MAHFxdJjUn62D88bywmHaFT7ftu8/4bh38G+aQsmTFW38li97FiLz+Ytz0X9oSCo1jerkC\n"
|
||||
"fYe8pcZZ7zWWSMzRnZKP11QMEkEQAAAAAAAAACRvcGVuc3Noa2V5LXRlc3QtZWQyNTUxOS\n"
|
||||
"1za0BrZWVwYXNzeGMBAgMEBQ==\n"
|
||||
"-----END OPENSSH PRIVATE KEY-----\n");
|
||||
|
||||
const QByteArray keyData = keyString.toLatin1();
|
||||
|
||||
OpenSSHKey key;
|
||||
QVERIFY(key.parsePKCS1PEM(keyData));
|
||||
QVERIFY(!key.encrypted());
|
||||
QCOMPARE(key.cipherName(), QString("none"));
|
||||
QCOMPARE(key.type(), QString("sk-ssh-ed25519@openssh.com"));
|
||||
QCOMPARE(key.comment(), QString("opensshkey-test-ed25519-sk@keepassxc"));
|
||||
QCOMPARE(key.fingerprint(), QString("SHA256:PGtS5WvbnYmNqFIeRbzO6cVP9GLh8eEzENgkHp02XIA"));
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ private slots:
|
||||
void testDecryptOpenSSHAES256CTR();
|
||||
void testDecryptRSAAES256CTR();
|
||||
void testDecryptUTF8();
|
||||
void testParseECDSASecurityKey();
|
||||
void testParseED25519SecurityKey();
|
||||
};
|
||||
|
||||
#endif // TESTOPENSSHKEY_H
|
||||
|
Loading…
Reference in New Issue
Block a user