Skip to content

Commit 4c0e2c2

Browse files
committed
5-7 C2
1 parent b22f7cd commit 4c0e2c2

File tree

4 files changed

+208
-119
lines changed

4 files changed

+208
-119
lines changed

contrib/win32/win32compat/ssh-agent/agent-main.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ BOOL WINAPI ctrl_c_handler(
8484
_In_ DWORD dwCtrlType
8585
) {
8686
/* for any Ctrl type, shutdown agent*/
87+
debug("Ctrl+C received");
8788
agent_shutdown();
8889
return TRUE;
8990
}
@@ -98,11 +99,11 @@ int main(int argc, char **argv) {
9899
/* console app - start in debug mode*/
99100
SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
100101
log_init("ssh-agent", 7, 1, 1);
101-
return agent_start(TRUE, FALSE, 0);
102+
return agent_start(TRUE, FALSE, 0, 0);
102103
}
103104
else {
104105
log_init("ssh-agent", config_log_level(), 1, 0);
105-
return agent_start(FALSE, TRUE, (HANDLE)atoi(*argv));
106+
return agent_start(FALSE, TRUE, (HANDLE)atoi(*(argv+1)), atoi(*(argv+2)));
106107
}
107108
}
108109
else
@@ -118,6 +119,6 @@ int scm_start_servie(DWORD num, LPWSTR* args) {
118119
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 300);
119120
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
120121
log_init("ssh-agent", config_log_level(), 1, 0);
121-
return agent_start(FALSE, FALSE, 0);
122+
return agent_start(FALSE, FALSE, 0, 0);
122123
}
123124

contrib/win32/win32compat/ssh-agent/agent.c

Lines changed: 193 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -32,144 +32,226 @@
3232
#define AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-agent"
3333
#define BUFSIZE 5 * 1024
3434

35-
static HANDLE ioc_port;
36-
static volatile long action_queue;
37-
static struct agent_connection* list;
38-
39-
#define ACTION_LISTEN 0x80000000
40-
#define ACTION_SHUTDOWN 0x40000000
41-
42-
void agent_sm_process_action_queue() {
43-
44-
do {
45-
if (action_queue & ACTION_SHUTDOWN) {
46-
/* go through the list and disconect each connection */
47-
struct agent_connection* tmp = list;
48-
while (tmp) {
49-
agent_connection_disconnect(tmp);
50-
tmp = tmp->next;
51-
}
35+
static HANDLE ioc_port = NULL;
36+
static BOOL debug_mode = FALSE;
5237

53-
/* remove unwanted queued actions */
54-
InterlockedAnd(&action_queue, ~ACTION_LISTEN);
55-
if (InterlockedAnd(&action_queue, ~ACTION_SHUTDOWN) == ACTION_SHUTDOWN)
56-
break;
57-
}
58-
else if (action_queue & ACTION_LISTEN) {
59-
HANDLE h;
60-
long prev_queue;
61-
SECURITY_ATTRIBUTES sa;
62-
struct agent_connection* con =
63-
(struct agent_connection*)malloc(sizeof(struct agent_connection));
64-
memset(con, 0, sizeof(struct agent_connection));
65-
memset(&sa, 0, sizeof(sa));
66-
sa.bInheritHandle = FALSE;
67-
sa.lpSecurityDescriptor = NULL;
68-
h = CreateNamedPipeW(
69-
AGENT_PIPE_ID, // pipe name
70-
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
71-
PIPE_TYPE_BYTE | // message type pipe
72-
PIPE_READMODE_BYTE | // message-read mode
73-
PIPE_WAIT, // blocking mode
74-
PIPE_UNLIMITED_INSTANCES, // max. instances
75-
BUFSIZE, // output buffer size
76-
BUFSIZE, // input buffer size
77-
0, // client time-out
78-
&sa);
79-
80-
/* remove action from queue before assigning iocp port*/
81-
con->connection = h;
82-
con->next = list;
83-
list = con;
84-
prev_queue = InterlockedAnd(&action_queue, ~ACTION_LISTEN);
85-
CreateIoCompletionPort(h, ioc_port, (ULONG_PTR)con, 0);
86-
ConnectNamedPipe(h, &con->ol);
87-
if (prev_queue == ACTION_LISTEN)
88-
break;
89-
}
90-
else {
91-
/* cleanup up a done connection*/
92-
struct agent_connection *prev = NULL, *tmp = list;
93-
while (tmp) {
94-
if (tmp->state == DONE) {
95-
if (prev == NULL)
96-
list = tmp->next;
97-
else
98-
prev->next = tmp->next;
99-
CloseHandle(tmp->connection);
100-
printf("deleting %p\n", tmp);
101-
free(tmp);
102-
break;
103-
}
104-
prev = tmp;
105-
tmp = tmp->next;
106-
}
107-
if (InterlockedDecrement(&action_queue) == 0)
108-
break;
109-
}
110-
} while (1);
111-
}
38+
#define NUM_LISTENERS 1
39+
#define KEY_AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-agent"
11240

113-
void
114-
agent_cleanup_connection(struct agent_connection* con) {
115-
if (InterlockedIncrement(&action_queue) == 1)
116-
agent_sm_process_action_queue();
117-
}
41+
static wchar_t *pipe_ids[NUM_LISTENERS] = { KEY_AGENT_PIPE_ID };
42+
static enum agent_type types[NUM_LISTENERS] = { KEY_AGENT };
43+
HANDLE event_stop_agent;
11844

119-
void
120-
agent_listen() {
121-
if (InterlockedOr(&action_queue, ACTION_LISTEN) == 0)
122-
agent_sm_process_action_queue();
123-
}
45+
struct listener {
46+
OVERLAPPED ol;
47+
HANDLE pipe;
48+
wchar_t *pipe_id;
49+
enum agent_type type;
50+
SECURITY_ATTRIBUTES sa;
51+
} listeners[NUM_LISTENERS];
12452

53+
static int
54+
init_listeners() {
55+
int i;
56+
memset(listeners, 0, sizeof(listeners));
57+
for (i = 0; i < NUM_LISTENERS; i++) {
58+
if ((listeners[i].ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
59+
debug("cannot create event ERROR:%d", GetLastError());
60+
return GetLastError();
61+
}
62+
listeners[i].pipe_id = pipe_ids[i];
63+
listeners[i].type = types[i];
64+
listeners[i].pipe = INVALID_HANDLE_VALUE;
65+
listeners[i].sa.bInheritHandle = TRUE;
66+
}
12567

126-
void agent_shutdown() {
127-
if (InterlockedOr(&action_queue, ACTION_SHUTDOWN) == 0)
128-
agent_sm_process_action_queue();
129-
while (list != NULL)
130-
Sleep(100);
131-
CloseHandle(ioc_port);
68+
return 0;
13269
}
13370

134-
HANDLE iocp_workers[4];
71+
static void
72+
agent_cleanup() {
73+
int i;
74+
for (i = 0; i < NUM_LISTENERS; i++) {
75+
if (listeners[i].ol.hEvent != NULL)
76+
CloseHandle(listeners[i].ol.hEvent);
77+
if (listeners[i].pipe != INVALID_HANDLE_VALUE)
78+
CloseHandle(listeners[i].pipe);
79+
}
80+
if (ioc_port)
81+
CloseHandle(ioc_port);
82+
return;
83+
}
13584

136-
DWORD WINAPI iocp_work(LPVOID lpParam) {
85+
static DWORD WINAPI
86+
iocp_work(LPVOID lpParam) {
13787
DWORD bytes;
13888
struct agent_connection* con = NULL;
13989
OVERLAPPED *p_ol;
14090
while (1) {
14191
con = NULL;
14292
p_ol = NULL;
14393
if (GetQueuedCompletionStatus(ioc_port, &bytes, &(ULONG_PTR)con, &p_ol, INFINITE) == FALSE) {
144-
printf("error: %d on %p \n", GetLastError(), con);
145-
if (con)
94+
debug("iocp error: %d on %p \n", GetLastError(), con);
95+
if (con)
14696
agent_connection_on_error(con, GetLastError());
14797
else
14898
return 0;
14999
}
150-
//printf("io on %p state %d bytes %d\n", con, con->state, bytes);
151-
agent_connection_on_io(con, bytes, p_ol);
100+
else
101+
agent_connection_on_io(con, bytes, p_ol);
152102

153103
}
154104
}
155105

156-
int agent_start(BOOL dbg, BOOL child, HANDLE pipe) {
157-
int i;
106+
107+
static int
108+
process_connection(HANDLE pipe, int type) {
109+
struct agent_connection* con;
110+
111+
if ((con = malloc(sizeof(struct agent_connection))) == NULL) {
112+
debug("out of memory");
113+
return ERROR_OUTOFMEMORY;
114+
}
115+
memset(con, 0, sizeof(struct agent_connection));
116+
con->connection = pipe;
117+
con->type = type;
118+
CreateIoCompletionPort(pipe, ioc_port, (ULONG_PTR)con, 0);
119+
agent_connection_on_io(con, 0, &con->ol);
120+
iocp_work(NULL);
121+
}
122+
123+
static void
124+
agent_listen_loop() {
125+
DWORD i, r;
126+
HANDLE wait_events[NUM_LISTENERS + 1];
127+
128+
wait_events[0] = event_stop_agent;
129+
for (i = 0; i < NUM_LISTENERS; i++)
130+
wait_events[i + 1] = listeners[i].ol.hEvent;
131+
132+
while (1) {
133+
for (i = 0; i < NUM_LISTENERS; i++) {
134+
if (listeners[i].pipe == INVALID_HANDLE_VALUE) {
135+
listeners[i].pipe = CreateNamedPipeW(
136+
listeners[i].pipe_id, // pipe name
137+
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
138+
PIPE_TYPE_BYTE | // message type pipe
139+
PIPE_READMODE_BYTE | // message-read mode
140+
PIPE_WAIT, // blocking mode
141+
PIPE_UNLIMITED_INSTANCES, // max. instances
142+
BUFSIZE, // output buffer size
143+
BUFSIZE, // input buffer size
144+
0, // client time-out
145+
&listeners[i].sa);
146+
147+
if (listeners[i].pipe == INVALID_HANDLE_VALUE) {
148+
debug("cannot create listener pipe ERROR:%d", GetLastError());
149+
SetEvent(event_stop_agent);
150+
}
151+
else if (ConnectNamedPipe(listeners[i].pipe, &listeners[i].ol) != FALSE) {
152+
debug("ConnectNamedPipe returned unexpectedly");
153+
SetEvent(event_stop_agent);
154+
}
155+
156+
if (GetLastError() == ERROR_PIPE_CONNECTED)
157+
SetEvent(listeners[i].ol.hEvent);
158+
159+
if (GetLastError() != ERROR_IO_PENDING) {
160+
debug("ConnectNamedPipe failed ERROR: %d", GetLastError());
161+
SetEvent(event_stop_agent);
162+
}
163+
164+
}
165+
}
166+
167+
r = WaitForMultipleObjects(NUM_LISTENERS + 1, wait_events, FALSE, INFINITE);
168+
if (r == WAIT_OBJECT_0) {
169+
//received signal to shutdown
170+
debug("shutting down");
171+
agent_cleanup();
172+
return;
173+
}
174+
else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + NUM_LISTENERS))) {
175+
/* process incoming connection */
176+
HANDLE con = listeners[r - 1].pipe;
177+
listeners[r - 1].pipe = INVALID_HANDLE_VALUE;
178+
179+
if (debug_mode) {
180+
process_connection(con, listeners[r - 1].type);
181+
agent_cleanup();
182+
return;
183+
}
184+
else {
185+
/* todo - spawn a child to take care of this*/
186+
wchar_t path[MAX_PATH], module_path[MAX_PATH];
187+
PROCESS_INFORMATION pi;
188+
STARTUPINFO si;
189+
190+
si.cb = sizeof(STARTUPINFO);
191+
memset(&si, 0, sizeof(STARTUPINFO));
192+
GetModuleFileNameW(NULL, module_path, MAX_PATH);
193+
swprintf_s(path, MAX_PATH, L"%s %d %d", module_path, con, listeners[r - 1].type);
194+
if (CreateProcessW(NULL, path, NULL, NULL, TRUE,
195+
DETACHED_PROCESS, NULL, NULL,
196+
&si, &pi) == FALSE) {
197+
debug("CreateProcess failure: %d", GetLastError());
198+
CloseHandle(con);
199+
agent_cleanup();
200+
return;
201+
}
202+
203+
CloseHandle(con);
204+
205+
}
206+
207+
}
208+
else {
209+
debug("wait on events ended with %d ERROR:%d", r, GetLastError());
210+
agent_cleanup();
211+
return;
212+
}
213+
214+
}
215+
}
216+
217+
void agent_cleanup_connection(struct agent_connection* con) {
218+
debug("connection %p clean up", con);
219+
CloseHandle(con->connection);
220+
free(con);
221+
CloseHandle(ioc_port);
222+
ioc_port = NULL;
223+
}
224+
225+
void agent_shutdown() {
226+
SetEvent(event_stop_agent);
227+
}
228+
229+
int agent_start(BOOL dbg_mode, BOOL child, HANDLE pipe, enum agent_type type) {
230+
int i, r;
158231
HKEY agent_root;
159232
DWORD process_id = GetCurrentProcessId();
160233

161-
debug("agent_start pid:%d, dbg:%d, child:%d, pipe:%d", process_id, dbg, child, pipe);
162-
action_queue = 0;
163-
list = NULL;
164-
ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0);
234+
debug("agent_start pid:%d, dbg:%d, child:%d, pipe:%d", process_id, dbg_mode, child, pipe);
235+
debug_mode = dbg_mode;
236+
237+
if ((ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0)) == NULL) {
238+
debug("cannot create ioc port ERROR:%d", GetLastError());
239+
return GetLastError();
240+
}
165241

166-
for (i = 0; i < 3; i++)
167-
QueueUserWorkItem(iocp_work, NULL, 0);
242+
if (child == FALSE) {
243+
RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT, 0, 0, 0, KEY_WRITE, 0, &agent_root, 0);
244+
RegSetValueExW(agent_root, L"ProcessID", 0, REG_DWORD, (BYTE*)&process_id, 4);
245+
if ((event_stop_agent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
246+
return GetLastError();
247+
if ((r = init_listeners()) != 0)
248+
return r;
249+
agent_listen_loop();
250+
}
251+
else {
252+
return process_connection(pipe, type);
253+
}
168254

169-
agent_listen();
170-
RegCreateKeyExW(HKEY_LOCAL_MACHINE, SSH_AGENT_ROOT, 0, 0, 0, KEY_WRITE, 0, &agent_root, 0);
171-
RegSetValueExW(agent_root, L"ProcessID", 0, REG_DWORD, (BYTE*)&process_id, 4);
172-
iocp_work(NULL);
173-
return 1;
255+
return 0;
174256
}
175257

0 commit comments

Comments
 (0)