parent
bc3f21a6a3
commit
1ff1b07410
Binary file not shown.
|
@ -11,70 +11,6 @@ $logsdir = Join-Path $scriptdir "logs"
|
||||||
|
|
||||||
$sshdAccount = "NT SERVICE\SSHD"
|
$sshdAccount = "NT SERVICE\SSHD"
|
||||||
|
|
||||||
#Idea borrowed from http://sqldbamusings.blogspot.com/2012/03/powershell-adding-accounts-to-local.html
|
|
||||||
function Add-Privilege
|
|
||||||
{
|
|
||||||
param(
|
|
||||||
[string] $Account,
|
|
||||||
|
|
||||||
[ValidateSet("SeAssignPrimaryTokenPrivilege", "SeServiceLogonRight")]
|
|
||||||
[string] $Privilege
|
|
||||||
)
|
|
||||||
|
|
||||||
#Get $Account SID
|
|
||||||
$account_sid = $null
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$ntprincipal = new-object System.Security.Principal.NTAccount "$Account"
|
|
||||||
$sid = $ntprincipal.Translate([System.Security.Principal.SecurityIdentifier])
|
|
||||||
$account_sid = $sid.Value.ToString()
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Throw 'Unable to resolve '+ $Account
|
|
||||||
}
|
|
||||||
|
|
||||||
#Prepare policy settings file to be applied
|
|
||||||
$settings_to_export = [System.IO.Path]::GetTempFileName()
|
|
||||||
"[Unicode]" | Set-Content $settings_to_export -Encoding Unicode
|
|
||||||
"Unicode=yes" | Add-Content $settings_to_export -Force -WhatIf:$false
|
|
||||||
"[Version]" | Add-Content $settings_to_export -Force -WhatIf:$false
|
|
||||||
"signature=`"`$CHICAGO`$`"" | Add-Content $settings_to_export -Force -WhatIf:$false
|
|
||||||
"Revision=1" | Add-Content $settings_to_export -Force -WhatIf:$false
|
|
||||||
"[Privilege Rights]" | Add-Content $settings_to_export -Force -WhatIf:$false
|
|
||||||
|
|
||||||
#Get Current policy settings
|
|
||||||
$imported_settings = [System.IO.Path]::GetTempFileName()
|
|
||||||
secedit.exe /export /areas USER_RIGHTS /cfg "$($imported_settings)" > $null
|
|
||||||
|
|
||||||
if (-not(Test-Path $imported_settings)) {
|
|
||||||
Throw "Unable to import current security policy settings"
|
|
||||||
}
|
|
||||||
|
|
||||||
#find current assigned accounts to $Privilege and add it to $settings_to_export
|
|
||||||
$current_settings = Get-Content $imported_settings -Encoding Unicode
|
|
||||||
$existing_setting = $null
|
|
||||||
foreach ($setting in $current_settings) {
|
|
||||||
if ($setting -like "$Privilege`*") {
|
|
||||||
$existing_setting = $setting
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#Add $account_sid to list
|
|
||||||
if ($existing_setting -eq $null) {
|
|
||||||
$Privilege + " = *" + $account_sid | Add-Content $settings_to_export -Force -WhatIf:$false
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$existing_setting + ",*" + $account_sid | Add-Content $settings_to_export -Force -WhatIf:$false
|
|
||||||
}
|
|
||||||
|
|
||||||
#export
|
|
||||||
secedit.exe /configure /db "secedit.sdb" /cfg "$($settings_to_export)" /areas USER_RIGHTS > $null
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (-not (Test-Path $sshdpath)) {
|
if (-not (Test-Path $sshdpath)) {
|
||||||
throw "sshd.exe is not present in script path"
|
throw "sshd.exe is not present in script path"
|
||||||
}
|
}
|
||||||
|
@ -95,10 +31,8 @@ New-Service -Name ssh-agent -BinaryPathName $sshagentpath -Description "SSH Agen
|
||||||
cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RP;;;AU)'
|
cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RP;;;AU)'
|
||||||
|
|
||||||
New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Daemon" -StartupType Manual -DependsOn ssh-agent | Out-Null
|
New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Daemon" -StartupType Manual -DependsOn ssh-agent | Out-Null
|
||||||
sc.exe config sshd obj= $sshdAccount
|
sc.exe config sshd obj= "NT AUTHORITY\NetworkService"
|
||||||
|
sc.exe sidtype sshd unrestricted
|
||||||
Add-Privilege -Account $sshdAccount -Privilege SeAssignPrimaryTokenPrivilege
|
|
||||||
Add-Privilege -Account $sshdAccount -Privilege SeServiceLogonRight
|
|
||||||
|
|
||||||
if(-not (test-path $logsdir -PathType Container))
|
if(-not (test-path $logsdir -PathType Container))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
|
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
|
||||||
* ssh-agent implementation on Windows
|
* ssh-agent implementation on Windows
|
||||||
|
* NT Service routines
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015 Microsoft Corp.
|
* Copyright (c) 2015 Microsoft Corp.
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -43,7 +44,8 @@ static SERVICE_STATUS_HANDLE service_status_handle;
|
||||||
static SERVICE_STATUS service_status;
|
static SERVICE_STATUS service_status;
|
||||||
|
|
||||||
|
|
||||||
static VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
|
static VOID
|
||||||
|
ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
|
||||||
{
|
{
|
||||||
service_status.dwCurrentState = dwCurrentState;
|
service_status.dwCurrentState = dwCurrentState;
|
||||||
service_status.dwWin32ExitCode = dwWin32ExitCode;
|
service_status.dwWin32ExitCode = dwWin32ExitCode;
|
||||||
|
@ -62,7 +64,8 @@ static VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD d
|
||||||
SetServiceStatus(service_status_handle, &service_status);
|
SetServiceStatus(service_status_handle, &service_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID WINAPI service_handler(DWORD dwControl)
|
static VOID WINAPI
|
||||||
|
service_handler(DWORD dwControl)
|
||||||
{
|
{
|
||||||
switch (dwControl)
|
switch (dwControl)
|
||||||
{
|
{
|
||||||
|
@ -81,22 +84,27 @@ static VOID WINAPI service_handler(DWORD dwControl)
|
||||||
ReportSvcStatus(service_status.dwCurrentState, NO_ERROR, 0);
|
ReportSvcStatus(service_status.dwCurrentState, NO_ERROR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI ctrl_c_handler(
|
BOOL WINAPI
|
||||||
_In_ DWORD dwCtrlType
|
ctrl_c_handler(_In_ DWORD dwCtrlType)
|
||||||
) {
|
{
|
||||||
/* for any Ctrl type, shutdown agent*/
|
/* for any Ctrl type, shutdown agent*/
|
||||||
debug("Ctrl+C received");
|
debug("Ctrl+C received");
|
||||||
agent_shutdown();
|
agent_shutdown();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wmain(int argc, wchar_t **argv) {
|
int
|
||||||
|
wmain(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
w32posix_initialize();
|
w32posix_initialize();
|
||||||
|
/* this exits() on failure*/
|
||||||
load_config();
|
load_config();
|
||||||
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
||||||
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
||||||
|
/*
|
||||||
|
* agent is not spawned by SCM
|
||||||
|
* Its either started in debug mode or a worker child
|
||||||
|
*/
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
if (wcsncmp(argv[1], L"-ddd", 4) == 0)
|
if (wcsncmp(argv[1], L"-ddd", 4) == 0)
|
||||||
log_init("ssh-agent", 7, 1, 1);
|
log_init("ssh-agent", 7, 1, 1);
|
||||||
|
@ -105,9 +113,10 @@ int wmain(int argc, wchar_t **argv) {
|
||||||
else if (wcsncmp(argv[1], L"-d", 2) == 0)
|
else if (wcsncmp(argv[1], L"-d", 2) == 0)
|
||||||
log_init("ssh-agent", 5, 1, 1);
|
log_init("ssh-agent", 5, 1, 1);
|
||||||
|
|
||||||
|
/* Set Ctrl+C handler if starting in debug mode */
|
||||||
if (wcsncmp(argv[1], L"-d", 2) == 0) {
|
if (wcsncmp(argv[1], L"-d", 2) == 0) {
|
||||||
SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
|
SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
|
||||||
agent_start(TRUE, FALSE, 0);
|
agent_start(TRUE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +125,7 @@ int wmain(int argc, wchar_t **argv) {
|
||||||
h += _wtoi(*(argv + 1));
|
h += _wtoi(*(argv + 1));
|
||||||
if (h != 0) {
|
if (h != 0) {
|
||||||
log_init("ssh-agent", config_log_level(), 1, 0);
|
log_init("ssh-agent", config_log_level(), 1, 0);
|
||||||
agent_start(FALSE, TRUE, h);
|
agent_process_connection(h);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,14 +155,16 @@ int wmain(int argc, wchar_t **argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scm_start_service(DWORD num, LPWSTR* args) {
|
int
|
||||||
|
scm_start_service(DWORD num, LPWSTR* args)
|
||||||
|
{
|
||||||
service_status_handle = RegisterServiceCtrlHandlerW(L"ssh-agent", service_handler);
|
service_status_handle = RegisterServiceCtrlHandlerW(L"ssh-agent", service_handler);
|
||||||
ZeroMemory(&service_status, sizeof(service_status));
|
ZeroMemory(&service_status, sizeof(service_status));
|
||||||
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||||
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 300);
|
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 300);
|
||||||
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||||
log_init("ssh-agent", config_log_level(), 1, 0);
|
log_init("ssh-agent", config_log_level(), 1, 0);
|
||||||
agent_start(FALSE, FALSE, 0);
|
agent_start(FALSE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,40 +44,21 @@ static OVERLAPPED ol;
|
||||||
static HANDLE pipe;
|
static HANDLE pipe;
|
||||||
static SECURITY_ATTRIBUTES sa;
|
static SECURITY_ATTRIBUTES sa;
|
||||||
|
|
||||||
static int
|
|
||||||
init_listener() {
|
|
||||||
{
|
|
||||||
if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
|
|
||||||
debug("cannot create event ERROR:%d", GetLastError());
|
|
||||||
return GetLastError();
|
|
||||||
}
|
|
||||||
pipe = INVALID_HANDLE_VALUE;
|
|
||||||
sa.bInheritHandle = FALSE;
|
|
||||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"D:P(A;; GA;;; AU)", SDDL_REVISION_1,
|
|
||||||
&sa.lpSecurityDescriptor, &sa.nLength)) {
|
|
||||||
debug("cannot convert sddl ERROR:%d", GetLastError());
|
|
||||||
return GetLastError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
agent_cleanup() {
|
agent_cleanup()
|
||||||
{
|
{
|
||||||
if (ol.hEvent != NULL)
|
if (ol.hEvent != NULL)
|
||||||
CloseHandle(ol.hEvent);
|
CloseHandle(ol.hEvent);
|
||||||
if (pipe != INVALID_HANDLE_VALUE)
|
if (pipe != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(pipe);
|
CloseHandle(pipe);
|
||||||
}
|
|
||||||
if (ioc_port)
|
if (ioc_port)
|
||||||
CloseHandle(ioc_port);
|
CloseHandle(ioc_port);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD WINAPI
|
static DWORD WINAPI
|
||||||
iocp_work(LPVOID lpParam) {
|
iocp_work(LPVOID lpParam)
|
||||||
|
{
|
||||||
DWORD bytes;
|
DWORD bytes;
|
||||||
struct agent_connection* con = NULL;
|
struct agent_connection* con = NULL;
|
||||||
OVERLAPPED *p_ol;
|
OVERLAPPED *p_ol;
|
||||||
|
@ -85,7 +66,7 @@ iocp_work(LPVOID lpParam) {
|
||||||
con = NULL;
|
con = NULL;
|
||||||
p_ol = NULL;
|
p_ol = NULL;
|
||||||
if (GetQueuedCompletionStatus(ioc_port, &bytes, &(ULONG_PTR)con, &p_ol, INFINITE) == FALSE) {
|
if (GetQueuedCompletionStatus(ioc_port, &bytes, &(ULONG_PTR)con, &p_ol, INFINITE) == FALSE) {
|
||||||
debug("iocp error: %d on %p \n", GetLastError(), con);
|
debug("iocp error: %d on %p", GetLastError(), con);
|
||||||
if (con)
|
if (con)
|
||||||
agent_connection_on_error(con, GetLastError());
|
agent_connection_on_error(con, GetLastError());
|
||||||
else
|
else
|
||||||
|
@ -93,38 +74,19 @@ iocp_work(LPVOID lpParam) {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
agent_connection_on_io(con, bytes, p_ol);
|
agent_connection_on_io(con, bytes, p_ol);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_connection(HANDLE pipe) {
|
agent_listen_loop()
|
||||||
struct agent_connection* con;
|
{
|
||||||
|
|
||||||
if ((con = malloc(sizeof(struct agent_connection))) == NULL)
|
|
||||||
fatal("failed to alloc");
|
|
||||||
|
|
||||||
memset(con, 0, sizeof(struct agent_connection));
|
|
||||||
con->connection = pipe;
|
|
||||||
if (CreateIoCompletionPort(pipe, ioc_port, (ULONG_PTR)con, 0) != ioc_port)
|
|
||||||
fatal("failed to assign pipe to ioc_port");
|
|
||||||
|
|
||||||
agent_connection_on_io(con, 0, &con->ol);
|
|
||||||
iocp_work(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
agent_listen_loop() {
|
|
||||||
DWORD r;
|
DWORD r;
|
||||||
HANDLE wait_events[2];
|
HANDLE wait_events[2];
|
||||||
|
|
||||||
wait_events[0] = event_stop_agent;
|
wait_events[0] = event_stop_agent;
|
||||||
|
|
||||||
wait_events[1] = ol.hEvent;
|
wait_events[1] = ol.hEvent;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
{
|
|
||||||
{
|
|
||||||
pipe = CreateNamedPipeW(
|
pipe = CreateNamedPipeW(
|
||||||
AGENT_PIPE_ID, // pipe name
|
AGENT_PIPE_ID, // pipe name
|
||||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
|
||||||
|
@ -140,8 +102,7 @@ agent_listen_loop() {
|
||||||
if (pipe == INVALID_HANDLE_VALUE) {
|
if (pipe == INVALID_HANDLE_VALUE) {
|
||||||
verbose("cannot create listener pipe ERROR:%d", GetLastError());
|
verbose("cannot create listener pipe ERROR:%d", GetLastError());
|
||||||
SetEvent(event_stop_agent);
|
SetEvent(event_stop_agent);
|
||||||
}
|
} else if (ConnectNamedPipe(pipe, &ol) != FALSE) {
|
||||||
else if (ConnectNamedPipe(pipe, &ol) != FALSE) {
|
|
||||||
verbose("ConnectNamedPipe returned TRUE unexpectedly ");
|
verbose("ConnectNamedPipe returned TRUE unexpectedly ");
|
||||||
SetEvent(event_stop_agent);
|
SetEvent(event_stop_agent);
|
||||||
}
|
}
|
||||||
|
@ -156,17 +117,13 @@ agent_listen_loop() {
|
||||||
SetEvent(event_stop_agent);
|
SetEvent(event_stop_agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = WaitForMultipleObjects(2, wait_events, FALSE, INFINITE);
|
r = WaitForMultipleObjects(2, wait_events, FALSE, INFINITE);
|
||||||
if (r == WAIT_OBJECT_0) {
|
if (r == WAIT_OBJECT_0) {
|
||||||
//received signal to shutdown
|
/*received signal to shutdown*/
|
||||||
debug("shutting down");
|
debug("shutting down");
|
||||||
agent_cleanup();
|
agent_cleanup();
|
||||||
return;
|
return;
|
||||||
}
|
} else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + 1))) {
|
||||||
else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + 1))) {
|
|
||||||
/* process incoming connection */
|
/* process incoming connection */
|
||||||
HANDLE con = pipe;
|
HANDLE con = pipe;
|
||||||
DWORD client_pid = 0;
|
DWORD client_pid = 0;
|
||||||
|
@ -174,11 +131,10 @@ agent_listen_loop() {
|
||||||
GetNamedPipeClientProcessId(con, &client_pid);
|
GetNamedPipeClientProcessId(con, &client_pid);
|
||||||
verbose("client pid %d connected", client_pid);
|
verbose("client pid %d connected", client_pid);
|
||||||
if (debug_mode) {
|
if (debug_mode) {
|
||||||
process_connection(con);
|
agent_process_connection(con);
|
||||||
agent_cleanup();
|
agent_cleanup();
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/* spawn a child to take care of this*/
|
/* spawn a child to take care of this*/
|
||||||
wchar_t path[PATH_MAX], module_path[PATH_MAX];
|
wchar_t path[PATH_MAX], module_path[PATH_MAX];
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
|
@ -193,8 +149,7 @@ agent_listen_loop() {
|
||||||
DETACHED_PROCESS, NULL, NULL,
|
DETACHED_PROCESS, NULL, NULL,
|
||||||
&si, &pi) == FALSE)) {
|
&si, &pi) == FALSE)) {
|
||||||
verbose("Failed to create child process %ls ERROR:%d", module_path, GetLastError());
|
verbose("Failed to create child process %ls ERROR:%d", module_path, GetLastError());
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
debug("spawned worker %d for agent client pid %d ", pi.dwProcessId, client_pid);
|
debug("spawned worker %d for agent client pid %d ", pi.dwProcessId, client_pid);
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
@ -203,17 +158,18 @@ agent_listen_loop() {
|
||||||
CloseHandle(con);
|
CloseHandle(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
fatal("wait on events ended with %d ERROR:%d", r, GetLastError());
|
fatal("wait on events ended with %d ERROR:%d", r, GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_cleanup_connection(struct agent_connection* con) {
|
void
|
||||||
|
agent_cleanup_connection(struct agent_connection* con)
|
||||||
|
{
|
||||||
debug("connection %p clean up", con);
|
debug("connection %p clean up", con);
|
||||||
CloseHandle(con->connection);
|
CloseHandle(con->pipe_handle);
|
||||||
if (con->hProfile)
|
if (con->hProfile)
|
||||||
UnloadUserProfile(con->auth_token, con->hProfile);
|
UnloadUserProfile(con->auth_token, con->hProfile);
|
||||||
if (con->auth_token)
|
if (con->auth_token)
|
||||||
|
@ -223,45 +179,59 @@ void agent_cleanup_connection(struct agent_connection* con) {
|
||||||
ioc_port = NULL;
|
ioc_port = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_shutdown() {
|
void
|
||||||
verbose("shutdown");
|
agent_shutdown()
|
||||||
|
{
|
||||||
SetEvent(event_stop_agent);
|
SetEvent(event_stop_agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REG_AGENT_SDDL L"D:P(A;; GR;;; AU)(A;; GA;;; SY)(A;; GA;;; BA)"
|
|
||||||
|
|
||||||
void
|
void
|
||||||
agent_start(BOOL dbg_mode, BOOL child, HANDLE pipe) {
|
agent_start(BOOL dbg_mode)
|
||||||
|
{
|
||||||
int r;
|
int r;
|
||||||
HKEY agent_root = NULL;
|
HKEY agent_root = NULL;
|
||||||
DWORD process_id = GetCurrentProcessId();
|
DWORD process_id = GetCurrentProcessId();
|
||||||
|
|
||||||
verbose("agent_start pid:%d, dbg:%d, child:%d, pipe:%d", process_id, dbg_mode, child, pipe);
|
verbose("%s pid:%d, dbg:%d", __FUNCTION__, process_id, dbg_mode);
|
||||||
debug_mode = dbg_mode;
|
debug_mode = dbg_mode;
|
||||||
|
|
||||||
if ((ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0)) == NULL)
|
|
||||||
fatal("cannot create ioc port ERROR:%d", GetLastError());
|
|
||||||
|
|
||||||
|
|
||||||
if (child == FALSE) {
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||||
sa.nLength = sizeof(sa);
|
sa.nLength = sizeof(sa);
|
||||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(REG_AGENT_SDDL, SDDL_REVISION_1, &sa.lpSecurityDescriptor, &sa.nLength))
|
/* allow access to Authenticated users and Network Service */
|
||||||
fatal("ConvertStringSecurityDescriptorToSecurityDescriptorW failed");
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"D:P(A;;GA;;;AU)(A;;GA;;;NS)", SDDL_REVISION_1,
|
||||||
|
&sa.lpSecurityDescriptor, &sa.nLength))
|
||||||
|
fatal("cannot convert sddl ERROR:%d", GetLastError());
|
||||||
if ((r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT, 0, 0, 0, KEY_WRITE, &sa, &agent_root, 0)) != ERROR_SUCCESS)
|
if ((r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT, 0, 0, 0, KEY_WRITE, &sa, &agent_root, 0)) != ERROR_SUCCESS)
|
||||||
fatal("cannot create agent root reg key, ERROR:%d", r);
|
fatal("cannot create agent root reg key, ERROR:%d", r);
|
||||||
if ((r = RegSetValueExW(agent_root, L"ProcessID", 0, REG_DWORD, (BYTE*)&process_id, 4)) != ERROR_SUCCESS)
|
if ((r = RegSetValueExW(agent_root, L"ProcessID", 0, REG_DWORD, (BYTE*)&process_id, 4)) != ERROR_SUCCESS)
|
||||||
fatal("cannot publish agent master process id ERROR:%d", r);
|
fatal("cannot publish agent master process id ERROR:%d", r);
|
||||||
if ((event_stop_agent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
|
if ((event_stop_agent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
|
||||||
fatal("cannot create global stop event ERROR:%d", GetLastError());
|
fatal("cannot create global stop event ERROR:%d", GetLastError());
|
||||||
if ((r = init_listener()) != 0)
|
if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
|
||||||
fatal("failed to create server pipes ERROR:%d", r);
|
fatal("cannot create event ERROR:%d", GetLastError());
|
||||||
|
pipe = INVALID_HANDLE_VALUE;
|
||||||
|
sa.bInheritHandle = FALSE;
|
||||||
agent_listen_loop();
|
agent_listen_loop();
|
||||||
}
|
}
|
||||||
else { /* this is a child process that processes one connection */
|
|
||||||
process_connection(pipe);
|
void
|
||||||
}
|
agent_process_connection(HANDLE pipe)
|
||||||
|
{
|
||||||
|
struct agent_connection* con;
|
||||||
|
verbose("%s pipe:%p", __FUNCTION__, pipe);
|
||||||
|
|
||||||
|
if ((ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0)) == NULL)
|
||||||
|
fatal("cannot create ioc port ERROR:%d", GetLastError());
|
||||||
|
|
||||||
|
if ((con = malloc(sizeof(struct agent_connection))) == NULL)
|
||||||
|
fatal("failed to alloc");
|
||||||
|
|
||||||
|
memset(con, 0, sizeof(struct agent_connection));
|
||||||
|
con->pipe_handle = pipe;
|
||||||
|
if (CreateIoCompletionPort(pipe, ioc_port, (ULONG_PTR)con, 0) != ioc_port)
|
||||||
|
fatal("failed to assign pipe to ioc_port");
|
||||||
|
|
||||||
|
agent_connection_on_io(con, 0, &con->ol);
|
||||||
|
iocp_work(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
struct agent_connection {
|
struct agent_connection {
|
||||||
OVERLAPPED ol;
|
OVERLAPPED ol;
|
||||||
HANDLE connection;
|
HANDLE pipe_handle;
|
||||||
struct {
|
struct {
|
||||||
DWORD num_bytes;
|
DWORD num_bytes;
|
||||||
DWORD transferred;
|
DWORD transferred;
|
||||||
|
@ -27,11 +27,9 @@ struct agent_connection {
|
||||||
} state;
|
} state;
|
||||||
enum {
|
enum {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
OTHER,
|
USER, /* client is running as some user */
|
||||||
LOCAL_SYSTEM,
|
MACHINE /* clinet is running as machine - System, NS or LS */
|
||||||
SSHD,
|
} client_type;
|
||||||
NETWORK_SERVICE
|
|
||||||
} client_process;
|
|
||||||
HANDLE auth_token;
|
HANDLE auth_token;
|
||||||
HANDLE hProfile;
|
HANDLE hProfile;
|
||||||
};
|
};
|
||||||
|
@ -40,7 +38,8 @@ void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
|
||||||
void agent_connection_on_error(struct agent_connection* , DWORD);
|
void agent_connection_on_error(struct agent_connection* , DWORD);
|
||||||
void agent_connection_disconnect(struct agent_connection*);
|
void agent_connection_disconnect(struct agent_connection*);
|
||||||
|
|
||||||
void agent_start(BOOL, BOOL, HANDLE);
|
void agent_start(BOOL);
|
||||||
|
void agent_process_connection(HANDLE);
|
||||||
void agent_shutdown();
|
void agent_shutdown();
|
||||||
void agent_cleanup_connection(struct agent_connection*);
|
void agent_cleanup_connection(struct agent_connection*);
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,6 @@ int load_config() {
|
||||||
wchar_t basePath[PATH_MAX] = { 0 };
|
wchar_t basePath[PATH_MAX] = { 0 };
|
||||||
wchar_t path[PATH_MAX] = { 0 };
|
wchar_t path[PATH_MAX] = { 0 };
|
||||||
|
|
||||||
/* TODO - account for UNICODE paths*/
|
|
||||||
if (GetCurrentModulePath(basePath, PATH_MAX) == -1)
|
if (GetCurrentModulePath(basePath, PATH_MAX) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
|
if ((FALSE == GetNamedPipeClientProcessId(con->pipe_handle, &client_pid)) ||
|
||||||
((client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
|
((client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
|
||||||
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
|
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
|
||||||
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
|
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
|
||||||
|
@ -317,7 +317,7 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) ||
|
if ((FALSE == GetNamedPipeClientProcessId(con->pipe_handle, &client_pid)) ||
|
||||||
( (client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
|
( (client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) ||
|
||||||
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
|
(FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) ||
|
||||||
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
|
(sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)) {
|
||||||
|
|
|
@ -39,21 +39,22 @@ int process_request(struct agent_connection*);
|
||||||
return; \
|
return; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void agent_connection_on_error(struct agent_connection* con, DWORD error) {
|
void
|
||||||
|
agent_connection_on_error(struct agent_connection* con, DWORD error)
|
||||||
|
{
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPED* ol) {
|
void
|
||||||
|
agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPED* ol)
|
||||||
|
{
|
||||||
/* process error */
|
/* process error */
|
||||||
debug3("connection io %p #bytes:%d state:%d", con, bytes, con->state);
|
debug3("connection io %p #bytes:%d state:%d", con, bytes, con->state);
|
||||||
if ((bytes == 0) && (GetOverlappedResult(con->connection, ol, &bytes, FALSE) == FALSE))
|
if ((bytes == 0) && (GetOverlappedResult(con->pipe_handle, ol, &bytes, FALSE) == FALSE))
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
|
|
||||||
if (con->state == DONE)
|
if (con->state == DONE)
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
|
|
||||||
{
|
|
||||||
switch (con->state) {
|
switch (con->state) {
|
||||||
case LISTENING:
|
case LISTENING:
|
||||||
case WRITING:
|
case WRITING:
|
||||||
|
@ -63,7 +64,7 @@ void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPE
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
con->state = READING_HEADER;
|
con->state = READING_HEADER;
|
||||||
ZeroMemory(&con->io_buf, sizeof(con->io_buf));
|
ZeroMemory(&con->io_buf, sizeof(con->io_buf));
|
||||||
if (!ReadFile(con->connection, con->io_buf.buf,
|
if (!ReadFile(con->pipe_handle, con->io_buf.buf,
|
||||||
HEADER_SIZE, NULL, &con->ol) && (GetLastError() != ERROR_IO_PENDING))
|
HEADER_SIZE, NULL, &con->ol) && (GetLastError() != ERROR_IO_PENDING))
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
break;
|
break;
|
||||||
|
@ -76,12 +77,11 @@ void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPE
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
|
|
||||||
con->state = READING;
|
con->state = READING;
|
||||||
if (!ReadFile(con->connection, con->io_buf.buf,
|
if (!ReadFile(con->pipe_handle, con->io_buf.buf,
|
||||||
con->io_buf.num_bytes, NULL, &con->ol)&&(GetLastError() != ERROR_IO_PENDING))
|
con->io_buf.num_bytes, NULL, &con->ol)&&(GetLastError() != ERROR_IO_PENDING))
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
}
|
} else {
|
||||||
else {
|
if (!ReadFile(con->pipe_handle, con->io_buf.buf + con->io_buf.num_bytes,
|
||||||
if (!ReadFile(con->connection, con->io_buf.buf + con->io_buf.num_bytes,
|
|
||||||
HEADER_SIZE - con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
|
HEADER_SIZE - con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
}
|
}
|
||||||
|
@ -93,12 +93,11 @@ void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPE
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
}
|
}
|
||||||
con->state = WRITING;
|
con->state = WRITING;
|
||||||
if (!WriteFile(con->connection, con->io_buf.buf,
|
if (!WriteFile(con->pipe_handle, con->io_buf.buf,
|
||||||
con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING) )
|
con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING) )
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
}
|
} else {
|
||||||
else {
|
if (!ReadFile(con->pipe_handle, con->io_buf.buf + con->io_buf.transferred,
|
||||||
if (!ReadFile(con->connection, con->io_buf.buf + con->io_buf.transferred,
|
|
||||||
con->io_buf.num_bytes - con->io_buf.transferred, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
|
con->io_buf.num_bytes - con->io_buf.transferred, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
|
||||||
ABORT_CONNECTION_RETURN(con);
|
ABORT_CONNECTION_RETURN(con);
|
||||||
}
|
}
|
||||||
|
@ -106,34 +105,32 @@ void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPE
|
||||||
default:
|
default:
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_connection_disconnect(struct agent_connection* con) {
|
void
|
||||||
CancelIoEx(con->connection, NULL);
|
agent_connection_disconnect(struct agent_connection* con)
|
||||||
DisconnectNamedPipe(con->connection);
|
{
|
||||||
|
CancelIoEx(con->pipe_handle, NULL);
|
||||||
|
DisconnectNamedPipe(con->pipe_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_con_client_type(HANDLE pipe) {
|
get_con_client_type(struct agent_connection* con)
|
||||||
|
{
|
||||||
int r = -1;
|
int r = -1;
|
||||||
wchar_t *sshd_act = L"NT SERVICE\\SSHD", *ref_dom = NULL;
|
|
||||||
PSID sshd_sid = NULL;
|
|
||||||
char system_sid[SECURITY_MAX_SID_SIZE];
|
char system_sid[SECURITY_MAX_SID_SIZE];
|
||||||
char ns_sid[SECURITY_MAX_SID_SIZE];
|
char ns_sid[SECURITY_MAX_SID_SIZE];
|
||||||
DWORD sshd_sid_len = 0, reg_dom_len = 0, info_len = 0, sid_size;
|
char ls_sid[SECURITY_MAX_SID_SIZE];
|
||||||
|
DWORD reg_dom_len = 0, info_len = 0, sid_size;
|
||||||
SID_NAME_USE nuse;
|
SID_NAME_USE nuse;
|
||||||
HANDLE token;
|
HANDLE token;
|
||||||
TOKEN_USER* info = NULL;
|
TOKEN_USER* info = NULL;
|
||||||
|
HANDLE pipe = con->pipe_handle;
|
||||||
|
|
||||||
if (ImpersonateNamedPipeClient(pipe) == FALSE)
|
if (ImpersonateNamedPipeClient(pipe) == FALSE)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (LookupAccountNameW(NULL, sshd_act, NULL, &sshd_sid_len, NULL, ®_dom_len, &nuse) == TRUE ||
|
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &token) == FALSE ||
|
||||||
(sshd_sid = malloc(sshd_sid_len)) == NULL ||
|
|
||||||
(ref_dom = (wchar_t*)malloc(reg_dom_len * 2)) == NULL ||
|
|
||||||
LookupAccountNameW(NULL, sshd_act, sshd_sid, &sshd_sid_len, ref_dom, ®_dom_len, &nuse) == FALSE ||
|
|
||||||
OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &token) == FALSE ||
|
|
||||||
GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
|
GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
|
||||||
(info = (TOKEN_USER*)malloc(info_len)) == NULL ||
|
(info = (TOKEN_USER*)malloc(info_len)) == NULL ||
|
||||||
GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE)
|
GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE)
|
||||||
|
@ -145,22 +142,20 @@ get_con_client_type(HANDLE pipe) {
|
||||||
sid_size = SECURITY_MAX_SID_SIZE;
|
sid_size = SECURITY_MAX_SID_SIZE;
|
||||||
if (CreateWellKnownSid(WinNetworkServiceSid, NULL, ns_sid, &sid_size) == FALSE)
|
if (CreateWellKnownSid(WinNetworkServiceSid, NULL, ns_sid, &sid_size) == FALSE)
|
||||||
goto done;
|
goto done;
|
||||||
|
sid_size = SECURITY_MAX_SID_SIZE;
|
||||||
|
if (CreateWellKnownSid(WinLocalServiceSid, NULL, ls_sid, &sid_size) == FALSE)
|
||||||
|
goto done;
|
||||||
|
|
||||||
if (EqualSid(info->User.Sid, system_sid))
|
if (EqualSid(info->User.Sid, system_sid) ||
|
||||||
r = LOCAL_SYSTEM;
|
EqualSid(info->User.Sid, ls_sid) ||
|
||||||
else if (EqualSid(info->User.Sid, sshd_sid))
|
EqualSid(info->User.Sid, ns_sid))
|
||||||
r = SSHD;
|
con->client_type = MACHINE;
|
||||||
else if (EqualSid(info->User.Sid, ns_sid))
|
|
||||||
r = NETWORK_SERVICE;
|
|
||||||
else
|
else
|
||||||
r = OTHER;
|
con->client_type = USER;
|
||||||
|
|
||||||
debug2("client type: %d", r);
|
debug2("client type: %s", con->client_type == MACHINE? "machine" : "user");
|
||||||
|
r = 0;
|
||||||
done:
|
done:
|
||||||
if (sshd_sid)
|
|
||||||
free(sshd_sid);
|
|
||||||
if (ref_dom)
|
|
||||||
free(ref_dom);
|
|
||||||
if (info)
|
if (info)
|
||||||
free(info);
|
free(info);
|
||||||
RevertToSelf();
|
RevertToSelf();
|
||||||
|
@ -168,23 +163,22 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_request(struct agent_connection* con) {
|
process_request(struct agent_connection* con)
|
||||||
|
{
|
||||||
int r = -1;
|
int r = -1;
|
||||||
struct sshbuf *request = NULL, *response = NULL;
|
struct sshbuf *request = NULL, *response = NULL;
|
||||||
|
u_char type;
|
||||||
|
|
||||||
if (con->client_process == UNKNOWN)
|
if (con->client_type == UNKNOWN && get_con_client_type(con) == -1) {
|
||||||
if ((con->client_process = get_con_client_type(con->connection)) == -1)
|
debug("unable to get client process type");
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
//Sleep(30 * 1000);
|
|
||||||
request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
|
request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
|
||||||
response = sshbuf_new();
|
response = sshbuf_new();
|
||||||
if ((request == NULL) || (response == NULL))
|
if ((request == NULL) || (response == NULL))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
{
|
|
||||||
u_char type;
|
|
||||||
|
|
||||||
if (sshbuf_get_u8(request, &type) != 0)
|
if (sshbuf_get_u8(request, &type) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
debug("process agent request type %d", type);
|
debug("process agent request type %d", type);
|
||||||
|
@ -213,7 +207,6 @@ process_request(struct agent_connection* con) {
|
||||||
r = -1;
|
r = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (request)
|
if (request)
|
||||||
|
|
|
@ -36,21 +36,33 @@
|
||||||
#define MAX_KEY_LENGTH 255
|
#define MAX_KEY_LENGTH 255
|
||||||
#define MAX_VALUE_NAME 16383
|
#define MAX_VALUE_NAME 16383
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get registry root where keys are stored
|
||||||
|
* user keys are stored in user's hive
|
||||||
|
* while system keys (host keys) in HKLM
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
get_user_root(struct agent_connection* con, HKEY *root){
|
get_user_root(struct agent_connection* con, HKEY *root)
|
||||||
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
*root = NULL;
|
LONG ret;
|
||||||
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (con->client_process > OTHER)
|
|
||||||
*root = HKEY_LOCAL_MACHINE;
|
*root = HKEY_LOCAL_MACHINE;
|
||||||
else if (RegOpenCurrentUser(KEY_ALL_ACCESS, root) != ERROR_SUCCESS)
|
|
||||||
r = -1;
|
|
||||||
|
|
||||||
if (*root == NULL)
|
if (con->client_type == USER) {
|
||||||
debug("cannot connect to user's registry root");
|
if (ImpersonateNamedPipeClient(con->pipe_handle) == FALSE)
|
||||||
|
return -1;
|
||||||
|
*root = NULL;
|
||||||
|
/*
|
||||||
|
* TODO - check that user profile is loaded,
|
||||||
|
* otherwise, this will return default profile
|
||||||
|
*/
|
||||||
|
if ((ret = RegOpenCurrentUser(KEY_ALL_ACCESS, root)) != ERROR_SUCCESS) {
|
||||||
|
debug("unable to open user's registry hive, ERROR - %d", ret);
|
||||||
|
r = -1;
|
||||||
|
}
|
||||||
|
|
||||||
RevertToSelf();
|
RevertToSelf();
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +71,8 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
||||||
int success = 0;
|
int success = 0;
|
||||||
DATA_BLOB in, out;
|
DATA_BLOB in, out;
|
||||||
|
|
||||||
if (con->client_process == OTHER)
|
if (con->client_type == USER)
|
||||||
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
if (ImpersonateNamedPipeClient(con->pipe_handle) == FALSE)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
in.cbData = blen;
|
in.cbData = blen;
|
||||||
|
@ -73,8 +85,7 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
||||||
debug("cannot encrypt data");
|
debug("cannot encrypt data");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (!CryptUnprotectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
|
if (!CryptUnprotectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
|
||||||
debug("cannot decrypt data");
|
debug("cannot decrypt data");
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -91,7 +102,7 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
||||||
done:
|
done:
|
||||||
if (out.pbData)
|
if (out.pbData)
|
||||||
LocalFree(out.pbData);
|
LocalFree(out.pbData);
|
||||||
if (con->client_process == OTHER)
|
if (con->client_type == USER)
|
||||||
RevertToSelf();
|
RevertToSelf();
|
||||||
return success? 0: -1;
|
return success? 0: -1;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +110,8 @@ done:
|
||||||
#define REG_KEY_SDDL L"D:P(A;; GA;;; SY)(A;; GA;;; BA)"
|
#define REG_KEY_SDDL L"D:P(A;; GA;;; SY)(A;; GA;;; BA)"
|
||||||
|
|
||||||
int
|
int
|
||||||
process_add_identity(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
process_add_identity(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con)
|
||||||
|
{
|
||||||
struct sshkey* key = NULL;
|
struct sshkey* key = NULL;
|
||||||
int r = 0, blob_len, eblob_len, request_invalid = 0, success = 0;
|
int r = 0, blob_len, eblob_len, request_invalid = 0, success = 0;
|
||||||
size_t comment_len, pubkey_blob_len;
|
size_t comment_len, pubkey_blob_len;
|
||||||
|
@ -170,7 +182,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
|
static int sign_blob(const struct sshkey *pubkey, u_char ** sig, size_t *siglen,
|
||||||
const u_char *blob, size_t blen, u_int flags, struct agent_connection* con) {
|
const u_char *blob, size_t blen, u_int flags, struct agent_connection* con)
|
||||||
|
{
|
||||||
HKEY reg = 0, sub = 0, user_root = 0;
|
HKEY reg = 0, sub = 0, user_root = 0;
|
||||||
int r = 0, success = 0;
|
int r = 0, success = 0;
|
||||||
struct sshkey* prikey = NULL;
|
struct sshkey* prikey = NULL;
|
||||||
|
@ -225,7 +238,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
process_sign_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
process_sign_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con)
|
||||||
|
{
|
||||||
u_char *blob, *data, *signature = NULL;
|
u_char *blob, *data, *signature = NULL;
|
||||||
size_t blen, dlen, slen = 0;
|
size_t blen, dlen, slen = 0;
|
||||||
u_int flags = 0;
|
u_int flags = 0;
|
||||||
|
@ -257,8 +271,7 @@ done:
|
||||||
sshbuf_put_string(response, signature, slen) != 0) {
|
sshbuf_put_string(response, signature, slen) != 0) {
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
if (sshbuf_put_u8(response, SSH_AGENT_FAILURE) != 0)
|
if (sshbuf_put_u8(response, SSH_AGENT_FAILURE) != 0)
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
|
@ -271,7 +284,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
process_remove_key(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
process_remove_key(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con)
|
||||||
|
{
|
||||||
HKEY user_root = 0, root = 0;
|
HKEY user_root = 0, root = 0;
|
||||||
char *blob, *thumbprint = NULL;
|
char *blob, *thumbprint = NULL;
|
||||||
size_t blen;
|
size_t blen;
|
||||||
|
@ -309,7 +323,8 @@ done:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
process_remove_all(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
process_remove_all(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con)
|
||||||
|
{
|
||||||
HKEY user_root = 0, root = 0;
|
HKEY user_root = 0, root = 0;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
|
@ -333,7 +348,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
process_request_identities(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
process_request_identities(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con)
|
||||||
|
{
|
||||||
int count = 0, index = 0, success = 0, r = 0;
|
int count = 0, index = 0, success = 0, r = 0;
|
||||||
HKEY root = NULL, sub = NULL, user_root = 0;
|
HKEY root = NULL, sub = NULL, user_root = 0;
|
||||||
char* count_ptr = NULL;
|
char* count_ptr = NULL;
|
||||||
|
@ -379,8 +395,7 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, stru
|
||||||
|
|
||||||
key_count++;
|
key_count++;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -393,8 +408,7 @@ done:
|
||||||
sshbuf_put_u32(response, key_count) != 0 ||
|
sshbuf_put_u32(response, key_count) != 0 ||
|
||||||
sshbuf_putb(response, identities) != 0)
|
sshbuf_putb(response, identities) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
r = -1;
|
r = -1;
|
||||||
|
|
||||||
if (pkblob)
|
if (pkblob)
|
||||||
|
@ -413,7 +427,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int process_keyagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
int process_keyagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con)
|
||||||
|
{
|
||||||
u_char type;
|
u_char type;
|
||||||
|
|
||||||
if (sshbuf_get_u8(request, &type) != 0)
|
if (sshbuf_get_u8(request, &type) != 0)
|
||||||
|
|
Loading…
Reference in New Issue