mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-23 05:55:41 +02:00
4-13 C1
This commit is contained in:
parent
8fb27e8fc6
commit
491769a99f
@ -20,8 +20,12 @@
|
|||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\ssh-agent-main.cpp" />
|
<ClCompile Include="..\win32compat\ssh-agent\agent-main.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ssh-agent\ssh-agent.cpp" />
|
<ClCompile Include="..\win32compat\ssh-agent\agent.c" />
|
||||||
|
<ClCompile Include="..\win32compat\ssh-agent\connection.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\win32compat\ssh-agent\agent.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{F6644EC5-D6B6-42A1-828C-75E2977470E0}</ProjectGuid>
|
<ProjectGuid>{F6644EC5-D6B6-42A1-828C-75E2977470E0}</ProjectGuid>
|
||||||
|
@ -66,7 +66,7 @@ static VOID WINAPI service_handler(DWORD dwControl)
|
|||||||
{
|
{
|
||||||
case SERVICE_CONTROL_STOP: {
|
case SERVICE_CONTROL_STOP: {
|
||||||
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 500);
|
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 500);
|
||||||
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
|
agent_shutdown();
|
||||||
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -79,11 +79,20 @@ 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(
|
||||||
|
_In_ DWORD dwCtrlType
|
||||||
|
) {
|
||||||
|
/* for any Ctrl type, shutdown agent*/
|
||||||
|
agent_shutdown();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
if (!StartServiceCtrlDispatcher(diapatch_table)) {
|
if (!StartServiceCtrlDispatcher(diapatch_table)) {
|
||||||
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
|
||||||
//console app
|
//console app
|
||||||
start_agent();
|
SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
|
||||||
|
return agent_start();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
@ -97,6 +106,6 @@ int scm_start_servie(DWORD num, LPWSTR* args) {
|
|||||||
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);
|
||||||
return start_agent();
|
return agent_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,17 +36,11 @@ static HANDLE ioc_port;
|
|||||||
static volatile long action_queue;
|
static volatile long action_queue;
|
||||||
static struct agent_connection* list;
|
static struct agent_connection* list;
|
||||||
|
|
||||||
enum agent_sm_event {
|
|
||||||
NEW_CLIENT_CONNECTION = 1,
|
|
||||||
CONNECTION_DONE = 2,
|
|
||||||
SHUTDOWN = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ACTION_LISTEN 0x80000000
|
#define ACTION_LISTEN 0x80000000
|
||||||
#define ACTION_SHUTDOWN 0x40000000
|
#define ACTION_SHUTDOWN 0x40000000
|
||||||
|
|
||||||
void agent_sm_process_action_queue() {
|
void agent_sm_process_action_queue() {
|
||||||
long actions_remaining = 0;
|
|
||||||
do {
|
do {
|
||||||
if (action_queue & ACTION_SHUTDOWN) {
|
if (action_queue & ACTION_SHUTDOWN) {
|
||||||
/* go through the list and disconect each connection */
|
/* go through the list and disconect each connection */
|
||||||
@ -58,10 +52,12 @@ void agent_sm_process_action_queue() {
|
|||||||
|
|
||||||
/* remove unwanted queued actions */
|
/* remove unwanted queued actions */
|
||||||
InterlockedAnd(&action_queue, ~ACTION_LISTEN);
|
InterlockedAnd(&action_queue, ~ACTION_LISTEN);
|
||||||
actions_remaining = InterlockedAnd(&action_queue, ~ACTION_SHUTDOWN);
|
if (InterlockedAnd(&action_queue, ~ACTION_SHUTDOWN) == ACTION_SHUTDOWN)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (action_queue & ACTION_LISTEN) {
|
else if (action_queue & ACTION_LISTEN) {
|
||||||
HANDLE h;
|
HANDLE h, temp;
|
||||||
|
long prev_queue;
|
||||||
struct agent_connection* con =
|
struct agent_connection* con =
|
||||||
(struct agent_connection*)malloc(sizeof(struct agent_connection));
|
(struct agent_connection*)malloc(sizeof(struct agent_connection));
|
||||||
memset(con, 0, sizeof(struct agent_connection));
|
memset(con, 0, sizeof(struct agent_connection));
|
||||||
@ -78,12 +74,13 @@ void agent_sm_process_action_queue() {
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* remove action from queue before assigning iocp port*/
|
/* remove action from queue before assigning iocp port*/
|
||||||
|
con->connection = h;
|
||||||
con->next = list;
|
con->next = list;
|
||||||
list = con;
|
list = con;
|
||||||
actions_remaining = InterlockedAnd(&action_queue, ~ACTION_LISTEN);
|
prev_queue = InterlockedAnd(&action_queue, ~ACTION_LISTEN);
|
||||||
CreateIoCompletionPort(h, ioc_port, con, 0);
|
temp = CreateIoCompletionPort(h, ioc_port, (ULONG_PTR)con, 0);
|
||||||
|
if (prev_queue == ACTION_LISTEN)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* cleanup up a done connection*/
|
/* cleanup up a done connection*/
|
||||||
@ -101,35 +98,30 @@ void agent_sm_process_action_queue() {
|
|||||||
prev = tmp;
|
prev = tmp;
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
actions_remaining = InterlockedDecrement(&action_queue);
|
if (InterlockedDecrement(&action_queue) == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while (actions_remaining);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_sm_raise(enum agent_sm_event event) {
|
void
|
||||||
long ret = 0;
|
agent_cleanup_connection(struct agent_connection* con) {
|
||||||
switch (event) {
|
if (InterlockedIncrement(&action_queue) == 1)
|
||||||
case NEW_CLIENT_CONNECTION:
|
agent_sm_process_action_queue();
|
||||||
ret = InterlockedOr(&action_queue, ACTION_LISTEN);
|
}
|
||||||
if (ret == 0)
|
|
||||||
agent_sm_process_action_queue();
|
|
||||||
break;
|
|
||||||
case SHUTDOWN:
|
|
||||||
ret = InterlockedOr(&action_queue, ACTION_SHUTDOWN);
|
|
||||||
if (ret == 0)
|
|
||||||
agent_sm_process_action_queue();
|
|
||||||
break;
|
|
||||||
case CONNECTION_DONE:
|
|
||||||
ret = InterlockedIncrement(&action_queue);
|
|
||||||
if (ret == 1)
|
|
||||||
agent_sm_process_action_queue();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DebugBreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is this the first action queued */
|
void
|
||||||
|
agent_listen() {
|
||||||
|
if (InterlockedOr(&action_queue, ACTION_LISTEN) == 0)
|
||||||
|
agent_sm_process_action_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void agent_shutdown() {
|
||||||
|
if (InterlockedOr(&action_queue, ACTION_SHUTDOWN) == 0)
|
||||||
|
agent_sm_process_action_queue();
|
||||||
|
while (list != NULL)
|
||||||
|
Sleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE iocp_workers[4];
|
HANDLE iocp_workers[4];
|
||||||
@ -139,7 +131,7 @@ DWORD WINAPI iocp_work(LPVOID lpParam) {
|
|||||||
struct agent_connection* con;
|
struct agent_connection* con;
|
||||||
OVERLAPPED *p_ol;
|
OVERLAPPED *p_ol;
|
||||||
while (1) {
|
while (1) {
|
||||||
GetQueuedCompletionStatus(ioc_port, &bytes, &con, &p_ol, INFINITE);
|
GetQueuedCompletionStatus(ioc_port, &bytes, &(ULONG_PTR)con, &p_ol, INFINITE);
|
||||||
agent_connection_on_io(con, bytes, p_ol);
|
agent_connection_on_io(con, bytes, p_ol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,17 +140,13 @@ int agent_start() {
|
|||||||
int i;
|
int i;
|
||||||
action_queue = 0;
|
action_queue = 0;
|
||||||
list = NULL;
|
list = NULL;
|
||||||
ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
|
ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0);
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 3; i++)
|
||||||
iocp_workers[i] = CreateThread(NULL, 0, iocp_work, NULL, 0, NULL);
|
QueueUserWorkItem(iocp_work, NULL, 0);
|
||||||
|
|
||||||
action_queue = ACTION_LISTEN;
|
agent_listen();
|
||||||
agent_sm_process_action_queue();
|
iocp_work(NULL);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void agent_shutdown() {
|
|
||||||
agent_sm_raise(SHUTDOWN);
|
|
||||||
while (list != NULL)
|
|
||||||
Sleep(100);
|
|
||||||
}
|
|
||||||
|
@ -1,20 +1,30 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#define BUFSIZE 5 * 1024
|
||||||
|
|
||||||
|
#define HEADER_SIZE 4
|
||||||
int agent_start();
|
|
||||||
void agent_shutdown();
|
|
||||||
|
|
||||||
struct agent_connection {
|
struct agent_connection {
|
||||||
|
OVERLAPPED ol;
|
||||||
|
HANDLE connection;
|
||||||
|
struct {
|
||||||
|
DWORD size;
|
||||||
|
DWORD read;
|
||||||
|
char buf[BUFSIZE];
|
||||||
|
} request;
|
||||||
enum {
|
enum {
|
||||||
LISTENING = 0,
|
LISTENING = 0,
|
||||||
|
READING_HEADER,
|
||||||
READING,
|
READING,
|
||||||
WRITING,
|
WRITING,
|
||||||
DONE
|
DONE
|
||||||
} state;
|
} state;
|
||||||
HANDLE connection;
|
struct agent_connection* next;
|
||||||
struct agent_con* next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
|
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
|
||||||
void agent_connection_disconnect(struct agent_connection*);
|
void agent_connection_disconnect(struct agent_connection*);
|
||||||
|
|
||||||
|
int agent_start();
|
||||||
|
void agent_shutdown();
|
||||||
|
void agent_listen();
|
||||||
|
void agent_cleanup_connection(struct agent_connection*);
|
||||||
|
@ -29,18 +29,100 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
#define BUFSIZE 5 * 1024
|
|
||||||
|
|
||||||
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) {
|
||||||
switch (con->state) {
|
|
||||||
case LISTENING:
|
/* process error */
|
||||||
break;
|
if ( (bytes == 0) && (GetOverlappedResult(con->connection, ol, &bytes, FALSE) == FALSE)) {
|
||||||
case READING:
|
con->state = DONE;
|
||||||
break;
|
agent_cleanup_connection(con);
|
||||||
case WRITING:
|
return;
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
|
if (con->state == DONE)
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
switch (con->state) {
|
||||||
|
case WRITING:
|
||||||
|
/* Writing is done, read next request */
|
||||||
|
case LISTENING:
|
||||||
|
con->state = READING_HEADER;
|
||||||
|
if (con->state == LISTENING)
|
||||||
|
agent_listen();
|
||||||
|
ZeroMemory(&con->request, sizeof(con->request));
|
||||||
|
if (ReadFile(con->connection, con->request.buf,
|
||||||
|
HEADER_SIZE, NULL, &con->ol)) {
|
||||||
|
bytes = HEADER_SIZE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (GetLastError() != ERROR_IO_PENDING) {
|
||||||
|
con->state = DONE;
|
||||||
|
agent_cleanup_connection(con);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case READING_HEADER:
|
||||||
|
con->request.read += bytes;
|
||||||
|
if (con->request.read == HEADER_SIZE) {
|
||||||
|
con->request.size = *((DWORD*)con->request.buf);
|
||||||
|
con->state = READING;
|
||||||
|
if (ReadFile(con->connection, con->request.buf,
|
||||||
|
con->request.size, NULL, &con->ol)) {
|
||||||
|
bytes = con->request.size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (GetLastError() != ERROR_IO_PENDING) {
|
||||||
|
con->state = DONE;
|
||||||
|
agent_cleanup_connection(con);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ReadFile(con->connection, con->request.buf + con->request.read,
|
||||||
|
HEADER_SIZE - con->request.read, NULL, &con->ol)) {
|
||||||
|
bytes = HEADER_SIZE - con->request.read;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (GetLastError() != ERROR_IO_PENDING) {
|
||||||
|
con->state = DONE;
|
||||||
|
agent_cleanup_connection(con);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case READING:
|
||||||
|
con->request.read += bytes;
|
||||||
|
if (con->request.read == con->request.size) {
|
||||||
|
/* process request and get response */
|
||||||
|
con->state = WRITING;
|
||||||
|
if (WriteFile(con->connection, con->request.buf,
|
||||||
|
con->request.size, NULL, &con->ol)) {
|
||||||
|
bytes = con->request.size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (GetLastError() != ERROR_IO_PENDING) {
|
||||||
|
con->state = DONE;
|
||||||
|
agent_cleanup_connection(con);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ReadFile(con->connection, con->request.buf + con->request.read,
|
||||||
|
con->request.size - con->request.read, NULL, &con->ol)) {
|
||||||
|
bytes = con->request.size - con->request.read;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (GetLastError() != ERROR_IO_PENDING) {
|
||||||
|
con->state = DONE;
|
||||||
|
agent_cleanup_connection(con);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DebugBreak();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user