Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSH Agent: Add support for OpenSSH for Windows #1994

Merged
merged 2 commits into from
Dec 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 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 All @@ -26,6 +27,21 @@
#undef MessageBox
#endif

#if defined(HAVE_RLIMIT_CORE)
#include <sys/resource.h>
#endif

#if defined(HAVE_PR_SET_DUMPABLE)
#include <sys/prctl.h>
#endif

#ifdef HAVE_PT_DENY_ATTACH
// clang-format off
#include <sys/types.h>
#include <sys/ptrace.h>
// clang-format on
#endif

namespace Bootstrap
{
/**
Expand Down Expand Up @@ -140,6 +156,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 +184,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 +218,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 +246,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
17 changes: 0 additions & 17 deletions src/core/Tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,6 @@
#include <time.h> // for nanosleep()
#endif

#include "config-keepassx.h"

#if defined(HAVE_RLIMIT_CORE)
#include <sys/resource.h>
#endif

#if defined(HAVE_PR_SET_DUMPABLE)
#include <sys/prctl.h>
#endif

#ifdef HAVE_PT_DENY_ATTACH
// clang-format off
#include <sys/types.h>
#include <sys/ptrace.h>
// clang-format on
#endif

namespace Tools
{
QString humanReadableFileSize(qint64 bytes, quint32 precision)
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