diff --git a/.gitignore b/.gitignore index ddffcd2..dcbf920 100644 --- a/.gitignore +++ b/.gitignore @@ -278,3 +278,4 @@ d2utmpa* configure contrib/win32/openssh/Win32-OpenSSH.VC.opendb *.opendb +*.db diff --git a/authfd.c b/authfd.c index 6bad964..786b073 100644 --- a/authfd.c +++ b/authfd.c @@ -107,7 +107,7 @@ ssh_get_authentication_socket(int *fdp) } h = CreateFile( - "\\\\.\\pipe\\ssh-keyagent", // pipe name + "\\\\.\\pipe\\ssh-agent", // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing diff --git a/contrib/win32/win32compat/ssh-agent/agent-main.c b/contrib/win32/win32compat/ssh-agent/agent-main.c index 952cfdf..81e94ce 100644 --- a/contrib/win32/win32compat/ssh-agent/agent-main.c +++ b/contrib/win32/win32compat/ssh-agent/agent-main.c @@ -98,20 +98,20 @@ int main(int argc, char **argv) { if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { /*todo - support debug mode*/ /* - if (debugmode) { + if (debugMode) { SetConsoleCtrlHandler(ctrl_c_handler, TRUE); log_init("ssh-agent", 7, 1, 1); - agent_start(TRUE, FALSE, 0, 0); + agent_start(TRUE, FALSE, 0); return 0; } */ - if (argc == 3) { + if (argc == 2) { /*agent process is likely a spawned child*/ char* h = 0; h += atoi(*(argv + 1)); if (h != 0) { log_init("ssh-agent", config_log_level(), 1, 0); - agent_start(FALSE, TRUE, h, atoi(*(argv + 2))); + agent_start(FALSE, TRUE, h); return 0; } } @@ -148,7 +148,7 @@ int scm_start_servie(DWORD num, LPWSTR* args) { 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, 0); + agent_start(FALSE, FALSE, 0); return 0; } diff --git a/contrib/win32/win32compat/ssh-agent/agent-request.h b/contrib/win32/win32compat/ssh-agent/agent-request.h index 7bd360b..3d7c3df 100644 --- a/contrib/win32/win32compat/ssh-agent/agent-request.h +++ b/contrib/win32/win32compat/ssh-agent/agent-request.h @@ -10,6 +10,12 @@ typedef unsigned __int64 u_int64_t; #include "digest.h" -int process_keyagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*); -int process_pubkeyagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*); -int process_authagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*); \ No newline at end of file +/* key management */ +int process_add_identity(struct sshbuf*, struct sshbuf*, struct agent_connection*); +int process_request_identities(struct sshbuf*, struct sshbuf*, struct agent_connection*); +int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*); +int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*); +int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*); +int process_authagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*); + +/* auth */ diff --git a/contrib/win32/win32compat/ssh-agent/agent.c b/contrib/win32/win32compat/ssh-agent/agent.c index deb5359..1bd936d 100644 --- a/contrib/win32/win32compat/ssh-agent/agent.c +++ b/contrib/win32/win32compat/ssh-agent/agent.c @@ -35,39 +35,24 @@ static HANDLE ioc_port = NULL; static BOOL debug_mode = FALSE; -#define NUM_LISTENERS 3 -#define KEY_AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-keyagent" -#define PUBKEY_AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-pubkeyagent" -#define AUTH_AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-authagent" +#define AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-agent" -static wchar_t *pipe_ids[NUM_LISTENERS] = { KEY_AGENT_PIPE_ID, PUBKEY_AGENT_PIPE_ID, AUTH_AGENT_PIPE_ID }; -static enum agent_type pipe_types[NUM_LISTENERS] = { KEY_AGENT, PUBKEY_AGENT, PUBKEY_AUTH_AGENT}; -static wchar_t *pipe_sddls[NUM_LISTENERS] = { L"D:P(A;; GA;;; AU)", L"D:P(A;; GA;;; AU)", L"D:P(A;; GA;;; AU)" }; -HANDLE event_stop_agent; - -struct listener { - OVERLAPPED ol; - HANDLE pipe; - wchar_t *pipe_id; - enum agent_type type; - SECURITY_ATTRIBUTES sa; -} listeners[NUM_LISTENERS]; +static HANDLE event_stop_agent; +static OVERLAPPED ol; +static HANDLE pipe; +static SECURITY_ATTRIBUTES sa; static int -init_listeners() { - int i; - memset(listeners, 0, sizeof(listeners)); - for (i = 0; i < NUM_LISTENERS; i++) { - if ((listeners[i].ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { +init_listener() { + { + if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) { debug("cannot create event ERROR:%d", GetLastError()); return GetLastError(); } - listeners[i].pipe_id = pipe_ids[i]; - listeners[i].type = pipe_types[i]; - listeners[i].pipe = INVALID_HANDLE_VALUE; - listeners[i].sa.bInheritHandle = FALSE; - if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(pipe_sddls[i], SDDL_REVISION_1, - &listeners[i].sa.lpSecurityDescriptor, &listeners[i].sa.nLength)) { + 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(); } @@ -78,12 +63,11 @@ init_listeners() { static void agent_cleanup() { - int i; - for (i = 0; i < NUM_LISTENERS; i++) { - if (listeners[i].ol.hEvent != NULL) - CloseHandle(listeners[i].ol.hEvent); - if (listeners[i].pipe != INVALID_HANDLE_VALUE) - CloseHandle(listeners[i].pipe); + { + if (ol.hEvent != NULL) + CloseHandle(ol.hEvent); + if (pipe != INVALID_HANDLE_VALUE) + CloseHandle(pipe); } if (ioc_port) CloseHandle(ioc_port); @@ -112,7 +96,7 @@ iocp_work(LPVOID lpParam) { } static void -process_connection(HANDLE pipe, int type) { +process_connection(HANDLE pipe) { struct agent_connection* con; if ((con = malloc(sizeof(struct agent_connection))) == NULL) @@ -120,7 +104,6 @@ process_connection(HANDLE pipe, int type) { memset(con, 0, sizeof(struct agent_connection)); con->connection = pipe; - con->type = type; if (CreateIoCompletionPort(pipe, ioc_port, (ULONG_PTR)con, 0) != ioc_port) fatal("failed to assign pipe to ioc_port"); @@ -130,18 +113,18 @@ process_connection(HANDLE pipe, int type) { static void agent_listen_loop() { - DWORD i, r; - HANDLE wait_events[NUM_LISTENERS + 1]; + DWORD r; + HANDLE wait_events[2]; wait_events[0] = event_stop_agent; - for (i = 0; i < NUM_LISTENERS; i++) - wait_events[i + 1] = listeners[i].ol.hEvent; + + wait_events[1] = ol.hEvent; while (1) { - for (i = 0; i < NUM_LISTENERS; i++) { - if (listeners[i].pipe == INVALID_HANDLE_VALUE) { - listeners[i].pipe = CreateNamedPipeW( - listeners[i].pipe_id, // pipe name + { + { + 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 @@ -150,20 +133,20 @@ agent_listen_loop() { BUFSIZE, // output buffer size BUFSIZE, // input buffer size 0, // client time-out - &listeners[i].sa); + &sa); - if (listeners[i].pipe == INVALID_HANDLE_VALUE) { + if (pipe == INVALID_HANDLE_VALUE) { verbose("cannot create listener pipe ERROR:%d", GetLastError()); SetEvent(event_stop_agent); } - else if (ConnectNamedPipe(listeners[i].pipe, &listeners[i].ol) != FALSE) { + else if (ConnectNamedPipe(pipe, &ol) != FALSE) { verbose("ConnectNamedPipe returned TRUE unexpectedly "); SetEvent(event_stop_agent); } if (GetLastError() == ERROR_PIPE_CONNECTED) { - debug("Client has already connection to %d", i); - SetEvent(listeners[i].ol.hEvent); + debug("Client has already connected"); + SetEvent(ol.hEvent); } if (GetLastError() != ERROR_IO_PENDING) { @@ -174,22 +157,22 @@ agent_listen_loop() { } } - r = WaitForMultipleObjects(NUM_LISTENERS + 1, wait_events, FALSE, INFINITE); + r = WaitForMultipleObjects(2, wait_events, FALSE, INFINITE); if (r == WAIT_OBJECT_0) { //received signal to shutdown debug("shutting down"); agent_cleanup(); return; } - else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + NUM_LISTENERS))) { + else if ((r > WAIT_OBJECT_0) && (r <= (WAIT_OBJECT_0 + 1))) { /* process incoming connection */ - HANDLE con = listeners[r - 1].pipe; + HANDLE con = pipe; DWORD client_pid = 0; - listeners[r - 1].pipe = INVALID_HANDLE_VALUE; + pipe = INVALID_HANDLE_VALUE; GetNamedPipeClientProcessId(con, &client_pid); - verbose("client pid %d connected on %ls", client_pid, pipe_ids[r-1]); + verbose("client pid %d connected", client_pid); if (debug_mode) { - process_connection(con, listeners[r - 1].type); + process_connection(con); agent_cleanup(); return; } @@ -203,14 +186,14 @@ agent_listen_loop() { memset(&si, 0, sizeof(STARTUPINFOW)); GetModuleFileNameW(NULL, module_path, MAX_PATH); SetHandleInformation(con, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - if ((swprintf_s(path, MAX_PATH, L"%s %d %d", module_path, con, listeners[r - 1].type) == -1 ) || + if ((swprintf_s(path, MAX_PATH, L"%s %d", module_path, con) == -1 ) || (CreateProcessW(NULL, path, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi) == FALSE)) { verbose("Failed to create child process %ls ERROR:%d", module_path, GetLastError()); } else { - debug("spawned child %d to process %d", pi.dwProcessId, i); + debug("spawned child %d ", pi.dwProcessId); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } @@ -242,7 +225,7 @@ void agent_shutdown() { #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, enum agent_type type) { +agent_start(BOOL dbg_mode, BOOL child, HANDLE pipe) { int r; HKEY agent_root = NULL; DWORD process_id = GetCurrentProcessId(); @@ -266,12 +249,12 @@ agent_start(BOOL dbg_mode, BOOL child, HANDLE pipe, enum agent_type type) { 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_listeners()) != 0) + 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, type); + process_connection(pipe); } } diff --git a/contrib/win32/win32compat/ssh-agent/agent.h b/contrib/win32/win32compat/ssh-agent/agent.h index 639c37f..7a7be7f 100644 --- a/contrib/win32/win32compat/ssh-agent/agent.h +++ b/contrib/win32/win32compat/ssh-agent/agent.h @@ -9,12 +9,6 @@ #define HEADER_SIZE 4 -enum agent_type { - KEY_AGENT, - PUBKEY_AGENT, - PUBKEY_AUTH_AGENT -}; - struct agent_connection { OVERLAPPED ol; HANDLE connection; @@ -38,14 +32,13 @@ struct agent_connection { SSHD, NETWORK_SERVICE } client_type; - enum agent_type type; }; 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, enum agent_type); +void agent_start(BOOL, BOOL, HANDLE); void agent_shutdown(); void agent_cleanup_connection(struct agent_connection*); diff --git a/contrib/win32/win32compat/ssh-agent/connection.c b/contrib/win32/win32compat/ssh-agent/connection.c index 2a19282..5657456 100644 --- a/contrib/win32/win32compat/ssh-agent/connection.c +++ b/contrib/win32/win32compat/ssh-agent/connection.c @@ -183,12 +183,31 @@ process_request(struct agent_connection* con) { if ((request == NULL) || (response == NULL)) goto done; - if (con->type == KEY_AGENT) - r = process_keyagent_request(request, response, con); - else if (con->type == PUBKEY_AGENT) - r = process_pubkeyagent_request(request, response, con); - else if (con->type == PUBKEY_AUTH_AGENT) - r = process_authagent_request(request, response, con); + { + u_char type; + + if (sshbuf_get_u8(request, &type) != 0) + return -1; + debug2("process key agent request type %d", type); + + switch (type) { + case SSH2_AGENTC_ADD_IDENTITY: + return process_add_identity(request, response, con); + case SSH2_AGENTC_REQUEST_IDENTITIES: + return process_request_identities(request, response, con); + case SSH2_AGENTC_SIGN_REQUEST: + return process_sign_request(request, response, con); + case SSH2_AGENTC_REMOVE_IDENTITY: + return process_remove_key(request, response, con); + case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: + return process_remove_all(request, response, con); + case 100: + return process_authagent_request(request, response, con); + default: + debug("unknown agent request %d", type); + return -1; + } + } done: if (request) diff --git a/contrib/win32/win32compat/ssh-agent/keyagent-request.c b/contrib/win32/win32compat/ssh-agent/keyagent-request.c index 50b59b8..7f9831c 100644 --- a/contrib/win32/win32compat/ssh-agent/keyagent-request.c +++ b/contrib/win32/win32compat/ssh-agent/keyagent-request.c @@ -98,7 +98,7 @@ done: #define REG_KEY_SDDL L"D:P(A;; GA;;; SY)(A;; GA;;; BA)" -static int +int 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; @@ -224,7 +224,7 @@ done: return success ? 0 : -1; } -static int +int 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; @@ -270,7 +270,7 @@ done: return r; } -static int +int process_remove_key(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { HKEY user_root = 0, root = 0; char *blob, *thumbprint = NULL; @@ -308,7 +308,7 @@ done: free(thumbprint); return r; } -static int +int process_remove_all(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { HKEY user_root = 0, root = 0; int r = 0; @@ -332,7 +332,7 @@ done: return r; } -static int +int 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;