Skip to content

Commit

Permalink
SSH Agent: Add support for OpenSSH for Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
hifi authored and droidmonkey committed Dec 25, 2018
1 parent 5488f1b commit 9f288ec
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 10 deletions.
31 changes: 30 additions & 1 deletion src/core/Bootstrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "Bootstrap.h"
#include "config-keepassx.h"
#include "core/Config.h"
#include "core/Translator.h"
#include "gui/MessageBox.h"
Expand Down Expand Up @@ -140,6 +141,8 @@ namespace Bootstrap
HANDLE hToken = nullptr;
PTOKEN_USER pTokenUser = nullptr;
DWORD cbBufferSize = 0;
PSID pLocalSystemSid = nullptr;
DWORD pLocalSystemSidSize = SECURITY_MAX_SID_SIZE;

// Access control list
PACL pACL = nullptr;
Expand All @@ -166,8 +169,19 @@ namespace Bootstrap
goto Cleanup;
}

// Retrieve LocalSystem account SID
pLocalSystemSid = static_cast<PSID>(HeapAlloc(GetProcessHeap(), 0, pLocalSystemSidSize));
if (pLocalSystemSid == nullptr) {
goto Cleanup;
}

if (!CreateWellKnownSid(WinLocalSystemSid, nullptr, pLocalSystemSid, &pLocalSystemSidSize)) {
goto Cleanup;
}

// Calculate the amount of memory that must be allocated for the DACL
cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid);
cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid)
+ sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pLocalSystemSid);

// Create and initialize an ACL
pACL = static_cast<PACL>(HeapAlloc(GetProcessHeap(), 0, cbACL));
Expand All @@ -189,6 +203,18 @@ namespace Bootstrap
goto Cleanup;
}

#ifdef WITH_XC_SSHAGENT
// OpenSSH for Windows ssh-agent service is running as LocalSystem
if (!AddAccessAllowedAce(
pACL,
ACL_REVISION,
PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE, // just enough for ssh-agent
pLocalSystemSid // known LocalSystem sid
)) {
goto Cleanup;
}
#endif

// Set discretionary access control list
bSuccess = ERROR_SUCCESS
== SetSecurityInfo(GetCurrentProcess(), // object handle
Expand All @@ -205,6 +231,9 @@ namespace Bootstrap
if (pACL != nullptr) {
HeapFree(GetProcessHeap(), 0, pACL);
}
if (pLocalSystemSid != nullptr) {
HeapFree(GetProcessHeap(), 0, pLocalSystemSid);
}
if (pTokenUser != nullptr) {
HeapFree(GetProcessHeap(), 0, pTokenUser);
}
Expand Down
9 changes: 9 additions & 0 deletions src/sshagent/AgentSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ AgentSettingsWidget::AgentSettingsWidget(QWidget* parent)
, m_ui(new Ui::AgentSettingsWidget())
{
m_ui->setupUi(this);
#ifndef Q_OS_WIN
m_ui->useOpenSSHCheckBox->setVisible(false);
#endif
}

AgentSettingsWidget::~AgentSettingsWidget()
Expand All @@ -35,9 +38,15 @@ AgentSettingsWidget::~AgentSettingsWidget()
void AgentSettingsWidget::loadSettings()
{
m_ui->enableSSHAgentCheckBox->setChecked(config()->get("SSHAgent", false).toBool());
#ifdef Q_OS_WIN
m_ui->useOpenSSHCheckBox->setChecked(config()->get("SSHAgentOpenSSH", false).toBool());
#endif
}

void AgentSettingsWidget::saveSettings()
{
config()->set("SSHAgent", m_ui->enableSSHAgentCheckBox->isChecked());
#ifdef Q_OS_WIN
config()->set("SSHAgentOpenSSH", m_ui->useOpenSSHCheckBox->isChecked());
#endif
}
7 changes: 7 additions & 0 deletions src/sshagent/AgentSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useOpenSSHCheckBox">
<property name="text">
<string>Use OpenSSH for Windows instead of Pageant</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
Expand Down
29 changes: 22 additions & 7 deletions src/sshagent/SSHAgent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
#include "SSHAgent.h"
#include "BinaryStream.h"
#include "KeeAgentSettings.h"

#ifndef Q_OS_WIN
#include "core/Config.h"
#include <QtNetwork>
#else

#ifdef Q_OS_WIN
#include <windows.h>
#endif

Expand All @@ -33,6 +33,8 @@ SSHAgent::SSHAgent(QObject* parent)
{
#ifndef Q_OS_WIN
m_socketPath = QProcessEnvironment::systemEnvironment().value("SSH_AUTH_SOCK");
#else
m_socketPath = "\\\\.\\pipe\\openssh-ssh-agent";
#endif
}

Expand Down Expand Up @@ -70,13 +72,22 @@ bool SSHAgent::isAgentRunning() const
#ifndef Q_OS_WIN
return !m_socketPath.isEmpty();
#else
return (FindWindowA("Pageant", "Pageant") != nullptr);
if (!config()->get("SSHAgentOpenSSH").toBool()) {
return (FindWindowA("Pageant", "Pageant") != nullptr);
} else {
return WaitNamedPipe(m_socketPath.toLatin1().data(), 100);
}
#endif
}

bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out)
{
#ifndef Q_OS_WIN
#ifdef Q_OS_WIN
if (!config()->get("SSHAgentOpenSSH").toBool()) {
return sendMessagePageant(in, out);
}
#endif

QLocalSocket socket;
BinaryStream stream(&socket);

Expand All @@ -97,7 +108,11 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out)
socket.close();

return true;
#else
}

#ifdef Q_OS_WIN
bool SSHAgent::sendMessagePageant(const QByteArray& in, QByteArray& out)
{
HWND hWnd = FindWindowA("Pageant", "Pageant");

if (!hWnd) {
Expand Down Expand Up @@ -157,8 +172,8 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out)
CloseHandle(handle);

return (res > 0);
#endif
}
#endif

/**
* Add the identity to the SSH agent.
Expand Down
6 changes: 4 additions & 2 deletions src/sshagent/SSHAgent.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ public slots:
~SSHAgent();

bool sendMessage(const QByteArray& in, QByteArray& out);
#ifdef Q_OS_WIN
bool sendMessagePageant(const QByteArray& in, QByteArray& out);
#endif

static SSHAgent* m_instance;

#ifndef Q_OS_WIN
QString m_socketPath;
#else
#ifdef Q_OS_WIN
const quint32 AGENT_MAX_MSGLEN = 8192;
const quint32 AGENT_COPYDATA_ID = 0x804e50ba;
#endif
Expand Down

0 comments on commit 9f288ec

Please sign in to comment.