parent
bc3f21a6a3
commit
1ff1b07410
Binary file not shown.
|
@ -11,70 +11,6 @@ $logsdir = Join-Path $scriptdir "logs"
|
|||
|
||||
$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)) {
|
||||
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)'
|
||||
|
||||
New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Daemon" -StartupType Manual -DependsOn ssh-agent | Out-Null
|
||||
sc.exe config sshd obj= $sshdAccount
|
||||
|
||||
Add-Privilege -Account $sshdAccount -Privilege SeAssignPrimaryTokenPrivilege
|
||||
Add-Privilege -Account $sshdAccount -Privilege SeServiceLogonRight
|
||||
sc.exe config sshd obj= "NT AUTHORITY\NetworkService"
|
||||
sc.exe sidtype sshd unrestricted
|
||||
|
||||
if(-not (test-path $logsdir -PathType Container))
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
|
||||
* ssh-agent implementation on Windows
|
||||
* NT Service routines
|
||||
*
|
||||
* Copyright (c) 2015 Microsoft Corp.
|
||||
* All rights reserved
|
||||
|
@ -43,7 +44,8 @@ static SERVICE_STATUS_HANDLE service_status_handle;
|
|||
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.dwWin32ExitCode = dwWin32ExitCode;
|
||||
|
@ -62,7 +64,8 @@ static VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD d
|
|||
SetServiceStatus(service_status_handle, &service_status);
|
||||
}
|
||||
|
||||
static VOID WINAPI service_handler(DWORD dwControl)
|
||||
static VOID WINAPI
|
||||
service_handler(DWORD dwControl)
|
||||
{
|
||||
switch (dwControl)
|
||||
{
|
||||
|
@ -81,22 +84,27 @@ static VOID WINAPI service_handler(DWORD dwControl)
|
|||
ReportSvcStatus(service_status.dwCurrentState, NO_ERROR, 0);
|
||||
}
|
||||
|
||||
BOOL WINAPI ctrl_c_handler(
|
||||
_In_ DWORD dwCtrlType
|
||||
) {
|
||||
BOOL WINAPI
|
||||
ctrl_c_handler(_In_ DWORD dwCtrlType)
|
||||
{
|
||||
/* for any Ctrl type, shutdown agent*/
|
||||
debug("Ctrl+C received");
|
||||
agent_shutdown();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t **argv) {
|
||||
|
||||
int
|
||||
wmain(int argc, wchar_t **argv)
|
||||
{
|
||||
w32posix_initialize();
|
||||
/* this exits() on failure*/
|
||||
load_config();
|
||||
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
||||
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 (wcsncmp(argv[1], L"-ddd", 4) == 0)
|
||||
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)
|
||||
log_init("ssh-agent", 5, 1, 1);
|
||||
|
||||
/* Set Ctrl+C handler if starting in debug mode */
|
||||
if (wcsncmp(argv[1], L"-d", 2) == 0) {
|
||||
SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
|
||||
agent_start(TRUE, FALSE, 0);
|
||||
agent_start(TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -116,7 +125,7 @@ int wmain(int argc, wchar_t **argv) {
|
|||
h += _wtoi(*(argv + 1));
|
||||
if (h != 0) {
|
||||
log_init("ssh-agent", config_log_level(), 1, 0);
|
||||
agent_start(FALSE, TRUE, h);
|
||||
agent_process_connection(h);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -146,14 +155,16 @@ int wmain(int argc, wchar_t **argv) {
|
|||
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);
|
||||
ZeroMemory(&service_status, sizeof(service_status));
|
||||
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 300);
|
||||
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||
log_init("ssh-agent", config_log_level(), 1, 0);
|
||||
agent_start(FALSE, FALSE, 0);
|
||||
agent_start(FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,40 +44,21 @@ static OVERLAPPED ol;
|
|||
static HANDLE pipe;
|
||||
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
|
||||
agent_cleanup() {
|
||||
{
|
||||
if (ol.hEvent != NULL)
|
||||
CloseHandle(ol.hEvent);
|
||||
if (pipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pipe);
|
||||
}
|
||||
agent_cleanup()
|
||||
{
|
||||
if (ol.hEvent != NULL)
|
||||
CloseHandle(ol.hEvent);
|
||||
if (pipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pipe);
|
||||
if (ioc_port)
|
||||
CloseHandle(ioc_port);
|
||||
return;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
iocp_work(LPVOID lpParam) {
|
||||
iocp_work(LPVOID lpParam)
|
||||
{
|
||||
DWORD bytes;
|
||||
struct agent_connection* con = NULL;
|
||||
OVERLAPPED *p_ol;
|
||||
|
@ -85,7 +66,7 @@ iocp_work(LPVOID lpParam) {
|
|||
con = NULL;
|
||||
p_ol = NULL;
|
||||
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)
|
||||
agent_connection_on_error(con, GetLastError());
|
||||
else
|
||||
|
@ -93,80 +74,56 @@ iocp_work(LPVOID lpParam) {
|
|||
}
|
||||
else
|
||||
agent_connection_on_io(con, bytes, p_ol);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_connection(HANDLE pipe) {
|
||||
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() {
|
||||
agent_listen_loop()
|
||||
{
|
||||
DWORD r;
|
||||
HANDLE wait_events[2];
|
||||
|
||||
wait_events[0] = event_stop_agent;
|
||||
|
||||
wait_events[1] = ol.hEvent;
|
||||
|
||||
while (1) {
|
||||
{
|
||||
{
|
||||
pipe = CreateNamedPipeW(
|
||||
AGENT_PIPE_ID, // pipe name
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
|
||||
PIPE_TYPE_BYTE | // message type pipe
|
||||
PIPE_READMODE_BYTE | // message-read mode
|
||||
PIPE_WAIT, // blocking mode
|
||||
PIPE_UNLIMITED_INSTANCES, // max. instances
|
||||
BUFSIZE, // output buffer size
|
||||
BUFSIZE, // input buffer size
|
||||
0, // client time-out
|
||||
&sa);
|
||||
pipe = CreateNamedPipeW(
|
||||
AGENT_PIPE_ID, // pipe name
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
|
||||
PIPE_TYPE_BYTE | // message type pipe
|
||||
PIPE_READMODE_BYTE | // message-read mode
|
||||
PIPE_WAIT, // blocking mode
|
||||
PIPE_UNLIMITED_INSTANCES, // max. instances
|
||||
BUFSIZE, // output buffer size
|
||||
BUFSIZE, // input buffer size
|
||||
0, // client time-out
|
||||
&sa);
|
||||
|
||||
if (pipe == INVALID_HANDLE_VALUE) {
|
||||
verbose("cannot create listener pipe ERROR:%d", GetLastError());
|
||||
SetEvent(event_stop_agent);
|
||||
}
|
||||
else if (ConnectNamedPipe(pipe, &ol) != FALSE) {
|
||||
verbose("ConnectNamedPipe returned TRUE unexpectedly ");
|
||||
SetEvent(event_stop_agent);
|
||||
}
|
||||
if (pipe == INVALID_HANDLE_VALUE) {
|
||||
verbose("cannot create listener pipe ERROR:%d", GetLastError());
|
||||
SetEvent(event_stop_agent);
|
||||
} else if (ConnectNamedPipe(pipe, &ol) != FALSE) {
|
||||
verbose("ConnectNamedPipe returned TRUE unexpectedly ");
|
||||
SetEvent(event_stop_agent);
|
||||
}
|
||||
|
||||
if (GetLastError() == ERROR_PIPE_CONNECTED) {
|
||||
debug("Client has already connected");
|
||||
SetEvent(ol.hEvent);
|
||||
}
|
||||
if (GetLastError() == ERROR_PIPE_CONNECTED) {
|
||||
debug("Client has already connected");
|
||||
SetEvent(ol.hEvent);
|
||||
}
|
||||
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
debug("ConnectNamedPipe failed ERROR: %d", GetLastError());
|
||||
SetEvent(event_stop_agent);
|
||||
}
|
||||
|
||||
}
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
debug("ConnectNamedPipe failed ERROR: %d", GetLastError());
|
||||
SetEvent(event_stop_agent);
|
||||
}
|
||||
|
||||
r = WaitForMultipleObjects(2, wait_events, FALSE, INFINITE);
|
||||
if (r == WAIT_OBJECT_0) {
|
||||
//received signal to shutdown
|
||||
/*received signal to shutdown*/
|
||||
debug("shutting down");
|
||||
agent_cleanup();
|
||||
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 */
|
||||
HANDLE con = pipe;
|
||||
DWORD client_pid = 0;
|
||||
|
@ -174,11 +131,10 @@ agent_listen_loop() {
|
|||
GetNamedPipeClientProcessId(con, &client_pid);
|
||||
verbose("client pid %d connected", client_pid);
|
||||
if (debug_mode) {
|
||||
process_connection(con);
|
||||
agent_process_connection(con);
|
||||
agent_cleanup();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* spawn a child to take care of this*/
|
||||
wchar_t path[PATH_MAX], module_path[PATH_MAX];
|
||||
PROCESS_INFORMATION pi;
|
||||
|
@ -193,8 +149,7 @@ agent_listen_loop() {
|
|||
DETACHED_PROCESS, NULL, NULL,
|
||||
&si, &pi) == FALSE)) {
|
||||
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);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
@ -203,17 +158,18 @@ agent_listen_loop() {
|
|||
CloseHandle(con);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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);
|
||||
CloseHandle(con->connection);
|
||||
CloseHandle(con->pipe_handle);
|
||||
if (con->hProfile)
|
||||
UnloadUserProfile(con->auth_token, con->hProfile);
|
||||
if (con->auth_token)
|
||||
|
@ -223,45 +179,59 @@ void agent_cleanup_connection(struct agent_connection* con) {
|
|||
ioc_port = NULL;
|
||||
}
|
||||
|
||||
void agent_shutdown() {
|
||||
verbose("shutdown");
|
||||
void
|
||||
agent_shutdown()
|
||||
{
|
||||
SetEvent(event_stop_agent);
|
||||
}
|
||||
|
||||
#define REG_AGENT_SDDL L"D:P(A;; GR;;; AU)(A;; GA;;; SY)(A;; GA;;; BA)"
|
||||
|
||||
void
|
||||
agent_start(BOOL dbg_mode, BOOL child, HANDLE pipe) {
|
||||
agent_start(BOOL dbg_mode)
|
||||
{
|
||||
int r;
|
||||
HKEY agent_root = NULL;
|
||||
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;
|
||||
|
||||
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.nLength = sizeof(sa);
|
||||
/* allow access to Authenticated users and Network Service */
|
||||
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)
|
||||
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)
|
||||
fatal("cannot publish agent master process id ERROR:%d", r);
|
||||
if ((event_stop_agent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
|
||||
fatal("cannot create global stop event ERROR:%d", GetLastError());
|
||||
if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
|
||||
fatal("cannot create event ERROR:%d", GetLastError());
|
||||
pipe = INVALID_HANDLE_VALUE;
|
||||
sa.bInheritHandle = FALSE;
|
||||
agent_listen_loop();
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
if (child == FALSE) {
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.nLength = sizeof(sa);
|
||||
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(REG_AGENT_SDDL, SDDL_REVISION_1, &sa.lpSecurityDescriptor, &sa.nLength))
|
||||
fatal("ConvertStringSecurityDescriptorToSecurityDescriptorW failed");
|
||||
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);
|
||||
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);
|
||||
if ((event_stop_agent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
|
||||
fatal("cannot create global stop event ERROR:%d", GetLastError());
|
||||
if ((r = init_listener()) != 0)
|
||||
fatal("failed to create server pipes ERROR:%d", r);
|
||||
agent_listen_loop();
|
||||
}
|
||||
else { /* this is a child process that processes one connection */
|
||||
process_connection(pipe);
|
||||
}
|
||||
|
||||
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 {
|
||||
OVERLAPPED ol;
|
||||
HANDLE connection;
|
||||
HANDLE pipe_handle;
|
||||
struct {
|
||||
DWORD num_bytes;
|
||||
DWORD transferred;
|
||||
|
@ -27,11 +27,9 @@ struct agent_connection {
|
|||
} state;
|
||||
enum {
|
||||
UNKNOWN = 0,
|
||||
OTHER,
|
||||
LOCAL_SYSTEM,
|
||||
SSHD,
|
||||
NETWORK_SERVICE
|
||||
} client_process;
|
||||
USER, /* client is running as some user */
|
||||
MACHINE /* clinet is running as machine - System, NS or LS */
|
||||
} client_type;
|
||||
HANDLE auth_token;
|
||||
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_disconnect(struct agent_connection*);
|
||||
|
||||
void agent_start(BOOL, BOOL, HANDLE);
|
||||
void agent_start(BOOL);
|
||||
void agent_process_connection(HANDLE);
|
||||
void agent_shutdown();
|
||||
void agent_cleanup_connection(struct agent_connection*);
|
||||
|
||||
|
|
|
@ -96,7 +96,6 @@ int load_config() {
|
|||
wchar_t basePath[PATH_MAX] = { 0 };
|
||||
wchar_t path[PATH_MAX] = { 0 };
|
||||
|
||||
/* TODO - account for UNICODE paths*/
|
||||
if (GetCurrentModulePath(basePath, PATH_MAX) == -1)
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response
|
|||
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) ||
|
||||
(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)) {
|
||||
|
@ -317,7 +317,7 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
|
|||
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) ||
|
||||
(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)) {
|
||||
|
|
|
@ -39,104 +39,101 @@ int process_request(struct agent_connection*);
|
|||
return; \
|
||||
} 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);
|
||||
}
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
if (con->state == DONE)
|
||||
DebugBreak();
|
||||
|
||||
{
|
||||
switch (con->state) {
|
||||
case LISTENING:
|
||||
case WRITING:
|
||||
/* Writing is done, read next request */
|
||||
/* assert on assumption that write always completes on sending all bytes*/
|
||||
if (bytes != con->io_buf.num_bytes)
|
||||
DebugBreak();
|
||||
con->state = READING_HEADER;
|
||||
ZeroMemory(&con->io_buf, sizeof(con->io_buf));
|
||||
if (!ReadFile(con->connection, con->io_buf.buf,
|
||||
HEADER_SIZE, NULL, &con->ol) && (GetLastError() != ERROR_IO_PENDING))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
break;
|
||||
case READING_HEADER:
|
||||
con->io_buf.transferred += bytes;
|
||||
if (con->io_buf.transferred == HEADER_SIZE) {
|
||||
con->io_buf.num_bytes = PEEK_U32(con->io_buf.buf);
|
||||
con->io_buf.transferred = 0;
|
||||
if (con->io_buf.num_bytes > MAX_MESSAGE_SIZE)
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
|
||||
con->state = READING;
|
||||
if (!ReadFile(con->connection, con->io_buf.buf,
|
||||
con->io_buf.num_bytes, NULL, &con->ol)&&(GetLastError() != ERROR_IO_PENDING))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
else {
|
||||
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))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
break;
|
||||
case READING:
|
||||
con->io_buf.transferred += bytes;
|
||||
if (con->io_buf.transferred == con->io_buf.num_bytes) {
|
||||
if (process_request(con) != 0) {
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
con->state = WRITING;
|
||||
if (!WriteFile(con->connection, con->io_buf.buf,
|
||||
con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING) )
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
else {
|
||||
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))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (con->state) {
|
||||
case LISTENING:
|
||||
case WRITING:
|
||||
/* Writing is done, read next request */
|
||||
/* assert on assumption that write always completes on sending all bytes*/
|
||||
if (bytes != con->io_buf.num_bytes)
|
||||
DebugBreak();
|
||||
}
|
||||
}
|
||||
con->state = READING_HEADER;
|
||||
ZeroMemory(&con->io_buf, sizeof(con->io_buf));
|
||||
if (!ReadFile(con->pipe_handle, con->io_buf.buf,
|
||||
HEADER_SIZE, NULL, &con->ol) && (GetLastError() != ERROR_IO_PENDING))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
break;
|
||||
case READING_HEADER:
|
||||
con->io_buf.transferred += bytes;
|
||||
if (con->io_buf.transferred == HEADER_SIZE) {
|
||||
con->io_buf.num_bytes = PEEK_U32(con->io_buf.buf);
|
||||
con->io_buf.transferred = 0;
|
||||
if (con->io_buf.num_bytes > MAX_MESSAGE_SIZE)
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
|
||||
con->state = READING;
|
||||
if (!ReadFile(con->pipe_handle, con->io_buf.buf,
|
||||
con->io_buf.num_bytes, NULL, &con->ol)&&(GetLastError() != ERROR_IO_PENDING))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
} else {
|
||||
if (!ReadFile(con->pipe_handle, con->io_buf.buf + con->io_buf.num_bytes,
|
||||
HEADER_SIZE - con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
break;
|
||||
case READING:
|
||||
con->io_buf.transferred += bytes;
|
||||
if (con->io_buf.transferred == con->io_buf.num_bytes) {
|
||||
if (process_request(con) != 0) {
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
con->state = WRITING;
|
||||
if (!WriteFile(con->pipe_handle, con->io_buf.buf,
|
||||
con->io_buf.num_bytes, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING) )
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
} else {
|
||||
if (!ReadFile(con->pipe_handle, con->io_buf.buf + con->io_buf.transferred,
|
||||
con->io_buf.num_bytes - con->io_buf.transferred, NULL, &con->ol)&& (GetLastError() != ERROR_IO_PENDING))
|
||||
ABORT_CONNECTION_RETURN(con);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DebugBreak();
|
||||
}
|
||||
}
|
||||
|
||||
void agent_connection_disconnect(struct agent_connection* con) {
|
||||
CancelIoEx(con->connection, NULL);
|
||||
DisconnectNamedPipe(con->connection);
|
||||
void
|
||||
agent_connection_disconnect(struct agent_connection* con)
|
||||
{
|
||||
CancelIoEx(con->pipe_handle, NULL);
|
||||
DisconnectNamedPipe(con->pipe_handle);
|
||||
}
|
||||
|
||||
static int
|
||||
get_con_client_type(HANDLE pipe) {
|
||||
get_con_client_type(struct agent_connection* con)
|
||||
{
|
||||
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 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;
|
||||
HANDLE token;
|
||||
TOKEN_USER* info = NULL;
|
||||
HANDLE pipe = con->pipe_handle;
|
||||
|
||||
if (ImpersonateNamedPipeClient(pipe) == FALSE)
|
||||
return -1;
|
||||
|
||||
if (LookupAccountNameW(NULL, sshd_act, NULL, &sshd_sid_len, NULL, ®_dom_len, &nuse) == TRUE ||
|
||||
(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 ||
|
||||
(info = (TOKEN_USER*)malloc(info_len)) == NULL ||
|
||||
GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE)
|
||||
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &token) == FALSE ||
|
||||
GetTokenInformation(token, TokenUser, NULL, 0, &info_len) == TRUE ||
|
||||
(info = (TOKEN_USER*)malloc(info_len)) == NULL ||
|
||||
GetTokenInformation(token, TokenUser, info, info_len, &info_len) == FALSE)
|
||||
goto done;
|
||||
|
||||
sid_size = SECURITY_MAX_SID_SIZE;
|
||||
|
@ -145,22 +142,20 @@ get_con_client_type(HANDLE pipe) {
|
|||
sid_size = SECURITY_MAX_SID_SIZE;
|
||||
if (CreateWellKnownSid(WinNetworkServiceSid, NULL, ns_sid, &sid_size) == FALSE)
|
||||
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))
|
||||
r = LOCAL_SYSTEM;
|
||||
else if (EqualSid(info->User.Sid, sshd_sid))
|
||||
r = SSHD;
|
||||
else if (EqualSid(info->User.Sid, ns_sid))
|
||||
r = NETWORK_SERVICE;
|
||||
if (EqualSid(info->User.Sid, system_sid) ||
|
||||
EqualSid(info->User.Sid, ls_sid) ||
|
||||
EqualSid(info->User.Sid, ns_sid))
|
||||
con->client_type = MACHINE;
|
||||
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:
|
||||
if (sshd_sid)
|
||||
free(sshd_sid);
|
||||
if (ref_dom)
|
||||
free(ref_dom);
|
||||
if (info)
|
||||
free(info);
|
||||
RevertToSelf();
|
||||
|
@ -168,51 +163,49 @@ done:
|
|||
}
|
||||
|
||||
static int
|
||||
process_request(struct agent_connection* con) {
|
||||
process_request(struct agent_connection* con)
|
||||
{
|
||||
int r = -1;
|
||||
struct sshbuf *request = NULL, *response = NULL;
|
||||
u_char type;
|
||||
|
||||
if (con->client_process == UNKNOWN)
|
||||
if ((con->client_process = get_con_client_type(con->connection)) == -1)
|
||||
goto done;
|
||||
if (con->client_type == UNKNOWN && get_con_client_type(con) == -1) {
|
||||
debug("unable to get client process type");
|
||||
goto done;
|
||||
}
|
||||
|
||||
//Sleep(30 * 1000);
|
||||
request = sshbuf_from(con->io_buf.buf, con->io_buf.num_bytes);
|
||||
response = sshbuf_new();
|
||||
if ((request == NULL) || (response == NULL))
|
||||
goto done;
|
||||
|
||||
{
|
||||
u_char type;
|
||||
if (sshbuf_get_u8(request, &type) != 0)
|
||||
return -1;
|
||||
debug("process agent request type %d", type);
|
||||
|
||||
if (sshbuf_get_u8(request, &type) != 0)
|
||||
return -1;
|
||||
debug("process agent request type %d", type);
|
||||
|
||||
switch (type) {
|
||||
case SSH2_AGENTC_ADD_IDENTITY:
|
||||
r = process_add_identity(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_REQUEST_IDENTITIES:
|
||||
r = process_request_identities(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_SIGN_REQUEST:
|
||||
r = process_sign_request(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_IDENTITY:
|
||||
r = process_remove_key(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||
r = process_remove_all(request, response, con);
|
||||
break;
|
||||
case SSH_AGENT_AUTHENTICATE:
|
||||
r = process_authagent_request(request, response, con);
|
||||
break;
|
||||
default:
|
||||
debug("unknown agent request %d", type);
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
switch (type) {
|
||||
case SSH2_AGENTC_ADD_IDENTITY:
|
||||
r = process_add_identity(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_REQUEST_IDENTITIES:
|
||||
r = process_request_identities(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_SIGN_REQUEST:
|
||||
r = process_sign_request(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_IDENTITY:
|
||||
r = process_remove_key(request, response, con);
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||
r = process_remove_all(request, response, con);
|
||||
break;
|
||||
case SSH_AGENT_AUTHENTICATE:
|
||||
r = process_authagent_request(request, response, con);
|
||||
break;
|
||||
default:
|
||||
debug("unknown agent request %d", type);
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
|
@ -36,21 +36,33 @@
|
|||
#define MAX_KEY_LENGTH 255
|
||||
#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
|
||||
get_user_root(struct agent_connection* con, HKEY *root){
|
||||
get_user_root(struct agent_connection* con, HKEY *root)
|
||||
{
|
||||
int r = 0;
|
||||
*root = NULL;
|
||||
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
||||
return -1;
|
||||
LONG ret;
|
||||
*root = HKEY_LOCAL_MACHINE;
|
||||
|
||||
if (con->client_process > OTHER)
|
||||
*root = HKEY_LOCAL_MACHINE;
|
||||
else if (RegOpenCurrentUser(KEY_ALL_ACCESS, root) != ERROR_SUCCESS)
|
||||
r = -1;
|
||||
|
||||
if (*root == NULL)
|
||||
debug("cannot connect to user's registry root");
|
||||
RevertToSelf();
|
||||
if (con->client_type == USER) {
|
||||
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();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -59,8 +71,8 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
|||
int success = 0;
|
||||
DATA_BLOB in, out;
|
||||
|
||||
if (con->client_process == OTHER)
|
||||
if (ImpersonateNamedPipeClient(con->connection) == FALSE)
|
||||
if (con->client_type == USER)
|
||||
if (ImpersonateNamedPipeClient(con->pipe_handle) == FALSE)
|
||||
return -1;
|
||||
|
||||
in.cbData = blen;
|
||||
|
@ -73,8 +85,7 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
|||
debug("cannot encrypt data");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (!CryptUnprotectData(&in, NULL, NULL, 0, NULL, 0, &out)) {
|
||||
debug("cannot decrypt data");
|
||||
goto done;
|
||||
|
@ -91,7 +102,7 @@ convert_blob(struct agent_connection* con, const char *blob, DWORD blen, char **
|
|||
done:
|
||||
if (out.pbData)
|
||||
LocalFree(out.pbData);
|
||||
if (con->client_process == OTHER)
|
||||
if (con->client_type == USER)
|
||||
RevertToSelf();
|
||||
return success? 0: -1;
|
||||
}
|
||||
|
@ -99,7 +110,8 @@ done:
|
|||
#define REG_KEY_SDDL L"D:P(A;; GA;;; SY)(A;; GA;;; BA)"
|
||||
|
||||
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;
|
||||
int r = 0, blob_len, eblob_len, request_invalid = 0, success = 0;
|
||||
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,
|
||||
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;
|
||||
int r = 0, success = 0;
|
||||
struct sshkey* prikey = NULL;
|
||||
|
@ -225,7 +238,8 @@ done:
|
|||
}
|
||||
|
||||
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;
|
||||
size_t blen, dlen, slen = 0;
|
||||
u_int flags = 0;
|
||||
|
@ -257,8 +271,7 @@ done:
|
|||
sshbuf_put_string(response, signature, slen) != 0) {
|
||||
r = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
if (sshbuf_put_u8(response, SSH_AGENT_FAILURE) != 0)
|
||||
r = -1;
|
||||
}
|
||||
|
@ -271,7 +284,8 @@ done:
|
|||
}
|
||||
|
||||
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;
|
||||
char *blob, *thumbprint = NULL;
|
||||
size_t blen;
|
||||
|
@ -285,10 +299,10 @@ process_remove_key(struct sshbuf* request, struct sshbuf* response, struct agent
|
|||
}
|
||||
|
||||
if ((thumbprint = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL ||
|
||||
get_user_root(con, &user_root) != 0 ||
|
||||
RegOpenKeyExW(user_root, SSH_KEYS_ROOT, 0,
|
||||
DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &root) != 0 ||
|
||||
RegDeleteTreeA(root, thumbprint) != 0)
|
||||
get_user_root(con, &user_root) != 0 ||
|
||||
RegOpenKeyExW(user_root, SSH_KEYS_ROOT, 0,
|
||||
DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &root) != 0 ||
|
||||
RegDeleteTreeA(root, thumbprint) != 0)
|
||||
goto done;
|
||||
success = 1;
|
||||
done:
|
||||
|
@ -309,7 +323,8 @@ done:
|
|||
return r;
|
||||
}
|
||||
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;
|
||||
int r = 0;
|
||||
|
||||
|
@ -333,7 +348,8 @@ done:
|
|||
}
|
||||
|
||||
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;
|
||||
HKEY root = NULL, sub = NULL, user_root = 0;
|
||||
char* count_ptr = NULL;
|
||||
|
@ -379,8 +395,7 @@ process_request_identities(struct sshbuf* request, struct sshbuf* response, stru
|
|||
|
||||
key_count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -393,8 +408,7 @@ done:
|
|||
sshbuf_put_u32(response, key_count) != 0 ||
|
||||
sshbuf_putb(response, identities) != 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
} else
|
||||
r = -1;
|
||||
|
||||
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;
|
||||
|
||||
if (sshbuf_get_u8(request, &type) != 0)
|
||||
|
|
Loading…
Reference in New Issue